Skip to content

Instantly share code, notes, and snippets.

@dsibiski
Forked from davetransom/DistinguishedName.cs
Created October 21, 2020 02:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dsibiski/4e42cffe8e587a6bbfb5efb6a386fdcf to your computer and use it in GitHub Desktop.
Save dsibiski/4e42cffe8e587a6bbfb5efb6a386fdcf to your computer and use it in GitHub Desktop.
Implementation of LDAP Distinguished Name parser, based on http://stackoverflow.com/a/25335936/137854. Also trims leading whitespace from attribute names and handles quoted values e.g. the `O="VeriSign, Inc."` in `CN=VeriSign Class 3 Secure Server CA - G3, OU=Terms of use at https://www.verisign.com/rpa (c)10, OU=VeriSign Trust Network, O="VeriS…
public class DistinguishedName
{
/// <summary>
/// Represents a name/value pair within a distinguished name, including the index of the part.
/// </summary>
public struct Part
{
public Part(string name, string value, int index = -1)
: this()
{
Name = name;
Value = value;
Index = index;
}
public string Name { get; private set; }
public string Value { get; private set; }
public int Index { get; private set; }
/// <summary>
/// Performs a case-insensitive name comparison
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public bool IsNamed(string name)
{
return string.Equals(name, this.Name, StringComparison.OrdinalIgnoreCase);
}
}
/// <summary>
/// Parses the given distinguished name into parts
/// </summary>
/// <param name="dn"></param>
/// <returns></returns>
public static IEnumerable<Part> Parse(string dn)
{
int i = 0;
int a = 0;
int v = 0;
int index = -1;
bool inNamePart = true;
bool isQuoted = false;
var namePart = new char[50];
var valuePart = new char[200];
string attrName, attrValue;
while (i < dn.Length)
{
char ch = dn[i++];
if (!inNamePart && ch == '"')
{
isQuoted = !isQuoted;
continue;
}
if (!isQuoted)
{
if (ch == '\\')
{
valuePart[v++] = ch;
valuePart[v++] = dn[i++];
continue;
}
if (ch == '=')
{
inNamePart = false;
isQuoted = false;
continue;
}
if (ch == ',')
{
inNamePart = true;
attrName = new string(namePart, 0, a);
attrValue = new string(valuePart, 0, v);
yield return new Part(attrName, attrValue, ++index);
isQuoted = false;
a = v = 0;
continue;
}
}
if (inNamePart && a == 0 && char.IsWhiteSpace(ch)) // skip whitespace
continue;
else if (inNamePart)
namePart[a++] = ch;
else
valuePart[v++] = ch;
}
attrName = new string(namePart, 0, a);
attrValue = new string(valuePart, 0, v);
yield return new Part(attrName, attrValue, ++index);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment