PkixNameConstraintValidator
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.X500;
using Org.BouncyCastle.Asn1.X500.Style;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.Encoders;
using System;
using System.Collections.Generic;
using System.Text;
namespace Org.BouncyCastle.Pkix
{
    public class PkixNameConstraintValidator
    {
        private static readonly DerObjectIdentifier SerialNumberOid = X509Name.SerialNumber;
        private HashSet<Asn1Sequence> excludedSubtreesDN = new HashSet<Asn1Sequence>();
        private HashSet<string> excludedSubtreesDns = new HashSet<string>();
        private HashSet<string> excludedSubtreesEmail = new HashSet<string>();
        private HashSet<string> excludedSubtreesUri = new HashSet<string>();
        private HashSet<byte[]> excludedSubtreesIP = new HashSet<byte[]>();
        private HashSet<OtherName> excludedSubtreesOtherName = new HashSet<OtherName>();
        private HashSet<Asn1Sequence> permittedSubtreesDN;
        private HashSet<string> permittedSubtreesDns;
        private HashSet<string> permittedSubtreesEmail;
        private HashSet<string> permittedSubtreesUri;
        private HashSet<byte[]> permittedSubtreesIP;
        private HashSet<OtherName> permittedSubtreesOtherName;
        private static bool WithinDNSubtree(Asn1Sequence dns, Asn1Sequence subtree)
        {
            if (subtree.Count < 1 || subtree.Count > dns.Count)
                return false;
            int num = 0;
            Rdn instance = Rdn.GetInstance(subtree[0]);
            for (int i = 0; i < dns.Count; i++) {
                num = i;
                Rdn instance2 = Rdn.GetInstance(dns[i]);
                if (IetfUtilities.RdnAreEqual(instance, instance2))
                    break;
            }
            if (subtree.Count > dns.Count - num)
                return false;
            for (int j = 0; j < subtree.Count; j++) {
                Rdn instance3 = Rdn.GetInstance(subtree[j]);
                Rdn instance4 = Rdn.GetInstance(dns[num + j]);
                if (instance3.Count == 1 && instance4.Count == 1 && SerialNumberOid.Equals(instance3.GetFirst().Type) && SerialNumberOid.Equals(instance4.GetFirst().Type)) {
                    if (!Platform.StartsWith(instance4.GetFirst().Value.ToString(), instance3.GetFirst().Value.ToString()))
                        return false;
                } else if (!IetfUtilities.RdnAreEqual(instance3, instance4)) {
                    return false;
                }
            }
            return true;
        }
        public void CheckExcludedDN(Asn1Sequence dn)
        {
            CheckExcludedDN(excludedSubtreesDN, dn);
        }
        public void CheckPermittedDN(Asn1Sequence dn)
        {
            CheckPermittedDN(permittedSubtreesDN, dn);
        }
        private void CheckExcludedDN(HashSet<Asn1Sequence> excluded, Asn1Sequence directory)
        {
            if (IsDNConstrained(excluded, directory))
                throw new PkixNameConstraintValidatorException("Subject distinguished name is from an excluded subtree");
        }
        private void CheckPermittedDN(HashSet<Asn1Sequence> permitted, Asn1Sequence directory)
        {
            if (permitted != null && (directory.Count != 0 || permitted.Count >= 1) && !IsDNConstrained(permitted, directory))
                throw new PkixNameConstraintValidatorException("Subject distinguished name is not from a permitted subtree");
        }
        private bool IsDNConstrained(HashSet<Asn1Sequence> constraints, Asn1Sequence directory)
        {
            foreach (Asn1Sequence constraint in constraints) {
                if (WithinDNSubtree(directory, constraint))
                    return true;
            }
            return false;
        }
        private HashSet<Asn1Sequence> IntersectDN(HashSet<Asn1Sequence> permitted, HashSet<GeneralSubtree> dns)
        {
            HashSet<Asn1Sequence> hashSet = new HashSet<Asn1Sequence>();
            foreach (GeneralSubtree dn in dns) {
                Asn1Sequence instance = Asn1Sequence.GetInstance(dn.Base.Name);
                if (permitted == null) {
                    if (instance != null)
                        hashSet.Add(instance);
                } else {
                    foreach (Asn1Sequence item in permitted) {
                        if (WithinDNSubtree(instance, item))
                            hashSet.Add(instance);
                        else if (WithinDNSubtree(item, instance)) {
                            hashSet.Add(item);
                        }
                    }
                }
            }
            return hashSet;
        }
        private HashSet<Asn1Sequence> UnionDN(HashSet<Asn1Sequence> excluded, Asn1Sequence dn)
        {
            if (excluded.Count < 1) {
                if (dn == null)
                    return excluded;
                excluded.Add(dn);
                return excluded;
            }
            HashSet<Asn1Sequence> hashSet = new HashSet<Asn1Sequence>();
            foreach (Asn1Sequence item in excluded) {
                if (WithinDNSubtree(dn, item))
                    hashSet.Add(item);
                else if (WithinDNSubtree(item, dn)) {
                    hashSet.Add(dn);
                } else {
                    hashSet.Add(item);
                    hashSet.Add(dn);
                }
            }
            return hashSet;
        }
        private void CheckExcludedOtherName(HashSet<OtherName> excluded, OtherName name)
        {
            if (IsOtherNameConstrained(excluded, name))
                throw new PkixNameConstraintValidatorException("OtherName is from an excluded subtree.");
        }
        private void CheckPermittedOtherName(HashSet<OtherName> permitted, OtherName name)
        {
            if (permitted != null && !IsOtherNameConstrained(permitted, name))
                throw new PkixNameConstraintValidatorException("Subject OtherName is not from a permitted subtree.");
        }
        private bool IsOtherNameConstrained(HashSet<OtherName> constraints, OtherName otherName)
        {
            foreach (OtherName constraint in constraints) {
                if (IsOtherNameConstrained(constraint, otherName))
                    return true;
            }
            return false;
        }
        private bool IsOtherNameConstrained(OtherName constraint, OtherName otherName)
        {
            return constraint.Equals(otherName);
        }
        private HashSet<OtherName> IntersectOtherName(HashSet<OtherName> permitted, HashSet<GeneralSubtree> otherNames)
        {
            HashSet<OtherName> hashSet = new HashSet<OtherName>();
            foreach (GeneralSubtree otherName in otherNames) {
                OtherName instance = OtherName.GetInstance(otherName.Base.Name);
                if (instance != null) {
                    if (permitted == null)
                        hashSet.Add(instance);
                    else {
                        foreach (OtherName item in permitted) {
                            IntersectOtherName(instance, item, hashSet);
                        }
                    }
                }
            }
            return hashSet;
        }
        private void IntersectOtherName(OtherName otherName1, OtherName otherName2, HashSet<OtherName> intersect)
        {
            if (otherName1.Equals(otherName2))
                intersect.Add(otherName1);
        }
        private HashSet<OtherName> UnionOtherName(HashSet<OtherName> permitted, OtherName otherName)
        {
            HashSet<OtherName> obj = (permitted != null) ? new HashSet<OtherName>(permitted) : new HashSet<OtherName>();
            obj.Add(otherName);
            return obj;
        }
        private void CheckExcludedEmail(HashSet<string> excluded, string email)
        {
            if (IsEmailConstrained(excluded, email))
                throw new PkixNameConstraintValidatorException("Email address is from an excluded subtree.");
        }
        private void CheckPermittedEmail(HashSet<string> permitted, string email)
        {
            if (permitted != null && (email.Length != 0 || permitted.Count >= 1) && !IsEmailConstrained(permitted, email))
                throw new PkixNameConstraintValidatorException("Subject email address is not from a permitted subtree.");
        }
        private bool IsEmailConstrained(HashSet<string> constraints, string email)
        {
            foreach (string constraint in constraints) {
                if (IsEmailConstrained(constraint, email))
                    return true;
            }
            return false;
        }
        private bool IsEmailConstrained(string constraint, string email)
        {
            string text = email.Substring(email.IndexOf('@') + 1);
            if (constraint.IndexOf('@') != -1) {
                if (string.Equals(email, constraint, StringComparison.OrdinalIgnoreCase))
                    return true;
            } else if (constraint[0] != '.') {
                if (string.Equals(text, constraint, StringComparison.OrdinalIgnoreCase))
                    return true;
            } else if (WithinDomain(text, constraint)) {
                return true;
            }
            return false;
        }
        private HashSet<string> IntersectEmail(HashSet<string> permitted, HashSet<GeneralSubtree> emails)
        {
            HashSet<string> hashSet = new HashSet<string>();
            foreach (GeneralSubtree email in emails) {
                string text = ExtractNameAsString(email.Base);
                if (permitted == null) {
                    if (text != null)
                        hashSet.Add(text);
                } else {
                    foreach (string item in permitted) {
                        IntersectEmail(text, item, hashSet);
                    }
                }
            }
            return hashSet;
        }
        private void IntersectEmail(string email1, string email2, HashSet<string> intersect)
        {
            if (email1.IndexOf('@') != -1) {
                string text = email1.Substring(email1.IndexOf('@') + 1);
                if (email2.IndexOf('@') != -1) {
                    if (Platform.EqualsIgnoreCase(email1, email2))
                        intersect.Add(email1);
                } else if (Platform.StartsWith(email2, ".")) {
                    if (WithinDomain(text, email2))
                        intersect.Add(email1);
                } else if (Platform.EqualsIgnoreCase(text, email2)) {
                    intersect.Add(email1);
                }
            } else if (Platform.StartsWith(email1, ".")) {
                if (email2.IndexOf('@') != -1) {
                    string testDomain = email2.Substring(email1.IndexOf('@') + 1);
                    if (WithinDomain(testDomain, email1))
                        intersect.Add(email2);
                } else if (Platform.StartsWith(email2, ".")) {
                    if (WithinDomain(email1, email2) || Platform.EqualsIgnoreCase(email1, email2))
                        intersect.Add(email1);
                    else if (WithinDomain(email2, email1)) {
                        intersect.Add(email2);
                    }
                } else if (WithinDomain(email2, email1)) {
                    intersect.Add(email2);
                }
            } else if (email2.IndexOf('@') != -1) {
                if (Platform.EqualsIgnoreCase(email2.Substring(email2.IndexOf('@') + 1), email1))
                    intersect.Add(email2);
            } else if (Platform.StartsWith(email2, ".")) {
                if (WithinDomain(email1, email2))
                    intersect.Add(email1);
            } else if (Platform.EqualsIgnoreCase(email1, email2)) {
                intersect.Add(email1);
            }
        }
        private HashSet<string> UnionEmail(HashSet<string> excluded, string email)
        {
            if (excluded.Count < 1) {
                if (email == null)
                    return excluded;
                excluded.Add(email);
                return excluded;
            }
            HashSet<string> hashSet = new HashSet<string>();
            foreach (string item in excluded) {
                UnionEmail(item, email, hashSet);
            }
            return hashSet;
        }
        private void UnionEmail(string email1, string email2, HashSet<string> union)
        {
            if (email1.IndexOf('@') != -1) {
                string text = email1.Substring(email1.IndexOf('@') + 1);
                if (email2.IndexOf('@') != -1) {
                    if (Platform.EqualsIgnoreCase(email1, email2))
                        union.Add(email1);
                    else {
                        union.Add(email1);
                        union.Add(email2);
                    }
                } else if (Platform.StartsWith(email2, ".")) {
                    if (WithinDomain(text, email2))
                        union.Add(email2);
                    else {
                        union.Add(email1);
                        union.Add(email2);
                    }
                } else if (Platform.EqualsIgnoreCase(text, email2)) {
                    union.Add(email2);
                } else {
                    union.Add(email1);
                    union.Add(email2);
                }
            } else if (Platform.StartsWith(email1, ".")) {
                if (email2.IndexOf('@') != -1) {
                    string testDomain = email2.Substring(email1.IndexOf('@') + 1);
                    if (WithinDomain(testDomain, email1))
                        union.Add(email1);
                    else {
                        union.Add(email1);
                        union.Add(email2);
                    }
                } else if (Platform.StartsWith(email2, ".")) {
                    if (WithinDomain(email1, email2) || Platform.EqualsIgnoreCase(email1, email2))
                        union.Add(email2);
                    else if (WithinDomain(email2, email1)) {
                        union.Add(email1);
                    } else {
                        union.Add(email1);
                        union.Add(email2);
                    }
                } else if (WithinDomain(email2, email1)) {
                    union.Add(email1);
                } else {
                    union.Add(email1);
                    union.Add(email2);
                }
            } else if (email2.IndexOf('@') != -1) {
                if (Platform.EqualsIgnoreCase(email2.Substring(email1.IndexOf('@') + 1), email1))
                    union.Add(email1);
                else {
                    union.Add(email1);
                    union.Add(email2);
                }
            } else if (Platform.StartsWith(email2, ".")) {
                if (WithinDomain(email1, email2))
                    union.Add(email2);
                else {
                    union.Add(email1);
                    union.Add(email2);
                }
            } else if (Platform.EqualsIgnoreCase(email1, email2)) {
                union.Add(email1);
            } else {
                union.Add(email1);
                union.Add(email2);
            }
        }
        private void CheckExcludedIP(HashSet<byte[]> excluded, byte[] ip)
        {
            if (IsIPConstrained(excluded, ip))
                throw new PkixNameConstraintValidatorException("IP is from an excluded subtree.");
        }
        private void CheckPermittedIP(HashSet<byte[]> permitted, byte[] ip)
        {
            if (permitted != null && (ip.Length != 0 || permitted.Count >= 1) && !IsIPConstrained(permitted, ip))
                throw new PkixNameConstraintValidatorException("IP is not from a permitted subtree.");
        }
        private bool IsIPConstrained(HashSet<byte[]> constraints, byte[] ip)
        {
            foreach (byte[] constraint in constraints) {
                if (IsIPConstrained(constraint, ip))
                    return true;
            }
            return false;
        }
        private bool IsIPConstrained(byte[] constraint, byte[] ip)
        {
            int num = ip.Length;
            if (num != constraint.Length / 2)
                return false;
            byte[] array = new byte[num];
            Array.Copy(constraint, num, array, 0, num);
            byte[] array2 = new byte[num];
            byte[] array3 = new byte[num];
            for (int i = 0; i < num; i++) {
                array2[i] = (byte)(constraint[i] & array[i]);
                array3[i] = (byte)(ip[i] & array[i]);
            }
            return Arrays.AreEqual(array2, array3);
        }
        private HashSet<byte[]> IntersectIP(HashSet<byte[]> permitted, HashSet<GeneralSubtree> ips)
        {
            HashSet<byte[]> hashSet = new HashSet<byte[]>();
            foreach (GeneralSubtree ip in ips) {
                byte[] octets = Asn1OctetString.GetInstance(ip.Base.Name).GetOctets();
                if (permitted == null) {
                    if (octets != null)
                        hashSet.Add(octets);
                } else {
                    foreach (byte[] item in permitted) {
                        hashSet.UnionWith(IntersectIPRange(item, octets));
                    }
                }
            }
            return hashSet;
        }
        private HashSet<byte[]> IntersectIPRange(byte[] ipWithSubmask1, byte[] ipWithSubmask2)
        {
            if (ipWithSubmask1.Length != ipWithSubmask2.Length)
                return new HashSet<byte[]>();
            byte[][] array = ExtractIPsAndSubnetMasks(ipWithSubmask1, ipWithSubmask2);
            byte[] ip = array[0];
            byte[] array2 = array[1];
            byte[] ip2 = array[2];
            byte[] array3 = array[3];
            byte[][] array4 = MinMaxIPs(ip, array2, ip2, array3);
            byte[] ip3 = Min(array4[1], array4[3]);
            if (CompareTo(Max(array4[0], array4[2]), ip3) == 1)
                return new HashSet<byte[]>();
            byte[] ip4 = Or(array4[0], array4[2]);
            byte[] subnetMask = Or(array2, array3);
            return new HashSet<byte[]> {
                IpWithSubnetMask(ip4, subnetMask)
            };
        }
        private HashSet<byte[]> UnionIP(HashSet<byte[]> excluded, byte[] ip)
        {
            if (excluded.Count < 1) {
                if (ip == null)
                    return excluded;
                excluded.Add(ip);
                return excluded;
            }
            HashSet<byte[]> hashSet = new HashSet<byte[]>();
            foreach (byte[] item in excluded) {
                hashSet.UnionWith(UnionIPRange(item, ip));
            }
            return hashSet;
        }
        private HashSet<byte[]> UnionIPRange(byte[] ipWithSubmask1, byte[] ipWithSubmask2)
        {
            HashSet<byte[]> hashSet = new HashSet<byte[]>();
            if (Arrays.AreEqual(ipWithSubmask1, ipWithSubmask2))
                hashSet.Add(ipWithSubmask1);
            else {
                hashSet.Add(ipWithSubmask1);
                hashSet.Add(ipWithSubmask2);
            }
            return hashSet;
        }
        private byte[] IpWithSubnetMask(byte[] ip, byte[] subnetMask)
        {
            int num = ip.Length;
            byte[] array = new byte[num * 2];
            Array.Copy(ip, 0, array, 0, num);
            Array.Copy(subnetMask, 0, array, num, num);
            return array;
        }
        private byte[][] ExtractIPsAndSubnetMasks(byte[] ipWithSubmask1, byte[] ipWithSubmask2)
        {
            int num = ipWithSubmask1.Length / 2;
            byte[] array = new byte[num];
            byte[] array2 = new byte[num];
            Array.Copy(ipWithSubmask1, 0, array, 0, num);
            Array.Copy(ipWithSubmask1, num, array2, 0, num);
            byte[] array3 = new byte[num];
            byte[] array4 = new byte[num];
            Array.Copy(ipWithSubmask2, 0, array3, 0, num);
            Array.Copy(ipWithSubmask2, num, array4, 0, num);
            return new byte[4][] {
                array,
                array2,
                array3,
                array4
            };
        }
        private byte[][] MinMaxIPs(byte[] ip1, byte[] subnetmask1, byte[] ip2, byte[] subnetmask2)
        {
            int num = ip1.Length;
            byte[] array = new byte[num];
            byte[] array2 = new byte[num];
            byte[] array3 = new byte[num];
            byte[] array4 = new byte[num];
            for (int i = 0; i < num; i++) {
                array[i] = (byte)(ip1[i] & subnetmask1[i]);
                array2[i] = (byte)((ip1[i] & subnetmask1[i]) | ~subnetmask1[i]);
                array3[i] = (byte)(ip2[i] & subnetmask2[i]);
                array4[i] = (byte)((ip2[i] & subnetmask2[i]) | ~subnetmask2[i]);
            }
            return new byte[4][] {
                array,
                array2,
                array3,
                array4
            };
        }
        private static byte[] Max(byte[] ip1, byte[] ip2)
        {
            for (int i = 0; i < ip1.Length; i++) {
                if (ip1[i] > ip2[i])
                    return ip1;
            }
            return ip2;
        }
        private static byte[] Min(byte[] ip1, byte[] ip2)
        {
            for (int i = 0; i < ip1.Length; i++) {
                if (ip1[i] < ip2[i])
                    return ip1;
            }
            return ip2;
        }
        private static int CompareTo(byte[] ip1, byte[] ip2)
        {
            if (Arrays.AreEqual(ip1, ip2))
                return 0;
            if (Arrays.AreEqual(Max(ip1, ip2), ip1))
                return 1;
            return -1;
        }
        private static byte[] Or(byte[] ip1, byte[] ip2)
        {
            byte[] array = new byte[ip1.Length];
            for (int i = 0; i < ip1.Length; i++) {
                array[i] = (byte)(ip1[i] | ip2[i]);
            }
            return array;
        }
        private void CheckExcludedDns(HashSet<string> excluded, string dns)
        {
            if (IsDnsConstrained(excluded, dns))
                throw new PkixNameConstraintValidatorException("DNS is from an excluded subtree.");
        }
        private void CheckPermittedDns(HashSet<string> permitted, string dns)
        {
            if (permitted != null && (dns.Length != 0 || permitted.Count >= 1) && !IsDnsConstrained(permitted, dns))
                throw new PkixNameConstraintValidatorException("DNS is not from a permitted subtree.");
        }
        private bool IsDnsConstrained(HashSet<string> constraints, string dns)
        {
            foreach (string constraint in constraints) {
                if (IsDnsConstrained(constraint, dns))
                    return true;
            }
            return false;
        }
        private bool IsDnsConstrained(string constraint, string dns)
        {
            if (!WithinDomain(dns, constraint))
                return Platform.EqualsIgnoreCase(dns, constraint);
            return true;
        }
        private HashSet<string> IntersectDns(HashSet<string> permitted, HashSet<GeneralSubtree> dnss)
        {
            HashSet<string> hashSet = new HashSet<string>();
            foreach (GeneralSubtree item in dnss) {
                string text = ExtractNameAsString(item.Base);
                if (permitted == null) {
                    if (text != null)
                        hashSet.Add(text);
                } else {
                    foreach (string item2 in permitted) {
                        if (WithinDomain(item2, text))
                            hashSet.Add(item2);
                        else if (WithinDomain(text, item2)) {
                            hashSet.Add(text);
                        }
                    }
                }
            }
            return hashSet;
        }
        private HashSet<string> UnionDns(HashSet<string> excluded, string dns)
        {
            if (excluded.Count < 1) {
                if (dns == null)
                    return excluded;
                excluded.Add(dns);
                return excluded;
            }
            HashSet<string> hashSet = new HashSet<string>();
            foreach (string item in excluded) {
                if (WithinDomain(item, dns))
                    hashSet.Add(dns);
                else if (WithinDomain(dns, item)) {
                    hashSet.Add(item);
                } else {
                    hashSet.Add(item);
                    hashSet.Add(dns);
                }
            }
            return hashSet;
        }
        private void CheckExcludedUri(HashSet<string> excluded, string uri)
        {
            if (IsUriConstrained(excluded, uri))
                throw new PkixNameConstraintValidatorException("URI is from an excluded subtree.");
        }
        private void CheckPermittedUri(HashSet<string> permitted, string uri)
        {
            if (permitted != null && (uri.Length != 0 || permitted.Count >= 1) && !IsUriConstrained(permitted, uri))
                throw new PkixNameConstraintValidatorException("URI is not from a permitted subtree.");
        }
        private bool IsUriConstrained(HashSet<string> constraints, string uri)
        {
            foreach (string constraint in constraints) {
                if (IsUriConstrained(constraint, uri))
                    return true;
            }
            return false;
        }
        private bool IsUriConstrained(string constraint, string uri)
        {
            string text = ExtractHostFromURL(uri);
            if (Platform.StartsWith(constraint, "."))
                return WithinDomain(text, constraint);
            return Platform.EqualsIgnoreCase(text, constraint);
        }
        private HashSet<string> IntersectUri(HashSet<string> permitted, HashSet<GeneralSubtree> uris)
        {
            HashSet<string> hashSet = new HashSet<string>();
            foreach (GeneralSubtree uri in uris) {
                string text = ExtractNameAsString(uri.Base);
                if (permitted == null) {
                    if (text != null)
                        hashSet.Add(text);
                } else {
                    foreach (string item in permitted) {
                        IntersectUri(item, text, hashSet);
                    }
                }
            }
            return hashSet;
        }
        private void IntersectUri(string email1, string email2, HashSet<string> intersect)
        {
            if (email1.IndexOf('@') != -1) {
                string text = email1.Substring(email1.IndexOf('@') + 1);
                if (email2.IndexOf('@') != -1) {
                    if (Platform.EqualsIgnoreCase(email1, email2))
                        intersect.Add(email1);
                } else if (Platform.StartsWith(email2, ".")) {
                    if (WithinDomain(text, email2))
                        intersect.Add(email1);
                } else if (Platform.EqualsIgnoreCase(text, email2)) {
                    intersect.Add(email1);
                }
            } else if (Platform.StartsWith(email1, ".")) {
                if (email2.IndexOf('@') != -1) {
                    string testDomain = email2.Substring(email1.IndexOf('@') + 1);
                    if (WithinDomain(testDomain, email1))
                        intersect.Add(email2);
                } else if (Platform.StartsWith(email2, ".")) {
                    if (WithinDomain(email1, email2) || Platform.EqualsIgnoreCase(email1, email2))
                        intersect.Add(email1);
                    else if (WithinDomain(email2, email1)) {
                        intersect.Add(email2);
                    }
                } else if (WithinDomain(email2, email1)) {
                    intersect.Add(email2);
                }
            } else if (email2.IndexOf('@') != -1) {
                if (Platform.EqualsIgnoreCase(email2.Substring(email2.IndexOf('@') + 1), email1))
                    intersect.Add(email2);
            } else if (Platform.StartsWith(email2, ".")) {
                if (WithinDomain(email1, email2))
                    intersect.Add(email1);
            } else if (Platform.EqualsIgnoreCase(email1, email2)) {
                intersect.Add(email1);
            }
        }
        private HashSet<string> UnionUri(HashSet<string> excluded, string uri)
        {
            if (excluded.Count < 1) {
                if (uri == null)
                    return excluded;
                excluded.Add(uri);
                return excluded;
            }
            HashSet<string> hashSet = new HashSet<string>();
            foreach (string item in excluded) {
                UnionUri(item, uri, hashSet);
            }
            return hashSet;
        }
        private void UnionUri(string email1, string email2, HashSet<string> union)
        {
            if (email1.IndexOf('@') != -1) {
                string text = email1.Substring(email1.IndexOf('@') + 1);
                if (email2.IndexOf('@') != -1) {
                    if (Platform.EqualsIgnoreCase(email1, email2))
                        union.Add(email1);
                    else {
                        union.Add(email1);
                        union.Add(email2);
                    }
                } else if (Platform.StartsWith(email2, ".")) {
                    if (WithinDomain(text, email2))
                        union.Add(email2);
                    else {
                        union.Add(email1);
                        union.Add(email2);
                    }
                } else if (Platform.EqualsIgnoreCase(text, email2)) {
                    union.Add(email2);
                } else {
                    union.Add(email1);
                    union.Add(email2);
                }
            } else if (Platform.StartsWith(email1, ".")) {
                if (email2.IndexOf('@') != -1) {
                    string testDomain = email2.Substring(email1.IndexOf('@') + 1);
                    if (WithinDomain(testDomain, email1))
                        union.Add(email1);
                    else {
                        union.Add(email1);
                        union.Add(email2);
                    }
                } else if (Platform.StartsWith(email2, ".")) {
                    if (WithinDomain(email1, email2) || Platform.EqualsIgnoreCase(email1, email2))
                        union.Add(email2);
                    else if (WithinDomain(email2, email1)) {
                        union.Add(email1);
                    } else {
                        union.Add(email1);
                        union.Add(email2);
                    }
                } else if (WithinDomain(email2, email1)) {
                    union.Add(email1);
                } else {
                    union.Add(email1);
                    union.Add(email2);
                }
            } else if (email2.IndexOf('@') != -1) {
                if (Platform.EqualsIgnoreCase(email2.Substring(email1.IndexOf('@') + 1), email1))
                    union.Add(email1);
                else {
                    union.Add(email1);
                    union.Add(email2);
                }
            } else if (Platform.StartsWith(email2, ".")) {
                if (WithinDomain(email1, email2))
                    union.Add(email2);
                else {
                    union.Add(email1);
                    union.Add(email2);
                }
            } else if (Platform.EqualsIgnoreCase(email1, email2)) {
                union.Add(email1);
            } else {
                union.Add(email1);
                union.Add(email2);
            }
        }
        private static string ExtractHostFromURL(string url)
        {
            string text = url.Substring(url.IndexOf(':') + 1);
            int num = Platform.IndexOf(text, "//");
            if (num != -1)
                text = text.Substring(num + 2);
            if (text.LastIndexOf(':') != -1)
                text = text.Substring(0, text.LastIndexOf(':'));
            text = text.Substring(text.IndexOf(':') + 1);
            text = text.Substring(text.IndexOf('@') + 1);
            if (text.IndexOf('/') != -1)
                text = text.Substring(0, text.IndexOf('/'));
            return text;
        }
        private bool WithinDomain(string testDomain, string domain)
        {
            string text = domain;
            if (Platform.StartsWith(text, "."))
                text = text.Substring(1);
            string[] array = text.Split(new char[1] {
                '.'
            });
            string[] array2 = testDomain.Split(new char[1] {
                '.'
            });
            if (array2.Length <= array.Length)
                return false;
            int num = array2.Length - array.Length;
            for (int i = -1; i < array.Length; i++) {
                if (i == -1) {
                    if (array2[i + num].Length < 1)
                        return false;
                } else if (!Platform.EqualsIgnoreCase(array2[i + num], array[i])) {
                    return false;
                }
            }
            return true;
        }
        [Obsolete("Use 'CheckPermittedName' instead")]
        public void checkPermitted(GeneralName name)
        {
            CheckPermittedName(name);
        }
        public void CheckPermittedName(GeneralName name)
        {
            switch (name.TagNo) {
            case 3:
            case 5:
                break;
            case 0:
                CheckPermittedOtherName(permittedSubtreesOtherName, OtherName.GetInstance(name.Name));
                break;
            case 1:
                CheckPermittedEmail(permittedSubtreesEmail, ExtractNameAsString(name));
                break;
            case 2:
                CheckPermittedDns(permittedSubtreesDns, ExtractNameAsString(name));
                break;
            case 4:
                CheckPermittedDN(Asn1Sequence.GetInstance(name.Name.ToAsn1Object()));
                break;
            case 6:
                CheckPermittedUri(permittedSubtreesUri, ExtractNameAsString(name));
                break;
            case 7:
                CheckPermittedIP(permittedSubtreesIP, Asn1OctetString.GetInstance(name.Name).GetOctets());
                break;
            }
        }
        [Obsolete("Use 'CheckExcludedName' instead")]
        public void checkExcluded(GeneralName name)
        {
            CheckExcludedName(name);
        }
        public void CheckExcludedName(GeneralName name)
        {
            switch (name.TagNo) {
            case 3:
            case 5:
                break;
            case 0:
                CheckExcludedOtherName(excludedSubtreesOtherName, OtherName.GetInstance(name.Name));
                break;
            case 1:
                CheckExcludedEmail(excludedSubtreesEmail, ExtractNameAsString(name));
                break;
            case 2:
                CheckExcludedDns(excludedSubtreesDns, ExtractNameAsString(name));
                break;
            case 4:
                CheckExcludedDN(Asn1Sequence.GetInstance(name.Name.ToAsn1Object()));
                break;
            case 6:
                CheckExcludedUri(excludedSubtreesUri, ExtractNameAsString(name));
                break;
            case 7:
                CheckExcludedIP(excludedSubtreesIP, Asn1OctetString.GetInstance(name.Name).GetOctets());
                break;
            }
        }
        public void IntersectPermittedSubtree(Asn1Sequence permitted)
        {
            Dictionary<int, HashSet<GeneralSubtree>> dictionary = new Dictionary<int, HashSet<GeneralSubtree>>();
            foreach (Asn1Encodable item in permitted) {
                GeneralSubtree instance = GeneralSubtree.GetInstance(item);
                int tagNo = instance.Base.TagNo;
                if (!dictionary.TryGetValue(tagNo, out HashSet<GeneralSubtree> value))
                    value = (dictionary[tagNo] = new HashSet<GeneralSubtree>());
                value.Add(instance);
            }
            foreach (KeyValuePair<int, HashSet<GeneralSubtree>> item2 in dictionary) {
                switch (item2.Key) {
                case 0:
                    permittedSubtreesOtherName = IntersectOtherName(permittedSubtreesOtherName, item2.Value);
                    break;
                case 1:
                    permittedSubtreesEmail = IntersectEmail(permittedSubtreesEmail, item2.Value);
                    break;
                case 2:
                    permittedSubtreesDns = IntersectDns(permittedSubtreesDns, item2.Value);
                    break;
                case 4:
                    permittedSubtreesDN = IntersectDN(permittedSubtreesDN, item2.Value);
                    break;
                case 6:
                    permittedSubtreesUri = IntersectUri(permittedSubtreesUri, item2.Value);
                    break;
                case 7:
                    permittedSubtreesIP = IntersectIP(permittedSubtreesIP, item2.Value);
                    break;
                }
            }
        }
        private string ExtractNameAsString(GeneralName name)
        {
            return DerIA5String.GetInstance(name.Name).GetString();
        }
        public void IntersectEmptyPermittedSubtree(int nameType)
        {
            switch (nameType) {
            case 3:
            case 5:
                break;
            case 0:
                permittedSubtreesOtherName = new HashSet<OtherName>();
                break;
            case 1:
                permittedSubtreesEmail = new HashSet<string>();
                break;
            case 2:
                permittedSubtreesDns = new HashSet<string>();
                break;
            case 4:
                permittedSubtreesDN = new HashSet<Asn1Sequence>();
                break;
            case 6:
                permittedSubtreesUri = new HashSet<string>();
                break;
            case 7:
                permittedSubtreesIP = new HashSet<byte[]>();
                break;
            }
        }
        public void AddExcludedSubtree(GeneralSubtree subtree)
        {
            GeneralName base = subtree.Base;
            switch (base.TagNo) {
            case 3:
            case 5:
                break;
            case 0:
                excludedSubtreesOtherName = UnionOtherName(excludedSubtreesOtherName, OtherName.GetInstance(base.Name));
                break;
            case 1:
                excludedSubtreesEmail = UnionEmail(excludedSubtreesEmail, ExtractNameAsString(base));
                break;
            case 2:
                excludedSubtreesDns = UnionDns(excludedSubtreesDns, ExtractNameAsString(base));
                break;
            case 4:
                excludedSubtreesDN = UnionDN(excludedSubtreesDN, (Asn1Sequence)base.Name.ToAsn1Object());
                break;
            case 6:
                excludedSubtreesUri = UnionUri(excludedSubtreesUri, ExtractNameAsString(base));
                break;
            case 7:
                excludedSubtreesIP = UnionIP(excludedSubtreesIP, Asn1OctetString.GetInstance(base.Name).GetOctets());
                break;
            }
        }
        public override int GetHashCode()
        {
            return HashCollection(excludedSubtreesDN) + HashCollection(excludedSubtreesDns) + HashCollection(excludedSubtreesEmail) + HashCollection(excludedSubtreesIP) + HashCollection(excludedSubtreesUri) + HashCollection(excludedSubtreesOtherName) + HashCollection(permittedSubtreesDN) + HashCollection(permittedSubtreesDns) + HashCollection(permittedSubtreesEmail) + HashCollection(permittedSubtreesIP) + HashCollection(permittedSubtreesUri) + HashCollection(permittedSubtreesOtherName);
        }
        private int HashCollection(HashSet<byte[]> c)
        {
            int num = 0;
            if (c != null) {
                foreach (byte[] item in c) {
                    num += Arrays.GetHashCode(item);
                }
                return num;
            }
            return num;
        }
        private int HashCollection<T>(HashSet<T> c)
        {
            int num = 0;
            if (c != null) {
                foreach (T item in c) {
                    num += item.GetHashCode();
                }
                return num;
            }
            return num;
        }
        public override bool Equals(object o)
        {
            PkixNameConstraintValidator pkixNameConstraintValidator = o as PkixNameConstraintValidator;
            if (pkixNameConstraintValidator == null)
                return false;
            if (AreEqualSets(pkixNameConstraintValidator.excludedSubtreesDN, excludedSubtreesDN) && AreEqualSets(pkixNameConstraintValidator.excludedSubtreesDns, excludedSubtreesDns) && AreEqualSets(pkixNameConstraintValidator.excludedSubtreesEmail, excludedSubtreesEmail) && AreEqualSets(pkixNameConstraintValidator.excludedSubtreesIP, excludedSubtreesIP) && AreEqualSets(pkixNameConstraintValidator.excludedSubtreesUri, excludedSubtreesUri) && AreEqualSets(pkixNameConstraintValidator.excludedSubtreesOtherName, excludedSubtreesOtherName) && AreEqualSets(pkixNameConstraintValidator.permittedSubtreesDN, permittedSubtreesDN) && AreEqualSets(pkixNameConstraintValidator.permittedSubtreesDns, permittedSubtreesDns) && AreEqualSets(pkixNameConstraintValidator.permittedSubtreesEmail, permittedSubtreesEmail) && AreEqualSets(pkixNameConstraintValidator.permittedSubtreesIP, permittedSubtreesIP) && AreEqualSets(pkixNameConstraintValidator.permittedSubtreesUri, permittedSubtreesUri))
                return AreEqualSets(pkixNameConstraintValidator.permittedSubtreesOtherName, permittedSubtreesOtherName);
            return false;
        }
        private bool AreEqualSets(HashSet<byte[]> set1, HashSet<byte[]> set2)
        {
            if (set1 == set2)
                return true;
            if (set1 == null || set2 == null || set1.Count != set2.Count)
                return false;
            foreach (byte[] item in set1) {
                bool flag = false;
                foreach (byte[] item2 in set2) {
                    if (Arrays.AreEqual(item, item2)) {
                        flag = true;
                        break;
                    }
                }
                if (!flag)
                    return false;
            }
            return true;
        }
        private bool AreEqualSets<T>(HashSet<T> set1, HashSet<T> set2)
        {
            if (set1 == set2)
                return true;
            if (set1 == null || set2 == null || set1.Count != set2.Count)
                return false;
            foreach (T item in set1) {
                if (!set2.Contains(item))
                    return false;
            }
            return true;
        }
        private string StringifyIP(byte[] ip)
        {
            string text = "";
            int num;
            for (int i = 0; i < ip.Length / 2; i++) {
                string str = text;
                num = (ip[i] & 255);
                text = str + num.ToString() + ".";
            }
            text = text.Substring(0, text.Length - 1);
            text += "/";
            for (int j = ip.Length / 2; j < ip.Length; j++) {
                string str2 = text;
                num = (ip[j] & 255);
                text = str2 + num.ToString() + ".";
            }
            return text.Substring(0, text.Length - 1);
        }
        private string StringifyIPCollection(HashSet<byte[]> ips)
        {
            string str = "";
            str += "[";
            foreach (byte[] ip in ips) {
                str = str + StringifyIP(ip) + ",";
            }
            if (str.Length > 1)
                str = str.Substring(0, str.Length - 1);
            return str + "]";
        }
        private string StringifyOtherNameCollection(HashSet<OtherName> otherNames)
        {
            StringBuilder stringBuilder = new StringBuilder(91);
            foreach (OtherName otherName in otherNames) {
                if (stringBuilder.Length > 1)
                    stringBuilder.Append(',');
                stringBuilder.Append(otherName.TypeID.Id);
                stringBuilder.Append(':');
                stringBuilder.Append(Hex.ToHexString(otherName.Value.GetEncoded()));
            }
            stringBuilder.Append(']');
            return stringBuilder.ToString();
        }
        public override string ToString()
        {
            StringBuilder stringBuilder = new StringBuilder("permitted:");
            stringBuilder.AppendLine();
            if (permittedSubtreesDN != null)
                Append(stringBuilder, "DN", permittedSubtreesDN);
            if (permittedSubtreesDns != null)
                Append(stringBuilder, "DNS", permittedSubtreesDns);
            if (permittedSubtreesEmail != null)
                Append(stringBuilder, "Email", permittedSubtreesEmail);
            if (permittedSubtreesUri != null)
                Append(stringBuilder, "URI", permittedSubtreesUri);
            if (permittedSubtreesIP != null)
                Append(stringBuilder, "IP", StringifyIPCollection(permittedSubtreesIP));
            if (permittedSubtreesOtherName != null)
                Append(stringBuilder, "OtherName", StringifyOtherNameCollection(permittedSubtreesOtherName));
            stringBuilder.AppendLine("excluded:");
            if (excludedSubtreesDN.Count > 0)
                Append(stringBuilder, "DN", excludedSubtreesDN);
            if (excludedSubtreesDns.Count > 0)
                Append(stringBuilder, "DNS", excludedSubtreesDns);
            if (excludedSubtreesEmail.Count > 0)
                Append(stringBuilder, "Email", excludedSubtreesEmail);
            if (excludedSubtreesUri.Count > 0)
                Append(stringBuilder, "URI", excludedSubtreesUri);
            if (excludedSubtreesIP.Count > 0)
                Append(stringBuilder, "IP", StringifyIPCollection(excludedSubtreesIP));
            if (excludedSubtreesOtherName.Count > 0)
                Append(stringBuilder, "OtherName", StringifyOtherNameCollection(excludedSubtreesOtherName));
            return stringBuilder.ToString();
        }
        private static void Append(StringBuilder sb, string name, object value)
        {
            sb.Append(name);
            sb.AppendLine(":");
            sb.Append(value);
            sb.AppendLine();
        }
    }
}