734 lines
25 KiB
C#
734 lines
25 KiB
C#
using System;
|
|
using System.Linq;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
|
|
namespace Unosquare.Swan.Networking.Ldap {
|
|
/// <summary>
|
|
/// Represents a single entry in a directory, consisting of
|
|
/// a distinguished name (DN) and zero or more attributes.
|
|
/// An instance of
|
|
/// LdapEntry is created in order to add an entry to a directory, and
|
|
/// instances of LdapEntry are returned on a search by enumerating an
|
|
/// LdapSearchResults.
|
|
/// </summary>
|
|
/// <seealso cref="LdapAttribute"></seealso>
|
|
/// <seealso cref="LdapAttributeSet"></seealso>
|
|
public class LdapEntry {
|
|
private readonly LdapAttributeSet _attrs;
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="LdapEntry" /> class.
|
|
/// Constructs a new entry with the specified distinguished name and set
|
|
/// of attributes.
|
|
/// </summary>
|
|
/// <param name="dn">The distinguished name of the new entry. The
|
|
/// value is not validated. An invalid distinguished
|
|
/// name will cause operations using this entry to fail.</param>
|
|
/// <param name="attrs">The initial set of attributes assigned to the
|
|
/// entry.</param>
|
|
public LdapEntry(String dn = null, LdapAttributeSet attrs = null) {
|
|
this.DN = dn ?? String.Empty;
|
|
this._attrs = attrs ?? new LdapAttributeSet();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns the distinguished name of the entry.
|
|
/// </summary>
|
|
/// <value>
|
|
/// The dn.
|
|
/// </value>
|
|
public String DN {
|
|
get;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns the attributes matching the specified attrName.
|
|
/// </summary>
|
|
/// <param name="attrName">The name of the attribute or attributes to return.</param>
|
|
/// <returns>
|
|
/// The attribute matching the name.
|
|
/// </returns>
|
|
public LdapAttribute GetAttribute(String attrName) => this._attrs[attrName];
|
|
|
|
/// <summary>
|
|
/// Returns the attribute set of the entry.
|
|
/// All base and subtype variants of all attributes are
|
|
/// returned. The LdapAttributeSet returned may be
|
|
/// empty if there are no attributes in the entry.
|
|
/// </summary>
|
|
/// <returns>
|
|
/// The attribute set of the entry.
|
|
/// </returns>
|
|
public LdapAttributeSet GetAttributeSet() => this._attrs;
|
|
|
|
/// <summary>
|
|
/// Returns an attribute set from the entry, consisting of only those
|
|
/// attributes matching the specified subtypes.
|
|
/// The getAttributeSet method can be used to extract only
|
|
/// a particular language variant subtype of each attribute,
|
|
/// if it exists. The "subtype" may be, for example, "lang-ja", "binary",
|
|
/// or "lang-ja;phonetic". If more than one subtype is specified, separated
|
|
/// with a semicolon, only those attributes with all of the named
|
|
/// subtypes will be returned. The LdapAttributeSet returned may be
|
|
/// empty if there are no matching attributes in the entry.
|
|
/// </summary>
|
|
/// <param name="subtype">One or more subtype specification(s), separated
|
|
/// with semicolons. The "lang-ja" and
|
|
/// "lang-en;phonetic" are valid subtype
|
|
/// specifications.</param>
|
|
/// <returns>
|
|
/// An attribute set from the entry with the attributes that
|
|
/// match the specified subtypes or an empty set if no attributes
|
|
/// match.
|
|
/// </returns>
|
|
public LdapAttributeSet GetAttributeSet(String subtype) => this._attrs.GetSubset(subtype);
|
|
}
|
|
|
|
/// <summary>
|
|
/// The name and values of one attribute of a directory entry.
|
|
/// LdapAttribute objects are used when searching for, adding,
|
|
/// modifying, and deleting attributes from the directory.
|
|
/// LdapAttributes are often used in conjunction with an
|
|
/// LdapAttributeSet when retrieving or adding multiple
|
|
/// attributes to an entry.
|
|
/// </summary>
|
|
public class LdapAttribute {
|
|
private readonly String _baseName; // cn of cn;lang-ja;phonetic
|
|
private readonly String[] _subTypes; // lang-ja of cn;lang-ja
|
|
private Object[] _values; // Array of byte[] attribute values
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="LdapAttribute"/> class.
|
|
/// Constructs an attribute with no values.
|
|
/// </summary>
|
|
/// <param name="attrName">Name of the attribute.</param>
|
|
/// <exception cref="ArgumentException">Attribute name cannot be null.</exception>
|
|
public LdapAttribute(String attrName) {
|
|
this.Name = attrName ?? throw new ArgumentNullException(nameof(attrName));
|
|
this._baseName = GetBaseName(attrName);
|
|
this._subTypes = GetSubtypes(attrName);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="LdapAttribute" /> class.
|
|
/// Constructs an attribute with a single <see cref="System.String" /> value.
|
|
/// </summary>
|
|
/// <param name="attrName">Name of the attribute.</param>
|
|
/// <param name="attrString">Value of the attribute as a string.</param>
|
|
/// <exception cref="ArgumentException">Attribute value cannot be null.</exception>
|
|
public LdapAttribute(String attrName, String attrString)
|
|
: this(attrName) => this.Add(Encoding.UTF8.GetSBytes(attrString));
|
|
|
|
/// <summary>
|
|
/// Returns the values of the attribute as an array of bytes.
|
|
/// </summary>
|
|
/// <value>
|
|
/// The byte value array.
|
|
/// </value>
|
|
public SByte[][] ByteValueArray {
|
|
get {
|
|
if(this._values == null) {
|
|
return new SByte[0][];
|
|
}
|
|
|
|
Int32 size = this._values.Length;
|
|
SByte[][] bva = new SByte[size][];
|
|
|
|
// Deep copy so application cannot change values
|
|
for(Int32 i = 0, u = size; i < u; i++) {
|
|
bva[i] = new SByte[((SByte[])this._values[i]).Length];
|
|
Array.Copy((Array)this._values[i], 0, bva[i], 0, bva[i].Length);
|
|
}
|
|
|
|
return bva;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns the values of the attribute as an array of strings.
|
|
/// </summary>
|
|
/// <value>
|
|
/// The string value array.
|
|
/// </value>
|
|
public String[] StringValueArray {
|
|
get {
|
|
if(this._values == null) {
|
|
return new String[0];
|
|
}
|
|
|
|
Int32 size = this._values.Length;
|
|
String[] sva = new String[size];
|
|
|
|
for(Int32 j = 0; j < size; j++) {
|
|
sva[j] = Encoding.UTF8.GetString((SByte[])this._values[j]);
|
|
}
|
|
|
|
return sva;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns the the first value of the attribute as an UTF-8 string.
|
|
/// </summary>
|
|
/// <value>
|
|
/// The string value.
|
|
/// </value>
|
|
public String StringValue => this._values == null ? null : Encoding.UTF8.GetString((SByte[])this._values[0]);
|
|
|
|
/// <summary>
|
|
/// Returns the first value of the attribute as a byte array or null.
|
|
/// </summary>
|
|
/// <value>
|
|
/// The byte value.
|
|
/// </value>
|
|
public SByte[] ByteValue {
|
|
get {
|
|
if(this._values == null) {
|
|
return null;
|
|
}
|
|
|
|
// Deep copy so app can't change the value
|
|
SByte[] bva = new SByte[((SByte[])this._values[0]).Length];
|
|
Array.Copy((Array)this._values[0], 0, bva, 0, bva.Length);
|
|
|
|
return bva;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns the language subtype of the attribute, if any.
|
|
/// For example, if the attribute name is cn;lang-ja;phonetic,
|
|
/// this method returns the string, lang-ja.
|
|
/// </summary>
|
|
/// <value>
|
|
/// The language subtype.
|
|
/// </value>
|
|
public String LangSubtype => this._subTypes?.FirstOrDefault(t => t.StartsWith("lang-"));
|
|
|
|
/// <summary>
|
|
/// Returns the name of the attribute.
|
|
/// </summary>
|
|
/// <value>
|
|
/// The name.
|
|
/// </value>
|
|
public String Name {
|
|
get;
|
|
}
|
|
|
|
internal String Value {
|
|
set {
|
|
this._values = null;
|
|
|
|
this.Add(Encoding.UTF8.GetSBytes(value));
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Extracts the subtypes from the specified attribute name.
|
|
/// For example, if the attribute name is cn;lang-ja;phonetic,
|
|
/// this method returns an array containing lang-ja and phonetic.
|
|
/// </summary>
|
|
/// <param name="attrName">Name of the attribute from which to extract
|
|
/// the subtypes.</param>
|
|
/// <returns>
|
|
/// An array subtypes or null if the attribute has none.
|
|
/// </returns>
|
|
/// <exception cref="ArgumentException">Attribute name cannot be null.</exception>
|
|
public static String[] GetSubtypes(String attrName) {
|
|
if(attrName == null) {
|
|
throw new ArgumentException("Attribute name cannot be null");
|
|
}
|
|
|
|
Tokenizer st = new Tokenizer(attrName, ";");
|
|
String[] subTypes = null;
|
|
Int32 cnt = st.Count;
|
|
|
|
if(cnt > 0) {
|
|
_ = st.NextToken(); // skip over basename
|
|
subTypes = new String[cnt - 1];
|
|
Int32 i = 0;
|
|
while(st.HasMoreTokens()) {
|
|
subTypes[i++] = st.NextToken();
|
|
}
|
|
}
|
|
|
|
return subTypes;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns the base name of the specified attribute name.
|
|
/// For example, if the attribute name is cn;lang-ja;phonetic,
|
|
/// this method returns cn.
|
|
/// </summary>
|
|
/// <param name="attrName">Name of the attribute from which to extract the
|
|
/// base name.</param>
|
|
/// <returns> The base name of the attribute. </returns>
|
|
/// <exception cref="ArgumentException">Attribute name cannot be null.</exception>
|
|
public static String GetBaseName(String attrName) {
|
|
if(attrName == null) {
|
|
throw new ArgumentException("Attribute name cannot be null");
|
|
}
|
|
|
|
Int32 idx = attrName.IndexOf(';');
|
|
return idx == -1 ? attrName : attrName.Substring(0, idx - 0);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Clones this instance.
|
|
/// </summary>
|
|
/// <returns>A cloned instance.</returns>
|
|
public LdapAttribute Clone() {
|
|
Object newObj = this.MemberwiseClone();
|
|
if(this._values != null) {
|
|
Array.Copy(this._values, 0, ((LdapAttribute)newObj)._values, 0, this._values.Length);
|
|
}
|
|
|
|
return (LdapAttribute)newObj;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds a <see cref="System.String" /> value to the attribute.
|
|
/// </summary>
|
|
/// <param name="attrString">Value of the attribute as a String.</param>
|
|
/// <exception cref="ArgumentException">Attribute value cannot be null.</exception>
|
|
public void AddValue(String attrString) {
|
|
if(attrString == null) {
|
|
throw new ArgumentException("Attribute value cannot be null");
|
|
}
|
|
|
|
this.Add(Encoding.UTF8.GetSBytes(attrString));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds a byte-formatted value to the attribute.
|
|
/// </summary>
|
|
/// <param name="attrBytes">Value of the attribute as raw bytes.
|
|
/// Note: If attrBytes represents a string it should be UTF-8 encoded.</param>
|
|
/// <exception cref="ArgumentException">Attribute value cannot be null.</exception>
|
|
public void AddValue(SByte[] attrBytes) {
|
|
if(attrBytes == null) {
|
|
throw new ArgumentException("Attribute value cannot be null");
|
|
}
|
|
|
|
this.Add(attrBytes);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds a base64 encoded value to the attribute.
|
|
/// The value will be decoded and stored as bytes. String
|
|
/// data encoded as a base64 value must be UTF-8 characters.
|
|
/// </summary>
|
|
/// <param name="attrString">The base64 value of the attribute as a String.</param>
|
|
/// <exception cref="ArgumentException">Attribute value cannot be null.</exception>
|
|
public void AddBase64Value(String attrString) {
|
|
if(attrString == null) {
|
|
throw new ArgumentException("Attribute value cannot be null");
|
|
}
|
|
|
|
this.Add(Convert.FromBase64String(attrString).ToSByteArray());
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds a base64 encoded value to the attribute.
|
|
/// The value will be decoded and stored as bytes. Character
|
|
/// data encoded as a base64 value must be UTF-8 characters.
|
|
/// </summary>
|
|
/// <param name="attrString">The base64 value of the attribute as a StringBuffer.</param>
|
|
/// <param name="start">The start index of base64 encoded part, inclusive.</param>
|
|
/// <param name="end">The end index of base encoded part, exclusive.</param>
|
|
/// <exception cref="ArgumentNullException">attrString.</exception>
|
|
public void AddBase64Value(StringBuilder attrString, Int32 start, Int32 end) {
|
|
if(attrString == null) {
|
|
throw new ArgumentNullException(nameof(attrString));
|
|
}
|
|
|
|
this.Add(Convert.FromBase64String(attrString.ToString(start, end)).ToSByteArray());
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds a base64 encoded value to the attribute.
|
|
/// The value will be decoded and stored as bytes. Character
|
|
/// data encoded as a base64 value must be UTF-8 characters.
|
|
/// </summary>
|
|
/// <param name="attrChars">The base64 value of the attribute as an array of
|
|
/// characters.</param>
|
|
/// <exception cref="ArgumentNullException">attrChars.</exception>
|
|
public void AddBase64Value(Char[] attrChars) {
|
|
if(attrChars == null) {
|
|
throw new ArgumentNullException(nameof(attrChars));
|
|
}
|
|
|
|
this.Add(Convert.FromBase64CharArray(attrChars, 0, attrChars.Length).ToSByteArray());
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns the base name of the attribute.
|
|
/// For example, if the attribute name is cn;lang-ja;phonetic,
|
|
/// this method returns cn.
|
|
/// </summary>
|
|
/// <returns>
|
|
/// The base name of the attribute.
|
|
/// </returns>
|
|
public String GetBaseName() => this._baseName;
|
|
|
|
/// <summary>
|
|
/// Extracts the subtypes from the attribute name.
|
|
/// For example, if the attribute name is cn;lang-ja;phonetic,
|
|
/// this method returns an array containing lang-ja and phonetic.
|
|
/// </summary>
|
|
/// <returns>
|
|
/// An array subtypes or null if the attribute has none.
|
|
/// </returns>
|
|
public String[] GetSubtypes() => this._subTypes;
|
|
|
|
/// <summary>
|
|
/// Reports if the attribute name contains the specified subtype.
|
|
/// For example, if you check for the subtype lang-en and the
|
|
/// attribute name is cn;lang-en, this method returns true.
|
|
/// </summary>
|
|
/// <param name="subtype">
|
|
/// The single subtype to check for.
|
|
/// </param>
|
|
/// <returns>
|
|
/// True, if the attribute has the specified subtype;
|
|
/// false, if it doesn't.
|
|
/// </returns>
|
|
public Boolean HasSubtype(String subtype) {
|
|
if(subtype == null) {
|
|
throw new ArgumentNullException(nameof(subtype));
|
|
}
|
|
|
|
return this._subTypes != null && this._subTypes.Any(t => String.Equals(t, subtype, StringComparison.OrdinalIgnoreCase));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Reports if the attribute name contains all the specified subtypes.
|
|
/// For example, if you check for the subtypes lang-en and phonetic
|
|
/// and if the attribute name is cn;lang-en;phonetic, this method
|
|
/// returns true. If the attribute name is cn;phonetic or cn;lang-en,
|
|
/// this method returns false.
|
|
/// </summary>
|
|
/// <param name="subtypes">
|
|
/// An array of subtypes to check for.
|
|
/// </param>
|
|
/// <returns>
|
|
/// True, if the attribute has all the specified subtypes;
|
|
/// false, if it doesn't have all the subtypes.
|
|
/// </returns>
|
|
public Boolean HasSubtypes(String[] subtypes) {
|
|
if(subtypes == null) {
|
|
throw new ArgumentNullException(nameof(subtypes));
|
|
}
|
|
|
|
for(Int32 i = 0; i < subtypes.Length; i++) {
|
|
foreach(String sub in this._subTypes) {
|
|
if(sub == null) {
|
|
throw new ArgumentException($"subtype at array index {i} cannot be null");
|
|
}
|
|
|
|
if(String.Equals(sub, subtypes[i], StringComparison.OrdinalIgnoreCase)) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Removes a string value from the attribute.
|
|
/// </summary>
|
|
/// <param name="attrString">Value of the attribute as a string.
|
|
/// Note: Removing a value which is not present in the attribute has
|
|
/// no effect.</param>
|
|
/// <exception cref="ArgumentNullException">attrString.</exception>
|
|
public void RemoveValue(String attrString) {
|
|
if(attrString == null) {
|
|
throw new ArgumentNullException(nameof(attrString));
|
|
}
|
|
|
|
this.RemoveValue(Encoding.UTF8.GetSBytes(attrString));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Removes a byte-formatted value from the attribute.
|
|
/// </summary>
|
|
/// <param name="attrBytes">Value of the attribute as raw bytes.
|
|
/// Note: If attrBytes represents a string it should be UTF-8 encoded.
|
|
/// Note: Removing a value which is not present in the attribute has
|
|
/// no effect.
|
|
/// </param>
|
|
/// <exception cref="ArgumentNullException">attrBytes.</exception>
|
|
public void RemoveValue(SByte[] attrBytes) {
|
|
if(attrBytes == null) {
|
|
throw new ArgumentNullException(nameof(attrBytes));
|
|
}
|
|
|
|
for(Int32 i = 0; i < this._values.Length; i++) {
|
|
if(!Equals(attrBytes, (SByte[])this._values[i])) {
|
|
continue;
|
|
}
|
|
|
|
if(i == 0 && this._values.Length == 1) {
|
|
// Optimize if first element of a single valued attr
|
|
this._values = null;
|
|
return;
|
|
}
|
|
|
|
if(this._values.Length == 1) {
|
|
this._values = null;
|
|
} else {
|
|
Int32 moved = this._values.Length - i - 1;
|
|
Object[] tmp = new Object[this._values.Length - 1];
|
|
if(i != 0) {
|
|
Array.Copy(this._values, 0, tmp, 0, i);
|
|
}
|
|
|
|
if(moved != 0) {
|
|
Array.Copy(this._values, i + 1, tmp, i, moved);
|
|
}
|
|
|
|
this._values = tmp;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns the number of values in the attribute.
|
|
/// </summary>
|
|
/// <returns>
|
|
/// The number of values in the attribute.
|
|
/// </returns>
|
|
public Int32 Size() => this._values?.Length ?? 0;
|
|
|
|
/// <summary>
|
|
/// Compares this object with the specified object for order.
|
|
/// Ordering is determined by comparing attribute names using the method Compare() of the String class.
|
|
/// </summary>
|
|
/// <param name="attribute">The LdapAttribute to be compared to this object.</param>
|
|
/// <returns>
|
|
/// Returns a negative integer, zero, or a positive
|
|
/// integer as this object is less than, equal to, or greater than the
|
|
/// specified object.
|
|
/// </returns>
|
|
public Int32 CompareTo(Object attribute)
|
|
=> String.Compare(this.Name, ((LdapAttribute)attribute).Name, StringComparison.Ordinal);
|
|
|
|
/// <summary>
|
|
/// Returns a string representation of this LdapAttribute.
|
|
/// </summary>
|
|
/// <returns>
|
|
/// a string representation of this LdapAttribute.
|
|
/// </returns>
|
|
/// <exception cref="Exception">NullReferenceException.</exception>
|
|
public override String ToString() {
|
|
StringBuilder result = new StringBuilder("LdapAttribute: ");
|
|
|
|
_ = result.Append("{type='" + this.Name + "'");
|
|
|
|
if(this._values != null) {
|
|
_ = result
|
|
.Append(", ")
|
|
.Append(this._values.Length == 1 ? "value='" : "values='");
|
|
|
|
for(Int32 i = 0; i < this._values.Length; i++) {
|
|
if(i != 0) {
|
|
_ = result.Append("','");
|
|
}
|
|
|
|
if(((SByte[])this._values[i]).Length == 0) {
|
|
continue;
|
|
}
|
|
|
|
String sval = Encoding.UTF8.GetString((SByte[])this._values[i]);
|
|
if(sval.Length == 0) {
|
|
// didn't decode well, must be binary
|
|
_ = result.Append("<binary value, length:" + sval.Length);
|
|
continue;
|
|
}
|
|
|
|
_ = result.Append(sval);
|
|
}
|
|
|
|
_ = result.Append("'");
|
|
}
|
|
|
|
_ = result.Append("}");
|
|
|
|
return result.ToString();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds an object to this object's list of attribute values.
|
|
/// </summary>
|
|
/// <param name="bytes">Ultimately all of this attribute's values are treated
|
|
/// as binary data so we simplify the process by requiring
|
|
/// that all data added to our list is in binary form.
|
|
/// Note: If attrBytes represents a string it should be UTF-8 encoded.</param>
|
|
private void Add(SByte[] bytes) {
|
|
if(this._values == null) {
|
|
this._values = new Object[] { bytes };
|
|
} else {
|
|
// Duplicate attribute values not allowed
|
|
if(this._values.Any(t => Equals(bytes, (SByte[])t))) {
|
|
return; // Duplicate, don't add
|
|
}
|
|
|
|
Object[] tmp = new Object[this._values.Length + 1];
|
|
Array.Copy(this._values, 0, tmp, 0, this._values.Length);
|
|
tmp[this._values.Length] = bytes;
|
|
this._values = tmp;
|
|
}
|
|
}
|
|
|
|
private static Boolean Equals(SByte[] e1, SByte[] e2) {
|
|
// If same object, they compare true
|
|
if(e1 == e2) {
|
|
return true;
|
|
}
|
|
|
|
// If either but not both are null, they compare false
|
|
if(e1 == null || e2 == null) {
|
|
return false;
|
|
}
|
|
|
|
// If arrays have different length, they compare false
|
|
Int32 length = e1.Length;
|
|
if(e2.Length != length) {
|
|
return false;
|
|
}
|
|
|
|
// If any of the bytes are different, they compare false
|
|
for(Int32 i = 0; i < length; i++) {
|
|
if(e1[i] != e2[i]) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// A set of LdapAttribute objects.
|
|
/// An LdapAttributeSet is a collection of LdapAttribute
|
|
/// classes as returned from an LdapEntry on a search or read
|
|
/// operation. LdapAttributeSet may be also used to construct an entry
|
|
/// to be added to a directory.
|
|
/// </summary>
|
|
/// <seealso cref="LdapAttribute"></seealso>
|
|
/// <seealso cref="LdapEntry"></seealso>
|
|
public class LdapAttributeSet : Dictionary<String, LdapAttribute> {
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="LdapAttributeSet"/> class.
|
|
/// </summary>
|
|
public LdapAttributeSet()
|
|
: base(StringComparer.OrdinalIgnoreCase) {
|
|
// placeholder
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a new attribute set containing only the attributes that have
|
|
/// the specified subtypes.
|
|
/// For example, suppose an attribute set contains the following
|
|
/// attributes:
|
|
/// <ul><li> cn</li><li> cn;lang-ja</li><li> sn;phonetic;lang-ja</li><li> sn;lang-us</li></ul>
|
|
/// Calling the <c>getSubset</c> method and passing lang-ja as the
|
|
/// argument, the method returns an attribute set containing the following
|
|
/// attributes:.
|
|
/// <ul><li>cn;lang-ja</li><li>sn;phonetic;lang-ja</li></ul>
|
|
/// </summary>
|
|
/// <param name="subtype">Semi-colon delimited list of subtypes to include. For
|
|
/// example:
|
|
/// <ul><li> "lang-ja" specifies only Japanese language subtypes</li><li> "binary" specifies only binary subtypes</li><li>
|
|
/// "binary;lang-ja" specifies only Japanese language subtypes
|
|
/// which also are binary
|
|
/// </li></ul>
|
|
/// Note: Novell eDirectory does not currently support language subtypes.
|
|
/// It does support the "binary" subtype.</param>
|
|
/// <returns>
|
|
/// An attribute set containing the attributes that match the
|
|
/// specified subtype.
|
|
/// </returns>
|
|
public LdapAttributeSet GetSubset(String subtype) {
|
|
// Create a new tempAttributeSet
|
|
LdapAttributeSet tempAttributeSet = new LdapAttributeSet();
|
|
|
|
foreach(KeyValuePair<String, LdapAttribute> kvp in this) {
|
|
if(kvp.Value.HasSubtype(subtype)) {
|
|
_ = tempAttributeSet.Add(kvp.Value.Clone());
|
|
}
|
|
}
|
|
|
|
return tempAttributeSet;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns <c>true</c> if this set contains an attribute of the same name
|
|
/// as the specified attribute.
|
|
/// </summary>
|
|
/// <param name="attr">Object of type <c>LdapAttribute</c>.</param>
|
|
/// <returns>
|
|
/// true if this set contains the specified attribute.
|
|
/// </returns>
|
|
public Boolean Contains(Object attr) => this.ContainsKey(((LdapAttribute)attr).Name);
|
|
|
|
/// <summary>
|
|
/// Adds the specified attribute to this set if it is not already present.
|
|
/// If an attribute with the same name already exists in the set then the
|
|
/// specified attribute will not be added.
|
|
/// </summary>
|
|
/// <param name="attr">Object of type <c>LdapAttribute</c>.</param>
|
|
/// <returns>
|
|
/// <c>true</c> if the attribute was added.
|
|
/// </returns>
|
|
public Boolean Add(LdapAttribute attr) {
|
|
String name = attr.Name;
|
|
|
|
if(this.ContainsKey(name)) {
|
|
return false;
|
|
}
|
|
|
|
this[name] = attr;
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Removes the specified object from this set if it is present.
|
|
/// If the specified object is of type <c>LdapAttribute</c>, the
|
|
/// specified attribute will be removed. If the specified object is of type
|
|
/// string, the attribute with a name that matches the string will
|
|
/// be removed.
|
|
/// </summary>
|
|
/// <param name="entry">The entry.</param>
|
|
/// <returns>
|
|
/// true if the object was removed.
|
|
/// </returns>
|
|
public Boolean Remove(LdapAttribute entry) => this.Remove(entry.Name);
|
|
|
|
/// <summary>
|
|
/// Returns a <see cref="System.String" /> that represents this instance.
|
|
/// </summary>
|
|
/// <returns>
|
|
/// A <see cref="System.String" /> that represents this instance.
|
|
/// </returns>
|
|
public override String ToString() {
|
|
StringBuilder retValue = new StringBuilder("LdapAttributeSet: ");
|
|
Boolean first = true;
|
|
|
|
foreach(KeyValuePair<String, LdapAttribute> attr in this) {
|
|
if(!first) {
|
|
_ = retValue.Append(" ");
|
|
}
|
|
|
|
first = false;
|
|
_ = retValue.Append(attr);
|
|
}
|
|
|
|
return retValue.ToString();
|
|
}
|
|
}
|
|
} |