A RDN encapsulates a single object's name of a Distinguished Name(DN). The object name represented by this class contains no context. Thus a Relative Distinguished Name (RDN) could be relative to anywhere in the Directories tree. For example, of following DN, 'cn=admin, ou=marketing, o=corporation', all possible RDNs are 'cn=admin', 'ou=marketing', and 'o=corporation'. Multivalued attributes are encapsulated in this class. For example the following could be represented by an RDN: 'cn=john + l=US', or 'cn=juan + l=ES'
상속: System.Object
예제 #1
0
        public virtual bool equals(RDN rdn)
        {
            if (this.values.Count != rdn.values.Count)
            {
                return(false);
            }
            int j, i;

            for (i = 0; i < this.values.Count; i++)
            {
                //verify that the current value and type exists in the other list
                j = 0;
                //May need a more intellegent compare
                while (j < values.Count && (!((string)this.values[i]).ToUpper().Equals(((string)rdn.values[j]).ToUpper()) || !equalAttrType((string)this.types[i], (string)rdn.types[j])))
                {
                    j++;
                }
                if (j >= rdn.values.Count)
                {
                    //couldn't find first value
                    return(false);
                }
            }
            return(true);
        }
예제 #2
0
        private string rawValue;  //the unnormalized value

        /// <summary> Creates an RDN object from the DN component specified in the string RDN
        ///
        /// </summary>
        /// <param name="rdn">the DN component
        /// </param>
        public RDN(string rdn)
        {
            rawValue = rdn;
            DN        dn   = new DN(rdn);
            ArrayList rdns = dn.RDNs;

            //there should only be one rdn
            if (rdns.Count != 1)
            {
                throw new ArgumentException("Invalid RDN: see API " + "documentation");
            }
            RDN thisRDN = (RDN)(rdns[0]);

            this.types    = thisRDN.types;
            this.values   = thisRDN.values;
            this.rawValue = thisRDN.rawValue;
        }
예제 #3
0
파일: LdapDN.cs 프로젝트: nickchal/pash
		/// <summary> Returns the individual components of a relative distinguished name
		/// (RDN), normalized.
		/// 
		/// </summary>
		/// <param name="rdn">    The relative distinguished name, or in other words,
		/// the left-most component of a distinguished name.
		/// 
		/// </param>
		/// <param name="noTypes">  If true, returns only the values of the
		/// components, and not the names of the component, for
		/// example "Babs Jensen" instead of "cn=Babs Jensen".
		/// 
		/// </param>
		/// <returns> An array of strings representing the individual components
		/// of an RDN, or null if the RDN is not a valid RDN.
		/// </returns>
		public static System.String[] explodeRDN(System.String rdn, bool noTypes)
		{
			RDN rdnToExplode = new RDN(rdn);
			return rdnToExplode.explodeRDN(noTypes);
		}
예제 #4
0
 /// <summary> Adds the RDN to the end of the current DN</summary>
 /// <param name="rdn">an RDN to be added
 /// </param>
 public virtual void addRDNToBack(RDN rdn)
 {
     rdnList.Add(rdn);
 }
예제 #5
0
 /// <summary> Adds the RDN to the beginning of the current DN.</summary>
 /// <param name="rdn">an RDN to be added
 /// </param>
 public virtual void addRDNToFront(RDN rdn)
 {
     rdnList.Insert(0, rdn);
 }
