ldapts
Version:
LDAP client
1,471 lines • 121 kB
JavaScript
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
//#region \0rolldown/runtime.js
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
key = keys[i];
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
get: ((k) => from[k]).bind(null, key),
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
});
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
value: mod,
enumerable: true
}) : target, mod));
//#endregion
let node_assert = require("node:assert");
node_assert = __toESM(node_assert, 1);
let node_util = require("node:util");
let node_crypto = require("node:crypto");
node_crypto = __toESM(node_crypto, 1);
let node_net = require("node:net");
node_net = __toESM(node_net, 1);
let node_tls = require("node:tls");
node_tls = __toESM(node_tls, 1);
let node_events = require("node:events");
//#region src/ber/Ber.ts
const Ber = {
EOC: 0,
Boolean: 1,
Integer: 2,
BitString: 3,
OctetString: 4,
Null: 5,
OID: 6,
ObjectDescriptor: 7,
External: 8,
Real: 9,
Enumeration: 10,
PDV: 11,
Utf8String: 12,
RelativeOID: 13,
Sequence: 16,
Set: 17,
NumericString: 18,
PrintableString: 19,
T61String: 20,
VideotexString: 21,
IA5String: 22,
UTCTime: 23,
GeneralizedTime: 24,
GraphicString: 25,
VisibleString: 26,
GeneralString: 28,
UniversalString: 29,
CharacterString: 30,
BMPString: 31,
Constructor: 32,
Context: 128
};
//#endregion
//#region src/ber/InvalidAsn1Error.ts
var InvalidAsn1Error = class extends Error {
constructor(message) {
super(message);
this.name = "InvalidAsn1Error";
}
};
//#endregion
//#region src/ber/BerReader.ts
var BerReader = class {
size;
currentLength = 0;
currentOffset = 0;
buffer;
constructor(data) {
if (!Buffer.isBuffer(data)) throw new TypeError("data must be a Buffer");
this.buffer = data;
this.size = data.length;
}
get length() {
return this.currentLength;
}
get offset() {
return this.currentOffset;
}
set offset(value) {
this.currentOffset = value;
}
get remain() {
return this.size - this.currentOffset;
}
get remainingBuffer() {
return this.buffer.subarray(this.currentOffset);
}
setBufferSize(size) {
this.size = size;
}
readByte(peek = false) {
if (this.size - this.currentOffset < 1) return null;
const byte = this.buffer.readUInt8(this.currentOffset);
if (!peek) this.currentOffset += 1;
return byte;
}
peek() {
return this.readByte(true);
}
readLength(startOffset) {
let offset = startOffset ?? this.currentOffset;
if (offset >= this.size) return null;
const lengthByte = this.buffer.readUInt8(offset);
offset += 1;
if ((lengthByte & 128) === 128) {
const numLengthBytes = lengthByte & 127;
if (numLengthBytes === 0) throw new InvalidAsn1Error("Indefinite length not supported");
if (numLengthBytes > 4) throw new InvalidAsn1Error("Encoding too long");
if (this.size - offset < numLengthBytes) return null;
this.currentLength = 0;
for (let i = 0; i < numLengthBytes; i++) {
this.currentLength = (this.currentLength << 8) + this.buffer.readUInt8(offset);
offset += 1;
}
} else this.currentLength = lengthByte;
return offset;
}
readSequence(expectedTag) {
const tag = this.peek();
if (tag === null) return null;
if (expectedTag !== void 0 && expectedTag !== tag) throw new InvalidAsn1Error(`Expected 0x${expectedTag.toString(16)}: got 0x${tag.toString(16)}`);
const newOffset = this.readLength(this.currentOffset + 1);
if (newOffset === null) return null;
this.currentOffset = newOffset;
return tag;
}
readInt() {
return this.readTag(Ber.Integer);
}
readBoolean() {
const value = this.readTag(Ber.Boolean);
if (value === null) return null;
return value !== 0;
}
readEnumeration() {
return this.readTag(Ber.Enumeration);
}
readString(tag = Ber.OctetString, asBuffer = false) {
const currentTag = this.peek();
if (currentTag === null) return null;
if (currentTag !== tag) throw new InvalidAsn1Error(`Expected 0x${tag.toString(16)}: got 0x${currentTag.toString(16)}`);
const newOffset = this.readLength(this.currentOffset + 1);
if (newOffset === null) return null;
if (this.currentLength > this.size - newOffset) return null;
this.currentOffset = newOffset;
if (this.currentLength === 0) return asBuffer ? Buffer.alloc(0) : "";
const value = this.buffer.subarray(this.currentOffset, this.currentOffset + this.currentLength);
this.currentOffset += this.currentLength;
return asBuffer ? value : value.toString("utf8");
}
readOID(tag = Ber.OID) {
const data = this.readString(tag, true);
if (data === null) return null;
const values = [];
let value = 0;
for (const byte of data) {
value = (value << 7) + (byte & 127);
if ((byte & 128) === 0) {
values.push(value);
value = 0;
}
}
const firstValue = values[0] ?? 0;
return [
Math.trunc(firstValue / 40),
firstValue % 40,
...values.slice(1)
].join(".");
}
readTag(tag) {
const currentTag = this.peek();
if (currentTag === null) return null;
if (currentTag !== tag) throw new InvalidAsn1Error(`Expected 0x${tag.toString(16)}: got 0x${currentTag.toString(16)}`);
const newOffset = this.readLength(this.currentOffset + 1);
if (newOffset === null) return null;
if (this.currentLength > 4) throw new InvalidAsn1Error(`Integer too long: ${this.currentLength}`);
if (this.currentLength > this.size - newOffset) return null;
this.currentOffset = newOffset;
const firstByte = this.buffer.readUInt8(this.currentOffset);
let value = 0;
for (let i = 0; i < this.currentLength; i++) {
value = value << 8 | this.buffer.readUInt8(this.currentOffset);
this.currentOffset += 1;
}
if ((firstByte & 128) === 128 && this.currentLength < 4) value -= 1 << this.currentLength * 8;
return value >> 0;
}
};
//#endregion
//#region src/ber/BerWriter.ts
var BerWriter = class {
data;
size;
currentOffset = 0;
growthFactor;
sequenceOffsets = [];
constructor(options = {}) {
const initialSize = options.size ?? 1024;
this.growthFactor = options.growthFactor ?? 8;
this.data = Buffer.alloc(initialSize);
this.size = initialSize;
}
get buffer() {
if (this.sequenceOffsets.length > 0) throw new InvalidAsn1Error(`${this.sequenceOffsets.length} unended sequence(s)`);
return this.data.subarray(0, this.currentOffset);
}
writeByte(value) {
this.ensureCapacity(1);
this.data[this.currentOffset++] = value;
}
writeInt(value, tag = Ber.Integer) {
let intValue = value;
let byteCount = 4;
while (((intValue & 4286578688) === 0 || (intValue & 4286578688) === -8388608) && byteCount > 1) {
byteCount--;
intValue <<= 8;
}
if (byteCount > 4) throw new InvalidAsn1Error("BER integers cannot be > 0xffffffff");
this.ensureCapacity(2 + byteCount);
this.data[this.currentOffset++] = tag;
this.data[this.currentOffset++] = byteCount;
while (byteCount > 0) {
byteCount--;
this.data[this.currentOffset++] = (intValue & 4278190080) >>> 24;
intValue <<= 8;
}
}
writeNull() {
this.writeByte(Ber.Null);
this.writeByte(0);
}
writeEnumeration(value, tag = Ber.Enumeration) {
this.writeInt(value, tag);
}
writeBoolean(value, tag = Ber.Boolean) {
this.ensureCapacity(3);
this.data[this.currentOffset++] = tag;
this.data[this.currentOffset++] = 1;
this.data[this.currentOffset++] = value ? 255 : 0;
}
writeString(value, tag = Ber.OctetString) {
const byteLength = Buffer.byteLength(value);
this.writeByte(tag);
this.writeLength(byteLength);
if (byteLength > 0) {
this.ensureCapacity(byteLength);
this.data.write(value, this.currentOffset);
this.currentOffset += byteLength;
}
}
writeBuffer(value, tag) {
this.writeByte(tag);
this.writeLength(value.length);
this.ensureCapacity(value.length);
value.copy(this.data, this.currentOffset, 0, value.length);
this.currentOffset += value.length;
}
writeStringArray(values) {
for (const value of values) this.writeString(value);
}
writeOID(value, tag = Ber.OID) {
if (!/^(\d+\.){3,}\d+$/.test(value)) throw new Error("Argument is not a valid OID string");
const parts = value.split(".");
const bytes = [];
const firstPart = parts[0] ?? "0";
const secondPart = parts[1] ?? "0";
bytes.push(Number(firstPart) * 40 + Number(secondPart));
for (const part of parts.slice(2)) this.encodeOidOctet(bytes, Number(part));
this.ensureCapacity(2 + bytes.length);
this.writeByte(tag);
this.writeLength(bytes.length);
for (const byte of bytes) this.writeByte(byte);
}
writeLength(length) {
this.ensureCapacity(4);
if (length <= 127) this.data[this.currentOffset++] = length;
else if (length <= 255) {
this.data[this.currentOffset++] = 129;
this.data[this.currentOffset++] = length;
} else if (length <= 65535) {
this.data[this.currentOffset++] = 130;
this.data[this.currentOffset++] = length >> 8;
this.data[this.currentOffset++] = length;
} else if (length <= 16777215) {
this.data[this.currentOffset++] = 131;
this.data[this.currentOffset++] = length >> 16;
this.data[this.currentOffset++] = length >> 8;
this.data[this.currentOffset++] = length;
} else throw new InvalidAsn1Error("Length too long (> 4 bytes)");
}
startSequence(tag = Ber.Sequence | Ber.Constructor) {
this.writeByte(tag);
this.sequenceOffsets.push(this.currentOffset);
this.ensureCapacity(3);
this.currentOffset += 3;
}
endSequence() {
const sequenceStart = this.sequenceOffsets.pop();
if (sequenceStart === void 0) throw new InvalidAsn1Error("No sequence to end");
const contentStart = sequenceStart + 3;
const contentLength = this.currentOffset - contentStart;
if (contentLength <= 127) {
this.shiftContent(contentStart, contentLength, -2);
this.data[sequenceStart] = contentLength;
} else if (contentLength <= 255) {
this.shiftContent(contentStart, contentLength, -1);
this.data[sequenceStart] = 129;
this.data[sequenceStart + 1] = contentLength;
} else if (contentLength <= 65535) {
this.data[sequenceStart] = 130;
this.data[sequenceStart + 1] = contentLength >> 8;
this.data[sequenceStart + 2] = contentLength;
} else if (contentLength <= 16777215) {
this.shiftContent(contentStart, contentLength, 1);
this.data[sequenceStart] = 131;
this.data[sequenceStart + 1] = contentLength >> 16;
this.data[sequenceStart + 2] = contentLength >> 8;
this.data[sequenceStart + 3] = contentLength;
} else throw new InvalidAsn1Error("Sequence too long");
}
encodeOidOctet(bytes, octet) {
if (octet < 128) bytes.push(octet);
else if (octet < 16384) {
bytes.push(octet >>> 7 | 128);
bytes.push(octet & 127);
} else if (octet < 2097152) {
bytes.push(octet >>> 14 | 128);
bytes.push((octet >>> 7 | 128) & 255);
bytes.push(octet & 127);
} else if (octet < 268435456) {
bytes.push(octet >>> 21 | 128);
bytes.push((octet >>> 14 | 128) & 255);
bytes.push((octet >>> 7 | 128) & 255);
bytes.push(octet & 127);
} else {
bytes.push((octet >>> 28 | 128) & 255);
bytes.push((octet >>> 21 | 128) & 255);
bytes.push((octet >>> 14 | 128) & 255);
bytes.push((octet >>> 7 | 128) & 255);
bytes.push(octet & 127);
}
}
shiftContent(start, length, shift) {
this.data.copy(this.data, start + shift, start, start + length);
this.currentOffset += shift;
}
ensureCapacity(needed) {
if (this.size - this.currentOffset < needed) {
let newSize = this.size * this.growthFactor;
if (newSize - this.currentOffset < needed) newSize += needed;
const newBuffer = Buffer.alloc(newSize);
this.data.copy(newBuffer, 0, 0, this.currentOffset);
this.data = newBuffer;
this.size = newSize;
}
}
};
//#endregion
//#region src/controls/Control.ts
var Control = class {
type;
critical;
constructor(type, options = {}) {
this.type = type;
this.critical = options.critical === true;
}
write(writer) {
writer.startSequence();
writer.writeString(this.type);
writer.writeBoolean(this.critical);
this.writeControl(writer);
writer.endSequence();
}
parse(reader) {
this.parseControl(reader);
}
writeControl(_) {}
parseControl(_) {}
};
//#endregion
//#region src/controls/EntryChangeNotificationControl.ts
var EntryChangeNotificationControl = class EntryChangeNotificationControl extends Control {
static type = "2.16.840.1.113730.3.4.7";
value;
constructor(options = {}) {
super(EntryChangeNotificationControl.type, options);
this.value = options.value;
}
parseControl(reader) {
if (reader.readSequence()) {
const changeType = reader.readInt() ?? 0;
let previousDN;
if (changeType === 8) previousDN = reader.readString();
const changeNumber = reader.readInt() ?? 0;
this.value = {
changeType,
previousDN,
changeNumber
};
}
}
writeControl(writer) {
if (!this.value) return;
const controlWriter = new BerWriter();
controlWriter.startSequence();
controlWriter.writeInt(this.value.changeType);
if (this.value.previousDN) controlWriter.writeString(this.value.previousDN);
controlWriter.writeInt(this.value.changeNumber);
controlWriter.endSequence();
writer.writeBuffer(controlWriter.buffer, 4);
}
};
//#endregion
//#region src/controls/PagedResultsControl.ts
var PagedResultsControl = class PagedResultsControl extends Control {
static type = "1.2.840.113556.1.4.319";
value;
constructor(options = {}) {
super(PagedResultsControl.type, options);
this.value = options.value;
}
parseControl(reader) {
if (reader.readSequence()) {
const size = reader.readInt() ?? 0;
const cookie = reader.readString(Ber.OctetString, true) ?? Buffer.alloc(0);
this.value = {
size,
cookie
};
}
}
writeControl(writer) {
if (!this.value) return;
const controlWriter = new BerWriter();
controlWriter.startSequence();
controlWriter.writeInt(this.value.size);
if (this.value.cookie?.length) controlWriter.writeBuffer(this.value.cookie, Ber.OctetString);
else controlWriter.writeString("");
controlWriter.endSequence();
writer.writeBuffer(controlWriter.buffer, 4);
}
};
//#endregion
//#region src/controls/PersistentSearchControl.ts
var PersistentSearchControl = class PersistentSearchControl extends Control {
static type = "2.16.840.1.113730.3.4.3";
value;
constructor(options = {}) {
super(PersistentSearchControl.type, options);
this.value = options.value;
}
parseControl(reader) {
if (reader.readSequence()) {
const changeTypes = reader.readInt() ?? 0;
const changesOnly = reader.readBoolean() ?? false;
const returnECs = reader.readBoolean() ?? false;
this.value = {
changeTypes,
changesOnly,
returnECs
};
}
}
writeControl(writer) {
if (!this.value) return;
const controlWriter = new BerWriter();
controlWriter.startSequence();
controlWriter.writeInt(this.value.changeTypes);
controlWriter.writeBoolean(this.value.changesOnly);
controlWriter.writeBoolean(this.value.returnECs);
controlWriter.endSequence();
writer.writeBuffer(controlWriter.buffer, 4);
}
};
//#endregion
//#region src/controls/ServerSideSortingRequestControl.ts
var ServerSideSortingRequestControl = class ServerSideSortingRequestControl extends Control {
static type = "1.2.840.113556.1.4.473";
values;
constructor(options = {}) {
super(ServerSideSortingRequestControl.type, options);
if (Array.isArray(options.value)) this.values = options.value;
else if (typeof options.value === "object") this.values = [options.value];
else this.values = [];
}
parseControl(reader) {
if (reader.readSequence(48)) while (reader.readSequence(48)) {
const attributeType = reader.readString() ?? "";
let orderingRule = "";
let reverseOrder = false;
if (reader.peek() === 128) orderingRule = reader.readString(128) ?? "";
if (reader.peek() === 129) reverseOrder = reader.readTag(129) !== 0;
this.values.push({
attributeType,
orderingRule,
reverseOrder
});
}
}
writeControl(writer) {
if (!this.values.length) return;
const controlWriter = new BerWriter();
controlWriter.startSequence(48);
for (const value of this.values) {
controlWriter.startSequence(48);
controlWriter.writeString(value.attributeType, Ber.OctetString);
if (value.orderingRule) controlWriter.writeString(value.orderingRule, 128);
if (typeof value.reverseOrder !== "undefined") controlWriter.writeBoolean(value.reverseOrder, 129);
controlWriter.endSequence();
}
controlWriter.endSequence();
writer.writeBuffer(controlWriter.buffer, 4);
}
};
//#endregion
//#region src/dn/RDN.ts
/**
* RDN is a part of DN, and it consists of key & value pair. This class also supports
* compound RDNs, meaning that one RDN can hold multiple key & value pairs.
*/
var RDN = class {
attrs = {};
constructor(attrs) {
if (attrs) for (const [key, value] of Object.entries(attrs)) this.set(key, value);
}
/**
* Set an RDN pair.
* @param {string} name
* @param {string} value
* @returns {object} RDN class
*/
set(name, value) {
this.attrs[name] = value;
return this;
}
/**
* Get an RDN value at the specified name.
* @param {string} name
* @returns {string | undefined} value
*/
get(name) {
return this.attrs[name];
}
/**
* Checks, if this instance of RDN is equal to the other RDN.
* @param {object} other
* @returns true if equal; otherwise false
*/
equals(other) {
const ourKeys = Object.keys(this.attrs);
const otherKeys = Object.keys(other.attrs);
if (ourKeys.length !== otherKeys.length) return false;
ourKeys.sort();
otherKeys.sort();
for (const [i, key] of ourKeys.entries()) {
if (key == null || key !== otherKeys[i]) return false;
const ourValue = this.attrs[key];
const otherValue = other.attrs[key];
if (ourValue == null && otherValue == null) continue;
if (ourValue == null || otherValue == null || ourValue !== otherValue) return false;
}
return true;
}
/**
* Parse the RDN, escape values & return a string representation.
* @returns {string} Escaped string representation of RDN.
*/
toString() {
let str = "";
for (const [key, value] of Object.entries(this.attrs)) {
if (str) str += "+";
str += `${key}=${this._escape(value)}`;
}
return str;
}
/**
* Escape values & return a string representation.
*
* RFC defines, that these characters should be escaped:
*
* Comma ,
* Backslash character \
* Pound sign (hash sign) #
* Plus sign +
* Less than symbol <
* Greater than symbol >
* Semicolon ;
* Double quote (quotation mark) "
* Equal sign =
* Leading or trailing spaces
* @param {string} value - RDN value to be escaped
* @returns {string} Escaped string representation of RDN
*/
_escape(value = "") {
let str = "";
let current = 0;
let quoted = false;
const len = value.length;
const escaped = /["\\]/;
const special = /[#+,;<=>]/;
if (len > 0) quoted = value.startsWith(" ") || value[len - 1] === " ";
while (current < len) {
const character = value[current] ?? "";
if (escaped.test(character) || !quoted && special.test(character)) str += "\\";
if (character) str += character;
current += 1;
}
if (quoted) str = `"${str}"`;
return str;
}
};
//#endregion
//#region src/dn/DN.ts
/**
* DN class provides chain building of multiple RDNs, which can be later build into
* escaped string representation.
*/
var DN = class DN {
rdns = [];
constructor(rdns) {
if (rdns) if (Array.isArray(rdns)) this.rdns = rdns;
else this.addRDNs(rdns);
}
/**
* Add an RDN component to the DN, consisting of key & value pair.
* @param {string} key
* @param {string} value
* @returns {object} DN
*/
addPairRDN(key, value) {
this.rdns.push(new RDN({ [key]: value }));
return this;
}
/**
* Add a single RDN component to the DN.
*
* Note, that this RDN can be compound (single RDN can have multiple key & value pairs).
* @param {object} rdn
* @returns {object} DN
*/
addRDN(rdn) {
if (rdn instanceof RDN) this.rdns.push(rdn);
else this.rdns.push(new RDN(rdn));
return this;
}
/**
* Add multiple RDN components to the DN.
*
* This method allows different interfaces to add RDNs into the DN.
* It can:
* - join other DN into this DN
* - join list of RDNs or RDNAttributes into this DN
* - create RDNs from object map, where every key & value will create a new RDN
* @param {object|object[]} rdns
* @returns {object} DN
*/
addRDNs(rdns) {
if (rdns instanceof DN) this.rdns.push(...rdns.rdns);
else if (Array.isArray(rdns)) for (const rdn of rdns) this.addRDN(rdn);
else for (const [name, value] of Object.entries(rdns)) if (Array.isArray(value)) for (const rdnValue of value) this.rdns.push(new RDN({ [name]: rdnValue }));
else this.rdns.push(new RDN({ [name]: value }));
return this;
}
getRDNs() {
return this.rdns;
}
get(index) {
return this.rdns[index];
}
set(rdn, index) {
if (rdn instanceof RDN) this.rdns[index] = rdn;
else this.rdns[index] = new RDN(rdn);
return this;
}
isEmpty() {
return !this.rdns.length;
}
/**
* Checks, if this instance of DN is equal to the other DN.
* @param {object} other
* @returns true if equal; otherwise false
*/
equals(other) {
if (this.rdns.length !== other.rdns.length) return false;
for (let i = 0; i < this.rdns.length; i += 1) {
const rdn = this.rdns[i];
const otherRdn = other.rdns[i];
if (rdn == null && otherRdn == null) continue;
if (rdn == null || otherRdn == null || !rdn.equals(otherRdn)) return false;
}
return true;
}
clone() {
return new DN([...this.rdns]);
}
reverse() {
this.rdns.reverse();
return this;
}
pop() {
return this.rdns.pop();
}
shift() {
return this.rdns.shift();
}
/**
* Parse the DN, escape values & return a string representation.
* @returns String representation of DN
*/
toString() {
let str = "";
for (const rdn of this.rdns) {
if (str.length) str += ",";
str += rdn.toString();
}
return str;
}
};
//#endregion
//#region src/errors/MessageParserError.ts
var MessageParserError = class MessageParserError extends Error {
messageDetails;
constructor(message) {
super(message);
this.name = "MessageParserError";
Object.setPrototypeOf(this, MessageParserError.prototype);
}
};
//#endregion
//#region src/errors/resultCodeErrors/ResultCodeError.ts
var ResultCodeError = class ResultCodeError extends Error {
code;
constructor(code, message) {
super(`${message} Code: 0x${code.toString(16)}`);
this.name = "ResultCodeError";
this.code = code;
Object.setPrototypeOf(this, ResultCodeError.prototype);
}
};
//#endregion
//#region src/errors/resultCodeErrors/AdminLimitExceededError.ts
var AdminLimitExceededError = class AdminLimitExceededError extends ResultCodeError {
constructor(message) {
super(11, message ?? "An LDAP server limit set by an administrative authority has been exceeded.");
this.name = "AdminLimitExceededError";
Object.setPrototypeOf(this, AdminLimitExceededError.prototype);
}
};
//#endregion
//#region src/errors/resultCodeErrors/AffectsMultipleDSAsError.ts
var AffectsMultipleDSAsError = class AffectsMultipleDSAsError extends ResultCodeError {
constructor(message) {
super(71, message ?? "The modify DN operation moves the entry from one LDAP server to another and thus requires more than one LDAP server.");
this.name = "AffectsMultipleDSAsError";
Object.setPrototypeOf(this, AffectsMultipleDSAsError.prototype);
}
};
//#endregion
//#region src/errors/resultCodeErrors/AliasDerefProblemError.ts
var AliasDerefProblemError = class AliasDerefProblemError extends ResultCodeError {
constructor(message) {
super(36, message ?? "Either the client does not have access rights to read the aliased object's name or dereferencing is not allowed.");
this.name = "AliasDerefProblemError";
Object.setPrototypeOf(this, AliasDerefProblemError.prototype);
}
};
//#endregion
//#region src/errors/resultCodeErrors/AliasProblemError.ts
var AliasProblemError = class AliasProblemError extends ResultCodeError {
constructor(message) {
super(33, message ?? "An error occurred when an alias was dereferenced.");
this.name = "AliasProblemError";
Object.setPrototypeOf(this, AliasProblemError.prototype);
}
};
//#endregion
//#region src/errors/resultCodeErrors/AlreadyExistsError.ts
var AlreadyExistsError = class AlreadyExistsError extends ResultCodeError {
constructor(message) {
super(68, message ?? "The add operation attempted to add an entry that already exists, or that the modify operation attempted to rename an entry to the name of an entry that already exists.");
this.name = "AlreadyExistsError";
Object.setPrototypeOf(this, AlreadyExistsError.prototype);
}
};
//#endregion
//#region src/errors/resultCodeErrors/AuthMethodNotSupportedError.ts
var AuthMethodNotSupportedError = class AuthMethodNotSupportedError extends ResultCodeError {
constructor(message) {
super(7, message ?? "The Directory Server does not support the requested Authentication Method.");
this.name = "AuthMethodNotSupportedError";
Object.setPrototypeOf(this, AuthMethodNotSupportedError.prototype);
}
};
//#endregion
//#region src/errors/resultCodeErrors/BusyError.ts
var BusyError = class BusyError extends ResultCodeError {
constructor(message) {
super(51, message ?? "The LDAP server is too busy to process the client request at this time.");
this.name = "BusyError";
Object.setPrototypeOf(this, BusyError.prototype);
}
};
//#endregion
//#region src/errors/resultCodeErrors/ConfidentialityRequiredError.ts
var ConfidentialityRequiredError = class ConfidentialityRequiredError extends ResultCodeError {
constructor(message) {
super(13, message ?? "The session is not protected by a protocol such as Transport Layer Security (TLS), which provides session confidentiality and the request will not be handled without confidentiality enabled.");
this.name = "ConfidentialityRequiredError";
Object.setPrototypeOf(this, ConfidentialityRequiredError.prototype);
}
};
//#endregion
//#region src/errors/resultCodeErrors/ConstraintViolationError.ts
var ConstraintViolationError = class ConstraintViolationError extends ResultCodeError {
constructor(message) {
super(19, message ?? "The attribute value specified in a Add Request, Modify Request or ModifyDNRequest operation violates constraints placed on the attribute. The constraint can be one of size or content (string only, no binary).");
this.name = "ConstraintViolationError";
Object.setPrototypeOf(this, ConstraintViolationError.prototype);
}
};
//#endregion
//#region src/errors/resultCodeErrors/InappropriateAuthError.ts
var InappropriateAuthError = class InappropriateAuthError extends ResultCodeError {
constructor(message) {
super(48, message ?? "The client is attempting to use an authentication method incorrectly.");
this.name = "InappropriateAuthError";
Object.setPrototypeOf(this, InappropriateAuthError.prototype);
}
};
//#endregion
//#region src/errors/resultCodeErrors/InappropriateMatchingError.ts
var InappropriateMatchingError = class InappropriateMatchingError extends ResultCodeError {
constructor(message) {
super(18, message ?? "The matching rule specified in the search filter does not match a rule defined for the attribute's syntax.");
this.name = "InappropriateMatchingError";
Object.setPrototypeOf(this, InappropriateMatchingError.prototype);
}
};
//#endregion
//#region src/errors/resultCodeErrors/InsufficientAccessError.ts
var InsufficientAccessError = class InsufficientAccessError extends ResultCodeError {
constructor(message) {
super(50, message ?? "The caller does not have sufficient rights to perform the requested operation.");
this.name = "InsufficientAccessError";
Object.setPrototypeOf(this, InsufficientAccessError.prototype);
}
};
//#endregion
//#region src/errors/resultCodeErrors/InvalidCredentialsError.ts
var InvalidCredentialsError = class InvalidCredentialsError extends ResultCodeError {
constructor(message) {
super(49, message ?? "Invalid credentials during a bind operation.");
this.name = "InvalidCredentialsError";
Object.setPrototypeOf(this, InvalidCredentialsError.prototype);
}
};
//#endregion
//#region src/errors/resultCodeErrors/InvalidDNSyntaxError.ts
var InvalidDNSyntaxError = class InvalidDNSyntaxError extends ResultCodeError {
constructor(message) {
super(34, message ?? "The syntax of the DN is incorrect.");
this.name = "InvalidDNSyntaxError";
Object.setPrototypeOf(this, InvalidDNSyntaxError.prototype);
}
};
//#endregion
//#region src/errors/resultCodeErrors/InvalidSyntaxError.ts
var InvalidSyntaxError = class InvalidSyntaxError extends ResultCodeError {
constructor(message) {
super(21, message ?? "The attribute value specified in an Add Request, Compare Request, or Modify Request operation is an unrecognized or invalid syntax for the attribute.");
this.name = "InvalidSyntaxError";
Object.setPrototypeOf(this, InvalidSyntaxError.prototype);
}
};
//#endregion
//#region src/errors/resultCodeErrors/IsLeafError.ts
var IsLeafError = class IsLeafError extends ResultCodeError {
constructor(message) {
super(35, message ?? "The specified operation cannot be performed on a leaf entry.");
this.name = "IsLeafError";
Object.setPrototypeOf(this, IsLeafError.prototype);
}
};
//#endregion
//#region src/errors/resultCodeErrors/LoopDetectError.ts
var LoopDetectError = class LoopDetectError extends ResultCodeError {
constructor(message) {
super(54, message ?? "The client discovered an alias or LDAP Referral loop, and is thus unable to complete this request.");
this.name = "LoopDetectError";
Object.setPrototypeOf(this, LoopDetectError.prototype);
}
};
//#endregion
//#region src/errors/resultCodeErrors/MoreResultsToReturnError.ts
var MoreResultsToReturnError = class MoreResultsToReturnError extends ResultCodeError {
constructor(message) {
super(95, message);
this.name = "MoreResultsToReturnError";
Object.setPrototypeOf(this, MoreResultsToReturnError.prototype);
}
};
//#endregion
//#region src/errors/resultCodeErrors/NamingViolationError.ts
var NamingViolationError = class NamingViolationError extends ResultCodeError {
constructor(message) {
super(64, message ?? "The Add Request or Modify DN Request operation violates the schema's structure rules.");
this.name = "NamingViolationError";
Object.setPrototypeOf(this, NamingViolationError.prototype);
}
};
//#endregion
//#region src/errors/resultCodeErrors/NoObjectClassModsError.ts
var NoObjectClassModsError = class NoObjectClassModsError extends ResultCodeError {
constructor(message) {
super(69, message ?? "The modify operation attempted to modify the structure rules of an object class.");
this.name = "NoObjectClassModsError";
Object.setPrototypeOf(this, NoObjectClassModsError.prototype);
}
};
//#endregion
//#region src/errors/resultCodeErrors/NoSuchAttributeError.ts
var NoSuchAttributeError = class NoSuchAttributeError extends ResultCodeError {
constructor(message) {
super(16, message ?? "The attribute specified in the Modify Request or Compare Request operation does not exist in the entry.");
this.name = "NoSuchAttributeError";
Object.setPrototypeOf(this, NoSuchAttributeError.prototype);
}
};
//#endregion
//#region src/errors/resultCodeErrors/NoSuchObjectError.ts
var NoSuchObjectError = class NoSuchObjectError extends ResultCodeError {
constructor(message) {
super(32, message ?? "The target object cannot be found.");
this.name = "NoSuchObjectError";
Object.setPrototypeOf(this, NoSuchObjectError.prototype);
}
};
//#endregion
//#region src/errors/resultCodeErrors/NotAllowedOnNonLeafError.ts
var NotAllowedOnNonLeafError = class NotAllowedOnNonLeafError extends ResultCodeError {
constructor(message) {
super(66, message ?? "The requested operation is permitted only on leaf entries.");
this.name = "NotAllowedOnNonLeafError";
Object.setPrototypeOf(this, NotAllowedOnNonLeafError.prototype);
}
};
//#endregion
//#region src/errors/resultCodeErrors/NotAllowedOnRDNError.ts
var NotAllowedOnRDNError = class NotAllowedOnRDNError extends ResultCodeError {
constructor(message) {
super(67, message ?? "The modify operation attempted to remove an attribute value that forms the entry's relative distinguished name.");
this.name = "NotAllowedOnRDNError";
Object.setPrototypeOf(this, NotAllowedOnRDNError.prototype);
}
};
//#endregion
//#region src/errors/resultCodeErrors/NoResultError.ts
var NoResultError = class NoResultError extends ResultCodeError {
constructor(message) {
super(248, message ?? "No result message for the request.");
this.name = "NoResultError";
Object.setPrototypeOf(this, NoResultError.prototype);
}
};
//#endregion
//#region src/errors/resultCodeErrors/ObjectClassViolationError.ts
var ObjectClassViolationError = class ObjectClassViolationError extends ResultCodeError {
constructor(message) {
super(65, message ?? "The Add Request, Modify Request, or modify DN operation violates the object class rules for the entry.");
this.name = "ObjectClassViolationError";
Object.setPrototypeOf(this, ObjectClassViolationError.prototype);
}
};
//#endregion
//#region src/errors/resultCodeErrors/OperationsError.ts
var OperationsError = class OperationsError extends ResultCodeError {
constructor(message) {
super(1, message ?? "Request was out of sequence with another operation in progress.");
this.name = "OperationsError";
Object.setPrototypeOf(this, OperationsError.prototype);
}
};
//#endregion
//#region src/errors/resultCodeErrors/ProtocolError.ts
var ProtocolError = class ProtocolError extends ResultCodeError {
constructor(message) {
super(2, message ?? "Client sent data to the server that did not comprise a valid LDAP request.");
this.name = "ProtocolError";
Object.setPrototypeOf(this, ProtocolError.prototype);
}
};
//#endregion
//#region src/errors/resultCodeErrors/ResultsTooLargeError.ts
var ResultsTooLargeError = class ResultsTooLargeError extends ResultCodeError {
constructor(message) {
super(70, message ?? "Results are too large.");
this.name = "ResultsTooLargeError";
Object.setPrototypeOf(this, ResultsTooLargeError.prototype);
}
};
//#endregion
//#region src/errors/resultCodeErrors/SaslBindInProgressError.ts
var SaslBindInProgressError = class SaslBindInProgressError extends ResultCodeError {
response;
constructor(response) {
super(14, response.errorMessage || "The server is ready for the next step in the SASL authentication process. The client must send the server the same SASL Mechanism to continue the process.");
this.response = response;
this.name = "SaslBindInProgressError";
Object.setPrototypeOf(this, SaslBindInProgressError.prototype);
}
};
//#endregion
//#region src/errors/resultCodeErrors/SizeLimitExceededError.ts
var SizeLimitExceededError = class SizeLimitExceededError extends ResultCodeError {
constructor(message) {
super(4, message ?? "There were more entries matching the criteria contained in a SearchRequest operation than were allowed to be returned by the size limit configuration.");
this.name = "SizeLimitExceededError";
Object.setPrototypeOf(this, SizeLimitExceededError.prototype);
}
};
//#endregion
//#region src/errors/resultCodeErrors/StrongAuthRequiredError.ts
var StrongAuthRequiredError = class StrongAuthRequiredError extends ResultCodeError {
constructor(message) {
super(8, message ?? "Client requested an operation that requires strong authentication.");
this.name = "StrongAuthRequiredError";
Object.setPrototypeOf(this, StrongAuthRequiredError.prototype);
}
};
//#endregion
//#region src/errors/resultCodeErrors/TimeLimitExceededError.ts
var TimeLimitExceededError = class TimeLimitExceededError extends ResultCodeError {
constructor(message) {
super(3, message ?? "Processing on the associated request Timeout limit specified by either the client request or the server administration limits has been exceeded and has been terminated because it took too long to complete.");
this.name = "TimeLimitExceededError";
Object.setPrototypeOf(this, TimeLimitExceededError.prototype);
}
};
//#endregion
//#region src/errors/resultCodeErrors/TLSNotSupportedError.ts
var TLSNotSupportedError = class TLSNotSupportedError extends ResultCodeError {
constructor(message) {
super(112, message ?? "TLS is not supported on the server.");
this.name = "TLSNotSupportedError";
Object.setPrototypeOf(this, TLSNotSupportedError.prototype);
}
};
//#endregion
//#region src/errors/resultCodeErrors/TypeOrValueExistsError.ts
var TypeOrValueExistsError = class TypeOrValueExistsError extends ResultCodeError {
constructor(message) {
super(20, message ?? "The attribute value specified in a Add Request or Modify Request operation already exists as a value for that attribute.");
this.name = "TypeOrValueExistsError";
Object.setPrototypeOf(this, TypeOrValueExistsError.prototype);
}
};
//#endregion
//#region src/errors/resultCodeErrors/UnavailableCriticalExtensionError.ts
var UnavailableCriticalExtensionError = class UnavailableCriticalExtensionError extends ResultCodeError {
constructor(message) {
super(12, message ?? "One or more critical extensions were not available by the LDAP server. Either the server does not support the control or the control is not appropriate for the operation type.");
this.name = "UnavailableCriticalExtensionError";
Object.setPrototypeOf(this, UnavailableCriticalExtensionError.prototype);
}
};
//#endregion
//#region src/errors/resultCodeErrors/UnavailableError.ts
var UnavailableError = class UnavailableError extends ResultCodeError {
constructor(message) {
super(52, message ?? "The LDAP server cannot process the client's bind request.");
this.name = "UnavailableError";
Object.setPrototypeOf(this, UnavailableError.prototype);
}
};
//#endregion
//#region src/errors/resultCodeErrors/UndefinedTypeError.ts
var UndefinedTypeError = class UndefinedTypeError extends ResultCodeError {
constructor(message) {
super(17, message ?? "The attribute specified in the modify or add operation does not exist in the LDAP server's schema.");
this.name = "UndefinedTypeError";
Object.setPrototypeOf(this, UndefinedTypeError.prototype);
}
};
//#endregion
//#region src/errors/resultCodeErrors/UnknownStatusCodeError.ts
var UnknownStatusCodeError = class UnknownStatusCodeError extends ResultCodeError {
constructor(code, message) {
super(code, message ?? "Unknown error.");
this.name = "UnknownStatusCodeError";
Object.setPrototypeOf(this, UnknownStatusCodeError.prototype);
}
};
//#endregion
//#region src/errors/resultCodeErrors/UnwillingToPerformError.ts
var UnwillingToPerformError = class UnwillingToPerformError extends ResultCodeError {
constructor(message) {
super(53, message ?? "The LDAP server cannot process the request because of server-defined restrictions.");
this.name = "UnwillingToPerformError";
Object.setPrototypeOf(this, UnwillingToPerformError.prototype);
}
};
//#endregion
//#region src/filters/Filter.ts
var Filter = class {
write(writer) {
writer.startSequence(this.type);
this.writeFilter(writer);
writer.endSequence();
}
parse(reader) {
this.parseFilter(reader);
}
matches(_ = {}, __) {
return true;
}
/**
* RFC 2254 Escaping of filter strings
* Raw Escaped
* (o=Parens (R Us)) (o=Parens \28R Us\29)
* (cn=star*) (cn=star\2A)
* (filename=C:\MyFile) (filename=C:\5cMyFile)
* @param {string|Buffer} input
* @returns Escaped string
*/
static escape(input) {
let escapedResult = "";
if (Buffer.isBuffer(input)) for (const inputChar of input) if (inputChar < 16) escapedResult += `\\0${inputChar.toString(16)}`;
else escapedResult += `\\${inputChar.toString(16)}`;
else for (const inputChar of input) switch (inputChar) {
case "*":
escapedResult += "\\2a";
break;
case "(":
escapedResult += "\\28";
break;
case ")":
escapedResult += "\\29";
break;
case "\\":
escapedResult += "\\5c";
break;
case "\0":
escapedResult += "\\00";
break;
default:
escapedResult += inputChar;
break;
}
return escapedResult;
}
parseFilter(_) {}
writeFilter(_) {}
getObjectValue(objectToCheck, key, strictAttributeCase) {
let objectKey;
if (typeof objectToCheck[key] !== "undefined") objectKey = key;
else if (!strictAttributeCase && key.toLowerCase() === "objectclass") {
for (const objectToCheckKey of Object.keys(objectToCheck)) if (objectToCheckKey.toLowerCase() === key.toLowerCase()) {
objectKey = objectToCheckKey;
break;
}
}
if (objectKey) return objectToCheck[objectKey];
}
};
//#endregion
//#region src/filters/escapeFilter.ts
/**
* Tagged template literal for building LDAP filter strings. Every interpolated value is escaped
* with {@link Filter.escape} (RFC 2254 / RFC 4515), which prevents filter syntax characters in
* untrusted input from being misinterpreted as syntax (injection attacks).
* @example
* const filter = escapeFilter`(&(objectClass=user)(uid=${untrustedInput}))`;
* @param {TemplateStringsArray} strings - Literal portions of the template
* @param {...Buffer|boolean|number|string} values - Values to escape before interpolating
* @returns {string} Filter string with all interpolated values escaped
*/
function escapeFilter(strings, ...values) {
let result = strings[0] ?? "";
for (const [index, value] of values.entries()) {
result += Filter.escape(typeof value === "string" || Buffer.isBuffer(value) ? value : String(value));
result += strings[index + 1] ?? "";
}
return result;
}
//#endregion
//#region src/SearchFilter.ts
const SearchFilter = {
and: 160,
or: 161,
not: 162,
equalityMatch: 163,
substrings: 164,
greaterOrEqual: 165,
lessOrEqual: 166,
present: 135,
approxMatch: 168,
extensibleMatch: 169
};
//#endregion
//#region src/filters/AndFilter.ts
var AndFilter = class extends Filter {
type = SearchFilter.and;
filters;
constructor(options) {
super();
this.filters = options.filters;
}
writeFilter(writer) {
for (const filter of this.filters) filter.write(writer);
}
matches(objectToCheck = {}, strictAttributeCase) {
if (!this.filters.length) return true;
for (const filter of this.filters) if (!filter.matches(objectToCheck, strictAttributeCase)) return false;
return true;
}
toString() {
let result = "(&";
for (const filter of this.filters) result += filter.toString();
result += ")";
return result;
}
};
//#endregion
//#region src/filters/ApproximateFilter.ts
var ApproximateFilter = class extends Filter {
type = SearchFilter.approxMatch;
attribute;
value;
constructor(options = {}) {
super();
this.attribute = options.attribute ?? "";
this.value = options.value ?? "";
}
parseFilter(reader) {
this.attribute = (reader.readString() ?? "").toLowerCase();
this.value = reader.readString() ?? "";
}
writeFilter(writer) {
writer.writeString(this.attribute);
writer.writeString(this.value);
}
matches(_ = {}, __) {
throw new Error("Approximate match implementation unknown");
}
toString() {
return `(${Filter.escape(this.attribute)}~=${Filter.escape(this.value)})`;
}
};
//#endregion
//#region src/filters/EqualityFilter.ts
var EqualityFilter = class extends Filter {
type = SearchFilter.equalityMatch;
attribute;
value;
constructor(options = {}) {
super();
this.attribute = options.attribute ?? "";
this.value = options.value ?? "";
}
parseFilter(reader) {
this.attribute = (reader.readString() ?? "").toLowerCase();
this.value = reader.readString() ?? "";
if (this.attribute === "objectclass") this.value = this.value.toLowerCase();
}
writeFilter(writer) {
writer.writeString(this.attribute);
if (Buffer.isBuffer(this.value)) writer.writeBuffer(this.value, Ber.OctetString);
else writer.writeString(this.value);
}
matches(objectToCheck = {}, strictAttributeCase) {
const objectToCheckValue = this.getObjectValue(objectToCheck, this.attribute, strictAttributeCase);
if (typeof objectToCheckValue !== "undefined") {
if (Buffer.isBuffer(this.value) && Buffer.isBuffer(objectToCheckValue)) return this.value === objectToCheckValue;
const stringValue = Buffer.isBuffer(this.value) ? this.value.toString("utf8") : this.value;
if (strictAttributeCase) return stringValue === objectToCheckValue;
return stringValue.toLowerCase() === objectToCheckValue.toLowerCase();
}
return false;
}
toString() {
return `(${Filter.escape(this.attribute)}=${Filter.escape(this.value)})`;
}
};
//#endregion
//#region src/filters/ExtensibleFilter.ts
var ExtensibleFilter = class extends Filter {
type = SearchFilter.extensibleMatch;
value;
rule;
matchType;
dnAttributes;
constructor(options = {}) {
super();
this.matchType = options.matchType ?? "";
this.rule = options.rule ?? "";
this.dnAttributes = options.dnAttributes === true;
this.value = options.value ?? "";
}
parseFilter(reader) {
const end = reader.offset + reader.length;
while (reader.offset < end) {
const tag = reader.peek();
switch (tag) {
case 129:
this.rule = reader.readString(tag) ?? "";
break;
case 130:
this.matchType = reader.readString(tag) ?? "";
break;
case 131:
this.value = reader.readString(tag) ?? "";
break;
case 132:
this.dnAttributes = reader.readBoolean() ?? false;
break;
default: {
let type = "<null>";
if (tag) type = `0x${tag.toString(16)}`;
throw new Error(`Invalid ext_match filter type: ${type}`);
}
}
}
}
writeFilter(writer) {
if (this.rule) writer.writeString(this.rule, 129);
if (this.matchType) writer.writeString(this.matchType, 130);
writer.writeString(this.value, 131);
if (this.dnAttributes) writer.writeBoolean(this.dnAttributes, 132);
}
matches(_ = {}, __) {
throw new Error("Approximate match implementation unknown");
}
toString() {
let result = `(${Filter.escape(this.matchType)}:`;
if (this.dnAttributes) result += "dn:";
if (this.rule) result += `${Filter.escape(this.rule)}:`;
result += `=${Filter.escape(this.value)})`;
return result;
}
};
//#endregion
//#region src/filters/GreaterThanEqualsFilter.ts
var GreaterThanEqualsFilter = class extends Filter {
type = SearchFilter.greaterOrEqual;
attribute;
value;
constructor(options = {}) {
super();
this.attribute = options.attribute ?? "";
this.value = options.value ?? "";
}
parseFilter(reader) {
this.attribute = reader.readString()?.toLowerCase() ?? "";
this.value = reader.readString() ?? "";
}
writeFilter(writer) {
writer.writeString(this.attribute);
writer.writeString(this.value);
}
matches(objectToCheck = {}, strictAttributeCase) {
const objectToCheckValue = this.getObjectValue(objectToCheck, this.attribute, strictAttributeCase);
if (typeof objectToCheckValue !== "undefined") {
if (strictAttributeCase) return objectToCheckValue >= this.value;
return objectToCheckValue.toLowerCase() >= this.value.toLowerCase();
}
return false;
}
toString() {
return `(${Filter.escape(this.attribute)}>=${Filter.escape(this.value)})`;
}
};
//#endregion
//#region src/filters/LessThanEqualsFilter.ts
var LessThanEqualsFilter = class extends Filter {
type = SearchFilter.lessOrEqual;
attribute;
value;
constructor(options = {}) {
super();
this.attribute = options.attribute ?? "";
this.value = options.value ?? "";
}
parseFilter(reader) {
this.attribute = reader.readString()?.toLowerCase() ?? "";
this.value = reader.readString() ?? "";
}
writeFilter(writer) {
writer.writeString(this.attribute);
writer.writeString(this.value);
}
matches(objectToCheck = {}, strictAttributeCase) {
const objectToCheckValue = this.getObjectValue(objectToCheck, this.attribute, strictAttributeCase);
if (typeof objectToCheckValue !== "undefined") {
if (strictAttributeCase) return objectToCheckValue <= this.value;
return objectToCheckValue.toLowerCase() <= this.value.toLowerCase();
}
return false;
}
toString() {
return `(${Filter.escape(this.attribute)}<=${Filter.escape(this.value)})`;
}
};
//#endregion
//#region src/filters/NotFilter.ts
var NotFilter = class extends Filter {
type = SearchFilter.not;
filter;
constructor(options) {
super();
this.filter = options.filter;
}
writeFilter(writer) {
this.filter.write(writer);
}
matches(objectToCheck = {}, strictAttributeCase) {
return !this.filter.matches(objectToCheck, strictAttributeCase);
}
toString() {
return `(!${this.filter.toString()})`;
}
};
//#endregion
//#region src/filters/OrFilter.ts
var OrFilter = class extends Filter {
type = SearchFilter.or;
filters;
constructor(options) {
super();
this.filters = options.filters;
}
writeFilter(writer) {
for (const filter of this.filters) filter.write(writer);
}
matches(objectToCheck = {}, strictAttributeCase) {
if (!this.filters.length) return true;
for (const filter of this.filters) if (filter.matches(objectToCheck, strictAttributeCase)) return true;
return false;
}
toString() {
let result = "(|";
for (const filter of this.filters) result += filter.toString();
result += ")";
return result;
}
};
//#endregion
//#region src/filters/PresenceFilter.ts
var PresenceFilter = class extends Filter {
type = SearchFilter.present;
attribute;
constructor(options = {}) {
super();
this.attribute = options.attribute ?? "";
}
parseFilter(reader) {
this.attribute = reader.buffer.subarray(0, reader.length).toString("utf8").toLowerCase();