a575963da9
Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
745 lines
22 KiB
C#
745 lines
22 KiB
C#
/******************************************************************************
|
|
* The MIT License
|
|
* Copyright (c) 2003 Novell Inc. www.novell.com
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the Software), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
* SOFTWARE.
|
|
*******************************************************************************/
|
|
//
|
|
// Novell.Directory.Ldap.Utilclass.DN.cs
|
|
//
|
|
// Author:
|
|
// Sunil Kumar (Sunilk@novell.com)
|
|
//
|
|
// (C) 2003 Novell, Inc (http://www.novell.com)
|
|
//
|
|
|
|
using System;
|
|
|
|
namespace Novell.Directory.Ldap.Utilclass
|
|
{
|
|
|
|
/// <summary> A DN encapsulates a Distinguished Name (an ldap name with context). A DN
|
|
/// does not need to be fully distinguished, or extend to the Root of a
|
|
/// directory. It provides methods to get information about the DN and to
|
|
/// manipulate the DN.
|
|
///
|
|
/// The following are examples of valid DN:
|
|
/// <ul>
|
|
/// <li>cn=admin,ou=marketing,o=corporation</li>
|
|
/// <li>cn=admin,ou=marketing</li>
|
|
/// <li>2.5.4.3=admin,ou=marketing</li>
|
|
/// <li>oid.2.5.4.3=admin,ou=marketing</li>
|
|
/// </ul>
|
|
///
|
|
/// Note: Multivalued attributes are all considered to be one
|
|
/// component and are represented in one RDN (see RDN)
|
|
///
|
|
///
|
|
/// </summary>
|
|
/// <seealso cref="RDN">
|
|
/// </seealso>
|
|
|
|
public class DN : System.Object
|
|
{
|
|
private void InitBlock()
|
|
{
|
|
rdnList = new System.Collections.ArrayList();
|
|
}
|
|
/// <summary> Retrieves a list of RDN Objects, or individual names of the DN</summary>
|
|
/// <returns> list of RDNs
|
|
/// </returns>
|
|
virtual public System.Collections.ArrayList RDNs
|
|
{
|
|
get
|
|
{
|
|
int size = rdnList.Count;
|
|
System.Collections.ArrayList v = new System.Collections.ArrayList(size);
|
|
for (int i = 0; i < size; i++)
|
|
{
|
|
v.Add(rdnList[i]);
|
|
}
|
|
return v;
|
|
}
|
|
|
|
}
|
|
/// <summary> Returns the Parent of this DN</summary>
|
|
/// <returns> Parent DN
|
|
/// </returns>
|
|
virtual public DN Parent
|
|
{
|
|
get
|
|
{
|
|
DN parent = new DN();
|
|
parent.rdnList = (System.Collections.ArrayList) this.rdnList.Clone();
|
|
if (parent.rdnList.Count >= 1)
|
|
parent.rdnList.Remove(rdnList[0]); //remove first object
|
|
return parent;
|
|
}
|
|
|
|
}
|
|
|
|
//parser state identifiers.
|
|
private const int LOOK_FOR_RDN_ATTR_TYPE = 1;
|
|
private const int ALPHA_ATTR_TYPE = 2;
|
|
private const int OID_ATTR_TYPE = 3;
|
|
private const int LOOK_FOR_RDN_VALUE = 4;
|
|
private const int QUOTED_RDN_VALUE = 5;
|
|
private const int HEX_RDN_VALUE = 6;
|
|
private const int UNQUOTED_RDN_VALUE = 7;
|
|
|
|
/* State transition table: Parsing starts in state 1.
|
|
|
|
State COMMA DIGIT "Oid." ALPHA EQUAL QUOTE SHARP HEX
|
|
--------------------------------------------------------------------
|
|
1 Err 3 3 2 Err Err Err Err
|
|
2 Err Err Err 2 4 Err Err Err
|
|
3 Err 3 Err Err 4 Err Err Err
|
|
4 Err 7 Err 7 Err 5 6 7
|
|
5 1 5 Err 5 Err 1 Err 7
|
|
6 1 6 Err Err Err Err Err 6
|
|
7 1 7 Err 7 Err Err Err 7
|
|
|
|
*/
|
|
|
|
|
|
private System.Collections.ArrayList rdnList;
|
|
|
|
public DN()
|
|
{
|
|
InitBlock();
|
|
return ;
|
|
}
|
|
/// <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);
|
|
}
|
|
} //end DN constructor (string dn)
|
|
|
|
|
|
/// <summary> Checks a character to see if it is an ascii alphabetic character in
|
|
/// ranges 65-90 or 97-122.
|
|
///
|
|
/// </summary>
|
|
/// <param name="ch">the character to be tested.
|
|
/// </param>
|
|
/// <returns> <code>true</code> if the character is an ascii alphabetic
|
|
/// character
|
|
/// </returns>
|
|
private bool isAlpha(char ch)
|
|
{
|
|
if (((ch < 91) && (ch > 64)) || ((ch < 123) && (ch > 96)))
|
|
//ASCII A-Z
|
|
return true;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
|
|
/// <summary> Checks a character to see if it is an ascii digit (0-9) character in
|
|
/// the ascii value range 48-57.
|
|
///
|
|
/// </summary>
|
|
/// <param name="ch">the character to be tested.
|
|
/// </param>
|
|
/// <returns> <code>true</code> if the character is an ascii alphabetic
|
|
/// character
|
|
/// </returns>
|
|
private bool isDigit(char ch)
|
|
{
|
|
if ((ch < 58) && (ch > 47))
|
|
//ASCII 0-9
|
|
return true;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
/// <summary> Checks a character to see if it is valid hex digit 0-9, a-f, or
|
|
/// A-F (ASCII value ranges 48-47, 65-70, 97-102).
|
|
///
|
|
/// </summary>
|
|
/// <param name="ch">the character to be tested.
|
|
/// </param>
|
|
/// <returns> <code>true</code> if the character is a valid hex digit
|
|
/// </returns>
|
|
|
|
private static bool isHexDigit(char ch)
|
|
{
|
|
if (((ch < 58) && (ch > 47)) || ((ch < 71) && (ch > 64)) || ((ch < 103) && (ch > 96)))
|
|
//ASCII A-F
|
|
return true;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
/// <summary> Checks a character to see if it must always be escaped in the
|
|
/// string representation of a DN. We must tests for space, sharp, and
|
|
/// equals individually.
|
|
///
|
|
/// </summary>
|
|
/// <param name="ch">the character to be tested.
|
|
/// </param>
|
|
/// <returns> <code>true</code> if the character needs to be escaped in at
|
|
/// least some instances.
|
|
/// </returns>
|
|
private bool needsEscape(char ch)
|
|
{
|
|
if ((ch == ',') || (ch == '+') || (ch == '\"') || (ch == ';') || (ch == '<') || (ch == '>') || (ch == '\\'))
|
|
return true;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
/// <summary> Converts two valid hex digit characters that form the string
|
|
/// representation of an ascii character value to the actual ascii
|
|
/// character.
|
|
///
|
|
/// </summary>
|
|
/// <param name="hex1">the hex digit for the high order byte.
|
|
/// </param>
|
|
/// <param name="hex0">the hex digit for the low order byte.
|
|
/// </param>
|
|
/// <returns> the character whose value is represented by the parameters.
|
|
/// </returns>
|
|
|
|
private static char hexToChar(char hex1, char hex0)
|
|
{
|
|
int result;
|
|
|
|
if ((hex1 < 58) && (hex1 > 47))
|
|
//ASCII 0-9
|
|
result = (hex1 - 48) * 16;
|
|
else if ((hex1 < 71) && (hex1 > 64))
|
|
//ASCII a-f
|
|
result = (hex1 - 55) * 16;
|
|
else if ((hex1 < 103) && (hex1 > 96))
|
|
//ASCII A-F
|
|
result = (hex1 - 87) * 16;
|
|
else
|
|
throw new System.ArgumentException("Not hex digit");
|
|
|
|
if ((hex0 < 58) && (hex0 > 47))
|
|
//ASCII 0-9
|
|
result += (hex0 - 48);
|
|
else if ((hex0 < 71) && (hex0 > 64))
|
|
//ASCII a-f
|
|
result += (hex0 - 55);
|
|
else if ((hex0 < 103) && (hex0 > 96))
|
|
//ASCII A-F
|
|
result += (hex0 - 87);
|
|
else
|
|
throw new System.ArgumentException("Not hex digit");
|
|
|
|
return (char) result;
|
|
}
|
|
|
|
/// <summary> Creates and returns a string that represents this DN. The string
|
|
/// follows RFC 2253, which describes String representation of DN's and
|
|
/// RDN's
|
|
///
|
|
/// </summary>
|
|
/// <returns> A DN string.
|
|
/// </returns>
|
|
public override System.String ToString()
|
|
{
|
|
int length = rdnList.Count;
|
|
System.String dn = "";
|
|
if (length < 1)
|
|
return null;
|
|
dn = rdnList[0].ToString();
|
|
for (int i = 1; i < length; i++)
|
|
{
|
|
dn += ("," + rdnList[i].ToString());
|
|
}
|
|
return dn;
|
|
}
|
|
|
|
|
|
/// <summary> Compares this DN to the specified DN to determine if they are equal.
|
|
///
|
|
/// </summary>
|
|
/// <param name="toDN">the DN to compare to
|
|
/// </param>
|
|
/// <returns> <code>true</code> if the DNs are equal; otherwise
|
|
/// <code>false</code>
|
|
/// </returns>
|
|
|
|
public System.Collections.ArrayList getrdnList()
|
|
{
|
|
return this.rdnList;
|
|
}
|
|
public override bool Equals(System.Object toDN)
|
|
{
|
|
return Equals((DN) toDN);
|
|
}
|
|
public bool Equals(DN toDN)
|
|
{
|
|
System.Collections.ArrayList aList=toDN.getrdnList();
|
|
int length = aList.Count;
|
|
|
|
if (this.rdnList.Count != length)
|
|
return false;
|
|
|
|
for (int i = 0; i < length; i++)
|
|
{
|
|
if (!((RDN) rdnList[i]).equals((RDN) toDN.getrdnList()[i]))
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/// <summary> return a string array of the individual RDNs contained in the DN
|
|
///
|
|
/// </summary>
|
|
/// <param name="noTypes"> If true, returns only the values of the
|
|
/// components, and not the names, e.g. "Babs
|
|
/// Jensen", "Accounting", "Acme", "us" - instead of
|
|
/// "cn=Babs Jensen", "ou=Accounting", "o=Acme", and
|
|
/// "c=us".
|
|
/// </param>
|
|
/// <returns> <code>String[]</code> containing the rdns in the DN with
|
|
/// the leftmost rdn in the first element of the array
|
|
///
|
|
/// </returns>
|
|
public virtual System.String[] explodeDN(bool noTypes)
|
|
{
|
|
int length = rdnList.Count;
|
|
System.String[] rdns = new System.String[length];
|
|
for (int i = 0; i < length; i++)
|
|
rdns[i] = ((RDN) rdnList[i]).toString(noTypes);
|
|
return rdns;
|
|
}
|
|
|
|
/// <summary> Retrieves the count of RDNs, or individule names, in the Distinguished name</summary>
|
|
/// <returns> the count of RDN
|
|
/// </returns>
|
|
public virtual int countRDNs()
|
|
{
|
|
return rdnList.Count;
|
|
}
|
|
|
|
/// <summary>Determines if this DN is <I>contained</I> by the DN passed in. For
|
|
/// example: "cn=admin, ou=marketing, o=corporation" is contained by
|
|
/// "o=corporation", "ou=marketing, o=corporation", and "ou=marketing"
|
|
/// but <B>not</B> by "cn=admin" or "cn=admin,ou=marketing,o=corporation"
|
|
/// Note: For users of Netscape's SDK this method is comparable to contains
|
|
///
|
|
/// </summary>
|
|
/// <param name="containerDN">of a container
|
|
/// </param>
|
|
/// <returns> true if containerDN contains this DN
|
|
/// </returns>
|
|
public virtual bool isDescendantOf(DN containerDN)
|
|
{
|
|
int i = containerDN.rdnList.Count - 1; //index to an RDN of the ContainerDN
|
|
int j = this.rdnList.Count - 1; //index to an RDN of the ContainedDN
|
|
//Search from the end of the DN for an RDN that matches the end RDN of
|
|
//containerDN.
|
|
while (!((RDN) this.rdnList[j]).equals((RDN) containerDN.rdnList[i]))
|
|
{
|
|
j--;
|
|
if (j <= 0)
|
|
return false;
|
|
//if the end RDN of containerDN does not have any equal
|
|
//RDN in rdnList, then containerDN does not contain this DN
|
|
}
|
|
i--; //avoid a redundant compare
|
|
j--;
|
|
//step backwards to verify that all RDNs in containerDN exist in this DN
|
|
for (; i >= 0 && j >= 0; i--, j--)
|
|
{
|
|
if (!((RDN) this.rdnList[j]).equals((RDN) containerDN.rdnList[i]))
|
|
return false;
|
|
}
|
|
if (j == 0 && i == 0)
|
|
//the DNs are identical and thus not contained
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
/// <summary> Adds the RDN to the beginning of the current DN.</summary>
|
|
/// <param name="rdn">an RDN to be added
|
|
/// </param>
|
|
public virtual void addRDN(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 virtual void addRDNToFront(RDN rdn)
|
|
{
|
|
rdnList.Insert(0, rdn);
|
|
}
|
|
|
|
/// <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);
|
|
}
|
|
} //end class DN
|
|
}
|