import { findSourceMap } from "node:module"; import { markAsUntransferable } from "node:worker_threads"; import { LDAPAttribute } from "./ConfigLoader"; export enum ClassType { eUnknown, eAbstract, eStructural, eAuxiliary } abstract class LDAPSchemaItem { public constructor(def: string) { this.fDefinition = def; this.fName = def.match(/NAME[\s\(]+'([^']+)'/)?.pop() || ""; this.fDescription = def.match(/DESC\s+'([^']+)'/)?.pop() || ""; this.fAliases = (def.match(/NAME\s*\(\s*([^\)]+)\)/)?.pop() || "").split(/\s+/).map(i => i.startsWith("'") ? i.substr(1, i.length - 2) : i).filter(i => i.length); if (this.fAliases.indexOf(this.fName) === -1) this.fAliases.push(this.fName); } public GetName(): string { return this.fName; } public GetDescription(): string { return this.fDescription; } public Match(str: string): boolean { for (let i of this.fAliases) if (i.toLowerCase() == str) return true; return false; } protected readonly fDefinition: string; private fName: string; private fAliases: Array; private fDescription: string; } function Find(key: string, arr: Iterable): LDAPSchemaItem | null { key = key.toLowerCase(); for (let i of arr) if (i.Match(key)) return i; return null; } export class LDAPSchemaAttribute extends LDAPSchemaItem{ public constructor(def: string) { super(def); this.fSyntax = def.match(/SYNTAX\s+([0-9\.]+)/)?.pop() || null; } private fSyntax: string|null; } export class LDAPSchemaObjectClass extends LDAPSchemaItem { public constructor(def: string, attributeDic: Map) { super(def); const abstract = /\s+ABSTRACT\s+/.test(def) ? 1 : 0; const aux = /\s+AUXILIARY\s+/.test(def) ? 1 : 0; const structural = /\s+STRUCTURAL\s+/.test(def) ? 1 : 0; if (abstract + aux + structural !== 1) this.fType = ClassType.eUnknown; else if (abstract) this.fType = ClassType.eAbstract; else if (aux) this.fType = ClassType.eAuxiliary; else if (structural) this.fType = ClassType.eStructural; else this.fType = ClassType.eUnknown; this.fParent = def.match(/\s+SUP\s+([^\s]+)\s/)?.pop() || null; } private defToAttributes(type: string): string[] { const reg = type === "MUST" ? /\s+MUST\s+(\w+|\([^\)]+\))/ : /\s+MAY\s+(\w+|\([^\)]+\))/; const res = (this.fDefinition.match(reg) || [])[1]; if (!res) return new Array(); let result = new Array(); if (!res.startsWith('(')) { result.push(res.trim()); return result; } for (let i of res.substr(1, res.length -2).split("$")) result.push(i.trim()); return result; } public Consolidate(classes: Map, attributes: Map) { if (this.fFinalized) return; this.fFinalized = true; let parent = this.fParent ? (Find(this.fParent, classes.values()) as LDAPSchemaObjectClass|null) : null; if (parent) { parent.Consolidate(classes, attributes); for (let [key, attr] of parent.fMayAttributes) { if (!this.fMustAttributes.has(key)) this.fMayAttributes.set(key, attr); } for (let [key, attr] of parent.fMustAttributes) { this.fMustAttributes.set(key, attr); if (this.fMayAttributes.has(key)) this.fMayAttributes.delete(key); } } for (let mustAttr of this.defToAttributes("MUST")) { if (this.fMustAttributes.has(mustAttr)) continue; if (this.fMayAttributes.has(mustAttr)) this.fMayAttributes.delete(mustAttr); let attr = Find(mustAttr, attributes.values()) as LDAPSchemaAttribute|null; attr && this.fMustAttributes.set(mustAttr, attr); } for (let mayAttr of this.defToAttributes("MAY")) { if (this.fMayAttributes.has(mayAttr) || this.fMustAttributes.has(mayAttr)) continue; let attr = Find(mayAttr, attributes.values()) as LDAPSchemaAttribute | null; attr && this.fMayAttributes.set(mayAttr, attr); } return; } public HasAttribute(key: string): boolean { return !!(Find(key, this.fMayAttributes.values()) || Find(key, this.fMustAttributes.values())); } public HasMust(attr: string): boolean { return this.fMustAttributes.has(attr); } public ListDescriptions(): Map { let result = new Map(); for (let [key, data] of this.fMayAttributes) result.set(key, data.GetDescription()); for (let [key, data] of this.fMustAttributes) result.set(key, data.GetDescription()); return result; } public ListMayAttributes(): string[] { let result = new Array(); for (let [key, _] of this.fMayAttributes) result.push(key); return result; } public ListMustAttributes(): string[] { let result = new Array(); for (let [key, _] of this.fMustAttributes) result.push(key); return result; } public ListAttributes(): string[] { let result = new Array(); for (let [key, _] of this.fMustAttributes) result.push(key); for (let [key, _] of this.fMayAttributes) result.push(key); return result; } public GetType(): ClassType { return this.fType; } private fParent: string|null; private fType: ClassType; private fFinalized: boolean = false; private fMayAttributes: Map = new Map(); private fMustAttributes: Map = new Map(); }