예제 #6
0
        /// <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)
        {
            InitBlock();
            /* the empty string is a valid DN */
            if (dnString.Length == 0)
            {
                return;
            }

            char currChar;
            char nextChar;
            int  currIndex;

            char[] tokenBuf = new char[dnString.Length];
            int    tokenIndex;
            int    lastIndex;
            int    valueStart;
            int    state;
            int    trailingSpaceCount = 0;
            string attrType           = "";
            string attrValue          = "";
            string rawValue           = "";
            int    hexDigitCount      = 0;
            RDN    currRDN            = new RDN();

            //indicates whether an OID number has a first digit of ZERO
            bool firstDigitZero = false;

            tokenIndex = 0;
            currIndex  = 0;
            valueStart = 0;
            state      = LOOK_FOR_RDN_ATTR_TYPE;
            lastIndex  = dnString.Length - 1;
            while (currIndex <= lastIndex)
            {
                currChar = dnString[currIndex];
                switch (state)
                {
                case LOOK_FOR_RDN_ATTR_TYPE:
                    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 = OID_ATTR_TYPE;
                            }
                            else
                            {
                                throw new ArgumentException(dnString);
                            }
                        }
                        else
                        {
                            tokenBuf[tokenIndex++] = currChar;
                            state = ALPHA_ATTR_TYPE;
                        }
                    }
                    else if (isDigit(currChar))
                    {
                        --currIndex;
                        state = OID_ATTR_TYPE;
                    }
                    else if (System.Globalization.CharUnicodeInfo.GetUnicodeCategory(currChar) != System.Globalization.UnicodeCategory.SpaceSeparator)
                    {
                        throw new ArgumentException(dnString);
                    }
                    break;


                case ALPHA_ATTR_TYPE:
                    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      = LOOK_FOR_RDN_VALUE;
                        }
                        else
                        {
                            throw new ArgumentException(dnString);
                        }
                    }
                    break;


                case OID_ATTR_TYPE:
                    if (!isDigit(currChar))
                    {
                        throw new ArgumentException(dnString);
                    }
                    firstDigitZero         = (currChar == '0');
                    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      = LOOK_FOR_RDN_VALUE;
                        }
                        else
                        {
                            throw new ArgumentException(dnString);
                        }
                    }
                    break;


                case LOOK_FOR_RDN_VALUE:
                    while (currChar == ' ')
                    {
                        if (currIndex < lastIndex)
                        {
                            currChar = dnString[++currIndex];
                        }
                        else
                        {
                            throw new ArgumentException(dnString);
                        }
                    }
                    if (currChar == '"')
                    {
                        state      = QUOTED_RDN_VALUE;
                        valueStart = currIndex;
                    }
                    else if (currChar == '#')
                    {
                        hexDigitCount          = 0;
                        tokenBuf[tokenIndex++] = currChar;
                        valueStart             = currIndex;
                        state = HEX_RDN_VALUE;
                    }
                    else
                    {
                        valueStart = currIndex;
                        //check this character again in the UNQUOTED_RDN_VALUE state
                        currIndex--;
                        state = UNQUOTED_RDN_VALUE;
                    }
                    break;


                case UNQUOTED_RDN_VALUE:
                    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 = LOOK_FOR_RDN_ATTR_TYPE;
                    }
                    else if (needsEscape(currChar))
                    {
                        throw new ArgumentException(dnString);
                    }
                    else
                    {
                        trailingSpaceCount     = 0;
                        tokenBuf[tokenIndex++] = currChar;
                    }
                    break;     //end UNQUOTED RDN VALUE


                case QUOTED_RDN_VALUE:
                    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 = LOOK_FOR_RDN_ATTR_TYPE;
                        }
                        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 HEX_RDN_VALUE:
                    if ((!isHexDigit(currChar)) || (currIndex > lastIndex))
                    {
                        //check for odd number of hex digits
                        if ((hexDigitCount % 2) != 0 || hexDigitCount == 0)
                        {
                            throw new ArgumentException(dnString);
                        }
                        else
                        {
                            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      = LOOK_FOR_RDN_ATTR_TYPE;
                            }
                            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 == UNQUOTED_RDN_VALUE || (state == HEX_RDN_VALUE && (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 == LOOK_FOR_RDN_VALUE)
            {
                //empty value is valid
                attrValue = "";
                rawValue  = dnString.Substring(valueStart);
                currRDN.add(attrType, attrValue, rawValue);
                rdnList.Add(currRDN);
            }
            else
            {
                throw new ArgumentException(dnString);
            }
        } //end DN constructor (string dn)
예제 #7
0
 public virtual bool equals(RDN rdn)
 {
     if (this.values.Count != rdn.values.Count)
     {
         return false;
     }
     int j, i;
     for (i = 0; i < this.values.Count; i++)
     {
         //verify that the current value and type exists in the other list
         j = 0;
         //May need a more intellegent compare
         while (j < values.Count && (!((System.String) this.values[i]).ToUpper().Equals(((System.String) rdn.values[j]).ToUpper()) || !equalAttrType((System.String) this.types[i], (System.String) rdn.types[j])))
         {
             j++;
         }
         if (j >= rdn.values.Count)
         //couldn't find first value
             return false;
     }
     return true;
 }
예제 #8
0
 /// <summary> Adds the RDN to the beginning of the current DN.</summary>
 /// <param name="rdn">an RDN to be added
 /// </param>
 public virtual void addRDNToFront(RDN rdn)
 {
     rdnList.Insert(0, rdn);
 }
예제 #9
0
 /// <summary> Adds the RDN to the end of the current DN</summary>
 /// <param name="rdn">an RDN to be added
 /// </param>
 public virtual void addRDNToBack(RDN rdn)
 {
     rdnList.Add(rdn);
 }
예제 #10
0
        /// <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(System.String dnString)
        {
            InitBlock();
            /* the empty string is a valid DN */
            if (dnString.Length == 0)
                return ;

            char currChar;
            char nextChar;
            int currIndex;
            char[] tokenBuf = new char[dnString.Length];
            int tokenIndex;
            int lastIndex;
            int valueStart;
            int state;
            int trailingSpaceCount = 0;
            System.String attrType = "";
            System.String attrValue = "";
            System.String rawValue = "";
            int hexDigitCount = 0;
            RDN currRDN = new RDN();

            //indicates whether an OID number has a first digit of ZERO
            bool firstDigitZero = false;

            tokenIndex = 0;
            currIndex = 0;
            valueStart = 0;
            state = LOOK_FOR_RDN_ATTR_TYPE;
            lastIndex = dnString.Length - 1;
            while (currIndex <= lastIndex)
            {
                currChar = dnString[currIndex];
                switch (state)
                {

                    case LOOK_FOR_RDN_ATTR_TYPE:
                        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 System.ArgumentException(dnString);
                                currChar = dnString[currIndex];
                                if (isDigit(currChar))
                                {
                                    tokenBuf[tokenIndex++] = currChar;
                                    state = OID_ATTR_TYPE;
                                }
                                else
                                    throw new System.ArgumentException(dnString);
                            }
                            else
                            {
                                tokenBuf[tokenIndex++] = currChar;
                                state = ALPHA_ATTR_TYPE;
                            }
                        }
                        else if (isDigit(currChar))
                        {
                            --currIndex;
                            state = OID_ATTR_TYPE;
                        }
                        else if (!(System.Char.GetUnicodeCategory(currChar) == System.Globalization.UnicodeCategory.SpaceSeparator))
                            throw new System.ArgumentException(dnString);
                        break;

                    case ALPHA_ATTR_TYPE:
                        if (isAlpha(currChar) || isDigit(currChar) || (currChar == '-'))
                            tokenBuf[tokenIndex++] = currChar;
                        else
                        {
                            //skip any spaces
                            while ((currChar == ' ') && (currIndex < lastIndex))
                                currChar = dnString[++currIndex];
                            if (currChar == '=')
                            {
                                attrType = new System.String(tokenBuf, 0, tokenIndex);
                                tokenIndex = 0;
                                state = LOOK_FOR_RDN_VALUE;
                            }
                            else
                                throw new System.ArgumentException(dnString);
                        }
                        break;

                    case OID_ATTR_TYPE:
                        if (!isDigit(currChar))
                            throw new System.ArgumentException(dnString);
                        firstDigitZero = (currChar == '0')?true:false;
                        tokenBuf[tokenIndex++] = currChar;
                        currChar = dnString[++currIndex];

                        if ((isDigit(currChar) && firstDigitZero) || (currChar == '.' && firstDigitZero))
                        {
                            throw new System.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 System.String(tokenBuf, 0, tokenIndex);
                                tokenIndex = 0;
                                state = LOOK_FOR_RDN_VALUE;
                            }
                            else
                                throw new System.ArgumentException(dnString);
                        }
                        break;

                    case LOOK_FOR_RDN_VALUE:
                        while (currChar == ' ')
                        {
                            if (currIndex < lastIndex)
                                currChar = dnString[++currIndex];
                            else
                                throw new System.ArgumentException(dnString);
                        }
                        if (currChar == '"')
                        {
                            state = QUOTED_RDN_VALUE;
                            valueStart = currIndex;
                        }
                        else if (currChar == '#')
                        {
                            hexDigitCount = 0;
                            tokenBuf[tokenIndex++] = currChar;
                            valueStart = currIndex;
                            state = HEX_RDN_VALUE;
                        }
                        else
                        {
                            valueStart = currIndex;
                            //check this character again in the UNQUOTED_RDN_VALUE state
                            currIndex--;
                            state = UNQUOTED_RDN_VALUE;
                        }
                        break;

                    case UNQUOTED_RDN_VALUE:
                        if (currChar == '\\')
                        {
                            if (!(currIndex < lastIndex))
                                throw new System.ArgumentException(dnString);
                            currChar = dnString[++currIndex];
                            if (isHexDigit(currChar))
                            {
                                if (!(currIndex < lastIndex))
                                    throw new System.ArgumentException(dnString);
                                nextChar = dnString[++currIndex];
                                if (isHexDigit(nextChar))
                                {
                                    tokenBuf[tokenIndex++] = hexToChar(currChar, nextChar);
                                    trailingSpaceCount = 0;
                                }
                                else
                                    throw new System.ArgumentException(dnString);
                            }
                            else if (needsEscape(currChar) || currChar == '#' || currChar == '=' || currChar == ' ')
                            {
                                tokenBuf[tokenIndex++] = currChar;
                                trailingSpaceCount = 0;
                            }
                            else
                                throw new System.ArgumentException(dnString);
                        }
                        else if (currChar == ' ')
                        {
                            trailingSpaceCount++;
                            tokenBuf[tokenIndex++] = currChar;
                        }
                        else if ((currChar == ',') || (currChar == ';') || (currChar == '+'))
                        {
                            attrValue = new System.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 = LOOK_FOR_RDN_ATTR_TYPE;
                        }
                        else if (needsEscape(currChar))
                        {
                            throw new System.ArgumentException(dnString);
                        }
                        else
                        {
                            trailingSpaceCount = 0;
                            tokenBuf[tokenIndex++] = currChar;
                        }
                        break; //end UNQUOTED RDN VALUE

                    case QUOTED_RDN_VALUE:
                        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 System.String(tokenBuf, 0, tokenIndex);

                                currRDN.add(attrType, attrValue, rawValue);
                                if (currChar != '+')
                                {
                                    rdnList.Add(currRDN);
                                    currRDN = new RDN();
                                }
                                trailingSpaceCount = 0;
                                tokenIndex = 0;
                                state = LOOK_FOR_RDN_ATTR_TYPE;
                            }
                            else
                                throw new System.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 System.ArgumentException(dnString);
                            }
                            else if (needsEscape(currChar) || currChar == '#' || currChar == '=' || currChar == ' ')
                            {
                                tokenBuf[tokenIndex++] = currChar;
                                trailingSpaceCount = 0;
                            }
                            else
                                throw new System.ArgumentException(dnString);
                        }
                        else
                            tokenBuf[tokenIndex++] = currChar;
                        break; //end QUOTED RDN VALUE

                    case HEX_RDN_VALUE:
                        if ((!isHexDigit(currChar)) || (currIndex > lastIndex))
                        {
                            //check for odd number of hex digits
                            if ((hexDigitCount % 2) != 0 || hexDigitCount == 0)
                                throw new System.ArgumentException(dnString);
                            else
                            {
                                rawValue = dnString.Substring(valueStart, (currIndex) - (valueStart));
                                //skip any spaces
                                while ((currChar == ' ') && (currIndex < lastIndex))
                                    currChar = dnString[++currIndex];
                                if ((currChar == ',') || (currChar == ';') || (currChar == '+') || (currIndex == lastIndex))
                                {
                                    attrValue = new System.String(tokenBuf, 0, tokenIndex);

                                    //added by cameron
                                    currRDN.add(attrType, attrValue, rawValue);
                                    if (currChar != '+')
                                    {
                                        rdnList.Add(currRDN);
                                        currRDN = new RDN();
                                    }
                                    tokenIndex = 0;
                                    state = LOOK_FOR_RDN_ATTR_TYPE;
                                }
                                else
                                {
                                    throw new System.ArgumentException(dnString);
                                }
                            }
                        }
                        else
                        {
                            tokenBuf[tokenIndex++] = currChar;
                            hexDigitCount++;
                        }
                        break; //end HEX RDN VALUE
                    } //end switch
                currIndex++;
            } //end while

            //check ending state
            if (state == UNQUOTED_RDN_VALUE || (state == HEX_RDN_VALUE && (hexDigitCount % 2) == 0) && hexDigitCount != 0)
            {
                attrValue = new System.String(tokenBuf, 0, tokenIndex - trailingSpaceCount);
                rawValue = dnString.Substring(valueStart, (currIndex - trailingSpaceCount) - (valueStart));
                currRDN.add(attrType, attrValue, rawValue);
                rdnList.Add(currRDN);
            }
            else if (state == LOOK_FOR_RDN_VALUE)
            {
                //empty value is valid
                attrValue = "";
                rawValue = dnString.Substring(valueStart);
                currRDN.add(attrType, attrValue, rawValue);
                rdnList.Add(currRDN);
            }
            else
            {
                throw new System.ArgumentException(dnString);
            }
        }