/* * Parse a string into a DN. The input is expected to use * RFC 4514 format. Name elements that are provided as * character strings will be mapped to ASN.1 PrintableString * values (if they are compatible with that string type) * or UTF8String values (otherwise). * * On parse error, an AsnException is thrown. */ public static X500Name Parse(string str) { int n = str.Length; int p = 0; bool acc = false; List <List <DNPart> > dn = new List <List <DNPart> >(); while (p < n) { /* * Find the next unescaped '+' or ',' sign. */ bool lcwb = false; int q; for (q = p; q < n; q++) { if (lcwb) { lcwb = false; continue; } switch (str[q]) { case ',': case '+': goto found; case '\\': lcwb = true; break; } } found: /* * Parse DN element. */ DNPart dnp = DNPart.Parse(str.Substring(p, q - p)); if (acc) { dn[dn.Count - 1].Add(dnp); } else { List <DNPart> r = new List <DNPart>(); r.Add(dnp); dn.Add(r); } p = q + 1; acc = q < n && str[q] == '+'; } dn.Reverse(); return(new X500Name(dn)); }
/* * Generic parsing. If 'strictStrings' is true, then the following * rules are enforced: * -- Every SET in the sequence of RDN must have size 1. * -- Every name element is decoded as a string (by tag). * * If 'strictStrings' is false, then multiple elements may appear * in each SET, and values needs not be decodable as string (values * with a known OID must still be decodable). * * This constructor checks that within a single RDN, no two * attributes may have the same type. * * On decoding error, an AsnException is thrown. */ public X500Name(AsnElt aDN, bool strictStrings) { /* * Note: the SEQUENCE tag MUST be present, since the * ASN.1 definition of Name starts with a CHOICE; thus, * any tag override would have to be explicit, not * implicit. */ aDN.CheckConstructed(); aDN.CheckTag(AsnElt.SEQUENCE); List <List <DNPart> > r = new List <List <DNPart> >(); foreach (AsnElt aRDN in aDN.Sub) { aRDN.CheckConstructed(); aRDN.CheckTag(AsnElt.SET); aRDN.CheckNumSubMin(1); int n = aRDN.Sub.Length; if (n != 1 && strictStrings) { throw new AsnException(String.Format( "several ({0}) values in RDN", n)); } List <DNPart> r2 = new List <DNPart>(); r.Add(r2); for (int i = 0; i < n; i++) { AsnElt aTV = aRDN.Sub[i]; aTV.CheckConstructed(); aTV.CheckTag(AsnElt.SEQUENCE); aTV.CheckNumSub(2); AsnElt aOID = aTV.GetSub(0); aOID.CheckTag(AsnElt.OBJECT_IDENTIFIER); AsnElt aVal = aTV.GetSub(1); string nt = aOID.GetOID(); DNPart dnp = new DNPart(nt, aVal); if (strictStrings && !dnp.IsString) { throw new AsnException( "RDN is not a string"); } r2.Add(dnp); } } Init(r); }
void Init(List <List <DNPart> > dn) { int n = dn.Count; List <DNPart> r = new List <DNPart>(); PartsGen_ = new DNPart[n][]; for (int i = 0; i < n; i++) { IDictionary <string, DNPart> dd = new SortedDictionary <string, DNPart>( StringComparer.Ordinal); foreach (DNPart dnp in dn[i]) { string nt = dnp.OID; if (dd.ContainsKey(nt)) { throw new AsnException(string.Format( "multiple values of type {0}" + " in RDN", nt)); } dd[nt] = dnp; } PartsGen_[i] = new DNPart[dd.Count]; int j = 0; foreach (DNPart p in dd.Values) { PartsGen_[i][j++] = p; r.Add(p); } } Parts_ = r.ToArray(); uint hc = 0; foreach (DNPart dnp in r) { hc = ((hc << 7) | (hc >> 25)) + (uint)dnp.GetHashCode(); } hashCode = (int)hc; }
public bool Equals(DNPart dnp) { if (dnp == null) { return(false); } if (OID != dnp.OID) { return(false); } if (IsString) { return(dnp.IsString && normValue == dnp.normValue); } else if (dnp.IsString) { return(false); } else { return(Eq(encodedValue, dnp.encodedValue)); } }