/// <summary> /// Compares the RDN to the rdn passed. Note: If an there exist any /// mulivalues in one RDN they must all be present in the other. /// </summary> /// <param name="rdn"> /// the RDN to compare to /// @throws IllegalArgumentException if the application compares a name /// with an OID. /// </param> public bool Equals(Rdn rdn) { if (_values.Count != rdn._values.Count) { return(false); } for (var i = 0; i < _values.Count; i++) { // verify that the current value and type exists in the other list var j = 0; var valuesEqual = _values[i].EqualsOrdinalCI(rdn._values[j]); var isEqualAttrType = EqualAttrType(_types[i], rdn._types[j]); while (j < _values.Count && (!valuesEqual || !isEqualAttrType)) { j++; } // couldn't find first value if (j >= rdn._values.Count) { return(false); } } return(true); }
/// <summary> /// Constructs a new DN based on the specified string representation of a /// distinguished name. The syntax of the DN must conform to that specified /// in RFC 2253. /// </summary> /// <param name="dnString"> /// a string representation of the distinguished name. /// </param> /// <exception> /// IllegalArgumentException if the the value of the dnString /// parameter does not adhere to the syntax described in /// RFC 2253. /// </exception> public Dn(string dnString) { /* the empty string is a valid DN */ if (dnString.Length == 0) { return; } var tokenBuf = new char[dnString.Length]; var trailingSpaceCount = 0; var attrType = string.Empty; var attrValue = string.Empty; var rawValue = string.Empty; var hexDigitCount = 0; var currRdn = new Rdn(); // indicates whether an OID number has a first digit of ZERO var tokenIndex = 0; var currIndex = 0; var valueStart = 0; var state = LookForRdnAttrType; var lastIndex = dnString.Length - 1; while (currIndex <= lastIndex) { var currChar = dnString[currIndex]; char nextChar; switch (state) { case LookForRdnAttrType: while (currChar == ' ' && currIndex < lastIndex) { currChar = dnString[++currIndex]; } if (IsAlpha(currChar)) { if (dnString.Substring(currIndex).StartsWith("oid.") || dnString.Substring(currIndex).StartsWith("OID.")) { // form is "oid.###.##.###... or OID.###.##.###... currIndex += 4; // skip oid. prefix and get to actual oid if (currIndex > lastIndex) { throw new ArgumentException(dnString); } currChar = dnString[currIndex]; if (IsDigit(currChar)) { tokenBuf[tokenIndex++] = currChar; state = OidAttrType; } else { throw new ArgumentException(dnString); } } else { tokenBuf[tokenIndex++] = currChar; state = AlphaAttrType; } } else if (IsDigit(currChar)) { --currIndex; state = OidAttrType; } else if (CharUnicodeInfo.GetUnicodeCategory(currChar) != UnicodeCategory.SpaceSeparator) { throw new ArgumentException(dnString); } break; case AlphaAttrType: if (IsAlpha(currChar) || IsDigit(currChar) || currChar == '-') { tokenBuf[tokenIndex++] = currChar; } else { // skip any spaces while (currChar == ' ' && currIndex < lastIndex) { currChar = dnString[++currIndex]; } if (currChar == '=') { attrType = new string(tokenBuf, 0, tokenIndex); tokenIndex = 0; state = LookForRdnValue; } else { throw new ArgumentException(dnString); } } break; case OidAttrType: if (!IsDigit(currChar)) { throw new ArgumentException(dnString); } var firstDigitZero = currChar == '0' ? true : false; tokenBuf[tokenIndex++] = currChar; currChar = dnString[++currIndex]; if (IsDigit(currChar) && firstDigitZero || currChar == '.' && firstDigitZero) { throw new ArgumentException(dnString); } // consume all numbers. while (IsDigit(currChar) && currIndex < lastIndex) { tokenBuf[tokenIndex++] = currChar; currChar = dnString[++currIndex]; } if (currChar == '.') { tokenBuf[tokenIndex++] = currChar; // The state remains at OID_ATTR_TYPE } else { // skip any spaces while (currChar == ' ' && currIndex < lastIndex) { currChar = dnString[++currIndex]; } if (currChar == '=') { attrType = new string(tokenBuf, 0, tokenIndex); tokenIndex = 0; state = LookForRdnValue; } else { throw new ArgumentException(dnString); } } break; case LookForRdnValue: while (currChar == ' ') { if (currIndex < lastIndex) { currChar = dnString[++currIndex]; } else { throw new ArgumentException(dnString); } } if (currChar == '"') { state = QuotedRdnValue; valueStart = currIndex; } else if (currChar == '#') { hexDigitCount = 0; tokenBuf[tokenIndex++] = currChar; valueStart = currIndex; state = HexRdnValue; } else { valueStart = currIndex; // check this character again in the UNQUOTED_RDN_VALUE state currIndex--; state = UnquotedRdnValue; } break; case UnquotedRdnValue: if (currChar == '\\') { if (!(currIndex < lastIndex)) { throw new ArgumentException(dnString); } currChar = dnString[++currIndex]; if (IsHexDigit(currChar)) { if (!(currIndex < lastIndex)) { throw new ArgumentException(dnString); } nextChar = dnString[++currIndex]; if (IsHexDigit(nextChar)) { tokenBuf[tokenIndex++] = HexToChar(currChar, nextChar); trailingSpaceCount = 0; } else { throw new ArgumentException(dnString); } } else if (NeedsEscape(currChar) || currChar == '#' || currChar == '=' || currChar == ' ') { tokenBuf[tokenIndex++] = currChar; trailingSpaceCount = 0; } else { throw new ArgumentException(dnString); } } else if (currChar == ' ') { trailingSpaceCount++; tokenBuf[tokenIndex++] = currChar; } else if (currChar == ',' || currChar == ';' || currChar == '+') { attrValue = new string(tokenBuf, 0, tokenIndex - trailingSpaceCount); rawValue = dnString.Substring(valueStart, currIndex - trailingSpaceCount - valueStart); currRdn.Add(attrType, attrValue, rawValue); if (currChar != '+') { _rdnList.Add(currRdn); currRdn = new Rdn(); } trailingSpaceCount = 0; tokenIndex = 0; state = LookForRdnAttrType; } else if (NeedsEscape(currChar)) { throw new ArgumentException(dnString); } else { trailingSpaceCount = 0; tokenBuf[tokenIndex++] = currChar; } break; // end UNQUOTED RDN VALUE case QuotedRdnValue: if (currChar == '"') { rawValue = dnString.Substring(valueStart, currIndex + 1 - valueStart); if (currIndex < lastIndex) { currChar = dnString[++currIndex]; } // skip any spaces while (currChar == ' ' && currIndex < lastIndex) { currChar = dnString[++currIndex]; } if (currChar == ',' || currChar == ';' || currChar == '+' || currIndex == lastIndex) { attrValue = new string(tokenBuf, 0, tokenIndex); currRdn.Add(attrType, attrValue, rawValue); if (currChar != '+') { _rdnList.Add(currRdn); currRdn = new Rdn(); } trailingSpaceCount = 0; tokenIndex = 0; state = LookForRdnAttrType; } else { throw new ArgumentException(dnString); } } else if (currChar == '\\') { currChar = dnString[++currIndex]; if (IsHexDigit(currChar)) { nextChar = dnString[++currIndex]; if (IsHexDigit(nextChar)) { tokenBuf[tokenIndex++] = HexToChar(currChar, nextChar); trailingSpaceCount = 0; } else { throw new ArgumentException(dnString); } } else if (NeedsEscape(currChar) || currChar == '#' || currChar == '=' || currChar == ' ') { tokenBuf[tokenIndex++] = currChar; trailingSpaceCount = 0; } else { throw new ArgumentException(dnString); } } else { tokenBuf[tokenIndex++] = currChar; } break; // end QUOTED RDN VALUE case HexRdnValue: if (!IsHexDigit(currChar) || currIndex > lastIndex) { // check for odd number of hex digits if (hexDigitCount % 2 != 0 || hexDigitCount == 0) { throw new ArgumentException(dnString); } rawValue = dnString.Substring(valueStart, currIndex - valueStart); // skip any spaces while (currChar == ' ' && currIndex < lastIndex) { currChar = dnString[++currIndex]; } if (currChar == ',' || currChar == ';' || currChar == '+' || currIndex == lastIndex) { attrValue = new string(tokenBuf, 0, tokenIndex); // added by cameron currRdn.Add(attrType, attrValue, rawValue); if (currChar != '+') { _rdnList.Add(currRdn); currRdn = new Rdn(); } tokenIndex = 0; state = LookForRdnAttrType; } else { throw new ArgumentException(dnString); } } else { tokenBuf[tokenIndex++] = currChar; hexDigitCount++; } break; // end HEX RDN VALUE } // end switch currIndex++; } // end while // check ending state if (state == UnquotedRdnValue || state == HexRdnValue && hexDigitCount % 2 == 0 && hexDigitCount != 0) { attrValue = new string(tokenBuf, 0, tokenIndex - trailingSpaceCount); rawValue = dnString.Substring(valueStart, currIndex - trailingSpaceCount - valueStart); currRdn.Add(attrType, attrValue, rawValue); _rdnList.Add(currRdn); } else if (state == LookForRdnValue) { // empty value is valid attrValue = string.Empty; rawValue = dnString.Substring(valueStart); currRdn.Add(attrType, attrValue, rawValue); _rdnList.Add(currRdn); } else { throw new ArgumentException(dnString); } } // end DN constructor (string dn)
/// <summary> Adds the RDN to the end of the current DN.</summary> /// <param name="rdn"> /// an RDN to be added. /// </param> public void AddRdnToBack(Rdn rdn) { _rdnList.Add(rdn); }
/// <summary> Adds the RDN to the beginning of the current DN.</summary> /// <param name="rdn"> /// an RDN to be added. /// </param> public void AddRdnToFront(Rdn rdn) { _rdnList.Insert(0, rdn); }
/// <summary> Adds the RDN to the beginning of the current DN.</summary> /// <param name="rdn"> /// an RDN to be added. /// </param> public void AddRdn(Rdn rdn) { _rdnList.Insert(0, rdn); }