From 304adb4f4a39311b2ea99f78dc5b689590b25a5e Mon Sep 17 00:00:00 2001 From: Matt Simerson Date: Mon, 25 May 2026 21:41:51 -0700 Subject: [PATCH] algo updates for ds, rrsig, compressed names, cjs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - lib/wire.js — hardened readWireName() - reject truncated pointers (pos+1 past packet end) - reject pointer targets past packet end - reject truncated labels (declared length exceeds packet) - reject reserved label-type codes (top bits 01/10) - reject labels > 63 bytes - reject unterminated names - reject out-of-bounds offset - new wirePackDomainCompressed() for RFC 1035 §4.1.4 name compression - charstrs decoder preserves multi-string boundaries - lib/bind.js — fromBind() returns array for charstrs (TXT) when input has multiple quoted strings. - rr/rrsig.js — getAlgorithmOptions() extended with DNSSEC algorithms 6, 7, 8, 10, 13, 14, 15, 16. - rr/ds.js — setDigestType() now accepts SHA-384 (4) - rr/txt.js — getWireRdata() and fromTinydnsGeneric() preserve per-segment boundaries. - package.json — engines lowered to >=20 - new build:cjs script via Rollup. - test/wire.js, test/base.js, test/rr/{rrsig,ds,txt}.js — round-trip + negative tests for each fix. - rr: add missing setters --- .prettierignore | 1 + .release | 2 +- CHANGELOG.md | 14 + CONTRIBUTORS.md | 4 +- README.md | 57 +- dist/dns-rr.cjs | 7050 ++++++++++++++++++++++++++++++++++++++++ dist/dns-rr.min.js | 28 +- dist/dns-rr.min.js.map | 6 +- lib/bind.js | 12 +- lib/wire.js | 114 +- package.json | 13 +- rr/cert.js | 8 + rr/cname.js | 5 + rr/dname.js | 5 + rr/ds.js | 21 +- rr/mx.js | 4 + rr/rrsig.js | 40 +- rr/spf.js | 6 +- rr/srv.js | 17 + rr/sshfp.js | 15 + rr/txt.js | 46 +- test/base.js | 10 +- test/rr/ds.js | 37 +- test/rr/rrsig.js | 12 + test/rr/spf.js | 10 + test/rr/sshfp.js | 22 +- test/rr/txt.js | 71 + test/wire.js | 131 + 28 files changed, 7699 insertions(+), 62 deletions(-) create mode 100644 dist/dns-rr.cjs diff --git a/.prettierignore b/.prettierignore index 849ddff..abe1c55 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1 +1,2 @@ dist/ +.release/ diff --git a/.release b/.release index 0512cc8..af474bd 160000 --- a/.release +++ b/.release @@ -1 +1 @@ -Subproject commit 0512cc83f7b2b50ca01b78299b7b2a18ca4f3e66 +Subproject commit af474bd435cf7075a74643dbe6278ac68917f7c4 diff --git a/CHANGELOG.md b/CHANGELOG.md index c60b043..bc1665e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,19 @@ Notable changes to this project are documented in this file. #### Unreleased +### [1.8.0] - 2026-05-25 + +- lib/wire.js — hardened readWireName() + - new wirePackDomainCompressed() for RFC 1035 §4.1.4 name compression + - charstrs decoder preserves multi-string boundaries +- lib/bind.js — fromBind() returns array for charstrs (TXT) when input has multiple quoted strings. +- rr/rrsig.js — getAlgorithmOptions() extended with DNSSEC algorithms 6, 7, 8, 10, 13, 14, 15, 16. +- rr/ds.js — setDigestType() now accepts SHA-384 (4) +- rr/txt.js — getWireRdata() and fromTinydnsGeneric() preserve per-segment boundaries. +- package.json — engines lowered to >=20 + - new build:cjs script via Rollup. +- test/wire.js, test/base.js, test/rr/{rrsig,ds,txt}.js — round-trip + negative tests for each fix. + ### [1.7.0] - 2026-04-20 #### Fixes @@ -418,3 +431,4 @@ Notable changes to this project are documented in this file. [1.6.0]: https://github.com/NicTool/dns-resource-record/releases/tag/v1.6.0 [1.6.1]: https://github.com/NicTool/dns-resource-record/releases/tag/v1.6.1 [1.7.0]: https://github.com/NicTool/dns-resource-record/releases/tag/v1.7.0 +[1.8.0]: https://github.com/NicTool/dns-resource-record/releases/tag/v1.8.0 diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index e71819c..81beec1 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -2,8 +2,8 @@ This handcrafted artisanal software is brought to you by: -|
msimerson (67) |
Copilot (3) | -| :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | +|
msimerson (68) | +| :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | this file is generated by [.release](https://github.com/msimerson/.release). Contribute to this project to get your GitHub profile included here. diff --git a/README.md b/README.md index a8826dc..039c620 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,24 @@ This module supports all current DNS RRs in active use on the internet. npm install @nictool/dns-resource-record ``` +### ESM and CommonJS + +The package ships both ESM and CJS, selected automatically via the package `exports` map: + +```js +// ESM +import * as RR from '@nictool/dns-resource-record' +import RR, { A, TXT } from '@nictool/dns-resource-record' +``` + +```js +// CommonJS +const RR = require('@nictool/dns-resource-record') +const { A, TXT } = require('@nictool/dns-resource-record') +``` + +The default export (the base `RR` class) is reached as `require('@nictool/dns-resource-record').default` from CommonJS. + ### Validation Validate an A record: @@ -57,14 +75,14 @@ const validA = new RR.A({ }) console.log(validA.toBind()) -// example.com 3600 IN A 192.0.2.1 +// example.com. 3600 IN A 192.0.2.1 ``` Invalid records throw immediately: ```js try { - new RR.A({ owner: 'example.com.', address: 'not-an-ip' }) + new RR.A({ owner: 'example.com.', address: 'not-an-ip', ttl: 3600 }) } catch (err) { console.error(err.message) // Error: A address must be IPv4 } @@ -148,7 +166,7 @@ new RR.MX({ exchange: 'mail.example.com.', ttl: 3600, }).toBind() -// example.com 3600 IN MX 10 mail.example.com. +// example.com. 3600 IN MX 10 mail.example.com. ``` **When to use:** Generating zone files, displaying records for editing, exporting to BIND nameservers. @@ -182,7 +200,7 @@ const fromTiny = RR.CAA.fromTinydns( ':ns1.example.com:257:\\000\\005issue"http\\072\\057\\057letsencrypt.org":3600::\n', ) console.log(fromTiny.toBind()) -// ns1.example.com 3600 IN CAA 0 issue "http://letsencrypt.org" +// ns1.example.com. 3600 IN CAA 0 issue "http://letsencrypt.org" ``` **When to use:** DNS migrations, format conversions, tool interoperability. @@ -204,7 +222,7 @@ a.setAddress('192.0.2.2') a.setTtl(7200) console.log(a.toBind()) -// example.com 7200 IN A 192.0.2.2 +// example.com. 7200 IN A 192.0.2.2 ``` Setters include validation. Invalid values throw with helpful error messages. @@ -214,7 +232,7 @@ For a list of available setters, check `getFields('rdata')` for your record type ```js new RR.SSHFP(null).getFields('rdata') // ['algorithm', 'fptype', 'fingerprint'] -// So use: setSshfp(), setFptype(), setFingerprint() +// So use: setAlgorithm(), setFptype(), setFingerprint() ``` --- @@ -340,23 +358,38 @@ Domain owner names are: **Example:** ```js -new RR.A({ owner: 'EXAMPLE.COM', address: '192.0.2.1', ttl: 3600 }) -// Automatically normalized to: 'example.com.' +const r = new RR.A({ owner: 'EXAMPLE.COM.', address: '192.0.2.1', ttl: 3600 }) +r.get('owner') // 'example.com.' — uppercase normalized to lowercase ``` +Owner names are required to be fully qualified (trailing dot). Unqualified +names throw at construction; this library does not add the dot for you. + ### Relative vs Absolute Names Master zone file expansions (relative domain names) are handled by [dns-zone](https://github.com/NicTool/dns-zone). This library works only with fully qualified names. ### Export Options -The `toBind()` and `toMaraDNS()` methods accept an options object to customize output: +The `toBind()` method accepts a zone-options object (typically supplied by +[dns-zone](https://github.com/NicTool/dns-zone) when emitting full zone files) +to elide redundant per-record output: ```js -record.toBind({ suppressTtl: true, suppressClass: true, relativeName: true }) +record.toBind({ + origin: 'example.com.', // strips matching suffix from owner; emits '@' for an exact match + ttl: 3600, // the zone default; lets `hide.ttl` skip records whose TTL matches it + previousOwner: 'example.com.', // lets `hide.sameOwner` blank the owner column when it repeats + hide: { + ttl: true, // omit TTL when it equals the zone default + class: true, // omit class column (usually IN) + sameOwner: true, // omit owner when it matches `previousOwner` + origin: true, // shorten owners relative to `origin` + }, +}) ``` -See [dns-zone](https://github.com/NicTool/dns-zone) for full options documentation. +See [dns-zone](https://github.com/NicTool/dns-zone) for the full per-zone pipeline that supplies these options. ## Development @@ -368,7 +401,7 @@ No external dependencies. Runs on node.js and modern browsers. - `npm run watch` — Run tests in watch mode during development - `npm run lint` — Check code with ESLint - `npm run format` — Auto-format with Prettier and fix linting issues -- `npm run build` — Regenerate browser bundle and README +- `npm run build` — Regenerate the browser and CommonJS bundles in `dist/` - `npm run test:coverage` — Generate test coverage report **Architecture:** diff --git a/dist/dns-rr.cjs b/dist/dns-rr.cjs new file mode 100644 index 0000000..4e6041f --- /dev/null +++ b/dist/dns-rr.cjs @@ -0,0 +1,7050 @@ +'use strict'; + +Object.defineProperty(exports, '__esModule', { value: true }); + +const octalRe = new RegExp(/\\(?:[1-7][0-7]{0,2}|[0-7]{2,3})/, 'g'); +const textDecoder = new TextDecoder(); + +function parseFields(tinyline, rdataCount) { + const parts = tinyline.slice(1).split(':'); + const owner = parts[0]; + const rdata = parts.slice(1, 1 + rdataCount); + const [ttl, timestamp, location] = parts.slice(1 + rdataCount); + return { owner, rdata, ttl, timestamp, location: location?.trim() ?? '' } +} + +function parseGenericLine(tinyline) { + // Generic form: :owner:typeId:rdata:ttl:timestamp:location + const [owner, typeId, rdata, ttl, timestamp, location] = tinyline.slice(1).split(':'); + return { owner, typeId, rdata, ttl: parseInt(ttl, 10), timestamp, location: location?.trim() ?? '' } +} + +function octalRdataToBytes(rdata) { + return Uint8Array.from(octalToChar(rdata), (c) => c.charCodeAt(0)) +} + +function parseSvcbLikeRdata(rdata, recordType) { + if (rdata.length < 6) { + throw new Error(`${recordType}: RDATA too short: ${rdata}`) + } + + const binary = octalRdataToBytes(rdata); + const priority = (binary[0] << 8) | binary[1]; + + let pos = 2; + const labels = []; + while (true) { + const len = binary[pos]; + pos += 1; + if (len === 0) break + labels.push(textDecoder.decode(binary.subarray(pos, pos + len))); + pos += len; + } + + return { + priority, + targetName: `${labels.join('.')}.`, + params: textDecoder.decode(binary.subarray(pos)), + } +} + +function to(rrInstance) { + if (rrInstance.constructor.tinydnsType) { + const fields = rrInstance.getFields('rdata'); + const rdata = fields + .map((f) => { + if (rrInstance.isFqdnField(f)) return rrInstance.getTinyFQDN(f) + return rrInstance.get(f) + }) + .join(':'); + return `${rrInstance.constructor.tinydnsType}${rrInstance.getTinyFQDN('owner')}:${rdata}:${rrInstance.getTinydnsPostamble()}\n` + } + return rrInstance.getTinydnsGeneric(bytesToOctalString(rrInstance.getWireRdata())) +} + +function fromGeneric(rrInstance, { tinyline }) { + const fields = rrInstance.getFields('rdata'); + const { owner, rdata, ttl, timestamp, location } = parseFields(tinyline, fields.length); + + const result = { + owner: rrInstance.fullyQualify(owner), + type: rrInstance.constructor.typeName, + ttl: parseInt(ttl, 10), + timestamp: timestamp, + location: location, + }; + + for (let i = 0; i < fields.length; i++) { + const val = rdata[i]; + result[fields[i]] = rrInstance.isFqdnField(fields[i]) ? rrInstance.fullyQualify(val) : val; + } + + return new rrInstance.constructor(result) +} + +function escapeOctal(re, str) { + let escaped = ''; + str.split(/(.{1})/g).map((c) => { + escaped += re.test(c) ? charToOctal(c) : c; + }); + return escaped +} + +function octalToChar(str) { + // relace instances of \NNN with ASCII + return str.replace(octalRe, (o) => String.fromCharCode(parseInt(o.slice(1), 8))) +} + +function octalToHex(str) { + // relace instances of \NNN with Hex + return str.replace(octalRe, (o) => { + // parseInt(n, 8) -> from octal to decimal + // .toString(16) -> decimal to hex + return parseInt(o.slice(1), 8).toString(16).padStart(2, 0) + }) +} + +function octalToUInt8(str) { + return parseInt(str.slice(1, 4), 8) & 0xff +} + +function octalToUInt16(str) { + return (parseInt(str.slice(1, 4), 8) << 8) | parseInt(str.slice(5, 8), 8) +} + +function octalToUInt32(str) { + const b0 = parseInt(str.slice(1, 4), 8); + const b1 = parseInt(str.slice(5, 8), 8); + const b2 = parseInt(str.slice(9, 12), 8); + const b3 = parseInt(str.slice(13, 16), 8); + return ((b0 << 24) | (b1 << 16) | (b2 << 8) | b3) >>> 0 +} + +function packString(str) { + return str + .match(/(.{1,255})/g) + .map((s) => `${UInt8toOctal(s.length)}${s}`) + .join('') +} + +function unpackString(str) { + const asBuf = Uint8Array.from(octalToChar(str.toString()), (c) => c.charCodeAt(0)); + const dec = new TextDecoder(); + const res = []; + let pos = 0; + let len; + while ((len = asBuf[pos])) { + // encoded length byte + pos++; + res.push(dec.decode(asBuf.subarray(pos, pos + len))); + pos = +(pos + len); + if (pos >= asBuf.length) break + } + return res +} + +function packDomainName(fqdn) { + const labelRegEx = new RegExp(/[^A-Za-z0-9-.]/, 'g'); + + // RFC 1035, 3.3 Standard RRs + // The standard wire format for DNS names. (1 octet length + octets) + let packed = ''; + fqdn.split('.').forEach((label) => { + if (label === undefined || !label.length) return + + packed += UInt8toOctal(label.length); + + packed += escapeOctal(labelRegEx, label); + }); + packed += '\\000'; // terminates with a zero length label + return packed +} + +function unpackDomainName(escaped) { + let pos = 0; + let binaryLen = 0; + const labels = []; + + // consume the next logical "byte" (char or octal escape) + const getNextByte = () => { + if (pos >= escaped.length) return null + + let value; + if (escaped[pos] === '\\') { + value = parseInt(escaped.slice(pos + 1, pos + 4), 8); + pos += 4; + } else { + value = escaped.charCodeAt(pos++); + } + + binaryLen++; + return value + }; + + let lengthByte; + while ((lengthByte = getNextByte()) && lengthByte !== 0) { + let label = ''; + for (let i = 0; i < lengthByte; i++) { + const char = getNextByte(); + if (char === null) break + label += String.fromCharCode(char); + } + labels.push(label); + } + + return [`${labels.join('.')}.`, pos, binaryLen] +} + +function packHex(str) { + let r = ''; + for (let i = 0; i < str.length; i = i + 2) { + // nibble off 2 hex bytes, encode to octal + r += UInt8toOctal(parseInt(str.slice(i, i + 2), 16)); + } + return r +} + +function charToOctal(c) { + if (typeof c === 'number') return UInt8toOctal(c) + + return UInt8toOctal(c.charCodeAt(0)) +} + +function UInt8toOctal(n) { + if (n > 255) { + throw new Error( + `UInt8toOctal: value ${n} exceeds 255 — tinydns encoders require Latin-1/byte input (code points <= 0xFF)`, + ) + } + + return `\\${parseInt(n, 10).toString(8).padStart(3, 0)}` +} + +function UInt16toOctal(n) { + return UInt8toOctal((n >>> 8) & 0xff) + UInt8toOctal(n & 0xff) +} + +function UInt32toOctal(n) { + return ( + UInt8toOctal((n >>> 24) & 0xff) + + UInt8toOctal((n >>> 16) & 0xff) + + UInt8toOctal((n >>> 8) & 0xff) + + UInt8toOctal(n & 0xff) + ) +} + +function ipv4toOctal(ip) { + return UInt32toOctal(ip.split`.`.reduce((int, value) => int * 256 + +value)) +} + +function octalToIPv4(str) { + const asInt = octalToUInt32(str); + return [24, 16, 8, 0].map((n) => (asInt >> n) & 0xff).join('.') +} + +function expandIPv6(val, delimiter = ':') { + const colons = val.match(/:/g); + if (colons?.length < 7) { + val = val.replace(/::/, ':'.repeat(9 - colons.length)); + } + return val + .split(':') + .map((s) => s.padStart(4, '0')) + .join(delimiter) + .toLowerCase() +} + +function ipv6toOctal(ip) { + return packHex(expandIPv6(ip, '')) +} + +function octalToIPv6(str) { + return octalToHex(str) + .match(/(.{4})/g) + .join(':') +} + +function base64toOctal(str) { + const binary = atob(str); + let escaped = ''; + for (let i = 0; i < binary.length; i++) { + const b = binary.charCodeAt(i); + escaped += /[A-Za-z0-9\-.]/.test(binary[i]) ? binary[i] : UInt8toOctal(b); + } + return escaped +} + +function octalToBase64(str) { + return btoa(octalToChar(str)) +} + +function bytesToOctalString(bytes) { + let result = ''; + for (const b of bytes) result += UInt8toOctal(b); + return result +} + +function hexToBytes(hex) { + return Uint8Array.from({ length: hex.length / 2 }, (_, i) => parseInt(hex.slice(i * 2, i * 2 + 2), 16)) +} + +function bytesToHex(bytes) { + return [...bytes].map((b) => b.toString(16).padStart(2, '0')).join('') +} + +function bytesToBase64(bytes) { + return btoa([...bytes].map((b) => String.fromCharCode(b)).join('')) +} + +function base64ToBytes(b64) { + return Uint8Array.from(atob(b64), (c) => c.charCodeAt(0)) +} + +// DNS type name → numeric type ID mapping (subset covering known RR types) +const DNS_TYPE_IDS = { + A: 1, + NS: 2, + MD: 3, + MF: 4, + CNAME: 5, + SOA: 6, + MB: 7, + MG: 8, + MR: 9, + NULL: 10, + WKS: 11, + PTR: 12, + HINFO: 13, + MINFO: 14, + MX: 15, + TXT: 16, + RP: 17, + AFSDB: 18, + X25: 19, + ISDN: 20, + RT: 21, + NSAP: 22, + NSAP_PTR: 23, + SIG: 24, + KEY: 25, + PX: 26, + GPOS: 27, + AAAA: 28, + LOC: 29, + NXT: 30, + EID: 31, + NIMLOC: 32, + SRV: 33, + ATMA: 34, + NAPTR: 35, + KX: 36, + CERT: 37, + A6: 38, + DNAME: 39, + SINK: 40, + OPT: 41, + APL: 42, + DS: 43, + SSHFP: 44, + IPSECKEY: 45, + RRSIG: 46, + NSEC: 47, + DNSKEY: 48, + DHCID: 49, + NSEC3: 50, + NSEC3PARAM: 51, + TLSA: 52, + SMIMEA: 53, + HIP: 55, + NINFO: 56, + RKEY: 57, + TALINK: 58, + CDS: 59, + CDNSKEY: 60, + OPENPGPKEY: 61, + CSYNC: 62, + ZONEMD: 63, + SVCB: 64, + HTTPS: 65, + SPF: 99, + UINFO: 100, + UID: 101, + GID: 102, + UNSPEC: 103, + NID: 104, + L32: 105, + L64: 106, + LP: 107, + EUI48: 108, + EUI64: 109, + TKEY: 249, + TSIG: 250, + IXFR: 251, + AXFR: 252, + MAILB: 253, + MAILA: 254, + ANY: 255, + URI: 256, + CAA: 257, + AVC: 258, + DOA: 259, + AMTRELAY: 260, + TA: 32768, + DLV: 32769, +}; + +// ── Uncompressed domain name decoding ──────────────────────────────────────── + +/** + * Decode a length-prefixed (uncompressed) DNS name from a Uint8Array. + * Returns { fqdn: string, end: number } where end is the offset after the name. + */ +function wireUnpackDomain(bytes, offset = 0) { + const labels = []; + let pos = offset; + while (pos < bytes.length) { + const len = bytes[pos]; + if (len === 0) { + pos++; + break + } + labels.push(new TextDecoder().decode(bytes.subarray(pos + 1, pos + 1 + len))); + pos += 1 + len; + } + return { fqdn: labels.length ? labels.join('.') + '.' : '.', end: pos } +} + +/** + * Pack a fully qualified domain name into wire format (Uint8Array). + * Domain labels are prefixed with their length; the name ends with a zero byte. + */ +function wirePackDomain(fqdn) { + if (fqdn === '.') return new Uint8Array([0]) + const enc = new TextEncoder(); + const labels = fqdn + .split('.') + .filter((p) => p.length > 0) + .map((p) => { + const b = enc.encode(p); + if (b.length > 63) throw new Error(`DNS label exceeds 63 bytes: ${p}`) + return b + }); + + const buf = new Uint8Array(labels.reduce((n, b) => n + b.length + 1, 1)); + let offset = 0; + for (const b of labels) { + buf[offset++] = b.length; + buf.set(b, offset); + offset += b.length; + } + buf[offset] = 0; + return buf +} + +/** + * Get wire format rdata for an RR instance. + * Derived classes should override this with direct RFC 1035 wire encoding. + * Fallback uses toTinydns() as an intermediate (less efficient but works for all types). + */ +function getWireRdata(rrInstance) { + const line = rrInstance.toTinydns(); + if (!line.startsWith(':')) { + throw new Error( + `${rrInstance.get('type')}: getWireRdata() not implemented. Override in rr/${rrInstance.get('type').toLowerCase()}.js`, + ) + } + // line: :fqdn:typeId:rdata:ttl:ts:loc\n + // Extract octal-encoded rdata and decode + const rdata = line.split(':')[3]; + return rrInstance.octalToUint8Array(rdata ?? '') +} + +/** + * Serialize an RR instance to DNS wire format (RFC 1035). + * Combines owner name, type, class, TTL, and rdata. + */ +function toWire(rrInstance, RRClasses) { + const rdata = rrInstance.getWireRdata(); + const owner = wirePackDomain(rrInstance.get('owner')); + const result = new Uint8Array(owner.length + 10 + rdata.length); + result.set(owner, 0); + const meta = new DataView(result.buffer, owner.length, 10); + meta.setUint16(0, rrInstance.getTypeId()); + meta.setUint16(2, RRClasses[rrInstance.get('class')] ?? 1); + meta.setUint32(4, rrInstance.get('ttl')); + meta.setUint16(8, rdata.length); + result.set(rdata, owner.length + 10); + return result +} + +/** + * Deserialize wire format bytes into an RR instance. + * Static method wrapper for RR.fromWire(). + */ +function fromWireBytes(RRConstructor, wireBytes, wireUnpackFn) { + const instance = new RRConstructor(null); + const bytes = wireBytes instanceof Uint8Array ? wireBytes : new Uint8Array(wireBytes); + const { fqdn: owner, end } = wireUnpackFn(bytes, 0); + const view = new DataView(bytes.buffer, bytes.byteOffset); + const classNum = view.getUint16(end + 2); + const RRClasses = { IN: 1, CS: 2, CH: 3, HS: 4, NONE: 254, ANY: 255 }; + const cls = Object.keys(RRClasses).find((k) => RRClasses[k] === classNum) ?? 'IN'; + const ttl = view.getUint32(end + 4); + const rdlen = view.getUint16(end + 8); + const rdata = bytes.slice(end + 10, end + 10 + rdlen); + return instance.fromWire({ owner, cls, ttl, rdata }) +} + +/** + * Generic fromWire decoder driven by rdataFields type annotations. + * Supports u8, u16, u32, fqdn, hex, base64, str, qstr, charstr, qcharstr, charstrs, svcparams, ipv4, ipv6. + * See rr/TEMPLATE.js for descriptions and example type usage. + * Last typed field consumes all remaining bytes. + */ +function fromWireGeneric(rrInstance, { owner, cls, ttl, rdata }) { + const result = { owner, ttl, class: cls, type: rrInstance.constructor.typeName }; + const rdataFields = rrInstance.constructor.rdataFields ?? []; + const dv = new DataView(rdata.buffer, rdata.byteOffset); + let pos = 0; + + for (let i = 0; i < rdataFields.length; i++) { + const entry = rdataFields[i]; + const fieldName = Array.isArray(entry) ? entry[0] : entry; + const fieldType = Array.isArray(entry) ? entry[1] : null; + + switch (fieldType) { + case 'u8': + result[fieldName] = rdata[pos++]; + break + case 'u16': + result[fieldName] = dv.getUint16(pos); + pos += 2; + break + case 'certtype': { + const certTypeNum = dv.getUint16(pos); + const reverse = rrInstance.constructor.CERT_TYPES_REVERSE; + result[fieldName] = reverse?.[certTypeNum] ?? certTypeNum; + pos += 2; + break + } + case 'u32': + result[fieldName] = dv.getUint32(pos); + pos += 4; + break + case 'fqdn': { + const { fqdn, end } = wireUnpackDomain(rdata, pos); + result[fieldName] = fqdn; + pos = end; + break + } + case 'hex': + result[fieldName] = bytesToHex(rdata.subarray(pos)).toUpperCase(); + pos = rdata.length; + break + case 'base64': + result[fieldName] = bytesToBase64(rdata.subarray(pos)); + pos = rdata.length; + break + case 'str': + result[fieldName] = new TextDecoder().decode(rdata.subarray(pos)); + pos = rdata.length; + break + case 'qstr': + result[fieldName] = new TextDecoder().decode(rdata.subarray(pos)); + pos = rdata.length; + break + case 'charstr': { + const strLen = rdata[pos++]; + result[fieldName] = new TextDecoder().decode(rdata.subarray(pos, pos + strLen)); + pos += strLen; + break + } + case 'qcharstr': { + const strLen = rdata[pos++]; + result[fieldName] = new TextDecoder().decode(rdata.subarray(pos, pos + strLen)); + pos += strLen; + break + } + case 'charstrs': { + // RFC 1035 §3.3.14: each on the wire is len-prefixed. + // Preserve multi-string boundaries by returning an array when >1. + const parts = []; + while (pos < rdata.length) { + const strLen = rdata[pos++]; + if (pos + strLen > rdata.length) { + throw new Error('fromWireGeneric: truncated character-string in rdata') + } + parts.push(new TextDecoder().decode(rdata.subarray(pos, pos + strLen))); + pos += strLen; + } + result[fieldName] = parts.length > 1 ? parts : (parts[0] ?? ''); + break + } + case 'svcparams': + result[fieldName] = svcParamsFromWire(rdata.subarray(pos)); + pos = rdata.length; + break + case 'ipv4': + result[fieldName] = [...rdata.subarray(pos, pos + 4)].join('.'); + pos += 4; + break + case 'ipv6': { + const parts = []; + for (let j = 0; j < 16; j += 2) { + parts.push( + dv + .getUint16(pos + j) + .toString(16) + .padStart(4, '0'), + ); + } + result[fieldName] = parts.join(':'); + pos += 16; + break + } + default: + result[fieldName] = rdata[pos++]; + break + } + } + + return new rrInstance.constructor(result) +} + +// ── SVCB/HTTPS parameter encoding (RFC 9460) ───────────────────────────────── + +const SVCPARAM_KEYS = { + mandatory: 0, + alpn: 1, + 'no-default-alpn': 2, + port: 3, + ipv4hint: 4, + ech: 5, + ipv6hint: 6, +}; + +/** + * Encode SVCB/HTTPS params string (e.g. 'alpn="h2,h3" port="8443"') to wire bytes. + */ +function svcParamsToWire(paramsStr) { + if (!paramsStr || !paramsStr.trim()) return new Uint8Array(0) + + const parts = []; + // Match: key, key=unquoted, or key="quoted" tokens + const re = /([^\s=]+)(?:=(?:"([^"]*)"|(\S*)))?(?=\s|$)/g; + let m; + while ((m = re.exec(paramsStr.trim())) !== null) { + const key = m[1].toLowerCase(); + const val = m[2] ?? m[3] ?? ''; + const keyId = SVCPARAM_KEYS[key]; + if (keyId === undefined) continue + + let valBytes; + if (keyId === 1) { + // alpn: comma-separated list, each entry length-prefixed + const enc = new TextEncoder(); + const entries = val.split(',').map((e) => enc.encode(e.trim())); + const total = entries.reduce((s, e) => s + 1 + e.length, 0); + valBytes = new Uint8Array(total); + let p = 0; + for (const e of entries) { + valBytes[p++] = e.length; + valBytes.set(e, p); + p += e.length; + } + } else if (keyId === 2) { + // no-default-alpn: no value + valBytes = new Uint8Array(0); + } else if (keyId === 3) { + // port: uint16 + valBytes = new Uint8Array(2); + new DataView(valBytes.buffer).setUint16(0, parseInt(val, 10)); + } else if (keyId === 4) { + // ipv4hint: one or more IPv4 addresses + const addrs = val.split(',').map((a) => a.trim().split('.').map(Number)); + valBytes = new Uint8Array(addrs.length * 4); + addrs.forEach((addr, i) => addr.forEach((b, j) => (valBytes[i * 4 + j] = b))); + } else if (keyId === 5) { + // ech: base64-encoded ECH config + valBytes = base64ToBytes(val); + } else if (keyId === 6) { + // ipv6hint: one or more IPv6 addresses (expand compressed form before encoding) + const addrs = val.split(',').map((a) => hexToBytes(expandIPv6(a.trim(), ''))); + valBytes = new Uint8Array(addrs.length * 16); + addrs.forEach((addr, i) => valBytes.set(addr, i * 16)); + } else { + valBytes = new TextEncoder().encode(val); + } + + const param = new Uint8Array(4 + valBytes.length); + new DataView(param.buffer).setUint16(0, keyId); + new DataView(param.buffer).setUint16(2, valBytes.length); + param.set(valBytes, 4); + parts.push(param); + } + + // Sort by key ID (SvcParams MUST be in ascending order per RFC 9460) + parts.sort((a, b) => new DataView(a.buffer).getUint16(0) - new DataView(b.buffer).getUint16(0)); + + const total = parts.reduce((s, p) => s + p.length, 0); + const result = new Uint8Array(total); + let pos = 0; + for (const p of parts) { + result.set(p, pos); + pos += p.length; + } + return result +} + +const SVCPARAM_KEY_NAMES = { + 0: 'mandatory', + 1: 'alpn', + 2: 'no-default-alpn', + 3: 'port', + 4: 'ipv4hint', + 5: 'ech', + 6: 'ipv6hint', +}; + +/** + * Decode SVCB/HTTPS wire params bytes back to a human-readable params string. + */ +function svcParamsFromWire(bytes) { + if (!bytes || bytes.length === 0) return '' + const parts = []; + let pos = 0; + while (pos + 4 <= bytes.length) { + const dv = new DataView(bytes.buffer, bytes.byteOffset + pos); + const keyId = dv.getUint16(0); + const valLen = dv.getUint16(2); + const val = bytes.subarray(pos + 4, pos + 4 + valLen); + pos += 4 + valLen; + + const keyName = SVCPARAM_KEY_NAMES[keyId] ?? `key${keyId}`; + if (keyId === 1) { + // alpn: comma-separated length-prefixed entries + const entries = []; + let p = 0; + while (p < val.length) { + const len = val[p++]; + entries.push(new TextDecoder().decode(val.subarray(p, p + len))); + p += len; + } + parts.push(`alpn="${entries.join(',')}"`); + } else if (keyId === 2) { + parts.push('no-default-alpn'); + } else if (keyId === 3) { + parts.push(`port=${new DataView(val.buffer, val.byteOffset).getUint16(0)}`); + } else if (keyId === 4) { + const addrs = []; + for (let i = 0; i < val.length; i += 4) addrs.push([...val.subarray(i, i + 4)].join('.')); + parts.push(`ipv4hint=${addrs.join(',')}`); + } else if (keyId === 5) { + parts.push(`ech=${btoa([...val].map((b) => String.fromCharCode(b)).join(''))}`); + } else if (keyId === 6) { + const addrs = []; + for (let i = 0; i < val.length; i += 16) { + const dv16 = new DataView(val.buffer, val.byteOffset + i); + const groups = []; + for (let j = 0; j < 16; j += 2) groups.push(dv16.getUint16(j).toString(16).padStart(4, '0')); + addrs.push(groups.join(':')); + } + parts.push(`ipv6hint=${addrs.join(',')}`); + } else { + parts.push(`${keyName}=${[...val].map((b) => b.toString(16).padStart(2, '0')).join('')}`); + } + } + return parts.join(' ') +} + +function parseBindLine(line, RRClasses) { + const res = { + class: 'IN', + type: '', + rdata: [], + }; + + // 1. Strip comments (not inside quotes) + let cleanLine = ''; + let inQuote = false; + for (let i = 0; i < line.length; i++) { + const c = line[i]; + if (c === '"') inQuote = !inQuote; + if (c === ';' && !inQuote) break + cleanLine += c; + } + cleanLine = cleanLine.trim(); + if (!cleanLine) return null + + // 2. Tokenize, respecting quoted strings + const tokens = cleanLine.match(/(".*?"|\S+)/g) || []; + if (tokens.length < 1) return null + + // 3. Owner handling + if (!/^\s/.test(line)) { + res.owner = tokens.shift(); + } + + // 4. Extract TTL, Class, and Type + while (tokens.length > 0) { + const token = tokens[0].toUpperCase(); + + if (RRClasses[token]) { + res.class = tokens.shift().toUpperCase(); + continue + } + + if (/^\d+$/.test(token)) { + res.ttl = parseInt(tokens.shift(), 10); + continue + } + + // If it's not a Class or TTL, it must be the RR Type (A, MX, etc.) + res.type = tokens.shift().toUpperCase(); + break + } + + // 5. Remaining tokens are RDATA + res.rdata = tokens; + + return res +} + +function fromBind(rrInstance, opts) { + const { owner, ttl, cls, rdata } = opts; + const result = { + owner, + ttl, + class: cls, + type: rrInstance.constructor.typeName, + }; + + const fields = rrInstance.getFields('rdata'); + const rdataDefs = rrInstance.constructor.rdataFields ?? []; + for (let i = 0; i < fields.length; i++) { + const isLastField = i === fields.length - 1; + if (isLastField && rrInstance.isQuotedField(fields[i])) { + // Collect all remaining tokens for TXT/etc + const tokens = rdata.slice(i).map((s) => s.replace(/^"|"$/g, '')); + // For `charstrs` (TXT), preserve multi-string boundaries (RFC 1035 §3.3.14). + // For `qstr`/`qcharstr` (single character-string), join into one string. + const def = rdataDefs[i]; + const fieldType = Array.isArray(def) ? def[1] : null; + result[fields[i]] = fieldType === 'charstrs' && tokens.length > 1 ? tokens : tokens.join(''); + break + } + + let val = rdata[i]; + if (rrInstance.isQuotedField(fields[i])) { + val = val?.replace(/^"|"$/g, ''); + } else if (/^\d+$/.test(val)) { + val = parseInt(val, 10); + } + result[fields[i]] = val; + } + + return new rrInstance.constructor(result) +} + +function toBind(rrInstance, zone_opts) { + const fields = rrInstance.getFields('rdata'); + const rdata = fields + .map((f) => (rrInstance.isFqdnField(f) ? rrInstance.getFQDN(f, zone_opts) : rrInstance.getQuoted(f))) + .join('\t'); + return `${rrInstance.getPrefix(zone_opts)}\t${rdata}\n` +} + +const customInspect = Symbol.for('nodejs.util.inspect.custom'); + +class RR { + static CLASSES = { IN: 1, CS: 2, CH: 3, HS: 4, NONE: 254, ANY: 255 } + static typeId + static RFCs = [] + static tags = [] + + constructor(opts) { + if (opts === null) return + + if (opts?.default) this.default = opts.default; + + // tinydns specific + this.setLocation(opts?.location); + this.setTimestamp(opts?.timestamp); + + this.setOwner(opts?.owner); + this.setType(opts?.type); + this.setTtl(opts?.ttl); + this.setClass(opts?.class); + + for (const entry of this.constructor.rdataFields ?? []) { + const f = RR.fieldName(entry); + const fieldType = Array.isArray(entry) ? entry[1] : null; + const fnName = `set${this.ucFirst(f)}`; + if (typeof this[fnName] === 'function') { + this[fnName](opts?.[f]); + } else if (fieldType) { + this.setTypedValue(fieldType, f, opts?.[f]); + } else { + this.set(f, opts?.[f]); + } + } + + if (opts?.comment) this.set('comment', opts.comment); + } + + static fromBind(line, opts = {}) { + const instance = new this(null); + if (opts.default !== undefined) instance.default = opts.default; + const parsed = this.parseBindLine(line); + if (!parsed) return null + return instance.fromBind({ ...opts, ...parsed, bindline: line }) + } + + fromBind(opts) { + return fromBind(this, opts) + } + + static parseBindLine(line) { + return parseBindLine(line, RR.CLASSES) + } + + static fromTinydns(line, opts = {}) { + const instance = new this(null); + if (opts.default !== undefined) instance.default = opts.default; + return instance.fromTinydns({ ...opts, tinyline: line }) + } + + fromTinydns(opts) { + return fromGeneric(this, opts) + } + + static fromWire(wireBytes) { + return fromWireBytes(this, wireBytes, wireUnpackDomain) + } + + fromWire(opts) { + return fromWireGeneric(this, opts) + } + + static #reserved = ['__proto__', 'constructor', 'prototype'] + + get(key) { + if (RR.#reserved.includes(key)) throw new Error(`Invalid field name: ${key}`) + return this[key] + } + + set(key, value) { + if (RR.#reserved.includes(key)) throw new Error(`Invalid field name: ${key}`) + this[key] = value; + return this + } + + toJSON() { + const fields = [...this.getFields(), 'location', 'timestamp', 'comment']; + const obj = {}; + for (const f of fields) { + const v = this.get(f); + if (v !== undefined) obj[f] = v; + } + return obj + } + + [customInspect](depth, options, nextInspect) { + // Returns a formatted string that looks like: A { ... } + return `${this.type} ${nextInspect(this.toJSON(), options)}` + } + + ucFirst(str) { + if (!str) return str + return str + .split(/\s/) + .map((w) => w.charAt(0).toUpperCase() + w.slice(1)) + .join('') + } + + setClass(c) { + if ([undefined, null, ''].includes(c)) { + this.set('class', 'IN'); + return + } + if (RR.CLASSES[c.toUpperCase()]) { + this.set('class', c.toUpperCase()); + return + } + this.throwHelp(`invalid class ${c}`); + } + + setLocation(l) { + switch (l) { + case undefined: + return + default: + this.set('location', l); + } + } + + setTimestamp(l) { + switch (l) { + case undefined: + return + default: + this.set('timestamp', l); + } + } + + setOwner(n) { + if (n === undefined) this.throwHelp(`owner is required`); + + if (n.length < 1 || n.length > 255) + this.throwHelp('Domain names must have 1-255 octets (characters): RFC 2181'); + + this.isFullyQualified(this.constructor.typeName ?? this.constructor.name, 'owner', n); + this.hasValidLabels(n); + + // wildcard records: RFC 1034, 4592 + if (/\*/.test(n)) { + if (!/^\*\./.test(n) && !/\.\*\./.test(n)) + this.throwHelp('only *.something or * (by itself) is a valid wildcard'); + } + + this.set('owner', n.toLowerCase()); + } + + setTtl(t) { + t = t ?? this.default?.ttl; + if (t === undefined) { + if (['SOA', 'SSHFP', 'RRSIG'].includes(this.get('type'))) return + this.throwHelp('TTL is required, no default available'); + } + + if (typeof t !== 'number') this.throwHelp(`TTL must be numeric (${typeof t})`); + + // RFC 1035, 2181 + this.is32bitInt(this.get('type'), 'TTL', t); + + this.set('ttl', t); + } + + setType(t) { + if ([undefined, ''].includes(t)) t = this.constructor.typeName; + + if (t === undefined) this.throwHelp(`type is required`); + + if (t.toUpperCase() !== this.constructor.typeName) + this.throwHelp(`type ${t} doesn't match ${this.constructor.typeName}`); + + this.set('type', t.toUpperCase()); + } + + throwHelp(e) { + if (!this.constructor.typeName) throw new Error(e) + + const typeName = this.constructor.typeName; + const example = this.getCanonical + ? `Example ${typeName}:\n${JSON.stringify(this.getCanonical(), null, '\t')}\n\n` + : `${typeName} records have the fields: ${this.getFields().join(', ')}\n\n`; + + throw new Error(`${e}\n\n${example}${this.citeRFC()}\n`) + } + + citeRFC() { + return `see RFC${this.getRFCs().length > 1 ? 's' : ''} ${this.getRFCs()}` + } + + fullyQualify(hostname, origin) { + if (!hostname) return hostname + if (hostname === '@' && origin) hostname = origin; + if (hostname.endsWith('.')) return hostname.toLowerCase() + if (origin) return `${hostname}.${origin}`.toLowerCase() + return `${hostname}.` + } + + getPrefix(zone_opts = {}) { + const classVal = zone_opts.hide?.class ? '' : this.get('class'); + + let rrTTL = this.get('ttl'); + if (zone_opts.hide?.ttl && rrTTL === zone_opts.ttl) rrTTL = ''; + + let owner = this.get('owner'); + if (zone_opts.hide?.sameOwner && zone_opts.previousOwner === owner) { + owner = ''; + } else { + owner = this.getFQDN('owner', zone_opts); + } + + return `${owner}\t${rrTTL}\t${classVal}\t${this.get('type')}` + } + + getEmpty(prop) { + return this.get(prop) ?? '' + } + + getComment(prop) { + const c = this.get('comment'); + if (!c || !c[prop]) return '' + return c[prop] + } + + getQuoted(prop) { + // if prop is not a quoted string field, return bare + if (!this.isQuotedField(prop)) return this.get(prop) + + // if it's already quoted, return as-is + if (/['"]/.test(this.get(prop)[0])) return this.get(prop) + + return `"${this.get(prop)}"` // add double quotes + } + + static fieldName(entry) { + return Array.isArray(entry) ? entry[0] : entry + } + + static fieldType(entry) { + return Array.isArray(entry) ? entry[1] : null + } + + getRdataFields() { + return (this.constructor.rdataFields ?? []).map((e) => RR.fieldName(e)) + } + + getTags() { + return this.constructor.tags ?? [] + } + + getRFCs() { + return this.constructor.RFCs ?? [] + } + + getTypeId() { + const typeId = this.constructor.typeId; + if (typeId === undefined) this.throwHelp(`${this.constructor.typeName}: missing static typeId`); + return typeId + } + + static getTypeId() { + return this.typeId + } + + getFields(arg) { + const commonFields = ['owner', 'ttl', 'class', 'type']; + Object.freeze(commonFields); + + const rdataFields = this.getRdataFields(); + + switch (arg) { + case 'common': + return commonFields + case 'rdata': + return rdataFields + default: + return commonFields.concat(rdataFields) + } + } + + getFQDN(field, zone_opts = {}) { + let fqdn = this.get(field); + if (!fqdn) this.throwHelp(`empty value for field ${field}`); + if (!fqdn.endsWith('.')) fqdn += '.'; + + if (zone_opts.hide?.origin && zone_opts.origin) { + if (fqdn === zone_opts.origin) return '@' + if (fqdn.endsWith(zone_opts.origin)) return fqdn.slice(0, fqdn.length - zone_opts.origin.length - 1) + } + + return fqdn + } + + getTinyFQDN(field) { + const val = this.get(field); + if (val === '') return val // empty + if (val === '.') return val // null MX + + // strip off trailing ., tinydns doesn't require it for FQDN + if (val.endsWith('.')) return val.slice(0, -1) + + return val + } + + getTinydnsGeneric(rdata) { + return `:${this.getTinyFQDN('owner')}:${this.getTypeId()}:${rdata}:${this.getTinydnsPostamble()}\n` + } + + getTinydnsPostamble() { + return ['ttl', 'timestamp', 'location'].map((f) => this.getEmpty(f)).join(':') + } + + hasValidLabels(hostname) { + // RFC 952 defined valid hostnames + // RFC 1035 limited domain label chars to letters, digits, and hyphen + // RFC 1123 allowed hostnames to start with a digit + // RFC 2181 'any binary string can be used as the label' + const fq = hostname.endsWith('.') ? hostname.slice(0, -1) : hostname; + for (const label of fq.split('.')) { + if (label.length < 1 || label.length > 63) + this.throwHelp('Labels must have 1-63 octets (characters), RFC 2181'); + } + } + + is8bitInt(type, field, value) { + if (Number.isInteger(value) && value >= 0 && value <= 255) return true + + this.throwHelp(`${type} ${field} must be a 8-bit integer (in the range 0-255)`); + } + + is16bitInt(type, field, value) { + if (Number.isInteger(value) && value >= 0 && value <= 65535) return true + + this.throwHelp(`${type} ${field} must be a 16-bit integer (in the range 0-65535)`); + } + + is32bitInt(type, field, value) { + if (Number.isInteger(value) && value >= 0 && value <= 4294967295) return true + + this.throwHelp(`${type} ${field} must be a 32-bit integer (in the range 0-4294967295)`); + } + + isBase64(type, field, value) { + if ( + typeof value === 'string' && + value.length > 0 && + value.length % 4 === 0 && + /^[A-Za-z0-9+/]*={0,2}$/.test(value) + ) + return true + + this.throwHelp(`${type} ${field} must be a valid base64 string`); + } + + isQuoted(val) { + return /^["']/.test(val) && /["']$/.test(val) + } + + setFqdnValue(typeName, fieldName, val) { + if (!val) this.throwHelp(`${typeName}: ${fieldName} is required`); + if (this.isIPv4(val) || this.isIPv6(val)) + this.throwHelp(`${typeName}: ${fieldName} must be a domain name`); + this.isFullyQualified(typeName, fieldName, val); + this.isValidHostname(typeName, fieldName, val); + this.set(fieldName, val.toLowerCase()); + } + + setTypedValue(type, fieldName, val) { + const typeName = this.constructor.typeName; + switch (type) { + case 'u8': + this.is8bitInt(typeName, fieldName, val); + this.set(fieldName, parseInt(val, 10)); + break + case 'u16': + this.is16bitInt(typeName, fieldName, val); + this.set(fieldName, parseInt(val, 10)); + break + case 'certtype': { + if (val === undefined || val === null || val === '') + this.throwHelp(`${typeName}: ${fieldName} is required`); + if (typeof val === 'string' && !/^[0-9]+$/.test(val)) { + const certTypes = this.constructor.CERT_TYPES; + if (!certTypes || !Object.hasOwn(certTypes, val)) { + this.throwHelp(`${typeName}: unknown cert type mnemonic: ${val}`); + } + this.set(fieldName, val); + break + } + this.is16bitInt(typeName, fieldName, val); + this.set(fieldName, parseInt(val, 10)); + break + } + case 'u32': + this.is32bitInt(typeName, fieldName, val); + this.set(fieldName, parseInt(val, 10)); + break + case 'fqdn': + this.setFqdnValue(typeName, fieldName, val); + break + case 'base64': + this.isBase64(typeName, fieldName, val); + this.set(fieldName, val); + break + case 'hex': + if (!/^[0-9a-fA-F]*$/.test(val)) this.throwHelp(`${typeName}: ${fieldName} must be hexadecimal`); + this.set(fieldName, val); + break + case 'str': + if (!val) this.throwHelp(`${typeName}: ${fieldName} is required`); + this.set(fieldName, val); + break + case 'qstr': + if (val === undefined || val === null) this.throwHelp(`${typeName}: ${fieldName} is required`); + this.set(fieldName, val); + break + case 'charstr': { + if (val === undefined || val === null) this.throwHelp(`${typeName}: ${fieldName} is required`); + const value = String(val); + const byteLen = new TextEncoder().encode(value).length; + if (byteLen > 255) this.throwHelp(`${typeName}: ${fieldName} must be <=255 bytes`); + this.set(fieldName, value); + break + } + case 'qcharstr': { + if (val === undefined || val === null) this.throwHelp(`${typeName}: ${fieldName} is required`); + const value = String(val); + const byteLen = new TextEncoder().encode(value).length; + if (byteLen > 255) this.throwHelp(`${typeName}: ${fieldName} must be <=255 bytes`); + this.set(fieldName, value); + break + } + case 'charstrs': + if (val === undefined || val === null) this.throwHelp(`${typeName}: ${fieldName} is required`); + this.set(fieldName, val); + break + case 'svcparams': + if (val === undefined || val === null) this.throwHelp(`${typeName}: ${fieldName} is required`); + this.set(fieldName, val); + break + case 'ipv4': + if (!this.isIPv4(val)) this.throwHelp(`${typeName}: ${fieldName} must be a valid IPv4 address`); + this.set(fieldName, val); + break + case 'ipv6': + if (!this.isIPv6(val)) this.throwHelp(`${typeName}: ${fieldName} must be a valid IPv6 address`); + this.set(fieldName, this.expandIPv6(val.toLowerCase())); // lower case: RFC 5952 + break + } + } + + isFullyQualified(type, field, hostname) { + if (hostname.endsWith('.')) return true + + this.throwHelp(`${type}: ${field} must be fully qualified`); + } + + isValidHostname(type, field, hostname) { + const allowed = new RegExp(/[^a-zA-Z0-9\-._/\\]/); + if (!allowed.test(hostname)) return true + + const matches = allowed.exec(hostname); + this.throwHelp(`${type}, ${field} has invalid hostname character (${matches[0]})`); + } + + isIPv4(string) { + // https://stackoverflow.com/questions/5284147/validating-ipv4-addresses-with-regexp + return /^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}$/.test(string) + } + + isIPv6(string) { + return /^(?:(?:[a-fA-F\d]{1,4}:){7}(?:[a-fA-F\d]{1,4}|:)|(?:[a-fA-F\d]{1,4}:){6}(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|:[a-fA-F\d]{1,4}|:)|(?:[a-fA-F\d]{1,4}:){5}(?::(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,2}|:)|(?:[a-fA-F\d]{1,4}:){4}(?:(?::[a-fA-F\d]{1,4}){0,1}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,3}|:)|(?:[a-fA-F\d]{1,4}:){3}(?:(?::[a-fA-F\d]{1,4}){0,2}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,4}|:)|(?:[a-fA-F\d]{1,4}:){2}(?:(?::[a-fA-F\d]{1,4}){0,3}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,5}|:)|(?:[a-fA-F\d]{1,4}:){1}(?:(?::[a-fA-F\d]{1,4}){0,4}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,6}|:)|(?::(?:(?::[a-fA-F\d]{1,4}){0,5}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,7}|:)))(?:%[0-9a-zA-Z]{1,})?$/gm.test( + string, + ) + } + + expandIPv6(val, delimiter) { + return expandIPv6(val, delimiter) + } + + compressIPv6(val) { + // * RFC 5952 + // * 4.1. Leading zeros MUST be suppressed...A single 16-bit 0000 field MUST be represented as 0. + // * 4.2.1 The use of the symbol "::" MUST be used to its maximum capability. + // * 4.2.2 The symbol "::" MUST NOT be used to shorten just one 16-bit 0 field. + // * 4.2.3 When choosing placement of a "::", the longest run...MUST be shortened + // * 4.3 The characters a-f in an IPv6 address MUST be represented in lowercase. + + // 4.3 Lowercase and 4.1 remove leading zeros per segment + const segments = val + .toLowerCase() + .split(':') + .map((s) => s.replace(/^0+/, '') || '0'); + + let bestStart = -1; + let bestLen = 0; + let curStart = -1; + let curLen = 0; + + // 4.2.1 & 4.2.3 Find the longest consecutive run of '0' + for (let i = 0; i < segments.length; i++) { + if (segments[i] === '0') { + if (curStart === -1) curStart = i; + curLen++; + if (curLen > bestLen) { + bestLen = curLen; + bestStart = curStart; + } + } else { + curStart = -1; + curLen = 0; + } + } + + // 4.2.2 Don't shorten a single 16-bit 0 field + if (bestLen < 2) { + return segments.join(':') + } + + const head = segments.slice(0, bestStart).join(':'); + const tail = segments.slice(bestStart + bestLen).join(':'); + + return `${head}::${tail}` + } + + octalToUint8Array(octalStr) { + const str = octalToChar(octalStr); + return Uint8Array.from(str, (c) => c.charCodeAt(0)) + } + + wireUnpackDomain(bytes, offset = 0) { + return wireUnpackDomain(bytes, offset) + } + + wirePackDomain(fqdn) { + return wirePackDomain(fqdn) + } + + getWireRdata() { + return getWireRdata(this) + } + + toWire() { + return toWire(this, RR.CLASSES) + } + + toBind(zone_opts) { + return toBind(this, zone_opts) + } + + parseTinydnsLine(tinyline) { + const parsed = parseGenericLine(tinyline); + return { ...parsed, owner: this.fullyQualify(parsed.owner) } + } + + toTinydns() { + return to(this) + } + + isFqdnField(field) { + return ( + (this.constructor.rdataFields ?? []).some( + (entry) => RR.fieldName(entry) === field && RR.fieldType(entry) === 'fqdn', + ) || false + ) + } + + isQuotedField(field) { + const quotedTypes = new Set(['qstr', 'qcharstr', 'charstrs']); + return ( + (this.constructor.rdataFields ?? []).some( + (entry) => RR.fieldName(entry) === field && quotedTypes.has(RR.fieldType(entry)), + ) || false + ) + } + + toMaraDNS() { + const type = this.get('type'); + const supportedTypes = 'A PTR MX AAAA SRV NAPTR NS SOA TXT SPF RAW FQDN4 FQDN6 CNAME HINFO WKS LOC'.split( + /\s+/g, + ); + if (!supportedTypes.includes(type)) return this.toMaraGeneric() + return `${this.get('owner')}\t+${this.get('ttl')}\t${type}\t${this.getFields('rdata') + .map((f) => this.getQuoted(f)) + .join('\t')} ~\n` + } + + toMaraGeneric() { + // this.throwHelp(`\nMaraDNS does not support ${type} records yet and this package does not support MaraDNS generic records. Yet.\n`) + return `${this.get('owner')}\t+${this.get('ttl')}\tRAW ${this.getTypeId()}\t'${this.getFields('rdata') + .map((f) => this.getQuoted(f)) + .join(' ')}' ~\n` + } +} + +class A extends RR { + static typeName = 'A' + static typeId = 1 + static RFCs = [1035] + static tinydnsType = '+' + static rdataFields = [['address', 'ipv4']] + static tags = ['common'] + + constructor(opts) { + super(opts); + } + + /****** Resource record specific setters *******/ + setAddress(val) { + if (!val) this.throwHelp('A: address is required'); + if (!this.isIPv4(val)) this.throwHelp('A address must be IPv4'); + this.set('address', val); + } + + getDescription() { + return 'Address' + } + + getCanonical() { + return { + owner: 'host.example.com.', + class: 'IN', + ttl: 3600, + type: 'A', + address: '192.0.2.127', + } + } + + /****** EXPORTERS *******/ + getWireRdata() { + return new Uint8Array(this.get('address').split('.').map(Number)) + } +} + +class AAAA extends RR { + static typeName = 'AAAA' + static typeId = 28 + static RFCs = [3596, 5952] + static rdataFields = [['address', 'ipv6']] + static tags = ['common'] + + constructor(opts) { + super(opts); + } + + /****** Resource record specific setters *******/ + setAddress(val) { + if (!val) this.throwHelp('AAAA: address is required'); + if (!this.isIPv6(val)) this.throwHelp(`AAAA: address must be IPv6 (${val})`); + + this.set('address', this.expandIPv6(val.toLowerCase())); // lower case: RFC 5952 + } + + getCompressed(val) { + return this.compressIPv6(val ?? this.get('address')) + } + + getDescription() { + return 'Address IPv6' + } + + getCanonical() { + return { + owner: 'host.example.com.', + address: '2001:0db8:0020:000a:0000:0000:0000:0004', + class: 'IN', + ttl: 3600, + type: 'AAAA', + } + } + + /****** IMPORTERS *******/ + fromTinydns({ tinyline }) { + const str = tinyline; + let fqdn, ip, n, rdata, ttl, ts, loc; + + switch (str[0]) { + case ':': +[fqdn, n, rdata, ttl, ts, loc] = str.slice(1).split(':'); + if (n != 28) this.throwHelp('AAAA fromTinydns, invalid n'); + ip = octalToHex(rdata) + .match(/([0-9a-fA-F]{4})/g) + .join(':'); + break + case '3': + case '6': +[fqdn, rdata, ttl, ts, loc] = str.slice(1).split(':'); + ip = rdata.match(/(.{4})/g).join(':'); + break + } + + return new AAAA({ + owner: this.fullyQualify(fqdn), + ttl: parseInt(ttl, 10), + type: 'AAAA', + address: ip, + timestamp: ts, + location: loc?.trim() ?? '', + }) + } + + /****** EXPORTERS *******/ + getWireRdata() { + const hex = this.expandIPv6(this.get('address'), ''); + const arr = new Uint8Array(hex.length / 2); + for (let i = 0; i < arr.length; i++) arr[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16); + return arr + } + + toBind(zone_opts) { + return `${this.getPrefix(zone_opts)}\t${this.getCompressed()}\n` + } + + toTinydns() { + // from AAAA notation (8 groups of 4 hex digits) to 16 escaped octals + const rdata = packHex(this.expandIPv6(this.get('address'), '')); + return this.getTinydnsGeneric(rdata) + } +} + +class APL extends RR { + static typeName = 'APL' + static typeId = 42 + static RFCs = [3123] + static rdataFields = ['apl rdata'] + + constructor(opts) { + super(opts); + } + + /****** Resource record specific setters *******/ + setAplRdata(val) { + if (!val) this.throwHelp('APL: apl rdata is required'); + this.set('apl rdata', val); + } + + getDescription() { + return 'Address Prefix List' + } + + getCanonical() { + return { + owner: 'example.com.', + ttl: 3600, + class: 'IN', + type: 'APL', + 'apl rdata': '1:192.0.2.1/24 !1:192.0.2.64/28 2:2001:db8::1/128', + } + } + + /****** IMPORTERS *******/ + fromTinydns({ tinyline }) { + // APL via generic, :fqdn:42:rdata:ttl:timestamp:lo + const [fqdn, n, rdata, ttl, ts, loc] = tinyline.slice(1).split(':'); + if (n != 42) this.throwHelp('APL fromTinydns, invalid n'); + + const bytes = Uint8Array.from(octalToChar(rdata), (c) => c.charCodeAt(0)); + const items = []; + let pos = 0; + + while (pos < bytes.length) { + const afi = (bytes[pos] << 8) | bytes[pos + 1]; + pos += 2; + const prefix = bytes[pos]; + pos++; + const adfLenByte = bytes[pos]; + pos++; + const neg = (adfLenByte & 0x80) !== 0; + const addrLen = adfLenByte & 0x7f; + const addrBytes = bytes.subarray(pos, pos + addrLen); + pos += addrLen; + + let addr; + if (afi === 1) { + const padded = new Uint8Array(4); + padded.set(addrBytes); + addr = [...padded].join('.'); + } else { + const padded = new Uint8Array(16); + padded.set(addrBytes); + const paddedDv = new DataView(padded.buffer); + const groups = []; + for (let i = 0; i < 16; i += 2) groups.push(paddedDv.getUint16(i).toString(16).padStart(4, '0')); + addr = this.compressIPv6(groups.join(':')); + } + + items.push(`${neg ? '!' : ''}${afi}:${addr}/${prefix}`); + } + + return new APL({ + owner: this.fullyQualify(fqdn), + ttl: parseInt(ttl, 10), + type: 'APL', + 'apl rdata': items.join(' '), + timestamp: ts, + location: loc?.trim() ?? '', + }) + } + + fromBind({ bindline }) { + // test.example.com 3600 IN APL {[!]afi:address/prefix}* + const parts = bindline.split(/\s+/); + const [owner, ttl, c, type] = parts; + return new APL({ + owner, + ttl: parseInt(ttl, 10), + class: c, + type, + 'apl rdata': parts.slice(4).join(' ').trim(), + }) + } + + fromWire({ owner, cls, ttl, rdata }) { + const items = []; + let pos = 0; + while (pos < rdata.length) { + const afi = (rdata[pos] << 8) | rdata[pos + 1]; + pos += 2; + const prefix = rdata[pos++]; + const adfLenByte = rdata[pos++]; + const neg = (adfLenByte & 0x80) !== 0; + const addrLen = adfLenByte & 0x7f; + const addrBytes = rdata.subarray(pos, pos + addrLen); + pos += addrLen; + + let addr; + if (afi === 1) { + const padded = new Uint8Array(4); + padded.set(addrBytes); + addr = [...padded].join('.'); + } else { + const padded = new Uint8Array(16); + padded.set(addrBytes); + const dv = new DataView(padded.buffer); + const groups = []; + for (let i = 0; i < 16; i += 2) groups.push(dv.getUint16(i).toString(16).padStart(4, '0')); + addr = this.compressIPv6(groups.join(':')); + } + items.push(`${neg ? '!' : ''}${afi}:${addr}/${prefix}`); + } + return new APL({ + owner, + ttl, + class: cls, + type: 'APL', + 'apl rdata': items.join(' '), + }) + } + + /****** EXPORTERS *******/ + toTinydns() { + return this.getTinydnsGeneric( + this.get('apl rdata') + .split(/\s+/) + .map((item) => { + const neg = item.startsWith('!'); + const bare = neg ? item.slice(1) : item; + const colonIdx = bare.indexOf(':'); + const afi = parseInt(bare.slice(0, colonIdx), 10); + const rest = bare.slice(colonIdx + 1); + const slashIdx = rest.lastIndexOf('/'); + const addr = rest.slice(0, slashIdx); + const prefix = parseInt(rest.slice(slashIdx + 1), 10); + + let addrBytes; + if (afi === 1) { + addrBytes = new Uint8Array(addr.split('.').map((n) => parseInt(n, 10))); + } else { + const dblIdx = addr.indexOf('::'); + let groups; + if (dblIdx !== -1) { + const left = addr + .slice(0, dblIdx) + .split(':') + .filter((s) => s !== ''); + const right = addr + .slice(dblIdx + 2) + .split(':') + .filter((s) => s !== ''); + groups = [...left, ...Array(8 - left.length - right.length).fill('0000'), ...right]; + } else { + groups = addr.split(':'); + } + const hexStr = groups.map((g) => g.padStart(4, '0')).join(''); + addrBytes = Uint8Array.from({ length: hexStr.length / 2 }, (_, i) => + parseInt(hexStr.slice(i * 2, i * 2 + 2), 16), + ); + } + + let len = addrBytes.length; + while (len > 0 && addrBytes[len - 1] === 0) len--; + const afdPart = addrBytes.slice(0, len); + + let r = UInt16toOctal(afi); + r += UInt8toOctal(prefix); + r += UInt8toOctal((neg ? 0x80 : 0) | afdPart.length); + for (const b of afdPart) r += UInt8toOctal(b); + return r + }) + .join(''), + ) + } + + getWireRdata() { + const items = this.get('apl rdata').split(/\s+/); + const rdata = []; + + for (const item of items) { + const neg = item.startsWith('!'); + const bare = neg ? item.slice(1) : item; + const colonIdx = bare.indexOf(':'); + const afi = parseInt(bare.slice(0, colonIdx), 10); + const rest = bare.slice(colonIdx + 1); + const slashIdx = rest.lastIndexOf('/'); + const addr = rest.slice(0, slashIdx); + const prefix = parseInt(rest.slice(slashIdx + 1), 10); + + let addrBytes; + if (afi === 1) { + addrBytes = new Uint8Array(addr.split('.').map((n) => parseInt(n, 10))); + } else { + const dblIdx = addr.indexOf('::'); + let groups; + if (dblIdx !== -1) { + const left = addr + .slice(0, dblIdx) + .split(':') + .filter((s) => s !== ''); + const right = addr + .slice(dblIdx + 2) + .split(':') + .filter((s) => s !== ''); + groups = [...left, ...Array(8 - left.length - right.length).fill('0000'), ...right]; + } else { + groups = addr.split(':'); + } + const hexStr = groups.map((g) => g.padStart(4, '0')).join(''); + addrBytes = Uint8Array.from({ length: hexStr.length / 2 }, (_, i) => + parseInt(hexStr.slice(i * 2, i * 2 + 2), 16), + ); + } + + let len = addrBytes.length; + while (len > 0 && addrBytes[len - 1] === 0) len--; + const afdPart = addrBytes.slice(0, len); + + const itemBytes = new Uint8Array(4 + afdPart.length); + const dv = new DataView(itemBytes.buffer, itemBytes.byteOffset); + dv.setUint16(0, afi); + itemBytes[2] = prefix; + itemBytes[3] = (neg ? 0x80 : 0) | afdPart.length; + itemBytes.set(afdPart, 4); + + rdata.push(itemBytes); + } + + const totalLen = rdata.reduce((sum, r) => sum + r.length, 0); + const bytes = new Uint8Array(totalLen); + let pos = 0; + for (const r of rdata) { + bytes.set(r, pos); + pos += r.length; + } + + return bytes + } +} + +class CAA extends RR { + static typeName = 'CAA' + static typeId = 257 + static RFCs = [6844, 8659, 9619] + static rdataFields = [ + ['flags', 'u8'], + ['tag', 'charstr'], + ['value', 'qstr'], + ] + static tags = ['security'] + + constructor(opts) { + super(opts); + } + + /****** Resource record specific setters *******/ + setFlags(val) { + this.is8bitInt('CAA', 'flags', val); + + if (!this.getFlagsOptions().has(val)) { + this.throwHelp(`CAA flags ${val} not recognized`); + } + + this.set('flags', val); + } + + getFlagsOptions() { + return new Map([ + [0, 'Non Critical'], + [128, 'Critical'], + ]) + } + + setTag(val) { + if (typeof val !== 'string' || val.length < 1 || /[^a-z0-9]/.test(val)) + this.throwHelp(`CAA tag must be a sequence of ASCII letters and numbers in lowercase`); + + if (!this.getTagOptions().has(val)) { + this.throwHelp(`CAA tag ${val} not recognized`); + } + this.set('tag', val); + } + + getTagOptions() { + return new Map([['issue'], ['issuewild'], ['iodef']]) + } + + setValue(val) { + // either (2) a quoted string or + // (1) a contiguous set of characters without interior spaces + if (this.isQuoted(val)) { + val = val.replace(/^["']|["']$/g, ''); // strip quotes + } + + // check if val starts with one of iodefSchemes + if (this.get('tag') === 'iodef') { + const iodefSchemes = ['mailto:', 'http:', 'https:']; + if (!iodefSchemes.filter((s) => val.startsWith(s)).length) { + this.throwHelp(`CAA value must have valid iodefScheme prefix`); + } + } + + this.set('value', val); + } + + getDescription() { + return 'Certification Authority Authorization' + } + + getCanonical() { + return { + owner: 'example.com.', + ttl: 3600, + class: 'IN', + type: 'CAA', + flags: 0, + tag: 'issue', + value: 'http://letsencrypt.org', + } + } + + /****** IMPORTERS *******/ + fromTinydns({ tinyline }) { + // CAA via generic, :fqdn:n:rdata:ttl:timestamp:lo + const { owner, typeId, rdata, ttl, timestamp, location } = this.parseTinydnsLine(tinyline); + if (typeId != this.getTypeId()) this.throwHelp('CAA fromTinydns, invalid typeId'); + + const flags = octalToUInt8(rdata.slice(0, 4)); + const taglen = octalToUInt8(rdata.slice(4, 8)); + + const unescaped = octalToChar(rdata.slice(8)); + const tag = unescaped.slice(0, taglen); + const fingerprint = unescaped.slice(taglen); + + return new CAA({ + owner, + ttl, + type: 'CAA', + flags, + tag, + value: fingerprint, + timestamp, + location, + }) + } + + /****** EXPORTERS *******/ + + getWireRdata() { + const tag = new TextEncoder().encode(this.get('tag')); + const value = new TextEncoder().encode(this.get('value')); + const result = new Uint8Array(2 + tag.length + value.length); + result[0] = this.get('flags'); + result[1] = tag.length; + result.set(tag, 2); + result.set(value, 2 + tag.length); + return result + } + + toTinydns() { + return this.getTinydnsGeneric( + UInt8toOctal(this.get('flags')) + + UInt8toOctal(this.get('tag').length) + + escapeOctal(/[\r\n\t:\\/]/, this.get('tag')) + + escapeOctal(/[\r\n\t:\\/]/, this.get('value')), + ) + } +} + +class CERT extends RR { + static typeName = 'CERT' + static typeId = 37 + static RFCs = [2538, 4398] + static rdataFields = [ + ['cert type', 'certtype'], + ['key tag', 'u16'], + ['algorithm', 'u8'], + ['certificate', 'base64'], + ] + + static CERT_TYPES = { + PKIX: 1, + SPKI: 2, + PGP: 3, + IPKIX: 4, + ISPKI: 5, + IPGP: 6, + ACPKIX: 7, + IACPKIX: 8, + URI: 253, + OID: 254, + } + + static CERT_TYPES_REVERSE = Object.fromEntries(Object.entries(CERT.CERT_TYPES).map(([k, v]) => [v, k])) + + constructor(opts) { + super(opts); + } + + /****** Resource record specific setters *******/ + setCertType(val) { + // The type field is the certificate type + // the type field as an unsigned decimal integer or as a mnemonic symbol + if (val === undefined || val === null || val === '') { + this.throwHelp('cert type is required'); + } + // Accept both mnemonic and numeric, but validate mnemonic + if (typeof val === 'string' && !/^[0-9]+$/.test(val)) { + if (!Object.hasOwn(CERT.CERT_TYPES, val)) { + this.throwHelp(`CERT: unknown cert type mnemonic: ${val}`); + } + } else { + this.is16bitInt('CERT', 'cert type', val); + } + this.set('cert type', val); + } + + getCertTypeValue(val) { + if (typeof val === 'number') return val + if (/^[0-9]+$/.test(val)) return parseInt(val, 10) + if (Object.hasOwn(CERT.CERT_TYPES, val)) return CERT.CERT_TYPES[val] + this.throwHelp(`CERT: unknown cert type mnemonic: ${val}`); + } + + setKeyTag(val) { + this.setTypedValue('u16', 'key tag', val); + } + + setAlgorithm(val) { + this.setTypedValue('u8', 'algorithm', val); + } + + setCertificate(val) { + // certificate/CRL portion is represented in base 64 [16] and may be + // divided into any number of white-space-separated substrings + if (val === undefined || val === null || val === '') { + this.throwHelp('certificate is required and cannot be empty'); + } + this.isBase64('CERT', 'certificate', val.replace(/[\s()]/g, '')); + this.set('certificate', val); + } + + getDescription() { + return 'Certificate' + } + + getCanonical() { + return { + owner: 'mail.example.com.', + ttl: 3600, + class: 'IN', + type: 'CERT', + 'cert type': 'PGP', + 'key tag': 0, + algorithm: 0, + certificate: 'AQIDBA==', + } + } + + /****** IMPORTERS *******/ + + fromTinydns({ tinyline }) { + const { owner, typeId, rdata, ttl, timestamp, location } = this.parseTinydnsLine(tinyline); + if (typeId != this.getTypeId()) this.throwHelp('CERT fromTinydns, invalid n'); + + const bytes = octalRdataToBytes(rdata); + const typeNum = (bytes[0] << 8) | bytes[1]; + + const certType = CERT.CERT_TYPES_REVERSE[typeNum] ?? typeNum; + + return new CERT({ + owner, + ttl, + type: 'CERT', + 'cert type': certType, + 'key tag': (bytes[2] << 8) | bytes[3], + algorithm: bytes[4], + certificate: bytesToBase64(bytes.subarray(5)), + timestamp, + location, + }) + } + + fromBind({ bindline }) { + // test.example.com 3600 IN CERT certtype, keytag, algo, cert + const [owner, ttl, c, type, certtype, keytag, algo, certificate] = bindline.split(/\s+/); + return new CERT({ + owner, + ttl: parseInt(ttl, 10), + class: c, + type, + 'cert type': /^[0-9]+$/.test(certtype) ? parseInt(certtype, 10) : certtype, + 'key tag': parseInt(keytag, 10), + algorithm: parseInt(algo, 10), + certificate, + }) + } + + /****** EXPORTERS *******/ + + toTinydns() { + return this.getTinydnsGeneric( + UInt16toOctal(this.getCertTypeValue(this.get('cert type'))) + + UInt16toOctal(this.get('key tag')) + + UInt8toOctal(this.get('algorithm')) + + base64toOctal(this.get('certificate').replace(/[\s()]/g, '')), + ) + } + + getWireRdata() { + const certBytes = base64ToBytes(this.get('certificate').replace(/[\s()]/g, '')); + const bytes = new Uint8Array(5 + certBytes.length); + const dv = new DataView(bytes.buffer, bytes.byteOffset); + dv.setUint16(0, this.getCertTypeValue(this.get('cert type'))); + dv.setUint16(2, this.get('key tag')); + bytes[4] = this.get('algorithm'); + bytes.set(certBytes, 5); + return bytes + } +} + +class CNAME extends RR { + static typeName = 'CNAME' + static typeId = 5 + static RFCs = [1035, 2181] + static tinydnsType = 'C' + static rdataFields = [['cname', 'fqdn']] + static tags = ['common'] + + constructor(opts) { + super(opts); + } + + /****** Resource record specific setters *******/ + setCname(val) { + this.setTypedValue('fqdn', 'cname', val); + } + + getDescription() { + return 'Canonical Name' + } + + getCanonical() { + return { + owner: 'www.example.com.', + ttl: 3600, + class: 'IN', + type: 'CNAME', + cname: 'web.example.com.', + } + } + + /****** EXPORTERS *******/ + getWireRdata() { + return this.wirePackDomain(this.get('cname')) + } +} + +class DHCID extends RR { + static typeName = 'DHCID' + static typeId = 49 + static RFCs = [4701] + static rdataFields = [['data', 'base64']] + + constructor(opts) { + super(opts); + } + + /****** Resource record specific setters *******/ + setData(val) { + if (!val) this.throwHelp('DHCID: data is required'); + this.isBase64('DHCID', 'data', val); + this.set('data', val); + } + + getDescription() { + return 'DHCP Identifier' + } + + getCanonical() { + return { + owner: 'host.example.com.', + ttl: 3600, + class: 'IN', + type: 'DHCID', + data: 'AAIBY2/AuCccgoJbsaxcQc9TUapptP69lOjxfNuVAA2kjEA=', + } + } + + /****** IMPORTERS *******/ + fromTinydns({ tinyline }) { + // DHCID via generic, :fqdn:49:rdata:ttl:timestamp:lo + const { owner, typeId, rdata, ttl, timestamp, location } = this.parseTinydnsLine(tinyline); + if (typeId != this.getTypeId()) this.throwHelp('DHCID fromTinydns, invalid n'); + + return new DHCID({ + owner, + ttl, + type: 'DHCID', + data: octalToBase64(rdata), + timestamp, + location, + }) + } + + /****** EXPORTERS *******/ + + getWireRdata() { + return new Uint8Array( + atob(this.get('data')) + .split('') + .map((c) => c.charCodeAt(0)), + ) + } + + toTinydns() { + return this.getTinydnsGeneric(base64toOctal(this.get('data'))) + } +} + +class DNAME extends RR { + static typeName = 'DNAME' + static typeId = 39 + static RFCs = [2672, 6672] + static rdataFields = [['target', 'fqdn']] + + constructor(opts) { + super(opts); + } + + /****** Resource record specific setters *******/ + setTarget(val) { + this.setTypedValue('fqdn', 'target', val); + } + + getDescription() { + return 'Delegation Name' + } + + getCanonical() { + return { + owner: 'example.com.', + ttl: 3600, + class: 'IN', + type: 'DNAME', + target: 'example.net.', + } + } + + /****** IMPORTERS *******/ + fromTinydns({ tinyline }) { + // DNAME via generic, :fqdn:n:rdata:ttl:timestamp:lo + const [fqdn, n, rdata, ttl, ts, loc] = tinyline.slice(1).split(':'); + if (n != 39) this.throwHelp('DNAME fromTinydns, invalid n'); + + return new DNAME({ + type: 'DNAME', + owner: this.fullyQualify(fqdn), + target: unpackDomainName(rdata)[0], + ttl: parseInt(ttl, 10), + timestamp: ts, + location: loc?.trim() ?? '', + }) + } + + /****** EXPORTERS *******/ + + getWireRdata() { + return this.wirePackDomain(this.get('target')) + } + + toTinydns() { + const rdata = packDomainName(this.get('target')); + return this.getTinydnsGeneric(rdata) + } +} + +class DNSKEY extends RR { + static typeName = 'DNSKEY' + static typeId = 48 + static RFCs = [4034, 6014, 8624, 9619, 9905] + static rdataFields = [ + ['flags', 'u16'], + ['protocol', 'u8'], + ['algorithm', 'u8'], + ['publickey', 'base64'], + ] + static tags = ['dnssec'] + + constructor(opts) { + super(opts); + } + + /****** Resource record specific setters *******/ + setFlags(val) { + // a 2 octet Flags Field + this.is16bitInt('DNSKEY', 'flags', val); + + if (!this.getFlagsOptions().has(val)) { + this.throwHelp(`DNSKEY: flags must be in the set: ${this.getFlagsOptions()}`); + } + + this.set('flags', val); + } + + // possible values are: 0, 256, and 257; RFC 4034 + getFlagsOptions() { + return new Map([[0], [256], [257]]) + } + + setProtocol(val) { + // 1 octet + this.is8bitInt('DNSKEY', 'protocol', val); + + // The Protocol Field MUST be represented as an unsigned decimal integer with a value of 3. + if (!this.getProtocolOptions().has(val)) this.throwHelp(`DNSKEY: protocol invalid`); + + this.set('protocol', val); + } + + getProtocolOptions() { + return new Map([[3]]) + } + + setAlgorithm(val) { + // 1 octet + this.is8bitInt('DNSKEY', 'algorithm', val); + + // https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml + if (!this.getAlgorithmOptions().has(val)) console.error(`DNSKEY: algorithm (${val}) not recognized`); + + this.set('algorithm', val); + } + + getAlgorithmOptions() { + return new Map([ + [1, 'RSA/MD5 (DEPRECATED)'], + [2, 'DH'], + [3, 'DSA/SHA-1'], + [4, 'EC'], + [5, 'RSA/SHA-1'], + [6, 'DSA-NSEC3-SHA1'], + [7, 'RSASHA1-NSEC3-SHA1'], + [8, 'RSA/SHA-256'], + [9, ''], + [10, 'RSA/SHA-512'], + [13, 'ECDSA Curve P-256 with SHA-256'], + [14, 'ECDSA Curve P-384 with SHA-384'], + [15, 'Ed25519'], + [16, 'Ed448'], + [253], + [254], + ]) + } + + setPublickey(val) { + if (!val) this.throwHelp(`DNSKEY: publickey is required`); + this.isBase64('DNSKEY', 'publickey', val.replace(/[\s()]/g, '')); + this.set('publickey', val); + } + + getDescription() { + return 'DNS Public Key' + } + + getCanonical() { + return { + owner: 'example.com.', + ttl: 3600, + class: 'IN', + type: 'DNSKEY', + flags: 256, + protocol: 3, + algorithm: 5, + publickey: + 'AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwIXAqcOTiW7iHnQt5hwVAAAAA==', + } + } + + /****** IMPORTERS *******/ + + fromBind({ bindline }) { + // test.example.com 3600 IN DNSKEY Flags Protocol Algorithm PublicKey + const regex = + /^(?\S+)\s+(?\d+)\s+(?\w+)\s+(?DNSKEY)\s+(?\d+)\s+(?\d+)\s+(?\d+)\s+(?\S.*)$/i; + + const match = bindline.trim().match(regex); + + if (!match) { + this.throwHelp(`unable to parse DNSKEY: ${bindline}`); + } + + const { owner, ttl, c, type, flags, protocol, algorithm, publickey } = match.groups; + + return new DNSKEY({ + owner, + ttl: parseInt(ttl, 10), + class: c, + type: type, + flags: parseInt(flags, 10), + protocol: parseInt(protocol, 10), + algorithm: parseInt(algorithm, 10), + publickey: publickey, + }) + } + + fromTinydns({ tinyline }) { + const { owner, typeId, rdata, ttl, timestamp, location } = this.parseTinydnsLine(tinyline); + if (typeId != this.getTypeId()) this.throwHelp('DNSKEY fromTinydns, invalid n'); + + const bytes = octalRdataToBytes(rdata); + + return new DNSKEY({ + owner, + ttl, + type: 'DNSKEY', + flags: (bytes[0] << 8) | bytes[1], + protocol: bytes[2], + algorithm: bytes[3], + publickey: bytesToBase64(bytes.subarray(4)), + timestamp, + location, + }) + } + + /****** EXPORTERS *******/ + + toTinydns() { + return this.getTinydnsGeneric( + UInt16toOctal(this.get('flags')) + + UInt8toOctal(this.get('protocol')) + + UInt8toOctal(this.get('algorithm')) + + base64toOctal(this.get('publickey').replace(/[\s()]/g, '')), + ) + } + + getWireRdata() { + const keyBytes = base64ToBytes(this.get('publickey').replace(/[\s()]/g, '')); + const bytes = new Uint8Array(4 + keyBytes.length); + const dv = new DataView(bytes.buffer, bytes.byteOffset); + dv.setUint16(0, this.get('flags')); + bytes[2] = this.get('protocol'); + bytes[3] = this.get('algorithm'); + bytes.set(keyBytes, 4); + return bytes + } +} + +class DS extends RR { + static typeName = 'DS' + static typeId = 43 + static RFCs = [4034, 4509, 9619] + static rdataFields = [['key tag', 'u16'], 'algorithm', 'digest type', ['digest', 'str']] + static tags = ['dnssec'] + + constructor(opts) { + super(opts); + } + + /****** Resource record specific setters *******/ + setKeyTag(val) { + this.setTypedValue('u16', 'key tag', val); + } + + setDigest(val) { + this.setTypedValue('str', 'digest', val); + } + + setAlgorithm(val) { + if (!this.getAlgorithmOptions().has(val)) this.throwHelp(`DS: algorithm invalid`); + + this.set('algorithm', val); + } + + getAlgorithmOptions() { + // IANA DNSSEC Algorithm Numbers + // https://www.iana.org/assignments/dns-sec-alg-numbers/ + return new Map([ + [1, 'RSA/MD5'], + [2, 'DH'], + [3, 'DSA/SHA-1'], + [4, 'EC'], + [5, 'RSA/SHA-1'], + [6, 'DSA-NSEC3-SHA1'], + [7, 'RSASHA1-NSEC3-SHA1'], + [8, 'RSA/SHA-256'], + [10, 'RSA/SHA-512'], + [13, 'ECDSA P-256/SHA-256'], + [14, 'ECDSA P-384/SHA-384'], + [15, 'Ed25519'], + [16, 'Ed448'], + [253, ''], + [254, ''], + ]) + } + + setDigestType(val) { + // 1=SHA-1 (RFC 4034), 2=SHA-256 (RFC 4509), 4=SHA-384 (RFC 6605) + if (![1, 2, 4].includes(val)) this.throwHelp(`DS: digest type invalid`); + + this.set('digest type', val); + } + + getDescription() { + return 'Delegation Signer' + } + + getCanonical() { + return { + owner: 'example.com.', + ttl: 3600, + class: 'IN', + type: 'DS', + 'key tag': 12345, + algorithm: 5, + 'digest type': 1, + digest: 'ABCDEF123...', + } + } + + /****** IMPORTERS *******/ + + fromTinydns(opts) { + const { tinyline } = opts; + const { owner, typeId, rdata, ttl, timestamp, location } = this.parseTinydnsLine(tinyline); + if (typeId != this.getTypeId()) this.throwHelp('DS fromTinydns, invalid n'); + + const binRdata = octalRdataToBytes(rdata); + + return new DS({ + owner, + ttl, + type: 'DS', + 'key tag': (binRdata[0] << 8) | binRdata[1], + algorithm: binRdata[2], + 'digest type': binRdata[3], + digest: bytesToHex(binRdata.subarray(4)).toUpperCase(), + timestamp, + location, + }) + } + + fromWire({ owner, cls, ttl, rdata }) { + const dv = new DataView(rdata.buffer, rdata.byteOffset); + return new DS({ + owner, + ttl, + class: cls, + type: 'DS', + 'key tag': dv.getUint16(0), + algorithm: rdata[2], + 'digest type': rdata[3], + digest: bytesToHex(rdata.subarray(4)).toUpperCase(), + }) + } + + /****** EXPORTERS *******/ + + toTinydns() { + return this.getTinydnsGeneric( + UInt16toOctal(this.get('key tag')) + + UInt8toOctal(this.get('algorithm')) + + UInt8toOctal(this.get('digest type')) + + packHex(this.get('digest').replace(/\s+/g, '')), + ) + } + + getWireRdata() { + const digestBytes = hexToBytes(this.get('digest').replace(/\s+/g, '')); + const bytes = new Uint8Array(4 + digestBytes.length); + const dv = new DataView(bytes.buffer, bytes.byteOffset); + dv.setUint16(0, this.get('key tag')); + bytes[2] = this.get('algorithm'); + bytes[3] = this.get('digest type'); + bytes.set(digestBytes, 4); + return bytes + } +} + +class HINFO extends RR { + static typeName = 'HINFO' + static typeId = 13 + static RFCs = [1034, 1035, 8482] + static rdataFields = [ + ['cpu', 'qcharstr'], + ['os', 'qcharstr'], + ] + static tags = ['obsolete'] + + constructor(opts) { + super(opts); + } + + /****** Resource record specific setters *******/ + setCpu(val) { + if (val.length > 255) this.throwHelp('HINFO cpu cannot exceed 255 chars'); + this.set('cpu', val.replace(/^["']|["']$/g, '')); + } + + setOs(val) { + if (val.length > 255) this.throwHelp('HINFO os cannot exceed 255 chars'); + this.set('os', val.replace(/^["']|["']$/g, '')); + } + + getDescription() { + return 'Host Info' + } + + getCanonical() { + return { + owner: 'test.example.com.', + ttl: 3600, + class: 'IN', + type: 'HINFO', + cpu: 'DEC-2060', + os: 'TOPS20', + } + } + + /****** IMPORTERS *******/ + fromTinydns({ tinyline }) { + // HINFO via generic, :fqdn:n:rdata:ttl:timestamp:lo + const [fqdn, , rdata, ttl, ts, loc] = tinyline.slice(1).split(':'); + const [cpu, os] = [...unpackString(rdata)]; + + return new this.constructor({ + owner: this.fullyQualify(fqdn), + ttl: parseInt(ttl, 10), + type: 'HINFO', + cpu, + os, + timestamp: ts, + location: loc?.trim() ?? '', + }) + } + + /****** EXPORTERS *******/ + + getWireRdata() { + const cpu = new TextEncoder().encode(this.get('cpu')); + const os = new TextEncoder().encode(this.get('os')); + const result = new Uint8Array(2 + cpu.length + os.length); + result[0] = cpu.length; + result.set(cpu, 1); + result[1 + cpu.length] = os.length; + result.set(os, 2 + cpu.length); + return result + } + + toTinydns() { + return this.getTinydnsGeneric( + [packString(this.get('cpu')), packString(this.get('os'))].join(''), + ) + } +} + +class HIP extends RR { + static typeName = 'HIP' + static typeId = 55 + static RFCs = [8005] + static rdataFields = ['pk algorithm', 'hit', 'public key', 'rendezvous servers'] + + constructor(opts) { + super(opts); + } + + /****** Resource record specific setters *******/ + setPkAlgorithm(val) { + if (val === undefined) this.throwHelp('HIP: pk algorithm is required'); + this.is8bitInt('HIP', 'pk algorithm', val); + this.set('pk algorithm', val); + } + + setHit(val) { + if (!val) this.throwHelp('HIP: hit is required'); + this.set('hit', val); + } + + setPublicKey(val) { + if (!val) this.throwHelp('HIP: public key is required'); + this.set('public key', val); + } + + setRendezvousServers(val) { + this.set('rendezvous servers', val ?? ''); + } + + getDescription() { + return 'Host Identity Protocol' + } + + getCanonical() { + return { + owner: 'example.com.', + ttl: 3600, + class: 'IN', + type: 'HIP', + 'pk algorithm': 2, + hit: '200100107B1A74DF365639CC39F1D578', + 'public key': + 'AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwIXAqcOTiW7iHnQt5hwVAAAAA==', + 'rendezvous servers': '', + } + } + + /****** IMPORTERS *******/ + fromTinydns({ tinyline }) { + // HIP via generic, :fqdn:55:rdata:ttl:timestamp:lo + const [fqdn, n, rdata, ttl, ts, loc] = tinyline.slice(1).split(':'); + if (n != 55) this.throwHelp('HIP fromTinydns, invalid n'); + + const bytes = Uint8Array.from(octalToChar(rdata), (c) => c.charCodeAt(0)); + const hitLen = bytes[0]; + const pkAlgorithm = bytes[1]; + const pkLen = (bytes[2] << 8) | bytes[3]; + + const hit = bytesToHex(bytes.subarray(4, 4 + hitLen)).toUpperCase(); + const publicKey = bytesToBase64(bytes.subarray(4 + hitLen, 4 + hitLen + pkLen)); + + const rvsNames = []; + let pos = 4 + hitLen + pkLen; + while (pos < bytes.length) { + const [name, newPos] = unpackDomainName( + [...bytes.subarray(pos)] + .map((b) => (b < 32 || b > 126 ? UInt8toOctal(b) : String.fromCharCode(b))) + .join(''), + ); + pos += newPos; + if (name !== '.') rvsNames.push(name); + } + + return new HIP({ + owner: this.fullyQualify(fqdn), + ttl: parseInt(ttl, 10), + type: 'HIP', + 'pk algorithm': pkAlgorithm, + hit, + 'public key': publicKey, + 'rendezvous servers': rvsNames.join(' '), + timestamp: ts, + location: loc?.trim() ?? '', + }) + } + + fromBind({ bindline }) { + // owner ttl IN HIP pk-algorithm HIT public-key [rendezvous-server...] + // The public key may be split across multiple lines and joined with spaces + // by the zone parser. Base64 chars are [A-Za-z0-9+/=]; domain names contain '.'. + const parts = bindline.split(/\s+/); + const [owner, ttl, c, type, pkAlgorithm, hit] = parts; + const rest = parts.slice(6); + const keyParts = []; + const rvsParts = []; + for (const token of rest) { + if (/^[A-Za-z0-9+/=]+$/.test(token)) { + keyParts.push(token); + } else { + rvsParts.push(token); + } + } + return new HIP({ + owner, + ttl: parseInt(ttl, 10), + class: c, + type, + 'pk algorithm': parseInt(pkAlgorithm, 10), + hit, + 'public key': keyParts.join(''), + 'rendezvous servers': rvsParts.join(' ').trim(), + }) + } + + fromWire({ owner, cls, ttl, rdata }) { + const dv = new DataView(rdata.buffer, rdata.byteOffset); + const hitLen = rdata[0]; + const pkAlgorithm = rdata[1]; + const pkLen = dv.getUint16(2); + const hit = bytesToHex(rdata.subarray(4, 4 + hitLen)).toUpperCase(); + const publicKey = bytesToBase64(rdata.subarray(4 + hitLen, 4 + hitLen + pkLen)); + const rvsNames = []; + let pos = 4 + hitLen + pkLen; + while (pos < rdata.length) { + const { fqdn, end } = this.wireUnpackDomain(rdata, pos); + rvsNames.push(fqdn); + pos = end; + } + return new HIP({ + owner, + ttl, + class: cls, + type: 'HIP', + 'pk algorithm': pkAlgorithm, + hit, + 'public key': publicKey, + 'rendezvous servers': rvsNames.join(' '), + }) + } + + /****** EXPORTERS *******/ + toBind(zone_opts) { + const rs = this.get('rendezvous servers'); + const rsPart = rs ? `\t${rs}` : ''; + return `${this.getPrefix(zone_opts)}\t${this.get('pk algorithm')}\t${this.get('hit')}\t${this.get('public key')}${rsPart}\n` + } + + toTinydns() { + const hitHex = this.get('hit'); + const hitBytes = hexToBytes(hitHex); + const pkBytes = base64ToBytes(this.get('public key')); + const rs = this.get('rendezvous servers'); + + let rdata = ''; + rdata += UInt8toOctal(hitBytes.length); + rdata += UInt8toOctal(this.get('pk algorithm')); + rdata += UInt16toOctal(pkBytes.length); + for (const b of hitBytes) rdata += UInt8toOctal(b); + for (const b of pkBytes) rdata += UInt8toOctal(b); + if (rs) { + for (const name of rs.split(/\s+/)) rdata += packDomainName(name); + } + + return this.getTinydnsGeneric(rdata) + } + + getWireRdata() { + const hitHex = this.get('hit'); + const hitBytes = hexToBytes(hitHex); + const pkBytes = base64ToBytes(this.get('public key')); + const rs = this.get('rendezvous servers'); + + const rsNames = rs ? rs.split(/\s+/) : []; + const rsDomains = rsNames.map((name) => wirePackDomain(name)); + const rsTotalLen = rsDomains.reduce((sum, b) => sum + b.length, 0); + + const totalLen = 1 + 1 + 2 + hitBytes.length + pkBytes.length + rsTotalLen; + const bytes = new Uint8Array(totalLen); + const dv = new DataView(bytes.buffer, bytes.byteOffset); + + let pos = 0; + bytes[pos++] = hitBytes.length; + bytes[pos++] = this.get('pk algorithm'); + dv.setUint16(pos, pkBytes.length); + pos += 2; + bytes.set(hitBytes, pos); + pos += hitBytes.length; + bytes.set(pkBytes, pos); + pos += pkBytes.length; + for (const rdomain of rsDomains) { + bytes.set(rdomain, pos); + pos += rdomain.length; + } + + return bytes + } +} + +class HTTPS extends RR { + static typeName = 'HTTPS' + static typeId = 65 + static RFCs = [9460] + static tags = ['common'] + static rdataFields = [ + ['priority', 'u16'], + ['target name', 'fqdn'], + ['params', 'svcparams'], + ] + + constructor(opts) { + super(opts); + } + + /****** Resource record specific setters *******/ + setPriority(val) { + this.is16bitInt('HTTPS', 'priority', val); + + this.set('priority', val); + } + + setTargetName(val) { + // this.isFullyQualified('HTTPS', 'target name', val) + // this.isValidHostname('HTTPS', 'target name', val) + + // RFC 4034: letters in the DNS names are lower cased + this.set('target name', val.toLowerCase()); + } + + setParams(val) { + // if (!val) this.throwHelp(`HTTPS: params is required`) + + this.set('params', val); + } + + getDescription() { + return 'HTTP Semantics' + } + + getCanonical() { + return { + owner: 'example.com.', + ttl: 3600, + class: 'IN', + type: 'HTTPS', + priority: 1, + 'target name': 'example.com.', + params: 'alpn="h2,h3"', + } + } + + /****** IMPORTERS *******/ + + fromBind({ bindline }) { + // test.example.com 3600 IN HTTPS Priority TargetName Params + const [owner, ttl, c, type, pri, fqdn] = bindline.split(/\s+/); + return new HTTPS({ + owner, + ttl: parseInt(ttl, 10), + class: c, + type, + priority: parseInt(pri, 10), + 'target name': fqdn, + params: bindline.split(/\s+/).slice(6).join(' ').trim(), + }) + } + + fromTinydns({ tinyline }) { + const { owner, typeId, rdata, ttl, timestamp, location } = this.parseTinydnsLine(tinyline); + if (typeId != this.getTypeId()) this.throwHelp('HTTPS fromTinydns, invalid n'); + const { priority, targetName, params } = parseSvcbLikeRdata(rdata, 'HTTPS'); + + return new HTTPS({ + owner, + ttl, + type: 'HTTPS', + priority, + 'target name': targetName, + params, + timestamp, + location, + }) + } + + /****** EXPORTERS *******/ + + toTinydns() { + const dataRe = new RegExp(/[\r\n\t:\\/]/, 'g'); + + return this.getTinydnsGeneric( + UInt16toOctal(this.get('priority')) + + packDomainName(this.get('target name')) + + escapeOctal(dataRe, this.get('params')), + ) + } + + getWireRdata() { + const targetBytes = this.wirePackDomain(this.get('target name')); + const paramsBytes = svcParamsToWire(this.get('params')); + const result = new Uint8Array(2 + targetBytes.length + paramsBytes.length); + new DataView(result.buffer).setUint16(0, this.get('priority')); + result.set(targetBytes, 2); + result.set(paramsBytes, 2 + targetBytes.length); + return result + } +} + +class IPSECKEY extends RR { + static typeName = 'IPSECKEY' + static typeId = 45 + static RFCs = [4025] + static rdataFields = ['precedence', 'gateway type', 'algorithm', 'gateway', 'publickey'] + static tags = ['security'] + + constructor(opts) { + super(opts); + } + + /****** Resource record specific setters *******/ + setPrecedence(val) { + // an 8-bit precedence for this record. + this.is8bitInt('IPSECKEY', 'precedence', val); + + this.set('precedence', val); + } + + setGatewayType(val) { + if (!this.getGatewayTypeOptions().has(val)) this.throwHelp(`IPSECKEY: Gateway Type is invalid`); + + this.set('gateway type', val); + } + + getGatewayTypeOptions() { + return new Map([ + [0, 'none'], + [1, '4-byte IPv4'], + [2, '16-byte IPv6'], + [3, 'wire encoded domain name'], + ]) + } + + setAlgorithm(val) { + if (!this.getAlgorithmOptions().has(val)) this.throwHelp(`IPSECKEY: Algorithm invalid`); + + this.set('algorithm', val); + } + + getAlgorithmOptions() { + return new Map([ + [1, 'DSA'], + [2, 'RSA'], + ]) + } + + setGateway(val) { + const type = this.get('gateway type'); + const gwErr = new Error(`IPSECKEY: gateway invalid (${val}) for type ${type}`); + switch (type) { + case 0: + if (val !== '.') throw gwErr + break + case 1: + if (!this.isIPv4(val)) throw gwErr + break + case 2: + if (!this.isIPv6(val)) throw gwErr + break + } + + this.set('gateway', val); + } + + setPublickey(val) { + if (val) this.isBase64('IPSECKEY', 'publickey', val); + this.set('publickey', val); + } + + getDescription() { + return 'IPsec Keying' + } + + getCanonical() { + return { + owner: '38.2.0.192.in-addr.arpa.', + ttl: 7200, + class: 'IN', + type: 'IPSECKEY', + precedence: 10, + 'gateway type': 1, + algorithm: 2, + gateway: '192.0.2.38', + publickey: 'AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==', + } + } + + /****** IMPORTERS *******/ + fromBind({ bindline }) { + // FQDN TTL CLASS IPSECKEY Precedence GatewayType Algorithm Gateway PublicKey + const [owner, ttl, c, type, prec, gwt, algo, gateway, publickey] = bindline.split(/\s+/); + return new IPSECKEY({ + owner, + ttl: parseInt(ttl, 10), + class: c, + type, + precedence: parseInt(prec, 10), + 'gateway type': parseInt(gwt, 10), + algorithm: parseInt(algo, 10), + gateway, + publickey, + }) + } + + fromTinydns({ tinyline }) { + const [fqdn, n, rdata, ttl, ts, loc] = tinyline.slice(1).split(':'); + if (n != 45) this.throwHelp('IPSECKEY fromTinydns, invalid n'); + + const precedence = octalToUInt8(rdata.slice(0, 4)); + const gwType = octalToUInt8(rdata.slice(4, 8)); + const algorithm = octalToUInt8(rdata.slice(8, 12)); + + let len, gateway, octalKey; + + switch (gwType) { + case 0: // no gateway + gateway = rdata.slice(12, 13); // should always be: '.' + octalKey = rdata.slice(13); + break + case 1: // 4-byte IPv4 address + gateway = octalToIPv4(rdata.slice(12, 28)); + octalKey = rdata.slice(28); + break + case 2: // 16-byte IPv6 + gateway = octalToIPv6(rdata.slice(12, 76)); + octalKey = rdata.slice(76); + break + case 3: // wire encoded domain name +[gateway, len] = unpackDomainName(rdata.slice(12)); + octalKey = rdata.slice(12 + len); + break + } + + return new IPSECKEY({ + owner: this.fullyQualify(fqdn), + ttl: parseInt(ttl, 10), + type: 'IPSECKEY', + precedence, + 'gateway type': gwType, + algorithm, + gateway, + publickey: octalToBase64(octalKey), + timestamp: ts, + location: loc?.trim() ?? '', + }) + } + + fromWire({ owner, cls, ttl, rdata }) { + const precedence = rdata[0]; + const gwType = rdata[1]; + const algorithm = rdata[2]; + let gateway, keyStart; + switch (gwType) { + case 0: + gateway = '.'; + keyStart = 3; + break + case 1: + gateway = [...rdata.subarray(3, 7)].join('.'); + keyStart = 7; + break + case 2: { + const dv = new DataView(rdata.buffer, rdata.byteOffset + 3); + const groups = []; + for (let i = 0; i < 16; i += 2) groups.push(dv.getUint16(i).toString(16).padStart(4, '0')); + gateway = groups.join(':'); + keyStart = 19; + break + } + case 3: { + const { fqdn, end } = this.wireUnpackDomain(rdata, 3); + gateway = fqdn; + keyStart = end; + break + } + } + const publickey = bytesToBase64(rdata.subarray(keyStart)); + return new IPSECKEY({ + owner, + ttl, + class: cls, + type: 'IPSECKEY', + precedence, + 'gateway type': gwType, + algorithm, + gateway, + publickey, + }) + } + + /****** EXPORTERS *******/ + + toTinydns() { + const rdataRe = new RegExp(/[\r\n\t:\\/]/, 'g'); + + let rdata = ''; + rdata += UInt8toOctal(this.get('precedence')); + rdata += UInt8toOctal(this.get('gateway type')); + rdata += UInt8toOctal(this.get('algorithm')); + + switch (this.get('gateway type')) { + case 0: + rdata += escapeOctal(rdataRe, '.'); + break + case 1: + rdata += ipv4toOctal(this.get('gateway')); + break + case 2: + rdata += ipv6toOctal(this.get('gateway')); + break + case 3: + rdata += packDomainName(this.get('gateway')); + break + } + + rdata += base64toOctal(this.get('publickey')); + + return this.getTinydnsGeneric(rdata) + } + + getWireRdata() { + const pubkeyBytes = base64ToBytes(this.get('publickey')); + const gwType = this.get('gateway type'); + + let gwBytes; + switch (gwType) { + case 0: + gwBytes = new Uint8Array(0); + break + case 1: + gwBytes = new Uint8Array(4); + this.get('gateway') + .split('.') + .forEach((part, i) => { + gwBytes[i] = parseInt(part, 10); + }); + break + case 2: + gwBytes = new Uint8Array(16); + { + const parts = this.get('gateway').split(':'); + let pos = 0; + for (const part of parts) { + if (part === '') continue + const val = parseInt(part, 16); + gwBytes[pos++] = (val >>> 8) & 0xff; + gwBytes[pos++] = val & 0xff; + } + } + break + case 3: + gwBytes = wirePackDomain(this.get('gateway')); + break + } + + const bytes = new Uint8Array(3 + gwBytes.length + pubkeyBytes.length); + bytes[0] = this.get('precedence'); + bytes[1] = gwType; + bytes[2] = this.get('algorithm'); + bytes.set(gwBytes, 3); + bytes.set(pubkeyBytes, 3 + gwBytes.length); + + return bytes + } +} + +class KEY extends RR { + static typeName = 'KEY' + static typeId = 25 + static RFCs = [2535, 3445, 4034, 6840] + static rdataFields = [ + ['flags', 'u16'], + ['protocol', 'u8'], + ['algorithm', 'u8'], + ['publickey', 'base64'], + ] + static tags = ['obsolete'] + + constructor(opts) { + super(opts); + } + + /****** Resource record specific setters *******/ + setFlags(val) { + // a 2 octet Flags Field + this.is16bitInt('KEY', 'flags', val); + + this.set('flags', val); + } + + setProtocol(val) { + // 1 octet + this.is8bitInt('KEY', 'protocol', val); + + this.set('protocol', val); + } + + setAlgorithm(val) { + // 1 octet + + if (!this.getAlgorithmOptions().has(val)) this.throwHelp(`KEY: algorithm invalid`); + + this.set('algorithm', val); + } + + getAlgorithmOptions() { + return new Map([ + [1, 'RSA/MD5'], + [2, 'DH'], + [3, 'DSA/SHA-1'], + [4, 'EC'], + [5, 'RSA/SHA-1'], + [253, ''], + [254, ''], + ]) + } + + setPublickey(val) { + if (!val) this.throwHelp(`KEY: publickey is required`); + this.isBase64('KEY', 'publickey', val.replace(/[\s()]/g, '')); + this.set('publickey', val); + } + + getDescription() { + return 'DNS Public Key' + } + + getCanonical() { + return { + owner: 'example.com.', + ttl: 3600, + class: 'IN', + type: 'KEY', + flags: 256, + protocol: 3, + algorithm: 5, + publickey: + 'AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwIXAqcOTiW7iHnQt5hwVAAAAA==', + } + } + + /****** IMPORTERS *******/ + + fromBind({ bindline }) { + // test.example.com 3600 IN KEY Flags Protocol Algorithm PublicKey + const [owner, ttl, c, type, flags, protocol, algorithm] = bindline.split(/\s+/); + return new KEY({ + owner, + ttl: parseInt(ttl, 10), + class: c, + type: type, + flags: parseInt(flags, 10), + protocol: parseInt(protocol, 10), + algorithm: parseInt(algorithm, 10), + publickey: bindline.split(/\s+/).slice(7).join(' ').trim(), + }) + } + + fromTinydns({ tinyline }) { + // RDATA format: Flags (8 octal chars) + Protocol (4 octal chars) + Algorithm (4 octal chars) + Public Key (escaped data) + const { owner, rdata, ttl, timestamp, location } = this.parseTinydnsLine(tinyline); + if (rdata.length < 16) { + this.throwHelp(`KEY: RDATA too short: ${rdata}`); + } + + return new KEY({ + owner, + ttl, + type: 'KEY', + flags: octalToUInt16(rdata.slice(0, 8)), + protocol: octalToUInt8(rdata.slice(8, 12)), + algorithm: octalToUInt8(rdata.slice(12, 16)), + publickey: octalToBase64(rdata.slice(16)), + timestamp, + location, + }) + } + + /****** EXPORTERS *******/ + toTinydns() { + return this.getTinydnsGeneric( + UInt16toOctal(this.get('flags')) + + UInt8toOctal(this.get('protocol')) + + UInt8toOctal(this.get('algorithm')) + + base64toOctal(this.get('publickey').replace(/[\s()]/g, '')), + ) + } + + getWireRdata() { + const keyBytes = base64ToBytes(this.get('publickey').replace(/[\s()]/g, '')); + const bytes = new Uint8Array(4 + keyBytes.length); + const dv = new DataView(bytes.buffer, bytes.byteOffset); + dv.setUint16(0, this.get('flags')); + bytes[2] = this.get('protocol'); + bytes[3] = this.get('algorithm'); + bytes.set(keyBytes, 4); + return bytes + } +} + +class KX extends RR { + static typeName = 'KX' + static typeId = 36 + static RFCs = [2230] + static rdataFields = [ + ['preference', 'u16'], + ['exchanger', 'fqdn'], + ] + + constructor(opts) { + super(opts); + } + + /****** Resource record specific setters *******/ + setPreference(val) { + if (val === undefined) this.throwHelp('KX: preference is required'); + this.is16bitInt('KX', 'preference', val); + this.set('preference', val); + } + + setExchanger(val) { + if (!val) this.throwHelp('KX: exchanger is required'); + + this.isFullyQualified('KX', 'exchanger', val); + this.isValidHostname('KX', 'exchanger', val); + + this.set('exchanger', val.toLowerCase()); + } + + getDescription() { + return 'Key Exchanger' + } + + getCanonical() { + return { + owner: 'example.com.', + ttl: 3600, + class: 'IN', + type: 'KX', + preference: 10, + exchanger: 'kx.example.com.', + } + } + + /****** IMPORTERS *******/ + fromTinydns({ tinyline }) { + // KX via generic, :fqdn:36:rdata:ttl:timestamp:lo + const [fqdn, n, rdata, ttl, ts, loc] = tinyline.slice(1).split(':'); + if (n != 36) this.throwHelp('KX fromTinydns, invalid n'); + + return new KX({ + owner: this.fullyQualify(fqdn), + ttl: parseInt(ttl, 10), + type: 'KX', + preference: octalToUInt16(rdata.slice(0, 8)), + exchanger: unpackDomainName(rdata.slice(8))[0], + timestamp: ts, + location: loc?.trim() ?? '', + }) + } + + /****** EXPORTERS *******/ + + getWireRdata() { + const exchanger = this.wirePackDomain(this.get('exchanger')); + const result = new Uint8Array(2 + exchanger.length); + const dv = new DataView(result.buffer); + dv.setUint16(0, this.get('preference')); + result.set(exchanger, 2); + return result + } + + toTinydns() { + return this.getTinydnsGeneric( + UInt16toOctal(this.get('preference')) + packDomainName(this.get('exchanger')), + ) + } +} + +const REF = { + // RFC 1876 + LATLON: 2 ** 31, // LAT equator, LON prime meridian + ALTITUDE: 100000 * 100, // reference spheroid used by GPS, in cm +}; + +const CONV = { + sec: 1000, + min: 60 * 1000, + deg: 60 * 60 * 1000, +}; + +class LOC extends RR { + static typeName = 'LOC' + static typeId = 29 + static RFCs = [1876] + static rdataFields = ['address'] + + constructor(opts) { + super(opts); + } + + /****** Resource record specific setters *******/ + setAddress(val) { + if (!val) this.throwHelp('LOC: address is required'); + + /* + ... LOC ( d1 [m1 [s1]] {"N"|"S"} d2 [m2 [s2]] + {"E"|"W"} alt["m"] [siz["m"] [hp["m"] + [vp["m"]]]] ) + */ + this.parseLoc(val); + + this.set('address', val); + } + + getDescription() { + return 'Location' + } + + getCanonical() { + return { + owner: 'example.com.', + ttl: 3600, + class: 'IN', + type: 'LOC', + address: '52 22 23.000 N 4 53 32.000 E 10m 100m 10m 2m', + } + } + + parseLoc(string) { + // d1 [m1 [s1]] + const dms = '(\\d+)\\s+(?:(\\d+)\\s+)?(?:([\\d.]+)\\s+)?'; + + // alt["m"] [siz["m"] [hp["m"] [vp["m"]]]] + const alt = '(-?[\\d.]+)m?(?:\\s+([\\d.]+)m?)?(?:\\s+([\\d.]+)m?)?(?:\\s+([\\d.]+)m?)?'; + + // put them all together + const locRe = new RegExp(`^${dms}(N|S)\\s+${dms}(E|W)\\s+${alt}`, 'i'); + const r = string.match(locRe); + if (!r) this.throwHelp('LOC address: invalid format, see RFC 1876'); + + const loc = { + latitude: { + degrees: r[1], + minutes: r[2], + seconds: r[3], + hemisphere: r[4].toUpperCase(), + }, + longitude: { + degrees: r[5], + minutes: r[6], + seconds: r[7], + hemisphere: r[8].toUpperCase(), + }, + altitude: r[9] * 100, // m -> cm + size: r[10] * 100, + precision: { + horizontal: r[11] * 100, + vertical: r[12] * 100, + }, + }; + + return loc + } + + /****** IMPORTERS *******/ + fromTinydns({ tinyline }) { + // LOC via generic, :fqdn:n:rdata:ttl:timestamp:lo + const [fqdn, n, rdata, ttl, ts, loc] = tinyline.slice(1).split(':'); + if (n != 29) this.throwHelp('LOC fromTinydns, invalid n'); + + // divide by 100 is to convert cm to meters + const l = { + version: octalToUInt8(rdata.slice(0, 4)), + size: this.fromExponent(octalToUInt8(rdata.slice(4, 8))), + precision: { + horizontal: this.fromExponent(octalToUInt8(rdata.slice(8, 12))), + vertical: this.fromExponent(octalToUInt8(rdata.slice(12, 16))), + }, + latitude: this.arcSecToDMS(octalToUInt32(rdata.slice(16, 32)), 'lat'), + longitude: this.arcSecToDMS(octalToUInt32(rdata.slice(32, 48)), 'lon'), + altitude: octalToUInt32(rdata.slice(48, 64)) - REF.ALTITUDE, + }; + + return new LOC({ + type: 'LOC', + owner: this.fullyQualify(fqdn), + address: this.toHuman(l), + ttl: parseInt(ttl, 10), + timestamp: ts, + location: loc?.trim() ?? '', + }) + } + + fromBind({ bindline }) { + const [owner, ttl, c, type] = bindline.split(/\s+/); + + return new LOC({ + owner, + ttl: parseInt(ttl, 10), + class: c, + type: type, + address: bindline.split(/\s+/).slice(4).join(' ').trim(), + }) + } + + dmsToArcSec(obj) { + let retval = obj.degrees * CONV.deg + (obj.minutes ?? 0) * CONV.min + (obj.seconds ?? 0) * CONV.sec; + switch (obj.hemisphere.toUpperCase()) { + case 'W': + case 'S': + retval = -retval; + break + } + retval += REF.LATLON; + return retval + } + + arcSecToDMS(rawmsec, latlon) { + let msec = Math.abs(rawmsec - REF.LATLON); + // console.log(`rawmsec: ${rawmsec}, abs msec: ${msec}`) + + const deg = Math.floor(msec / CONV.deg); + msec -= deg * CONV.deg; + + const min = Math.floor(msec / CONV.min); + msec -= min * CONV.min; + + const sec = Math.floor(msec / CONV.sec); + msec -= sec * CONV.sec; + + let hem; + switch (latlon) { + case 'lat': + hem = rawmsec >= REF.LATLON ? 'N' : 'S'; + break + case 'lon': + hem = rawmsec >= REF.LATLON ? 'E' : 'W'; + break + default: + this.throwHelp('unknown or missing hemisphere'); + } + + return `${deg} ${min} ${sec}${msec ? '.' + msec : ''} ${hem}` + } + + fromExponent(prec) { + const mantissa = ((prec >> 4) & 0x0f) % 10; + const exponent = ((prec >> 0) & 0x0f) % 10; + return mantissa * Math.pow(10, exponent) + } + + toExponent(val) { + /* + RFC 1876, ... expressed as a pair of four-bit unsigned + integers, each ranging from zero to nine, with the most + significant four bits representing the base and the second + number representing the power of ten by which to multiply + the base. + */ + let exponent = 0; + while (val >= 10) { + val /= 10; + ++exponent; + } + return (parseInt(val) << 4) | (exponent & 0x0f) + } + + toHuman(obj) { + let r = `${obj.latitude} ${obj.longitude} ${obj.altitude / 100}m`; + if (obj.size) r += ` ${obj.size / 100}m`; + if (obj.precision.horizontal) r += ` ${obj.precision.horizontal / 100}m`; + if (obj.precision.vertical) r += ` ${obj.precision.vertical / 100}m`; + return r + } + + fromWire({ owner, cls, ttl, rdata }) { + const dv = new DataView(rdata.buffer, rdata.byteOffset); + const l = { + size: this.fromExponent(rdata[1]), + precision: { + horizontal: this.fromExponent(rdata[2]), + vertical: this.fromExponent(rdata[3]), + }, + latitude: this.arcSecToDMS(dv.getUint32(4), 'lat'), + longitude: this.arcSecToDMS(dv.getUint32(8), 'lon'), + altitude: dv.getUint32(12) - REF.ALTITUDE, + }; + return new LOC({ + owner, + ttl, + class: cls, + type: 'LOC', + address: this.toHuman(l), + }) + } + + /****** EXPORTERS *******/ + + toTinydns() { + const loc = this.parseLoc(this.get('address')); + + // LOC format declares in meters, tinydns uses cm (hence * 100) + let rdata = ''; + rdata += UInt8toOctal(0); // version + rdata += UInt8toOctal(this.toExponent(loc.size)); + rdata += UInt8toOctal(this.toExponent(loc.precision.horizontal)); + rdata += UInt8toOctal(this.toExponent(loc.precision.vertical)); + rdata += UInt32toOctal(this.dmsToArcSec(loc.latitude)); + rdata += UInt32toOctal(this.dmsToArcSec(loc.longitude)); + rdata += UInt32toOctal(loc.altitude + REF.ALTITUDE); + + return this.getTinydnsGeneric(rdata) + } + + getWireRdata() { + const loc = this.parseLoc(this.get('address')); + const bytes = new Uint8Array(16); + const dv = new DataView(bytes.buffer, bytes.byteOffset); + + bytes[0] = 0; // version + bytes[1] = this.toExponent(loc.size); + bytes[2] = this.toExponent(loc.precision.horizontal); + bytes[3] = this.toExponent(loc.precision.vertical); + dv.setUint32(4, this.dmsToArcSec(loc.latitude)); + dv.setUint32(8, this.dmsToArcSec(loc.longitude)); + dv.setUint32(12, loc.altitude + REF.ALTITUDE); + + return bytes + } +} + +class MX extends RR { + static typeName = 'MX' + static typeId = 15 + static RFCs = [1035, 2181, 7505] + static tinydnsType = '@' + static rdataFields = [ + ['preference', 'u16'], + ['exchange', 'fqdn'], + ] + static tags = ['common'] + + constructor(opts) { + super(opts); + } + + /****** Resource record specific setters *******/ + setPreference(val) { + if (val === undefined) val = this?.default?.preference; + if (val === undefined) this.throwHelp('MX: preference is required'); + this.is16bitInt('MX', 'preference', val); + this.set('preference', val); + } + + setExchange(val) { + this.setTypedValue('fqdn', 'exchange', val); + } + + getDescription() { + return 'Mail Exchanger' + } + + getCanonical() { + return { + owner: 'example.com.', + ttl: 43200, + class: 'IN', + type: 'MX', + preference: 10, + exchange: 'mail.example.com.', + } + } + + /****** IMPORTERS *******/ + fromTinydns({ tinyline }) { + // @fqdn:ip:x:dist:ttl:timestamp:lo + const [owner, _ip, x, preference, ttl, ts, loc] = tinyline.slice(1).split(':'); + + return new MX({ + type: 'MX', + owner: this.fullyQualify(owner), + exchange: this.fullyQualify(/\./.test(x) ? x : `${x}.mx.${owner}`), + preference: parseInt(preference, 10) || 0, + ttl: parseInt(ttl, 10), + timestamp: ts, + location: loc?.trim() ?? '', + }) + } + + /****** EXPORTERS *******/ + getWireRdata() { + const domain = this.wirePackDomain(this.get('exchange')); + const result = new Uint8Array(2 + domain.length); + new DataView(result.buffer).setUint16(0, this.get('preference')); + result.set(domain, 2); + return result + } + + toTinydns() { + return `@${this.getTinyFQDN('owner')}::${this.getTinyFQDN('exchange')}:${this.get('preference')}:${this.getTinydnsPostamble()}\n` + } +} + +const rdataRe = /[\r\n\t:\\/]/; + +class NAPTR extends RR { + static typeName = 'NAPTR' + static typeId = 35 + static RFCs = [2915, 3403, 4848] + static rdataFields = [ + ['order', 'u16'], + ['preference', 'u16'], + ['flags', 'qcharstr'], + ['service', 'qcharstr'], + ['regexp', 'qcharstr'], + ['replacement', 'fqdn'], + ] + + constructor(opts) { + super(opts); + } + + getDescription() { + return 'Naming Authority Pointer' + } + + getCanonical() { + return { + owner: 'cid.urn.arpa.', + ttl: 3600, + class: 'IN', + type: 'NAPTR', + order: 100, + preference: 10, + flags: 'S', + service: 'z3950+N2L+N2R', + regexp: '', + replacement: 'gatekeeper.example.com.', + } + } + + /****** Resource record specific setters *******/ + setOrder(val) { + this.is16bitInt('NAPTR', 'order', val); + this.set('order', val); + } + + setPreference(val) { + this.is16bitInt('NAPTR', 'preference', val); + this.set('preference', val); + } + + setFlags(val) { + if (!this.getFlagsOptions().has(val.toUpperCase())) this.throwHelp(`NAPTR flags are invalid`); + + this.set('flags', val.toUpperCase()); + } + + getFlagsOptions() { + return new Map([[''], ['S'], ['A'], ['U'], ['P']]) + } + + setService(val) { + this.set('service', val); + } + + setRegexp(val) { + this.set('regexp', val); + } + + setReplacement(val) { + this.set('replacement', val); + } + + /****** IMPORTERS *******/ + fromTinydns({ tinyline }) { + // NAPTR via generic, :fqdn:n:rdata:ttl:timestamp:lo + const { owner, typeId, rdata, ttl, timestamp, location } = this.parseTinydnsLine(tinyline); + if (typeId != this.getTypeId()) this.throwHelp('NAPTR fromTinydns, invalid n'); + + const binRdata = octalRdataToBytes(rdata); + const dv = new DataView(binRdata.buffer, binRdata.byteOffset, binRdata.byteLength); + + const rec = { + type: 'NAPTR', + owner, + ttl, + timestamp, + location, + order: dv.getUint16(0), + preference: dv.getUint16(2), + }; + + let idx = 4; + const flagsLength = binRdata[idx]; + idx++; + rec.flags = new TextDecoder().decode(binRdata.subarray(idx, idx + flagsLength)); + idx += flagsLength; + + const serviceLen = binRdata[idx]; + idx++; + rec.service = new TextDecoder().decode(binRdata.subarray(idx, idx + serviceLen)); + idx += serviceLen; + + const regexpLen = binRdata[idx]; + idx++; + rec.regexp = new TextDecoder().decode(binRdata.subarray(idx, idx + regexpLen)); + idx += regexpLen; + + const replaceLen = binRdata[idx]; + idx++; + rec.replacement = new TextDecoder().decode(binRdata.subarray(idx, idx + replaceLen)); + + return new NAPTR(rec) + } + + fromBind({ bindline }) { + const regex = + /^(?\S+)\s+(?\d+)\s+(?\S+)\s+(?NAPTR)\s+(?\d+)\s+(?\d+)\s+["'](?[^"']*)["']\s+["'](?[^"']*)["']\s+["'](?[^"']*)["']\s+(?\S+)$/; + + const match = bindline.trim().match(regex); + + if (!match) { + throw new Error(`Invalid NAPTR BIND line: ${bindline}`) + } + + const { owner, ttl, type, order, preference, flags, service, regexp, replacement } = match.groups; + + return new NAPTR({ + owner: this.fullyQualify(owner), + ttl: parseInt(ttl, 10), + class: match.groups.class, + type, + order: parseInt(order, 10), + preference: parseInt(preference, 10), + flags, + service, + regexp, + replacement, + }) + } + + /****** EXPORTERS *******/ + toTinydns() { + let rdata = + UInt16toOctal(this.get('order')) + + UInt16toOctal(this.get('preference')) + + UInt8toOctal(this.get('flags').length) + + this.get('flags') + + UInt8toOctal(this.get('service').length) + + escapeOctal(rdataRe, this.get('service')) + + UInt8toOctal(this.get('regexp').length) + + escapeOctal(rdataRe, this.get('regexp')); + + const replacement = this.get('replacement'); + if (replacement !== '') { + rdata += UInt8toOctal(replacement.length); + rdata += escapeOctal(rdataRe, replacement); + } + rdata += '\\000'; + + return this.getTinydnsGeneric(rdata) + } + + getWireRdata() { + const enc = new TextEncoder(); + const flags = enc.encode(this.get('flags')); + const service = enc.encode(this.get('service')); + const regexp = enc.encode(this.get('regexp')); + const replacementBytes = this.wirePackDomain(this.get('replacement')); + + const len = 4 + 1 + flags.length + 1 + service.length + 1 + regexp.length + replacementBytes.length; + const buf = new Uint8Array(len); + const view = new DataView(buf.buffer); + let pos = 0; + view.setUint16(pos, this.get('order')); + pos += 2; + view.setUint16(pos, this.get('preference')); + pos += 2; + buf[pos++] = flags.length; + buf.set(flags, pos); + pos += flags.length; + buf[pos++] = service.length; + buf.set(service, pos); + pos += service.length; + buf[pos++] = regexp.length; + buf.set(regexp, pos); + pos += regexp.length; + buf.set(replacementBytes, pos); + return buf + } +} + +class NS extends RR { + static typeName = 'NS' + static typeId = 2 + static RFCs = [1035] + static tinydnsType = '&' + static rdataFields = [['dname', 'fqdn']] + static tags = ['common'] + + constructor(opts) { + super(opts); + } + + /****** Resource record specific setters *******/ + setDname(val) { + if (!val) this.throwHelp(`NS: dname is required`); + + this.isFullyQualified('NS', 'dname', val); + this.isValidHostname('NS', 'dname', val); + + // RFC 4034: letters in the DNS names are lower cased + this.set('dname', val.toLowerCase()); + } + + getDescription() { + return 'Name Server' + } + + getCanonical() { + return { + owner: 'example.com.', + ttl: 3600, + class: 'IN', + type: 'NS', + dname: 'ns1.example.com.', + } + } + + /****** IMPORTERS *******/ + fromTinydns({ tinyline }) { + // &fqdn:ip:x:ttl:timestamp:lo + const [fqdn, _ip, dname, ttl, ts, loc] = tinyline.slice(1).split(':'); + + return new NS({ + type: 'NS', + owner: this.fullyQualify(fqdn), + dname: this.fullyQualify(/\./.test(dname) ? dname : `${dname}.ns.${fqdn}`), + ttl: parseInt(ttl, 10), + timestamp: ts, + location: loc?.trim() ?? '', + }) + } + + /****** EXPORTERS *******/ + getWireRdata() { + return this.wirePackDomain(this.get('dname')) + } + + toTinydns() { + return `&${this.getTinyFQDN('owner')}::${this.getTinyFQDN('dname')}:${this.getTinydnsPostamble()}\n` + } +} + +class NSEC extends RR { + static typeName = 'NSEC' + static typeId = 47 + static RFCs = [4034] + static rdataFields = ['next domain', 'type bit maps'] + static tags = ['dnssec'] + + constructor(opts) { + super(opts); + if (opts === null) return + } + + /****** Resource record specific setters *******/ + setNextDomain(val) { + if (!val) this.throwHelp(`NSEC: 'next domain' is required:`); + + this.isFullyQualified('NSEC', 'next domain', val); + this.isValidHostname('NSEC', 'next domain', val); + + // RFC 4034: letters in the DNS names are lower cased + this.set('next domain', val.toLowerCase()); + } + + setTypeBitMaps(val) { + if (!val) this.throwHelp(`NSEC: 'type bit maps' is required`); + + this.set('type bit maps', val); + } + + getDescription() { + return 'Next Secure' + } + + getCanonical() { + return { + owner: 'alfa.example.com.', + ttl: 3600, + class: 'IN', + type: 'NSEC', + 'next domain': 'host.example.com.', + 'type bit maps': 'A MX RRSIG NSEC TYPE1234', + } + } + + /****** IMPORTERS *******/ + + fromTinydns({ tinyline }) { + const [owner, _typeId, rdata, ttl, ts, loc] = tinyline.slice(1).split(':'); + const binaryRdata = Uint8Array.from(octalToChar(rdata), (c) => c.charCodeAt(0)); + const [nextDomain, _escapedLen, binaryLen] = unpackDomainName(rdata); + + return new NSEC({ + owner: this.fullyQualify(owner), + ttl: parseInt(ttl, 10), + type: 'NSEC', + 'next domain': nextDomain, + 'type bit maps': new TextDecoder().decode(binaryRdata.subarray(binaryLen)), + timestamp: ts, + location: loc?.trim() ?? '', + }) + } + + fromBind({ bindline }) { + // test.example.com 3600 IN NSEC NextDomain TypeBitMaps + const [owner, ttl, c, type, next] = bindline.split(/\s+/); + return new NSEC({ + owner, + ttl: parseInt(ttl, 10), + class: c, + type: type, + 'next domain': next, + 'type bit maps': bindline.split(/\s+/).slice(5).filter(removeParens$1).join(' ').trim(), + }) + } + + fromWire({ owner, cls, ttl, rdata }) { + const { fqdn: nextDomain, end } = this.wireUnpackDomain(rdata, 0); + const typeBitMaps = nsecBitmapToTypes(rdata.subarray(end)); + return new NSEC({ + owner, + ttl, + class: cls, + type: 'NSEC', + 'next domain': nextDomain, + 'type bit maps': typeBitMaps, + }) + } + + /****** EXPORTERS *******/ + + toTinydns() { + const dataRe = new RegExp(/[\r\n\t:\\/]/, 'g'); + + return this.getTinydnsGeneric( + packDomainName(this.get('next domain')) + + escapeOctal(dataRe, this.get('type bit maps')), + ) + } + + getWireRdata() { + const nameBytes = this.wirePackDomain(this.get('next domain')); + const bitmapBytes = typesToNsecBitmap(this.get('type bit maps')); + const result = new Uint8Array(nameBytes.length + bitmapBytes.length); + result.set(nameBytes); + result.set(bitmapBytes, nameBytes.length); + return result + } +} + +const removeParens$1 = (a) => !['(', ')'].includes(a); + +function nsecBitmapToTypes(bitmap) { + const DNS_TYPE_NAMES = Object.fromEntries(Object.entries(DNS_TYPE_IDS).map(([k, v]) => [v, k])); + const types = []; + let pos = 0; + while (pos + 2 <= bitmap.length) { + const windowNum = bitmap[pos]; + const bitmapLen = bitmap[pos + 1]; + pos += 2; + for (let i = 0; i < bitmapLen; i++) { + const byte = bitmap[pos + i]; + for (let bit = 0; bit < 8; bit++) { + if (byte & (0x80 >> bit)) { + const typeId = windowNum * 256 + i * 8 + bit; + types.push(DNS_TYPE_NAMES[typeId] ?? `TYPE${typeId}`); + } + } + } + pos += bitmapLen; + } + return types.join(' ') +} + +function typesToNsecBitmap(typeNamesStr) { + const typeIds = typeNamesStr + .trim() + .split(/\s+/) + .map((t) => { + if (/^TYPE\d+$/i.test(t)) return parseInt(t.slice(4), 10) + return DNS_TYPE_IDS[t.toUpperCase()] + }) + .filter((id) => id !== undefined && id >= 0); + + const windows = new Map(); + for (const id of typeIds) { + const w = Math.floor(id / 256); + if (!windows.has(w)) windows.set(w, []); + windows.get(w).push(id % 256); + } + + const blocks = []; + for (const [wNum, bits] of [...windows.entries()].sort((a, b) => a[0] - b[0])) { + const maxBit = Math.max(...bits); + const bitmapLen = Math.floor(maxBit / 8) + 1; + const bitmap = new Uint8Array(bitmapLen); + for (const b of bits) bitmap[Math.floor(b / 8)] |= 0x80 >> (b % 8); + blocks.push(new Uint8Array([wNum, bitmapLen, ...bitmap])); + } + + const total = blocks.reduce((s, b) => s + b.length, 0); + const result = new Uint8Array(total); + let pos = 0; + for (const b of blocks) { + result.set(b, pos); + pos += b.length; + } + return result +} + +class NSEC3 extends RR { + static typeName = 'NSEC3' + static typeId = 50 + static RFCs = [5155, 9077] + static rdataFields = [ + 'hash algorithm', + 'flags', + 'iterations', + 'salt', + 'next hashed owner name', + 'type bit maps', + ] + static tags = ['dnssec'] + + constructor(opts) { + super(opts); + if (opts === null) return + } + + /****** Resource record specific setters *******/ + setHashAlgorithm(val) { + // Hash Algorithm is a single octet. + // The Hash Algorithm field is represented as an unsigned decimal integer. + if (!val) this.throwHelp(`NSEC3: 'hash algorithm' is required`); + + this.is8bitInt('NSEC3', 'hash algorithm', val); + + this.set('hash algorithm', val); + } + + setFlags(val) { + // The Flags field is represented as an unsigned decimal integer. + if (!val) this.throwHelp(`NSEC3: 'flags' is required`); + + this.is8bitInt('NSEC3', 'flags', val); + + this.set('flags', val); + } + + setIterations(val) { + // The Iterations field is represented as an unsigned decimal integer. 0-65535 + if (!val) this.throwHelp(`NSEC3: 'iterations' is required`); + + this.is16bitInt('NSEC3', 'flags', val); + + this.set('iterations', val); + } + + setSalt(val) { + // The Salt field is represented as a sequence of case-insensitive + // hexadecimal digits. Whitespace is not allowed within the + // sequence. The Salt field is represented as "-" (without the + // quotes) when the Salt Length field has a value of 0 + this.set('salt', val); + } + + setNextHashedOwnerName(val) { + // The Next Hashed Owner Name field is represented as an unpadded + // sequence of case-insensitive base32 digits, without whitespace + if (!val) this.throwHelp(`NSEC3: 'next hashed owner name' is required`); + + this.set('next hashed owner name', val); + } + + setTypeBitMaps(val) { + // The Type Bit Maps field is represented as a sequence of RR type mnemonics. + if (!val) this.throwHelp(`NSEC3: 'type bit maps' is required`); + + this.set('type bit maps', val); + } + + getDescription() { + return 'Next Secure' + } + + getCanonical() { + return { + owner: 'test.example.com.', + ttl: 3600, + class: 'IN', + type: 'NSEC3', + 'hash algorithm': 1, + flags: 1, + iterations: 12, + salt: 'aabbccdd', + 'next hashed owner name': '2vptu5timamqttgl4luu9kg21e0aor3s', + 'type bit maps': 'A RRSIG', + } + } + + /****** IMPORTERS *******/ + + fromBind({ bindline }) { + // test.example.com. 3600 IN NSEC3 1 1 12 aabbccdd (2vptu5timamqttgl4luu9kg21e0aor3s A RRSIG) + const [owner, ttl, c, type, ha, flags, iterations, salt] = bindline.split(/\s+/); + // rdata may be parenthesized or inline + const rdataStr = bindline.includes('(') + ? bindline.split(/\(|\)/)[1] + : bindline.split(/\s+/).slice(8).join(' '); + + return new NSEC3({ + owner, + ttl: parseInt(ttl, 10), + class: c, + type: type, + 'hash algorithm': parseInt(ha, 10), + flags: parseInt(flags, 10), + iterations: parseInt(iterations, 10), + salt, + 'next hashed owner name': rdataStr.trim().split(/\s+/)[0], + 'type bit maps': rdataStr.trim().split(/\s+/).slice(1).join('\t'), + }) + } + + fromTinydns({ tinyline }) { + const [fqdn, n, rdata, ttl, ts, loc] = tinyline.slice(1).split(':'); + if (n != 50) this.throwHelp('NSEC3 fromTinydns, invalid n'); + + const bytes = Uint8Array.from(octalToChar(rdata), (c) => c.charCodeAt(0)); + const dv = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength); + + const hashAlgorithm = bytes[0]; + const flags = bytes[1]; + const iterations = dv.getUint16(2); + + // The remaining bytes in the buffer contain: + // Salt Length (1 octet) + // Salt (variable length based on Salt Length) + // Next Hashed Owner Name (variable length) + // Type Bit Maps (variable length) + const { salt, nextHashedOwnerName, typeBitMaps } = parseNSEC3Buffer(bytes); + + return new NSEC3({ + owner: this.fullyQualify(fqdn), + ttl: parseInt(ttl, 10), + type: 'NSEC3', + 'hash algorithm': hashAlgorithm, + flags: flags, + iterations: iterations, + salt: salt, + 'next hashed owner name': nextHashedOwnerName, + 'type bit maps': typeBitMaps, + timestamp: ts, + location: loc?.trim() ?? '', + }) + } + + fromWire({ owner, cls, ttl, rdata }) { + const dv = new DataView(rdata.buffer, rdata.byteOffset); + const { salt, nextHashedOwnerName, typeBitMaps } = parseNSEC3Buffer(rdata); + return new NSEC3({ + owner, + ttl, + class: cls, + type: 'NSEC3', + 'hash algorithm': rdata[0], + flags: rdata[1], + iterations: dv.getUint16(2), + salt, + 'next hashed owner name': nextHashedOwnerName, + 'type bit maps': typeBitMaps, + }) + } + + /****** EXPORTERS *******/ + + toBind(zone_opts) { + return `${this.getFQDN('owner', zone_opts)} ${this.get('ttl')} ${this.get('class')} NSEC3${this.getRdataFields() + .slice(0, 4) + .map((f) => ' ' + this.get(f)) + .join('')} (${this.getRdataFields() + .slice(4) + .map((f) => this.get(f)) + .join(' ')}) +` + } + + toTinydns() { + const dataRe = new RegExp(/[\r\n\t:\\/]/, 'g'); + + return this.getTinydnsGeneric( + UInt8toOctal(this.get('hash algorithm')) + + UInt8toOctal(this.get('flags')) + + UInt16toOctal(this.get('iterations')) + + escapeOctal(dataRe, this.get('salt')) + + escapeOctal(dataRe, this.get('next hashed owner name')) + + escapeOctal(dataRe, this.get('type bit maps')), + ) + } + + getWireRdata() { + const tail = `${this.get('salt')}${this.get('next hashed owner name')}${this.get('type bit maps')}`; + const tailBytes = new TextEncoder().encode(tail); + + const totalLen = 4 + tailBytes.length; + const bytes = new Uint8Array(totalLen); + const dv = new DataView(bytes.buffer, bytes.byteOffset); + + let pos = 0; + bytes[pos++] = this.get('hash algorithm'); + bytes[pos++] = this.get('flags'); + dv.setUint16(pos, this.get('iterations')); + pos += 2; + bytes.set(tailBytes, pos); + + return bytes + } +} + +function parseNSEC3Buffer(bytes) { + // bytes is a Uint8Array containing the full RDATA binary (hash alg, flags, iterations, then ASCII salt + next-hashed + type bit maps) + // Start after the first 4 bytes (hash alg, flags, iterations) + const rest = new TextDecoder().decode(bytes.subarray(4)); + + // determine expected next hashed owner name length from hash algorithm + const hashAlgorithm = bytes[0]; + // common mapping: algorithm 1 => SHA-1 => 20 bytes => base32 length 32 + const expectedLen = hashAlgorithm === 1 ? 32 : hashAlgorithm === 2 ? 52 : 32; + + // salt length is ambiguous in this representation; try to find a split where + // the following segment matches expected base32 length + let salt = ''; + let nextHashedOwnerName = ''; + let typeBitMaps = ''; + + const maxSl = Math.min(64, rest.length); + for (let sl = maxSl; sl >= 1; sl--) { + const candNext = rest.slice(sl, sl + expectedLen); + if (candNext.length !== expectedLen) continue + if (!/^[0-9a-z]+$/.test(candNext)) continue + // candidate looks like a base32 name; accept and treat remainder as type bit maps + const saltCandidate = rest.slice(0, sl); + if (!/^[0-9A-Fa-f]+$/.test(saltCandidate)) continue + salt = saltCandidate; + nextHashedOwnerName = candNext; + typeBitMaps = rest.slice(sl + expectedLen); + break + } + + // fallback: if we couldn't find a split, treat everything up to first non-hex as salt + if (!nextHashedOwnerName) { + const saltMatch = rest.match(/^([0-9A-Fa-f]*)/); + salt = saltMatch ? saltMatch[1] : ''; + nextHashedOwnerName = rest.slice(salt.length); + typeBitMaps = ''; + } + + return { + salt, + nextHashedOwnerName, + typeBitMaps, + } +} + +class NSEC3PARAM extends RR { + static typeName = 'NSEC3PARAM' + static typeId = 51 + static RFCs = [5155] + static rdataFields = ['hash algorithm', 'flags', 'iterations', 'salt'] + static tags = ['dnssec'] + + constructor(opts) { + super(opts); + if (opts === null) return + } + + /****** Resource record specific setters *******/ + setHashAlgorithm(val) { + // Hash Algorithm is a single octet. + // The Hash Algorithm field is represented as an unsigned decimal integer. + if (val === undefined || val === null) this.throwHelp(`NSEC3PARAM: 'hash algorithm' is required`); + + this.is8bitInt('NSEC3PARAM', 'hash algorithm', val); + + this.set('hash algorithm', val); + } + + setFlags(val) { + // The Flags field is represented as an unsigned decimal integer. + if (val === undefined || val === null) this.throwHelp(`NSEC3PARAM: 'flags' is required`); + + this.is8bitInt('NSEC3PARAM', 'flags', val); + + this.set('flags', val); + } + + setIterations(val) { + // The Iterations field is represented as an unsigned decimal integer. 0-65535 + if (val === undefined || val === null) this.throwHelp(`NSEC3PARAM: 'iterations' is required`); + + this.is16bitInt('NSEC3PARAM', 'iterations', val); + + this.set('iterations', val); + } + + setSalt(val) { + // The Salt field is represented as a sequence of case-insensitive + // hexadecimal digits. Whitespace is not allowed within the + // sequence. The Salt field is represented as "-" (without the + // quotes) when the Salt Length field has a value of 0 + if (val === '-') { + this.set('salt', val); + return + } + + if (val !== undefined && val !== null && !/^[0-9A-Fa-f]*$/.test(val)) { + this.throwHelp(`NSEC3PARAM: 'salt' must be hex or '-'`); + } + + this.set('salt', val); + } + + getDescription() { + return 'Next Secure Parameters' + } + + getCanonical() { + return { + owner: 'example.com.', + ttl: 3600, + class: 'IN', + type: 'NSEC3PARAM', + 'hash algorithm': 1, + flags: 1, + iterations: 12, + salt: 'aabbccdd', + } + } + + /****** IMPORTERS *******/ + + fromTinydns({ tinyline }) { + // RDATA format: Hash Algorithm (3 octal chars) + Flags (3 octal chars) + Iterations (6 octal chars) + Salt (escaped hex string) + const { owner, typeId, rdata, ttl, timestamp, location } = this.parseTinydnsLine(tinyline); + if (typeId != this.getTypeId()) this.throwHelp('NSEC3PARAM fromTinydns, invalid n'); + if (rdata.length < 4) { + this.throwHelp(`NSEC3PARAM: RDATA too short: ${rdata}`); + } + + // rd may contain actual binary characters (from JS string '\\001' -> char 0x01), + // so convert via octalToChar and read bytes from a Uint8Array for robust parsing. + const bytes = octalRdataToBytes(rdata); + + return new NSEC3PARAM({ + owner, + ttl, + type: 'NSEC3PARAM', + 'hash algorithm': bytes[0], + flags: bytes[1], + iterations: (bytes[2] << 8) | bytes[3], + salt: bytes[4] === 0 ? '-' : bytesToHex(bytes.subarray(5, 5 + bytes[4])), + timestamp, + location, + }) + } + + fromWire({ owner, cls, ttl, rdata }) { + const dv = new DataView(rdata.buffer, rdata.byteOffset); + const saltLen = rdata[4]; + const salt = saltLen === 0 ? '-' : bytesToHex(rdata.subarray(5, 5 + saltLen)); + return new NSEC3PARAM({ + owner, + ttl, + class: cls, + type: 'NSEC3PARAM', + 'hash algorithm': rdata[0], + flags: rdata[1], + iterations: dv.getUint16(2), + salt, + }) + } + + /****** EXPORTERS *******/ + + toTinydns() { + const salt = this.get('salt'); + const saltOctal = + salt === '-' ? UInt8toOctal(0) : UInt8toOctal(salt.length / 2) + packHex(salt); + + return this.getTinydnsGeneric( + UInt8toOctal(this.get('hash algorithm')) + + UInt8toOctal(this.get('flags')) + + UInt16toOctal(this.get('iterations')) + + saltOctal, + ) + } + + getWireRdata() { + const salt = this.get('salt'); + const saltBytes = salt === '-' ? new Uint8Array(0) : hexToBytes(salt); + const bytes = new Uint8Array(4 + 1 + saltBytes.length); + const dv = new DataView(bytes.buffer, bytes.byteOffset); + + bytes[0] = this.get('hash algorithm'); + bytes[1] = this.get('flags'); + dv.setUint16(2, this.get('iterations')); + bytes[4] = saltBytes.length; + bytes.set(saltBytes, 5); + + return bytes + } +} + +class NXT extends RR { + static typeName = 'NXT' + static typeId = 30 + static RFCs = [2065] + static rdataFields = ['next domain', 'type bit map'] + static tags = ['obsolete'] + + constructor(opts) { + super(opts); + if (opts === null) return + } + + /****** Resource record specific setters *******/ + setNextDomain(val) { + if (!val) this.throwHelp(`NXT: 'next domain' is required`); + + this.isFullyQualified('NXT', 'next domain', val); + this.isValidHostname('NXT', 'next domain', val); + + // RFC 4034: letters in the DNS names are lower cased + this.set('next domain', val.toLowerCase()); + } + + setTypeBitMap(val) { + if (!val) this.throwHelp(`NXT: 'type bit map' is required`); + + this.set('type bit map', val); + } + + getDescription() { + return 'Next Secure' + } + + getCanonical() { + return { + owner: 'big.example.com.', + ttl: 3600, + class: 'IN', + type: 'NXT', + 'next domain': 'host.example.com.', + 'type bit map': 'A MX NXT', + } + } + + /****** IMPORTERS *******/ + + fromTinydns({ tinyline }) { + const [owner, n, rdata, ttl, ts, loc] = tinyline.slice(1).split(':'); + if (parseInt(n, 10) !== this.getTypeId()) this.throwHelp('NXT fromTinydns, invalid n'); + + const binaryRdata = Uint8Array.from(octalToChar(rdata), (c) => c.charCodeAt(0)); + const [nextDomain, _escapedLen, binaryLen] = unpackDomainName(rdata); + + return new NXT({ + owner: this.fullyQualify(owner), + ttl: parseInt(ttl, 10), + type: 'NXT', + 'next domain': nextDomain, + 'type bit map': new TextDecoder().decode(binaryRdata.subarray(binaryLen)), + timestamp: ts, + location: loc?.trim() ?? '', + }) + } + + fromBind({ bindline }) { + // test.example.com 3600 IN NXT NextDomain TypeBitMap + const [owner, ttl, c, type, next] = bindline.split(/\s+/); + return new NXT({ + owner, + ttl: parseInt(ttl, 10), + class: c, + type: type, + 'next domain': next, + 'type bit map': bindline.split(/\s+/).slice(5).filter(removeParens).join(' ').trim(), + }) + } + + fromWire({ owner, cls, ttl, rdata }) { + const { fqdn: nextDomain, end } = this.wireUnpackDomain(rdata, 0); + const typeBitMap = nxtBitmapToTypes(rdata.subarray(end)); + return new NXT({ + owner, + ttl, + class: cls, + type: 'NXT', + 'next domain': nextDomain, + 'type bit map': typeBitMap, + }) + } + + /****** EXPORTERS *******/ + + toTinydns() { + const dataRe = new RegExp(/[\r\n\t:\\/]/, 'g'); + + return this.getTinydnsGeneric( + packDomainName(this.get('next domain')) + escapeOctal(dataRe, this.get('type bit map')), + ) + } + + getWireRdata() { + const nameBytes = this.wirePackDomain(this.get('next domain')); + const bitmapBytes = typesToNxtBitmap(this.get('type bit map')); + const result = new Uint8Array(nameBytes.length + bitmapBytes.length); + result.set(nameBytes); + result.set(bitmapBytes, nameBytes.length); + return result + } +} + +const removeParens = (a) => !['(', ')'].includes(a); + +function nxtBitmapToTypes(bitmap) { + const DNS_TYPE_NAMES = Object.fromEntries(Object.entries(DNS_TYPE_IDS).map(([k, v]) => [v, k])); + const types = []; + for (let i = 0; i < bitmap.length; i++) { + const byte = bitmap[i]; + for (let bit = 0; bit < 8; bit++) { + if (byte & (0x80 >> bit)) { + const typeId = i * 8 + bit; + types.push(DNS_TYPE_NAMES[typeId] ?? `TYPE${typeId}`); + } + } + } + return types.join(' ') +} + +function typesToNxtBitmap(typeNamesStr) { + const bitmap = new Uint8Array(16); + for (const name of typeNamesStr.trim().split(/\s+/)) { + const id = /^TYPE\d+$/i.test(name) ? parseInt(name.slice(4), 10) : DNS_TYPE_IDS[name.toUpperCase()]; + if (id !== undefined && id < 128) bitmap[Math.floor(id / 8)] |= 0x80 >> (id % 8); + } + let len = bitmap.length; + while (len > 0 && bitmap[len - 1] === 0) len--; + return bitmap.slice(0, len) +} + +class OPENPGPKEY extends RR { + static typeName = 'OPENPGPKEY' + static typeId = 61 + static RFCs = [4880, 7929] + static rdataFields = [['public key', 'base64']] + static tags = ['security'] + + constructor(opts) { + super(opts); + } + + /****** Resource record specific setters *******/ + setPublicKey(val) { + this.isBase64('OPENPGPKEY', 'public key', val); + this.set('public key', val); + } + + getDescription() { + return 'OpenPGP Public Key' + } + + getCanonical() { + return { + owner: 'matt.example.com.', + ttl: 3600, + class: 'IN', + type: 'OPENPGPKEY', + 'public key': + 'AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwIXAqcOTiW7iHnQt5hwVAAAAA==', + } + } + + /****** IMPORTERS *******/ + fromBind({ bindline: bindline }) { + // test.example.com 3600 IN OPENPGPKEY + const regex = + /^(?\S+)\s+(?\d{1,10})\s+(?IN)\s+(?OPENPGPKEY)\s+(?\S[\s\S]*)$/i; + const match = bindline.trim().match(regex); + if (!match) this.throwHelp(`unable to parse OPENPGPKEY: ${bindline}`); + + const { owner, ttl, class: c, type, publickey } = match.groups; + const keyStr = publickey.trim().replace(/\s+/g, ''); + + return new OPENPGPKEY({ + owner, + ttl: parseInt(ttl, 10), + class: c, + type: type, + 'public key': keyStr, + }) + } + + fromTinydns({ tinyline }) { + const { owner, typeId, rdata, ttl, timestamp, location } = this.parseTinydnsLine(tinyline); + if (typeId != this.getTypeId()) this.throwHelp('OPENPGPKEY fromTinydns, invalid n'); + return new OPENPGPKEY({ + owner, + ttl, + type: 'OPENPGPKEY', + 'public key': octalToBase64(rdata), + timestamp, + location, + }) + } + + /****** EXPORTERS *******/ + toTinydns() { + return this.getTinydnsGeneric(base64toOctal(this.get('public key'))) + } + + getWireRdata() { + return base64ToBytes(this.get('public key')) + } +} + +class PTR extends RR { + static typeName = 'PTR' + static typeId = 12 + static RFCs = [1035] + static tinydnsType = '^' + static rdataFields = [['dname', 'fqdn']] + static tags = ['common'] + + constructor(opts) { + super(opts); + } + + /****** Resource record specific setters *******/ + setDname(val) { + this.isFullyQualified('PTR', 'dname', val); + this.isValidHostname('PTR', 'dname', val); + + // RFC 4034: letters in the DNS names are lower cased + this.set('dname', val.toLowerCase()); + } + + getDescription() { + return 'Pointer' + } + + getCanonical() { + return { + owner: '2.2.0.192.in-addr.arpa.', + ttl: 3600, + class: 'IN', + type: 'PTR', + dname: 'host.example.com.', + } + } + + /****** EXPORTERS *******/ + getWireRdata() { + return this.wirePackDomain(this.get('dname')) + } +} + +class RP extends RR { + static typeName = 'RP' + static rdataFields = [ + ['mbox', 'fqdn'], + ['txt', 'fqdn'], + ] + + constructor(opts) { + super(opts); + } + + /****** Resource record specific setters *******/ + setMbox(val) { + if (!val) this.throwHelp('RP: mbox is required'); + + this.isFullyQualified('RP', 'mbox', val); + + this.set('mbox', val.toLowerCase()); + } + + setTxt(val) { + if (!val) this.throwHelp('RP: txt is required'); + + this.isFullyQualified('RP', 'txt', val); + + this.set('txt', val.toLowerCase()); + } + + getDescription() { + return 'Responsible Person' + } + static tags = ['obsolete'] + static RFCs = [1183] + static typeId = 17 + getCanonical() { + return { + owner: 'example.com.', + ttl: 3600, + class: 'IN', + type: 'RP', + mbox: 'admin.example.com.', + txt: 'info.example.com.', + } + } + + /****** IMPORTERS *******/ + fromTinydns({ tinyline }) { + const [owner, _typeId, rdata, ttl, ts, loc] = tinyline.slice(1).split(':'); + + const [mbox, consumed] = unpackDomainName(rdata); + const txt = unpackDomainName(rdata.slice(consumed))[0]; + + return new RP({ + owner: this.fullyQualify(owner), + ttl: parseInt(ttl, 10), + type: 'RP', + mbox, + txt, + timestamp: ts, + location: loc?.trim() ?? '', + }) + } + + /****** EXPORTERS *******/ + + getWireRdata() { + const mbox = this.wirePackDomain(this.get('mbox')); + const txt = this.wirePackDomain(this.get('txt')); + const result = new Uint8Array(mbox.length + txt.length); + result.set(mbox, 0); + result.set(txt, mbox.length); + return result + } + + toTinydns() { + return this.getTinydnsGeneric( + packDomainName(this.get('mbox')) + packDomainName(this.get('txt')), + ) + } +} + +class RRSIG extends RR { + static typeName = 'RRSIG' + static typeId = 46 + static RFCs = [4034] + static rdataFields = [ + ['type covered', 'u16'], + ['algorithm', 'u8'], + ['labels', 'u8'], + ['original ttl', 'u32'], + ['signature expiration', 'u32'], + ['signature inception', 'u32'], + ['key tag', 'u16'], + ['signers name', 'fqdn'], + ['signature', 'str'], + ] + static tags = ['dnssec'] + + constructor(opts) { + super(opts); + } + + /****** Resource record specific setters *******/ + setTypeCovered(val) { + // a 16-bit Type Covered field (RFC 4034 §3.1.1) + if (!val && val !== 0) this.throwHelp(`RRSIG: 'type covered' is required`); + if (typeof val === 'string') { + const typeNN = val.match(/^TYPE(\d+)$/i); + if (typeNN) { + val = parseInt(typeNN[1], 10); + } else { + const id = DNS_TYPE_IDS[val.toUpperCase()]; + if (id === undefined) this.throwHelp(`RRSIG: 'type covered' is not a recognized type name`); + val = id; + } + } + this.is16bitInt('RRSIG', 'type covered', val); + this.set('type covered', val); + } + + setAlgorithm(val) { + // a 1 octet Algorithm field + if (!this.getAlgorithmOptions().has(val)) this.throwHelp(`RRSIG: algorithm invalid`); + + this.set('algorithm', val); + } + + setLabels(val) { + this.setTypedValue('u8', 'labels', val); + } + + setOriginalTtl(val) { + this.setTypedValue('u32', 'original ttl', val); + } + + setSignatureExpiration(val) { + this.setTypedValue('u32', 'signature expiration', val); + } + + setSignatureInception(val) { + this.setTypedValue('u32', 'signature inception', val); + } + + setKeyTag(val) { + this.setTypedValue('u16', 'key tag', val); + } + + setSignersName(val) { + this.setTypedValue('fqdn', 'signers name', val); + } + + setSignature(val) { + this.setTypedValue('str', 'signature', val); + } + + getAlgorithmOptions() { + // IANA DNSSEC Algorithm Numbers + // https://www.iana.org/assignments/dns-sec-alg-numbers/ + return new Map([ + [1, 'RSA/MD5'], + [2, 'DH'], + [3, 'DSA/SHA-1'], + [4, 'EC'], + [5, 'RSA/SHA-1'], + [6, 'DSA-NSEC3-SHA1'], + [7, 'RSASHA1-NSEC3-SHA1'], + [8, 'RSA/SHA-256'], + [10, 'RSA/SHA-512'], + [13, 'ECDSA P-256/SHA-256'], + [14, 'ECDSA P-384/SHA-384'], + [15, 'Ed25519'], + [16, 'Ed448'], + [253], + [254], + ]) + } + + getDescription() { + return 'Resource Record Signature' + } + + getCanonical() { + return { + owner: 'example.com.', + ttl: 3600, + class: 'IN', + type: 'RRSIG', + 'type covered': 1, + algorithm: 5, + labels: 3, + 'original ttl': 3600, + 'signature expiration': 1045053120, + 'signature inception': 1042461120, + 'key tag': 12345, + 'signers name': 'example.com.', + signature: 'ABCDEF...', + } + } + + /****** IMPORTERS *******/ + + fromBind({ bindline }) { + // example.com. 3600 IN RRSIG typecovered algorithm labels origttl sigexp siginc keytag signersname ( signature ) + const parts = bindline.trim().split(/\s+/); + const typeCoveredStr = parts[4]; + // type covered may be a type name ('A', 'MX'), TYPEnn (RFC 3597), or a numeric ID + const typeNN = typeCoveredStr.match(/^TYPE(\d+)$/i); + const typeCovered = /^\d+$/.test(typeCoveredStr) + ? parseInt(typeCoveredStr, 10) + : typeNN + ? parseInt(typeNN[1], 10) + : (DNS_TYPE_IDS[typeCoveredStr.toUpperCase()] ?? parseInt(typeCoveredStr, 10)); + return new RRSIG({ + owner: parts[0], + ttl: parseInt(parts[1], 10), + class: parts[2], + type: 'RRSIG', + 'type covered': typeCovered, + algorithm: parseInt(parts[5], 10), + labels: parseInt(parts[6], 10), + 'original ttl': parseInt(parts[7], 10), + 'signature expiration': parseInt(parts[8], 10), + 'signature inception': parseInt(parts[9], 10), + 'key tag': parseInt(parts[10], 10), + 'signers name': parts[11], + signature: parts + .slice(12) + .filter((a) => a !== '(' && a !== ')') + .join(' ') + .trim(), + }) + } + + fromTinydns({ tinyline }) { + const [fqdn, n, rdata, ttl, ts, loc] = tinyline.slice(1).split(':'); + if (parseInt(n, 10) !== this.getTypeId()) this.throwHelp('RRSIG fromTinydns, invalid n'); + + const bytes = Uint8Array.from(octalToChar(rdata), (c) => c.charCodeAt(0)); + const dv = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength); + const typeCovered = dv.getUint16(0); + const algorithm = bytes[2]; + const labels = bytes[3]; + const originalTtl = dv.getUint32(4); + const signatureExpiration = dv.getUint32(8); + const signatureInception = dv.getUint32(12); + const keyTag = dv.getUint16(16); + + let pos = 18; + const labelArr = []; + while (pos < bytes.length) { + const len = bytes[pos++]; + if (len === 0) break + labelArr.push(new TextDecoder().decode(bytes.subarray(pos, pos + len))); + pos += len; + } + const signersName = `${labelArr.join('.')}.`; + const signature = new TextDecoder().decode(bytes.subarray(pos)); + + return new RRSIG({ + owner: this.fullyQualify(fqdn), + ttl: parseInt(ttl, 10), + type: 'RRSIG', + 'type covered': typeCovered, + algorithm, + labels, + 'original ttl': originalTtl, + 'signature expiration': signatureExpiration, + 'signature inception': signatureInception, + 'key tag': keyTag, + 'signers name': signersName, + signature, + timestamp: ts, + location: loc?.trim() ?? '', + }) + } + + /****** EXPORTERS *******/ + + toTinydns() { + const dataRe = new RegExp(/[\r\n\t:]/, 'g'); + return this.getTinydnsGeneric( + UInt16toOctal(this.get('type covered')) + + UInt8toOctal(this.get('algorithm')) + + UInt8toOctal(this.get('labels')) + + UInt32toOctal(this.get('original ttl')) + + UInt32toOctal(this.get('signature expiration')) + + UInt32toOctal(this.get('signature inception')) + + UInt16toOctal(this.get('key tag')) + + packDomainName(this.get('signers name')) + + escapeOctal(dataRe, this.get('signature')), + ) + } + + getWireRdata() { + const signerBytes = wirePackDomain(this.get('signers name')); + const sigBytes = new TextEncoder().encode(this.get('signature')); + + const totalLen = 2 + 1 + 1 + 4 + 4 + 4 + 2 + signerBytes.length + sigBytes.length; + const bytes = new Uint8Array(totalLen); + const dv = new DataView(bytes.buffer, bytes.byteOffset); + + let pos = 0; + dv.setUint16(pos, this.get('type covered')); + pos += 2; + bytes[pos++] = this.get('algorithm'); + bytes[pos++] = this.get('labels'); + dv.setUint32(pos, this.get('original ttl')); + pos += 4; + dv.setUint32(pos, this.get('signature expiration')); + pos += 4; + dv.setUint32(pos, this.get('signature inception')); + pos += 4; + dv.setUint16(pos, this.get('key tag')); + pos += 2; + bytes.set(signerBytes, pos); + pos += signerBytes.length; + bytes.set(sigBytes, pos); + + return bytes + } +} + +class SIG extends RR { + static typeName = 'SIG' + static typeId = 24 + static RFCs = [2535, 3755] + static rdataFields = [ + ['type covered', 'u16'], + ['algorithm', 'u8'], + ['labels', 'u8'], + ['original ttl', 'u32'], + ['signature expiration', 'u32'], + ['signature inception', 'u32'], + ['key tag', 'u16'], + ['signers name', 'fqdn'], + ['signature', 'str'], + ] + static tags = ['obsolete'] + + constructor(opts) { + super(opts); + } + + /****** Resource record specific setters *******/ + setTypeCovered(val) { + // a 2 octet Type Covered field + if (!val) this.throwHelp(`SIG: 'type covered' is required`); + + this.set('type covered', val); + } + + setAlgorithm(val) { + // a 1 octet Algorithm field + this.is8bitInt('SIG', 'algorithm', val); + + this.set('algorithm', val); + } + + setLabels(val) { + // a 1 octet Labels field + this.is8bitInt('SIG', 'labels', val); + + this.set('labels', val); + } + + setOriginalTtl(val) { + // a 4 octet Original TTL field + this.is32bitInt('SIG', 'original ttl', val); + + this.set('original ttl', val); + } + + setSignatureExpiration(val) { + // a 4 octet Signature Expiration field + this.set('signature expiration', val); + } + + setSignatureInception(val) { + // a 4 octet Signature Inception field + this.set('signature inception', val); + } + + setKeyTag(val) { + // a 2 octet Key tag + this.set('key tag', val); + } + + setSignersName(val) { + // the domain name of the signer generating the SIG RR + + // RFC 4034: letters in the DNS names are lower cased + this.set('signers name', val.toLowerCase()); + } + + setSignature(val) { + // the Signature field. + + this.set('signature', val); + } + + getDescription() { + return 'Signature' + } + + getCanonical() { + return { + owner: 'example.com.', + ttl: 3600, + class: 'IN', + type: 'SIG', + 'type covered': 1, + algorithm: 5, + labels: 3, + 'original ttl': 3600, + 'signature expiration': 1045053120, + 'signature inception': 1042461120, + 'key tag': 12345, + 'signers name': 'example.com.', + signature: 'ABCDEF...', + } + } + + /****** IMPORTERS *******/ + + fromBind({ bindline }) { + // example.com. 3600 IN SIG TypeCovered Algorithm Labels OrigTTL SigExpiration SigInception KeyTag SignersName ( Signature ) + const parts = bindline.trim().split(/\s+/); + const typeCoveredStr = parts[4]; + const typeCovered = /^\d+$/.test(typeCoveredStr) + ? parseInt(typeCoveredStr, 10) + : (DNS_TYPE_IDS[typeCoveredStr.toUpperCase()] ?? parseInt(typeCoveredStr, 10)); + + return new SIG({ + owner: parts[0], + ttl: parseInt(parts[1], 10), + class: parts[2], + type: 'SIG', + 'type covered': typeCovered, + algorithm: parseInt(parts[5], 10), + labels: parseInt(parts[6], 10), + 'original ttl': parseInt(parts[7], 10), + 'signature expiration': parseInt(parts[8], 10), + 'signature inception': parseInt(parts[9], 10), + 'key tag': parseInt(parts[10], 10), + 'signers name': parts[11], + signature: parts + .slice(12) + .filter((a) => a !== '(' && a !== ')') + .join(' ') + .trim(), + }) + } + + /****** EXPORTERS *******/ + toTinydns() { + const dataRe = new RegExp(/[\r\n\t:]/, 'g'); + + return this.getTinydnsGeneric( + UInt16toOctal(this.get('type covered')) + + UInt8toOctal(this.get('algorithm')) + + UInt8toOctal(this.get('labels')) + + UInt32toOctal(this.get('original ttl')) + + UInt32toOctal(this.get('signature expiration')) + + UInt32toOctal(this.get('signature inception')) + + UInt16toOctal(this.get('key tag')) + + packDomainName(this.get('signers name')) + + escapeOctal(dataRe, this.get('signature')), + ) + } + + getWireRdata() { + const signerBytes = wirePackDomain(this.get('signers name')); + const sigBytes = new TextEncoder().encode(this.get('signature')); + + const totalLen = 2 + 1 + 1 + 4 + 4 + 4 + 2 + signerBytes.length + sigBytes.length; + const bytes = new Uint8Array(totalLen); + const dv = new DataView(bytes.buffer, bytes.byteOffset); + + let pos = 0; + dv.setUint16(pos, this.get('type covered')); + pos += 2; + bytes[pos++] = this.get('algorithm'); + bytes[pos++] = this.get('labels'); + dv.setUint32(pos, this.get('original ttl')); + pos += 4; + dv.setUint32(pos, this.get('signature expiration')); + pos += 4; + dv.setUint32(pos, this.get('signature inception')); + pos += 4; + dv.setUint16(pos, this.get('key tag')); + pos += 2; + bytes.set(signerBytes, pos); + pos += signerBytes.length; + bytes.set(sigBytes, pos); + + return bytes + } + + fromTinydns({ tinyline }) { + const { owner, typeId, rdata, ttl, timestamp, location } = this.parseTinydnsLine(tinyline); + if (parseInt(typeId, 10) !== this.getTypeId()) this.throwHelp('SIG fromTinydns, invalid n'); + + const bytes = octalRdataToBytes(rdata); + const dv = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength); + + const typeCovered = dv.getUint16(0); + const algorithm = bytes[2]; + const labels = bytes[3]; + const originalTtl = dv.getUint32(4); + const signatureExpiration = dv.getUint32(8); + const signatureInception = dv.getUint32(12); + const keyTag = dv.getUint16(16); + + // parse signers name from binary starting at offset 18 + let pos = 18; + const labelsArr = []; + while (pos < bytes.length) { + const len = bytes[pos++]; + if (len === 0) break + labelsArr.push(new TextDecoder().decode(bytes.subarray(pos, pos + len))); + pos += len; + } + const signersName = `${labelsArr.join('.')}.`; + + const signature = new TextDecoder().decode(bytes.subarray(pos)); + + return new SIG({ + owner, + ttl, + type: 'SIG', + 'type covered': typeCovered, + algorithm, + labels, + 'original ttl': originalTtl, + 'signature expiration': signatureExpiration, + 'signature inception': signatureInception, + 'key tag': keyTag, + 'signers name': signersName, + signature, + timestamp, + location, + }) + } + + toBind(zone_opts) { + return `${this.getFQDN('owner', zone_opts)} ${this.get('ttl')} ${this.get('class')} SIG${this.getRdataFields() + .slice(0, 4) + .map((f) => ' ' + this.get(f)) + .join('')} ${this.getRdataFields() + .slice(4, 8) + .map((f) => this.get(f)) + .join(' ')} ( ${this.get('signature')} )` + } +} + +class SMIMEA extends RR { + static typeName = 'SMIMEA' + static typeId = 53 + static RFCs = [8162] + static rdataFields = [ + ['certificate usage', 'u8'], + ['selector', 'u8'], + ['matching type', 'u8'], + ['certificate association data', 'hex'], + ] + static tags = ['security'] + + constructor(opts) { + super(opts); + } + + /****** Resource record specific setters *******/ + setCertificateUsage(val) { + if (!this.getCertificateUsageOptions().has(val)) this.throwHelp(`SMIMEA: certificate usage invalid`); + + this.set('certificate usage', val); + } + + getCertificateUsageOptions() { + return new Map([ + [0, 'CA certificate'], + [1, 'an end entity certificate'], + [2, 'the trust anchor'], + [3, 'domain-issued certificate'], + ]) + } + + setSelector(val) { + if (!this.getSelectorOptions().has(val)) this.throwHelp(`SMIMEA: selector invalid`); + + this.set('selector', val); + } + + getSelectorOptions() { + return new Map([ + [0, 'Full certificate'], + [1, 'SubjectPublicKeyInfo'], + ]) + } + + setMatchingType(val) { + if (!this.getMatchingTypeOptions().has(val)) this.throwHelp(`SMIMEA: matching type`); + + this.set('matching type', val); + } + + getMatchingTypeOptions() { + return new Map([ + [0, 'Exact match'], + [1, 'SHA-256 hash'], + [2, 'SHA-512 hash'], + ]) + } + + setCertificateAssociationData(val) { + this.set('certificate association data', val); + } + + getDescription() { + return 'S/MIME cert association' + } + + getCanonical() { + return { + owner: '_443._tcp.www.example.com.', + ttl: 3600, + class: 'IN', + type: 'SMIMEA', + 'certificate usage': 0, + selector: 0, + 'matching type': 1, + 'certificate association data': 'ABCDEF...', + } + } + + /****** IMPORTERS *******/ + + fromBind({ bindline }) { + // test.example.com 3600 IN SMIMEA, usage, selector, match, data + const [owner, ttl, c, type, usage, selector, match] = bindline.split(/\s+/); + return new SMIMEA({ + owner, + ttl: parseInt(ttl, 10), + class: c, + type: type, + 'certificate usage': parseInt(usage, 10), + selector: parseInt(selector, 10), + 'matching type': parseInt(match, 10), + 'certificate association data': bindline.split(/\s+/).slice(7).join(' ').trim(), + }) + } + + fromTinydns({ tinyline }) { + const { owner, rdata, ttl, timestamp, location } = this.parseTinydnsLine(tinyline); + const binaryRdata = octalRdataToBytes(rdata); + + return new SMIMEA({ + owner, + ttl, + type: 'SMIMEA', + 'certificate usage': binaryRdata[0], + selector: binaryRdata[1], + 'matching type': binaryRdata[2], + 'certificate association data': bytesToHex(binaryRdata.subarray(3)), + timestamp, + location, + }) + } + + /****** EXPORTERS *******/ + toTinydns() { + return this.getTinydnsGeneric( + UInt8toOctal(this.get('certificate usage')) + + UInt8toOctal(this.get('selector')) + + UInt8toOctal(this.get('matching type')) + + packHex(this.get('certificate association data').replace(/[\s()]/g, '')), + ) + } + + getWireRdata() { + const cadBytes = hexToBytes(this.get('certificate association data').replace(/[\s()]/g, '')); + const bytes = new Uint8Array(3 + cadBytes.length); + bytes[0] = this.get('certificate usage'); + bytes[1] = this.get('selector'); + bytes[2] = this.get('matching type'); + bytes.set(cadBytes, 3); + return bytes + } +} + +class SOA extends RR { + static typeName = 'SOA' + static typeId = 6 + static RFCs = [1035, 2308] + static tinydnsType = 'Z' + static rdataFields = [ + ['mname', 'fqdn'], + ['rname', 'fqdn'], + ['serial', 'u32'], + ['refresh', 'u32'], + ['retry', 'u32'], + ['expire', 'u32'], + ['minimum', 'u32'], + ] + static tags = ['common'] + + constructor(opts) { + super(opts); + } + + /****** Resource record specific setters *******/ + setMinimum(val) { + // minimum (used for negative caching, since RFC 2308) + // RFC 1912 sugggests 1-5 days + // RIPE recommends 3600 (1 hour) + this.is32bitInt('SOA', 'minimum', val); + + this.set('minimum', val); + } + + setMname(val) { + // MNAME (primary NS) + this.isValidHostname('SOA', 'MNAME', val); + this.isFullyQualified('SOA', 'MNAME', val); + + // RFC 4034: letters in the DNS names are lower cased + this.set('mname', val.toLowerCase()); + } + + setRname(val) { + // RNAME (email of admin) (escape . with \) + this.isValidHostname('SOA', 'RNAME', val); + this.isFullyQualified('SOA', 'RNAME', val); + if (/@/.test(val)) this.throwHelp(`SOA rname replaces @ with a . (dot)`); + + // RFC 4034: letters in the DNS names are lower cased + this.set('rname', val.toLowerCase()); + } + + setSerial(val) { + this.is32bitInt('SOA', 'serial', val); + + this.set('serial', val); + } + + setRefresh(val) { + // refresh (seconds after which to check with master for update) + // RFC 1912 suggests 20 min to 12 hours + // RIPE recommends 86400 (24 hours) + this.is32bitInt('SOA', 'refresh', val); + + this.set('refresh', val); + } + + setRetry(val) { + // seconds after which to retry serial # update + // RIPE recommends 7200 seconds (2 hours) + + this.is32bitInt('SOA', 'retry', val); + + this.set('retry', val); + } + + setExpire(val) { + // seconds after which secondary should drop zone if no master response + // RFC 1912 suggests 2-4 weeks + // RIPE suggests 3600000 (1,000 hours, 6 weeks) + this.is32bitInt('SOA', 'expire', val); + + this.set('expire', val); + } + + getDescription() { + return 'Start Of Authority' + } + + getCanonical() { + return { + owner: 'example.com.', + ttl: 3600, + class: 'IN', + type: 'SOA', + mname: 'ns1.example.com.', + rname: 'admin.example.com.', + serial: 2023051001, + refresh: 7200, + retry: 3600, + expire: 1209600, + minimum: 3600, + } + } + + /****** IMPORTERS *******/ + fromTinydns({ tinyline }) { + // Zfqdn:mname:rname:ser:ref:ret:exp:min:ttl:time:lo + const [fqdn, mname, rname, ser, ref, ret, exp, min, ttl, ts, loc] = tinyline.slice(1).split(':'); + + return new SOA({ + owner: this.fullyQualify(fqdn), + ttl: parseInt(ttl, 10), + type: 'SOA', + mname: this.fullyQualify(mname), + rname: this.fullyQualify(rname), + serial: parseInt(ser ?? this.default?.serial, 10), + refresh: parseInt(ref, 10) || 16384, + retry: parseInt(ret, 10) || 2048, + expire: parseInt(exp, 10) || 1048576, + minimum: parseInt(min, 10) || 2560, + timestamp: parseInt(ts) || '', + location: loc?.trim() ?? '', + }) + } + + /****** EXPORTERS *******/ + toMaraDNS() { + return `${this.get('owner')}\t SOA\t${this.getFields('rdata') + .map((f) => this.getQuoted(f)) + .join('\t')} ~\n` + } + + getWireRdata() { + const mname = this.wirePackDomain(this.get('mname')); + const rname = this.wirePackDomain(this.get('rname')); + const result = new Uint8Array(mname.length + rname.length + 20); + let offset = 0; + result.set(mname, offset); + offset += mname.length; + result.set(rname, offset); + offset += rname.length; + const view = new DataView(result.buffer, offset); + view.setUint32(0, this.get('serial')); + view.setUint32(4, this.get('refresh')); + view.setUint32(8, this.get('retry')); + view.setUint32(12, this.get('expire')); + view.setUint32(16, this.get('minimum')); + return result + } + + toTinydns() { + return `Z${this.getTinyFQDN('owner')}:${this.getTinyFQDN('mname')}:${this.getTinyFQDN('rname')}:${this.getEmpty('serial')}:${this.getEmpty('refresh')}:${this.getEmpty('retry')}:${this.getEmpty('expire')}:${this.getEmpty('minimum')}:${this.getTinydnsPostamble()}\n` + } +} + +class TXT extends RR { + static typeName = 'TXT' + static typeId = 16 + static RFCs = [1035, 4408, 7208, 6376] + static tinydnsType = "'" + static rdataFields = [['data', 'charstrs']] + static tags = ['common'] + + constructor(opts) { + super(opts); + } + + /****** Resource record specific setters *******/ + setData(val) { + this.set('data', val); + } + + getDescription() { + return 'Text' + } + + getCanonical() { + return { + owner: 'example.com.', + ttl: 3600, + class: 'IN', + type: 'TXT', + data: 'v=spf1 mx -all', + } + } + + /****** IMPORTERS *******/ + fromTinydns({ tinyline }) { + const str = tinyline; + let fqdn, rdata, s, ttl, ts, loc; + // 'fqdn:s:ttl:timestamp:lo + if (str[0] === "'") { +[fqdn, s, ttl, ts, loc] = str.slice(1).split(':'); + rdata = octalToChar(s); + } else { +[fqdn, rdata, ttl, ts, loc] = this.fromTinydnsGeneric(str); + } + + return new this.constructor({ + owner: this.fullyQualify(fqdn), + ttl: parseInt(ttl, 10), + type: 'TXT', + data: rdata, + timestamp: ts, + location: loc?.trim() || '', + }) + } + + fromTinydnsGeneric(str) { + // generic: :fqdn:n:rdata:ttl:timestamp:location + // eslint-disable-next-line prefer-const + let [fqdn, n, rdata, ttl, ts, loc] = str.slice(1).split(':'); + if (n != 16) this.throwHelp('TXT fromTinydns, invalid n'); + + rdata = octalToChar(rdata); + // Walk RFC 1035 §3.3.14 len-prefixed segments. + const parts = []; + let pos = 0; + while (pos < rdata.length) { + const len = rdata.charCodeAt(pos); + pos += 1; + if (pos + len > rdata.length) { + this.throwHelp('TXT fromTinydnsGeneric: truncated character-string in rdata'); + } + parts.push(rdata.slice(pos, pos + len)); + pos += len; + } + const data = parts.length > 1 ? parts : (parts[0] ?? ''); + return [fqdn, data, ttl, ts, loc] + } + + /****** EXPORTERS *******/ + toBind(zone_opts) { + return `${this.getPrefix(zone_opts)}\t"${asQuotedStrings(this.get('data'))}"\n` + } + + toMaraDNS() { + const data = asQuotedStrings(this.get('data')).replace(/"/g, "'"); + return `${this.get('owner')}\t+${this.get('ttl')}\t${this.get('type')}\t'${data}' ~\n` + } + + getWireRdata() { + // RFC 1035 §3.3.14: TXT rdata is one or more s, each up + // to 255 bytes. An array preserves explicit boundaries between strings; + // each element MUST be <= 255 UTF-8 bytes, otherwise we would silently + // split it and the boundary the caller asked us to preserve would be lost. + // A single string is auto-chunked at 255-byte UTF-8 boundaries. + const data = this.get('data'); + if (Array.isArray(data)) { + const enc = new TextEncoder(); + const buffers = data.map((s, i) => { + if (enc.encode(s).length > 255) { + this.throwHelp( + `TXT: array element ${i} exceeds 255 bytes; split it yourself or pass a single string to auto-chunk`, + ); + } + return packStringWire(s) + }); + const total = buffers.reduce((n, b) => n + b.length, 0); + const out = new Uint8Array(total); + let off = 0; + for (const b of buffers) { + out.set(b, off); + off += b.length; + } + return out + } + return packStringWire(data) + } + + toTinydns() { + let data = this.get('data'); + if (Array.isArray(data)) data = data.join(''); + const rdata = escapeOctal(new RegExp(/[\r\n\t:\\/]/, 'g'), data); + return `'${this.getTinyFQDN('owner')}:${rdata}:${this.getTinydnsPostamble()}\n` + } +} + +function asQuotedStrings(data) { + // RFC 1035 character-strings are 255 bytes max; chunk by UTF-8 bytes, + // not JS chars, so non-ASCII TXT data doesn't overflow the 255-byte limit. + const enc = new TextEncoder(); + + if (Array.isArray(data)) { + const anyTooLong = data.some((s) => enc.encode(s).length > 255); + if (!anyTooLong) return data.join('" "') + return chunkByBytes(data.join(''), 255).join('" "') + } + + if (enc.encode(data).length <= 255) return data + return chunkByBytes(data, 255).join('" "') +} + +function chunkByBytes(str, maxBytes) { + const bytes = new TextEncoder().encode(str); + const dec = new TextDecoder(); + const chunks = []; + let start = 0; + while (start < bytes.length) { + let end = Math.min(start + maxBytes, bytes.length); + // back up to a UTF-8 codepoint boundary so decode() returns whole chars + while (end < bytes.length && (bytes[end] & 0xc0) === 0x80) end--; + chunks.push(dec.decode(bytes.subarray(start, end))); + start = end; + } + return chunks +} + +function packStringWire(str) { + const encoded = new TextEncoder().encode(str); + if (encoded.length === 0) return new Uint8Array([0]) + + const chunks = []; + for (let i = 0; i < encoded.length; i += 255) chunks.push(encoded.subarray(i, i + 255)); + + const buf = new Uint8Array(encoded.length + chunks.length); + let offset = 0; + for (const chunk of chunks) { + buf[offset++] = chunk.length; + buf.set(chunk, offset); + offset += chunk.length; + } + return buf +} + +// obsoleted by RFC 7208 + + +class SPF extends TXT { + static typeName = 'SPF' + static typeId = 99 + static RFCs = [4408, 7208] + static rdataFields = [['data', 'charstrs']] + static tags = ['obsolete'] + + constructor(opts) { + super(opts); + } + + /****** Resource record specific setters *******/ + setData(val) { + this.set('data', val); + } + + getDescription() { + return 'Sender Policy Framework' + } + getCanonical() { + return { + owner: 'example.com.', + ttl: 3600, + class: 'IN', + type: 'SPF', + data: 'v=spf1 mx -all', + } + } + + /****** IMPORTERS *******/ + fromTinydns({ tinyline }) { + // SPF via generic, :fqdn:n:rdata:ttl:timestamp:lo + const [fqdn, n, rdata, ttl, ts, loc] = tinyline.slice(1).split(':'); + if (n != 99) this.throwHelp('SPF fromTinydns, invalid n'); + + return new SPF({ + type: 'SPF', + owner: this.fullyQualify(fqdn), + data: octalToChar(rdata), + ttl: parseInt(ttl, 10), + timestamp: ts, + location: loc?.trim() ?? '', + }) + } + + /****** EXPORTERS *******/ + getWireRdata() { + return super.getWireRdata() + } + + toTinydns() { + // `data` may be a string or an array of s (RFC 1035 §3.3.14). + // tinydns generic format stores rdata as a flat byte stream, so join here. + let data = this.get('data'); + if (Array.isArray(data)) data = data.join(''); + const rdata = escapeOctal(new RegExp(/[\r\n\t:\\/]/, 'g'), data); + return this.getTinydnsGeneric(rdata) + } +} + +class SRV extends RR { + static typeName = 'SRV' + static typeId = 33 + static RFCs = [2782] + static rdataFields = [ + ['priority', 'u16'], + ['weight', 'u16'], + ['port', 'u16'], + ['target', 'fqdn'], + ] + static tags = ['common'] + + constructor(opts) { + super(opts); + } + + /****** Resource record specific setters *******/ + setPriority(val) { + this.setTypedValue('u16', 'priority', val); + } + + setWeight(val) { + this.setTypedValue('u16', 'weight', val); + } + + setPort(val) { + this.setTypedValue('u16', 'port', val); + } + + setTarget(val) { + this.setTypedValue('fqdn', 'target', val); + } + + getDescription() { + return 'Service' + } + + getCanonical() { + return { + owner: '_imaps._tcp.example.com.', + ttl: 3600, + class: 'IN', + type: 'SRV', + priority: 10, + weight: 10, + port: 993, + target: 'mail.example.com.', + } + } + + /****** IMPORTERS *******/ + fromTinydns({ tinyline }) { + const str = tinyline; + let fqdn, addr, port, pri, weight, ttl, ts, loc, n, rdata; + + if (str[0] === 'S') { +[fqdn, addr, port, pri, weight, ttl, ts, loc] = str.slice(1).split(':'); + } else { +[fqdn, n, rdata, ttl, ts, loc] = str.slice(1).split(':'); + if (n != 33) this.throwHelp('SRV fromTinydns: invalid n'); + + pri = octalToUInt16(rdata.slice(0, 8)); + weight = octalToUInt16(rdata.slice(8, 16)); + port = octalToUInt16(rdata.slice(16, 24)); + addr = unpackDomainName(rdata.slice(24))[0]; + } + + return new SRV({ + owner: this.fullyQualify(fqdn), + ttl: parseInt(ttl, 10), + type: 'SRV', + priority: parseInt(pri, 10), + weight: parseInt(weight, 10), + port: parseInt(port, 10), + target: this.fullyQualify(addr), + timestamp: ts, + location: loc?.trim() ?? '', + }) + } + + /****** EXPORTERS *******/ + + getWireRdata() { + const target = this.wirePackDomain(this.get('target')); + const result = new Uint8Array(6 + target.length); + const dv = new DataView(result.buffer); + dv.setUint16(0, this.get('priority')); + dv.setUint16(2, this.get('weight')); + dv.setUint16(4, this.get('port')); + result.set(target, 6); + return result + } + + toTinydns() { + let rdata = ''; + + for (const e of ['priority', 'weight', 'port']) { + rdata += UInt16toOctal(this.get(e)); + } + + rdata += packDomainName(this.get('target')); + + return this.getTinydnsGeneric(rdata) + } +} + +class SSHFP extends RR { + static typeName = 'SSHFP' + static typeId = 44 + static RFCs = [4255, 7479, 8709] + static rdataFields = [ + ['algorithm', 'u8'], + ['fptype', 'u8'], + ['fingerprint', 'hex'], + ] + static tags = ['security'] + + constructor(opts) { + super(opts); + } + + /****** Resource record specific setters *******/ + setAlgorithm(val) { + if (!this.getAlgorithmOptions().has(val)) this.throwHelp(`SSHFP: algorithm invalid`); + this.setTypedValue('u8', 'algorithm', val); + } + + setFptype(val) { + if (!this.getFptypeOptions().has(val)) this.throwHelp(`SSHFP: fptype invalid`); + this.setTypedValue('u8', 'fptype', val); + } + + setFingerprint(val) { + this.setTypedValue('hex', 'fingerprint', val); + } + + getAlgorithmOptions() { + return new Map([ + [0, 'reserved'], + [1, 'RSA'], + [2, 'DSA'], + [3, 'ECDSA'], + [4, 'Ed25519'], + [6, 'Ed448'], + ]) + } + + getFptypeOptions() { + return new Map([ + [0, 'reserved'], + [1, 'SHA-1'], + [2, 'SHA-256'], + ]) + } + + getDescription() { + return 'Secure Shell Key Fingerprints' + } + + getCanonical() { + return { + owner: 'mail.example.com.', + ttl: 3600, + class: 'IN', + type: 'SSHFP', + algorithm: 2, + fptype: 1, + fingerprint: '123456789abcdef6789abcdf6789abdf6789abcd', + } + } + + /****** IMPORTERS *******/ + fromTinydns({ tinyline }) { + // SSHFP via generic, :fqdn:n:rdata:ttl:timestamp:lo + const { owner, typeId, rdata, ttl, timestamp, location } = this.parseTinydnsLine(tinyline); + if (typeId != this.getTypeId()) this.throwHelp('SSHFP fromTinydns, invalid n'); + + return new SSHFP({ + owner, + ttl, + type: 'SSHFP', + algorithm: octalToUInt8(rdata.slice(0, 4)), + fptype: octalToUInt8(rdata.slice(4, 8)), + fingerprint: octalToHex(rdata.slice(8)), + timestamp, + location, + }) + } + + /****** EXPORTERS *******/ + + toTinydns() { + return this.getTinydnsGeneric( + UInt8toOctal(this.get('algorithm')) + + UInt8toOctal(this.get('fptype')) + + packHex(this.get('fingerprint')), + ) + } + + getWireRdata() { + const bytes = new Uint8Array(2 + hexToBytes(this.get('fingerprint')).length); + bytes[0] = this.get('algorithm'); + bytes[1] = this.get('fptype'); + bytes.set(hexToBytes(this.get('fingerprint')), 2); + return bytes + } +} + +class SVCB extends RR { + static typeName = 'SVCB' + static typeId = 64 + static RFCs = [9460] + static rdataFields = [ + ['priority', 'u16'], + ['target name', 'fqdn'], + ['params', 'svcparams'], + ] + + constructor(opts) { + super(opts); + } + + /****** Resource record specific setters *******/ + setPriority(val) { + this.is16bitInt('SVCB', 'priority', val); + + this.set('priority', val); + } + + setTargetName(val) { + // this.isFullyQualified('SVCB', 'target name', val) + // this.isValidHostname('SVCB', 'target name', val) + + // RFC 4034: letters in the DNS names are lower cased + this.set('target name', val.toLowerCase()); + } + + setParams(val) { + // if (!val) throw new Error(`SVCB: params is required`) + + this.set('params', val); + } + + getDescription() { + return 'Service Binding' + } + + getCanonical() { + return { + owner: '_8443._foo.api.example.com.', + ttl: 3600, + class: 'IN', + type: 'SVCB', + priority: 1, + 'target name': 'svc4.example.net.', + params: 'alpn="h2,h3"', + } + } + + /****** IMPORTERS *******/ + + fromBind({ bindline }) { + // test.example.com 3600 IN SVCB Priority TargetName Params + // _8443._foo.api.example.com. 7200 IN SVCB 0 svc4.example.net. + // svc4.example.net. 7200 IN SVCB 3 svc4.example.net. ( alpn="bar" port="8004" ) + const [owner, ttl, c, type, pri, fqdn] = bindline.split(/\s+/); + return new SVCB({ + owner, + ttl: parseInt(ttl, 10), + class: c, + type, + priority: parseInt(pri, 10), + 'target name': fqdn, + params: bindline.split(/\s+/).slice(6).join(' ').trim(), + }) + } + + fromTinydns({ tinyline }) { + const { owner, typeId, rdata, ttl, timestamp, location } = this.parseTinydnsLine(tinyline); + if (typeId != this.getTypeId()) this.throwHelp('SVCB fromTinydns, invalid n'); + const { priority, targetName, params } = parseSvcbLikeRdata(rdata, 'SVCB'); + + return new SVCB({ + owner, + ttl, + type: 'SVCB', + priority: priority, + 'target name': targetName, + params: params, + timestamp, + location, + }) + } + + /****** EXPORTERS *******/ + + toTinydns() { + const dataRe = new RegExp(/[\r\n\t:\\/]/, 'g'); + + return this.getTinydnsGeneric( + UInt16toOctal(this.get('priority')) + + packDomainName(this.get('target name')) + + escapeOctal(dataRe, this.get('params')), + ) + } + + getWireRdata() { + const targetBytes = this.wirePackDomain(this.get('target name')); + const paramsBytes = svcParamsToWire(this.get('params')); + const result = new Uint8Array(2 + targetBytes.length + paramsBytes.length); + new DataView(result.buffer).setUint16(0, this.get('priority')); + result.set(targetBytes, 2); + result.set(paramsBytes, 2 + targetBytes.length); + return result + } +} + +class TLSA extends RR { + static typeName = 'TLSA' + static typeId = 52 + static RFCs = [6698, 7671] + static rdataFields = [ + ['certificate usage', 'u8'], + ['selector', 'u8'], + ['matching type', 'u8'], + ['certificate association data', 'hex'], + ] + static tags = ['security'] + + constructor(opts) { + super(opts); + } + + /****** Resource record specific setters *******/ + setCertificateUsage(val) { + if (!this.getCertificateUsageOptions().has(val)) this.throwHelp(`TLSA: certificate usage invalid`); + + this.set('certificate usage', val); + } + + getCertificateUsageOptions() { + return new Map([ + [0, 'CA certificate'], + [1, 'an end entity certificate'], + [2, 'the trust anchor'], + [3, 'domain-issued certificate'], + ]) + } + + setSelector(val) { + if (!this.getSelectorOptions().has(val)) this.throwHelp(`TLSA: selector invalid`); + + this.set('selector', val); + } + + getSelectorOptions() { + return new Map([ + [0, 'Full certificate'], + [1, 'SubjectPublicKeyInfo'], + ]) + } + + setMatchingType(val) { + if (!this.getMatchingTypeOptions().has(val)) this.throwHelp(`TLSA: matching type`); + + this.set('matching type', val); + } + + getMatchingTypeOptions() { + return new Map([ + [0, 'Exact match'], + [1, 'SHA-256 hash'], + [2, 'SHA-512 hash'], + ]) + } + + setCertificateAssociationData(val) { + this.set('certificate association data', val); + } + + getDescription() { + return 'TLSA certificate association' + } + + getCanonical() { + return { + owner: '_443._tcp.www.example.com.', + ttl: 3600, + class: 'IN', + type: 'TLSA', + 'certificate usage': 3, + selector: 1, + 'matching type': 1, + 'certificate association data': 'ABCDEF...', + } + } + + /****** IMPORTERS *******/ + + fromBind({ bindline }) { + // test.example.com 3600 IN TLSA, usage, selector, match, data + const regex = + /^(?\S+)\s+(?\d{1,10})\s+(?IN)\s+(?TLSA)\s+(?\d+)\s+(?\d+)\s+(?\d+)\s+(?\S.*)$/i; + const match = bindline.trim().match(regex); + if (!match) this.throwHelp(`unable to parse TLSA: ${bindline}`); + const { owner, ttl, cls, type, usage, selector, matchtype, cad } = match.groups; + + return new TLSA({ + owner: this.fullyQualify(owner), + ttl: parseInt(ttl, 10), + class: cls.toUpperCase(), + type: type.toUpperCase(), + 'certificate usage': parseInt(usage, 10), + selector: parseInt(selector, 10), + 'matching type': parseInt(matchtype, 10), + 'certificate association data': cad.trim(), + }) + } + + fromTinydns({ tinyline }) { + const { owner, typeId, rdata, ttl, timestamp, location } = this.parseTinydnsLine(tinyline); + if (typeId != this.getTypeId()) this.throwHelp('TLSA fromTinydns, invalid n'); + + const bytes = octalRdataToBytes(rdata); + + return new TLSA({ + owner, + ttl, + type: 'TLSA', + 'certificate usage': bytes[0], + selector: bytes[1], + 'matching type': bytes[2], + 'certificate association data': bytesToHex(bytes.subarray(3)), + timestamp, + location, + }) + } + + /****** EXPORTERS *******/ + toTinydns() { + return this.getTinydnsGeneric( + UInt8toOctal(this.get('certificate usage')) + + UInt8toOctal(this.get('selector')) + + UInt8toOctal(this.get('matching type')) + + packHex(this.get('certificate association data').replace(/[\s()]/g, '')), + ) + } + + getWireRdata() { + const cadBytes = hexToBytes(this.get('certificate association data').replace(/[\s()]/g, '')); + const bytes = new Uint8Array(3 + cadBytes.length); + bytes[0] = this.get('certificate usage'); + bytes[1] = this.get('selector'); + bytes[2] = this.get('matching type'); + bytes.set(cadBytes, 3); + return bytes + } +} + +class TSIG extends RR { + static typeName = 'TSIG' + static typeId = 250 + static RFCs = [2845, 8945] + static rdataFields = ['algorithm name', 'time signed', 'fudge', 'mac', 'original id', 'error', 'other'] + + constructor(opts) { + super(opts); + if (opts === null) return + } + + /****** Resource record specific setters *******/ + + getDescription() { + return 'Transaction Signature' + } + + getCanonical() { + return { + owner: 'test.example.', + ttl: 0, + class: 'ANY', + type: 'TSIG', + 'algorithm name': 'hmac-sha256.', + 'time signed': 1620650000, + fudge: 300, + mac: 'ABCDEF...', + 'original id': 12345, + error: 0, + other: '', + } + } + + setClass(t) { + if (t !== 'ANY') this.throwHelp('TSIG: Class is required to be ANY'); + this.set('class', t); + } + + setTtl(t) { + if (t !== 0) this.throwHelp('TSIG: TTL is required to be 0'); + this.set('ttl', t); + } + + setAlgorithmName(val) { + if (!val) this.throwHelp(`TSIG: 'algorithm name' is required`); + this.set('algorithm name', val); + } + + setTimeSigned(val) { + // a 48-bit unsigned integer, as seconds since the UNIX epoch + if (val === undefined) this.throwHelp(`TSIG: 'time signed' is required`); + this.set('time signed', val); + } + + setFudge(val) { + // 16-bit unsigned + this.is16bitInt('TSIG', 'fudge', val); + this.set('fudge', val); + } + + setMac(val) { + this.set('mac', val ?? ''); + } + + setOriginalId(val) { + this.is16bitInt('TSIG', 'original id', val); + this.set('original id', val); + } + + setError(val) { + this.is16bitInt('TSIG', 'error', val); + this.set('error', val); + } + + setOther(val) { + this.set('other', val ?? ''); + } + + /****** IMPORTERS *******/ + + fromBind({ bindline }) { + // owner ttl ANY TSIG alg time fudge mac_size mac original_id error other_len + const parts = bindline.trimEnd().split('\t'); + const [owner, ttl, cls, type, alg, time, fudge, , mac, origId, error] = parts; + + return new TSIG({ + owner, + ttl: parseInt(ttl, 10), + class: cls, + type: type.toUpperCase(), + 'algorithm name': alg, + 'time signed': parseInt(time, 10), + fudge: parseInt(fudge, 10), + mac: mac || '', + 'original id': parseInt(origId, 10), + error: parseInt(error, 10), + other: '', + }) + } + + fromTinydns({ tinyline }) { + const [owner, _typeId, rdata, ttl, ts, loc] = tinyline.slice(1).split(':'); + + const algUnpacked = unpackDomainName(rdata); + const algBinaryLen = algUnpacked[2]; + + const bytes = Uint8Array.from(octalToChar(rdata), (c) => c.charCodeAt(0)); + const dv = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength); + let bpos = algBinaryLen; + + const timeSigned = dv.getUint32(bpos); + bpos += 4; + const fudge = dv.getUint16(bpos); + bpos += 2; + const macSize = dv.getUint16(bpos); + bpos += 2; + const mac = macSize > 0 ? bytesToHex(bytes.subarray(bpos, bpos + macSize)) : ''; + bpos += macSize; + const originalId = dv.getUint16(bpos); + bpos += 2; + const error = dv.getUint16(bpos); + bpos += 2; + const other = bpos < bytes.length ? new TextDecoder().decode(bytes.subarray(bpos)) : ''; + + return new TSIG({ + owner: this.fullyQualify(owner), + ttl: parseInt(ttl, 10), + class: 'ANY', + type: 'TSIG', + 'algorithm name': algUnpacked[0], + 'time signed': timeSigned, + fudge, + mac, + 'original id': originalId, + error, + other, + timestamp: ts, + location: loc?.trim() ?? '', + }) + } + + fromWire({ owner, cls, ttl, rdata }) { + const { fqdn: algorithmName, end } = this.wireUnpackDomain(rdata, 0); + const dv = new DataView(rdata.buffer, rdata.byteOffset); + let pos = end; + const timeSigned = dv.getUint32(pos); + pos += 4; + const fudge = dv.getUint16(pos); + pos += 2; + const macSize = dv.getUint16(pos); + pos += 2; + const mac = macSize > 0 ? bytesToHex(rdata.subarray(pos, pos + macSize)) : ''; + pos += macSize; + const originalId = dv.getUint16(pos); + pos += 2; + const error = dv.getUint16(pos); + pos += 2; + const other = pos < rdata.length ? new TextDecoder().decode(rdata.subarray(pos)) : ''; + return new TSIG({ + owner, + ttl: 0, + class: 'ANY', + type: 'TSIG', + 'algorithm name': algorithmName, + 'time signed': timeSigned, + fudge, + mac, + 'original id': originalId, + error, + other, + }) + } + + /****** EXPORTERS *******/ + toBind(zone_opts) { + const mac = this.get('mac') ?? ''; + const macSize = mac.length > 0 ? mac.length : ''; + const other = this.get('other') ?? ''; + const otherLen = other.length > 0 ? other.length : 0; + return ( + [ + this.getFQDN('owner', zone_opts), + this.get('ttl'), + this.get('class'), + this.get('type'), + this.get('algorithm name'), + this.get('time signed'), + this.get('fudge'), + macSize, + mac, + this.get('original id'), + this.get('error'), + otherLen, + ].join('\t') + '\n' + ) + } + + getWireRdata() { + const algWire = wirePackDomain(this.get('algorithm name') || ''); + const mac = this.get('mac') ?? ''; + const macBytes = mac.length > 0 ? hexToBytes(mac) : new Uint8Array(); + const other = this.get('other') ?? ''; + const otherBytes = other.length > 0 ? new TextEncoder().encode(other) : new Uint8Array(); + + const bytes = new Uint8Array(algWire.length + 4 + 2 + 2 + macBytes.length + 2 + 2 + otherBytes.length); + const dv = new DataView(bytes.buffer, bytes.byteOffset); + let pos = 0; + + bytes.set(algWire, pos); + pos += algWire.length; + dv.setUint32(pos, this.get('time signed') ?? 0); + pos += 4; + dv.setUint16(pos, this.get('fudge') ?? 0); + pos += 2; + dv.setUint16(pos, macBytes.length); + pos += 2; + if (macBytes.length > 0) { + bytes.set(macBytes, pos); + pos += macBytes.length; + } + dv.setUint16(pos, this.get('original id') ?? 0); + pos += 2; + dv.setUint16(pos, this.get('error') ?? 0); + pos += 2; + if (otherBytes.length > 0) bytes.set(otherBytes, pos); + + return bytes + } + + toTinydns() { + const alg = this.get('algorithm name') || ''; + const mac = this.get('mac') ?? ''; + const macByteLen = mac.length > 0 ? mac.length / 2 : 0; + + return this.getTinydnsGeneric( + packDomainName(alg) + + UInt32toOctal(this.get('time signed') ?? 0) + + UInt16toOctal(this.get('fudge')) + + UInt16toOctal(macByteLen) + + (macByteLen > 0 ? packHex(mac) : '') + + UInt16toOctal(this.get('original id') ?? 0) + + UInt16toOctal(this.get('error') ?? 0) + + (this.get('other').length > 0 + ? escapeOctal(new RegExp(/[\r\n\t:\\/]/, 'g'), this.get('other')) + : ''), + ) + } +} + +class URI extends RR { + static typeName = 'URI' + static typeId = 256 + static RFCs = [7553] + static rdataFields = [ + ['priority', 'u16'], + ['weight', 'u16'], + ['target', 'qstr'], + ] + + constructor(opts) { + super(opts); + } + + /****** Resource record specific setters *******/ + setPriority(val) { + this.is16bitInt('URI', 'priority', val); + + this.set('priority', val); + } + + setWeight(val) { + this.is16bitInt('URI', 'weight', val); + + this.set('weight', val); + } + + setTarget(val) { + if (!val) this.throwHelp(`URI: target is required`); + + this.set('target', val); + } + + /****** IMPORTERS *******/ + fromTinydns({ tinyline }) { + // URI via generic, :fqdn:n:rdata:ttl:timestamp:lo + const [fqdn, n, rdata, ttl, ts, loc] = tinyline.slice(1).split(':'); + if (n != 256) this.throwHelp('URI fromTinydns, invalid n'); + + return new URI({ + type: 'URI', + owner: this.fullyQualify(fqdn), + priority: octalToUInt16(rdata.slice(0, 8)), + weight: octalToUInt16(rdata.slice(8, 16)), + target: octalToChar(rdata.slice(16)), + ttl: parseInt(ttl, 10), + timestamp: ts, + location: loc?.trim() ?? '', + }) + } + + /****** MISC *******/ + getDescription() { + return 'URI' + } + + getCanonical() { + return { + owner: 'www.example.com.', + ttl: 3600, + class: 'IN', + type: 'URI', + priority: 10, + weight: 10, + target: 'http://www.example.com/', + } + } + + /****** EXPORTERS *******/ + + getWireRdata() { + const target = new TextEncoder().encode(this.get('target')); + const result = new Uint8Array(4 + target.length); + const dv = new DataView(result.buffer); + dv.setUint16(0, this.get('priority')); + dv.setUint16(2, this.get('weight')); + result.set(target, 4); + return result + } + + toTinydns() { + const dataRe = new RegExp(/[\r\n\t:\\/]/, 'g'); + let rdata = ''; + + for (const e of ['priority', 'weight']) { + rdata += UInt16toOctal(this.get(e)); + } + + rdata += escapeOctal(dataRe, this.get('target')); + return this.getTinydnsGeneric(rdata) + } +} + +const WELL_KNOWN_PORTS = { + echo: 7, + discard: 9, + systat: 11, + daytime: 13, + netstat: 15, + ftp_data: 20, + ftp: 21, + ssh: 22, + telnet: 23, + smtp: 25, + time: 37, + rlp: 39, + nameserver: 42, + nicname: 43, + domain: 53, + mtp: 57, + bootps: 67, + bootpc: 68, + tftp: 69, + gopher: 70, + rje: 77, + finger: 79, + http: 80, + link: 87, + supdup: 95, + hostnames: 101, + iso_tsap: 102, + csnet_ns: 105, + pop_2: 109, + pop3: 110, + sunrpc: 111, + auth: 113, + sftp: 115, + uucp_path: 117, + nntp: 119, + ntp: 123, + netbios_ns: 137, + netbios_dgm: 138, + netbios_ssn: 139, + imap: 143, + sql_net: 150, + snmp: 161, + snmp_trap: 162, + cmip_man: 163, + cmip_agent: 164, + xdmcp: 177, + nextstep: 178, + bgp: 179, + prospero: 191, + irc: 194, + smux: 199, + at_rtmp: 201, + at_nbp: 202, + at_echo: 204, + at_zis: 206, + qmtp: 209, + z3950: 210, + ipx: 213, + imap3: 220, + ulistproc: 372, + https: 443, + snpp: 444, + microsoft_ds: 445, + kpasswd: 464, + urd: 465, + saft: 487, + isakmp: 500, + exec: 512, + biff: 512, + login: 513, + who: 513, + cmd: 514, + syslog: 514, + printer: 515, + talk: 517, + ntalk: 518, + route: 520, + timed: 525, + tempo: 526, + courier: 530, + netnews: 532, + netwall: 533, + uucp: 540, + remotefs: 556, + nntps: 563, + ldap: 389, +}; + +class WKS extends RR { + static typeName = 'WKS' + static typeId = 11 + static RFCs = [883, 1035] + static rdataFields = ['address', 'protocol', 'bit map'] + static tags = ['obsolete'] + + constructor(opts) { + super(opts); + } + + /****** Resource record specific setters *******/ + setAddress(val) { + if (!val) this.throwHelp('WKS: address is required'); + if (!this.isIPv4(val)) this.throwHelp('WKS address must be IPv4'); + this.set('address', val); + } + + setProtocol(val) { + if (!val) this.throwHelp('WKS: protocol is required'); + const upper = typeof val === 'string' ? val.toUpperCase() : val; + if (!['TCP', 'UDP', 6, 17].includes(upper)) this.throwHelp('WKS protocol must be TCP or UDP'); + this.set('protocol', upper); + } + + setBitMap(val) { + this.set('bit map', val ?? ''); + } + + getDescription() { + return 'Well Known Service' + } + + getCanonical() { + return { + owner: 'host.example.com.', + ttl: 3600, + class: 'IN', + type: 'WKS', + address: '192.0.2.1', + protocol: 'TCP', + 'bit map': 'ftp smtp', + } + } + + /****** IMPORTERS *******/ + + fromBind({ bindline }) { + // test.example.com 3600 IN WKS 192.168.1.1 TCP ftp smtp + const parts = bindline.split(/\s+/); + const [owner, ttl, c, type, address, protocol] = parts; + return new WKS({ + owner, + ttl: parseInt(ttl, 10), + class: c, + type, + address, + protocol, + 'bit map': parts.slice(6).join(' ').trim(), + }) + } + + fromTinydns({ tinyline }) { + const [owner, _typeId, rdata, ttl, ts, loc] = tinyline.slice(1).split(':'); + + const binary = Uint8Array.from(octalToChar(rdata), (c) => c.charCodeAt(0)); + const address = [binary[0], binary[1], binary[2], binary[3]].join('.'); + const protoNum = binary[4]; + const protoMap = { 6: 'TCP', 17: 'UDP' }; + const protocol = protoMap[protoNum] ?? protoNum; + const bitmap = new TextDecoder().decode(binary.subarray(5)); + + return new WKS({ + owner: this.fullyQualify(owner), + ttl: parseInt(ttl, 10), + type: 'WKS', + address, + protocol, + 'bit map': bitmap, + timestamp: ts, + location: loc?.trim() ?? '', + }) + } + + fromWire({ owner, cls, ttl, rdata }) { + const address = [...rdata.subarray(0, 4)].join('.'); + const protoNum = rdata[4]; + const protoMap = { 6: 'TCP', 17: 'UDP' }; + const protocol = protoMap[protoNum] ?? String(protoNum); + const PORT_NAMES = Object.fromEntries(Object.entries(WELL_KNOWN_PORTS).map(([k, v]) => [v, k])); + const bitmap = rdata.subarray(5); + const ports = []; + for (let i = 0; i < bitmap.length; i++) { + for (let bit = 0; bit < 8; bit++) { + if (bitmap[i] & (0x80 >> bit)) { + const port = i * 8 + bit; + ports.push(PORT_NAMES[port] ?? String(port)); + } + } + } + return new WKS({ + owner, + ttl, + class: cls, + type: 'WKS', + address, + protocol, + 'bit map': ports.join(' '), + }) + } + + /****** EXPORTERS *******/ + + toTinydns() { + const dataRe = new RegExp(/[\r\n\t:\\/]/, 'g'); + const protoMap = { TCP: 6, UDP: 17, 6: 6, 17: 17 }; + const protoNum = protoMap[this.get('protocol')]; + + return this.getTinydnsGeneric( + ipv4toOctal(this.get('address')) + + UInt8toOctal(protoNum) + + escapeOctal(dataRe, this.get('bit map')), + ) + } + + getWireRdata() { + const protoMap = { TCP: 6, UDP: 17, 6: 6, 17: 17 }; + const addrBytes = this.get('address').split('.').map(Number); + const protoNum = protoMap[this.get('protocol')]; + + const portNums = this.get('bit map') + .trim() + .split(/\s+/) + .map((s) => { + if (/^\d+$/.test(s)) return parseInt(s, 10) + return WELL_KNOWN_PORTS[s.toLowerCase()] + }) + .filter((p) => p !== undefined); + + if (portNums.length === 0) return new Uint8Array([...addrBytes, protoNum]) + + const maxPort = Math.max(...portNums); + const bitmapLen = Math.floor(maxPort / 8) + 1; + const bitmap = new Uint8Array(bitmapLen); + for (const port of portNums) bitmap[Math.floor(port / 8)] |= 0x80 >> (port % 8); + + const result = new Uint8Array(5 + bitmapLen); + result.set(addrBytes); + result[4] = protoNum; + result.set(bitmap, 5); + return result + } +} + +const typeMap = {}; +const classes = [ + A, + AAAA, + APL, + CAA, + CERT, + CNAME, + DHCID, + DNAME, + DNSKEY, + DS, + HINFO, + HIP, + HTTPS, + IPSECKEY, + KEY, + KX, + LOC, + MX, + NAPTR, + NS, + NSEC, + NSEC3, + NSEC3PARAM, + NXT, + OPENPGPKEY, + PTR, + RP, + RRSIG, + SIG, + SMIMEA, + SSHFP, + SOA, + SPF, + SRV, + SVCB, + TLSA, + TSIG, + TXT, + URI, + WKS, +]; + +for (const c of classes) { + const id = c.getTypeId(); + typeMap[id] = c.typeName; + typeMap[c.typeName] = id; +} + +exports.A = A; +exports.AAAA = AAAA; +exports.APL = APL; +exports.CAA = CAA; +exports.CERT = CERT; +exports.CNAME = CNAME; +exports.DHCID = DHCID; +exports.DNAME = DNAME; +exports.DNSKEY = DNSKEY; +exports.DS = DS; +exports.HINFO = HINFO; +exports.HIP = HIP; +exports.HTTPS = HTTPS; +exports.IPSECKEY = IPSECKEY; +exports.KEY = KEY; +exports.KX = KX; +exports.LOC = LOC; +exports.MX = MX; +exports.NAPTR = NAPTR; +exports.NS = NS; +exports.NSEC = NSEC; +exports.NSEC3 = NSEC3; +exports.NSEC3PARAM = NSEC3PARAM; +exports.NXT = NXT; +exports.OPENPGPKEY = OPENPGPKEY; +exports.PTR = PTR; +exports.RP = RP; +exports.RRSIG = RRSIG; +exports.SIG = SIG; +exports.SMIMEA = SMIMEA; +exports.SOA = SOA; +exports.SPF = SPF; +exports.SRV = SRV; +exports.SSHFP = SSHFP; +exports.SVCB = SVCB; +exports.TLSA = TLSA; +exports.TSIG = TSIG; +exports.TXT = TXT; +exports.URI = URI; +exports.WKS = WKS; +exports.default = RR; +exports.typeMap = typeMap; diff --git a/dist/dns-rr.min.js b/dist/dns-rr.min.js index a6d80f1..5b4fdc5 100644 --- a/dist/dns-rr.min.js +++ b/dist/dns-rr.min.js @@ -1,6 +1,6 @@ -const Ot=new RegExp(/\\(?:[1-7][0-7]{0,2}|[0-7]{2,3})/,"g"),Lt=new TextDecoder;function vt(l,t){const e=l.slice(1).split(":"),s=e[0],i=e.slice(1,1+t),[n,a,o]=e.slice(1+t);return{owner:s,rdata:i,ttl:n,timestamp:a,location:o?.trim()??""}}function Jt(l){const[t,e,s,i,n,a]=l.slice(1).split(":");return{owner:t,typeId:e,rdata:s,ttl:parseInt(i,10),timestamp:n,location:a?.trim()??""}}function H(l){return Uint8Array.from(x(l),t=>t.charCodeAt(0))}function Mt(l,t){if(l.length<6)throw new Error(`${t}: RDATA too short: ${l}`);const e=H(l),s=e[0]<<8|e[1];let i=2;const n=[];for(;;){const a=e[i];if(i+=1,a===0)break;n.push(Lt.decode(e.subarray(i,i+a))),i+=a}return{priority:s,targetName:`${n.join(".")}.`,params:Lt.decode(e.subarray(i))}}function Zt(l){if(l.constructor.tinydnsType){const e=l.getFields("rdata").map(s=>l.isFqdnField(s)?l.getTinyFQDN(s):l.get(s)).join(":");return`${l.constructor.tinydnsType}${l.getTinyFQDN("owner")}:${e}:${l.getTinydnsPostamble()} -`}return l.getTinydnsGeneric(re(l.getWireRdata()))}function _t(l,{tinyline:t}){const e=l.getFields("rdata"),{owner:s,rdata:i,ttl:n,timestamp:a,location:o}=vt(t,e.length),r={owner:l.fullyQualify(s),type:l.constructor.typeName,ttl:parseInt(n,10),timestamp:a,location:o};for(let c=0;c{e+=l.test(s)?ee(s):s}),e}function x(l){return l.replace(Ot,t=>String.fromCharCode(parseInt(t.slice(1),8)))}function Pt(l){return l.replace(Ot,t=>parseInt(t.slice(1),8).toString(16).padStart(2,0))}function E(l){return parseInt(l.slice(1,4),8)&255}function B(l){return parseInt(l.slice(1,4),8)<<8|parseInt(l.slice(5,8),8)}function gt(l){const t=parseInt(l.slice(1,4),8),e=parseInt(l.slice(5,8),8),s=parseInt(l.slice(9,12),8),i=parseInt(l.slice(13,16),8);return(t<<24|e<<16|s<<8|i)>>>0}function Bt(l){return l.match(/(.{1,255})/g).map(t=>`${u(t.length)}${t}`).join("")}function te(l){const t=Uint8Array.from(x(l.toString()),a=>a.charCodeAt(0)),e=new TextDecoder,s=[];let i=0,n;for(;(n=t[i])&&(i++,s.push(e.decode(t.subarray(i,i+n))),i=+(i+n),!(i>=t.length)););return s}function N(l){const t=new RegExp(/[^A-Za-z0-9-.]/,"g");let e="";return l.split(".").forEach(s=>{s===void 0||!s.length||(e+=u(s.length),e+=I(t,s))}),e+="\\000",e}function U(l){let t=0,e=0;const s=[],i=()=>{if(t>=l.length)return null;let a;return l[t]==="\\"?(a=parseInt(l.slice(t+1,t+4),8),t+=4):a=l.charCodeAt(t++),e++,a};let n;for(;(n=i())&&n!==0;){let a="";for(let o=0;o255)throw new Error(`UInt8toOctal: value ${l} exceeds 255 \u2014 tinydns encoders require Latin-1/byte input (code points <= 0xFF)`);return`\\${parseInt(l,10).toString(8).padStart(3,0)}`}function A(l){return u(l>>>8&255)+u(l&255)}function P(l){return u(l>>>24&255)+u(l>>>16&255)+u(l>>>8&255)+u(l&255)}function qt(l){return P(l.split`.`.reduce((t,e)=>t*256+ +e))}function se(l){const t=gt(l);return[24,16,8,0].map(e=>t>>e&255).join(".")}function Rt(l,t=":"){const e=l.match(/:/g);return e?.length<7&&(l=l.replace(/::/,":".repeat(9-e.length))),l.split(":").map(s=>s.padStart(4,"0")).join(t).toLowerCase()}function ie(l){return O(Rt(l,""))}function ne(l){return Pt(l).match(/(.{4})/g).join(":")}function G(l){const t=atob(l);let e="";for(let s=0;sparseInt(l.slice(e*2,e*2+2),16))}function R(l){return[...l].map(t=>t.toString(16).padStart(2,"0")).join("")}function V(l){return btoa([...l].map(t=>String.fromCharCode(t)).join(""))}function L(l){return Uint8Array.from(atob(l),t=>t.charCodeAt(0))}const q={A:1,NS:2,MD:3,MF:4,CNAME:5,SOA:6,MB:7,MG:8,MR:9,NULL:10,WKS:11,PTR:12,HINFO:13,MINFO:14,MX:15,TXT:16,RP:17,AFSDB:18,X25:19,ISDN:20,RT:21,NSAP:22,NSAP_PTR:23,SIG:24,KEY:25,PX:26,GPOS:27,AAAA:28,LOC:29,NXT:30,EID:31,NIMLOC:32,SRV:33,ATMA:34,NAPTR:35,KX:36,CERT:37,A6:38,DNAME:39,SINK:40,OPT:41,APL:42,DS:43,SSHFP:44,IPSECKEY:45,RRSIG:46,NSEC:47,DNSKEY:48,DHCID:49,NSEC3:50,NSEC3PARAM:51,TLSA:52,SMIMEA:53,HIP:55,NINFO:56,RKEY:57,TALINK:58,CDS:59,CDNSKEY:60,OPENPGPKEY:61,CSYNC:62,ZONEMD:63,SVCB:64,HTTPS:65,SPF:99,UINFO:100,UID:101,GID:102,UNSPEC:103,NID:104,L32:105,L64:106,LP:107,EUI48:108,EUI64:109,TKEY:249,TSIG:250,IXFR:251,AXFR:252,MAILB:253,MAILA:254,ANY:255,URI:256,CAA:257,AVC:258,DOA:259,AMTRELAY:260,TA:32768,DLV:32769};function Ut(l,t=0){const e=[];let s=t;for(;sn.length>0).map(n=>{const a=t.encode(n);if(a.length>63)throw new Error(`DNS label exceeds 63 bytes: ${n}`);return a}),s=new Uint8Array(e.reduce((n,a)=>n+a.length+1,1));let i=0;for(const n of e)s[i++]=n.length,s.set(n,i),i+=n.length;return s[i]=0,s}function ae(l){const t=l.toTinydns();if(!t.startsWith(":"))throw new Error(`${l.get("type")}: getWireRdata() not implemented. Override in rr/${l.get("type").toLowerCase()}.js`);const e=t.split(":")[3];return l.octalToUint8Array(e??"")}function oe(l,t){const e=l.getWireRdata(),s=W(l.get("owner")),i=new Uint8Array(s.length+10+e.length);i.set(s,0);const n=new DataView(i.buffer,s.length,10);return n.setUint16(0,l.getTypeId()),n.setUint16(2,t[l.get("class")]??1),n.setUint32(4,l.get("ttl")),n.setUint16(8,e.length),i.set(e,s.length+10),i}function ce(l,t,e){const s=new l(null),i=t instanceof Uint8Array?t:new Uint8Array(t),{fqdn:n,end:a}=e(i,0),o=new DataView(i.buffer,i.byteOffset),r=o.getUint16(a+2),c={IN:1,CS:2,CH:3,HS:4,NONE:254,ANY:255},h=Object.keys(c).find(y=>c[y]===r)??"IN",p=o.getUint32(a+4),d=o.getUint16(a+8),g=i.slice(a+10,a+10+d);return s.fromWire({owner:n,cls:h,ttl:p,rdata:g})}function le(l,{owner:t,cls:e,ttl:s,rdata:i}){const n={owner:t,ttl:s,class:e,type:l.constructor.typeName},a=l.constructor.rdataFields??[],o=new DataView(i.buffer,i.byteOffset);let r=0;for(let c=0;cd.encode(b.trim())),y=g.reduce((b,w)=>b+1+w.length,0);h=new Uint8Array(y);let m=0;for(const b of g)h[m++]=b.length,h.set(b,m),m+=b.length}else if(c===2)h=new Uint8Array(0);else if(c===3)h=new Uint8Array(2),new DataView(h.buffer).setUint16(0,parseInt(r,10));else if(c===4){const d=r.split(",").map(g=>g.trim().split(".").map(Number));h=new Uint8Array(d.length*4),d.forEach((g,y)=>g.forEach((m,b)=>h[y*4+b]=m))}else if(c===5)h=L(r);else if(c===6){const d=r.split(",").map(g=>F(Rt(g.trim(),"")));h=new Uint8Array(d.length*16),d.forEach((g,y)=>h.set(g,y*16))}else h=new TextEncoder().encode(r);const p=new Uint8Array(4+h.length);new DataView(p.buffer).setUint16(0,c),new DataView(p.buffer).setUint16(2,h.length),p.set(h,4),t.push(p)}t.sort((o,r)=>new DataView(o.buffer).getUint16(0)-new DataView(r.buffer).getUint16(0));const i=t.reduce((o,r)=>o+r.length,0),n=new Uint8Array(i);let a=0;for(const o of t)n.set(o,a),a+=o.length;return n}const pe={0:"mandatory",1:"alpn",2:"no-default-alpn",3:"port",4:"ipv4hint",5:"ech",6:"ipv6hint"};function de(l){if(!l||l.length===0)return"";const t=[];let e=0;for(;e+4<=l.length;){const s=new DataView(l.buffer,l.byteOffset+e),i=s.getUint16(0),n=s.getUint16(2),a=l.subarray(e+4,e+4+n);e+=4+n;const o=pe[i]??`key${i}`;if(i===1){const r=[];let c=0;for(;cString.fromCharCode(r)).join(""))}`);else if(i===6){const r=[];for(let c=0;cr.toString(16).padStart(2,"0")).join("")}`)}return t.join(" ")}function ge(l,t){const e={class:"IN",type:"",rdata:[]};let s="",i=!1;for(let a=0;a0;){const a=n[0].toUpperCase();if(t[a]){e.class=n.shift().toUpperCase();continue}if(/^\d+$/.test(a)){e.ttl=parseInt(n.shift(),10);continue}e.type=n.shift().toUpperCase();break}return e.rdata=n,e}function ue(l,t){const{owner:e,ttl:s,cls:i,rdata:n}=t,a={owner:e,ttl:s,class:i,type:l.constructor.typeName},o=l.getFields("rdata");for(let r=0;rd.replace(/^"|"$/g,"")).join("");a[o[r]]=p;break}let h=n[r];l.isQuotedField(o[r])?h=h?.replace(/^"|"$/g,""):/^\d+$/.test(h)&&(h=parseInt(h,10)),a[o[r]]=h}return new l.constructor(a)}function ye(l,t){const s=l.getFields("rdata").map(i=>l.isFqdnField(i)?l.getFQDN(i,t):l.getQuoted(i)).join(" ");return`${l.getPrefix(t)} ${s} -`}const fe=Symbol.for("nodejs.util.inspect.custom");class f{static CLASSES={IN:1,CS:2,CH:3,HS:4,NONE:254,ANY:255};static typeId;static RFCs=[];static tags=[];constructor(t){if(t!==null){t?.default&&(this.default=t.default),this.setLocation(t?.location),this.setTimestamp(t?.timestamp),this.setOwner(t?.owner),this.setType(t?.type),this.setTtl(t?.ttl),this.setClass(t?.class);for(const e of this.constructor.rdataFields??[]){const s=f.fieldName(e),i=Array.isArray(e)?e[1]:null,n=`set${this.ucFirst(s)}`;typeof this[n]=="function"?this[n](t?.[s]):i?this.setTypedValue(i,s,t?.[s]):this.set(s,t?.[s])}t?.comment&&this.set("comment",t.comment)}}static fromBind(t,e={}){const s=new this(null);e.default!==void 0&&(s.default=e.default);const i=this.parseBindLine(t);return i?s.fromBind({...e,...i,bindline:t}):null}fromBind(t){return ue(this,t)}static parseBindLine(t){return ge(t,f.CLASSES)}static fromTinydns(t,e={}){const s=new this(null);return e.default!==void 0&&(s.default=e.default),s.fromTinydns({...e,tinyline:t})}fromTinydns(t){return _t(this,t)}static fromWire(t){return ce(this,t,Ut)}fromWire(t){return le(this,t)}static#t=["__proto__","constructor","prototype"];get(t){if(f.#t.includes(t))throw new Error(`Invalid field name: ${t}`);return this[t]}set(t,e){if(f.#t.includes(t))throw new Error(`Invalid field name: ${t}`);return this[t]=e,this}toJSON(){const t=[...this.getFields(),"location","timestamp","comment"],e={};for(const s of t){const i=this.get(s);i!==void 0&&(e[s]=i)}return e}[fe](t,e,s){return`${this.type} ${s(this.toJSON(),e)}`}ucFirst(t){return t&&t.split(/\s/).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join("")}setClass(t){if([void 0,null,""].includes(t)){this.set("class","IN");return}if(f.CLASSES[t.toUpperCase()]){this.set("class",t.toUpperCase());return}this.throwHelp(`invalid class ${t}`)}setLocation(t){t!==void 0&&this.set("location",t)}setTimestamp(t){t!==void 0&&this.set("timestamp",t)}setOwner(t){t===void 0&&this.throwHelp("owner is required"),(t.length<1||t.length>255)&&this.throwHelp("Domain names must have 1-255 octets (characters): RFC 2181"),this.isFullyQualified(this.constructor.typeName??this.constructor.name,"owner",t),this.hasValidLabels(t),/\*/.test(t)&&!/^\*\./.test(t)&&!/\.\*\./.test(t)&&this.throwHelp("only *.something or * (by itself) is a valid wildcard"),this.set("owner",t.toLowerCase())}setTtl(t){if(t=t??this.default?.ttl,t===void 0){if(["SOA","SSHFP","RRSIG"].includes(this.get("type")))return;this.throwHelp("TTL is required, no default available")}typeof t!="number"&&this.throwHelp(`TTL must be numeric (${typeof t})`),this.is32bitInt(this.get("type"),"TTL",t),this.set("ttl",t)}setType(t){[void 0,""].includes(t)&&(t=this.constructor.typeName),t===void 0&&this.throwHelp("type is required"),t.toUpperCase()!==this.constructor.typeName&&this.throwHelp(`type ${t} doesn't match ${this.constructor.typeName}`),this.set("type",t.toUpperCase())}throwHelp(t){if(!this.constructor.typeName)throw new Error(t);const e=this.constructor.typeName,s=this.getCanonical?`Example ${e}: +const Ot=new RegExp(/\\(?:[1-7][0-7]{0,2}|[0-7]{2,3})/,"g"),Lt=new TextDecoder;function Jt(l,t){const e=l.slice(1).split(":"),s=e[0],i=e.slice(1,1+t),[n,a,o]=e.slice(1+t);return{owner:s,rdata:i,ttl:n,timestamp:a,location:o?.trim()??""}}function Zt(l){const[t,e,s,i,n,a]=l.slice(1).split(":");return{owner:t,typeId:e,rdata:s,ttl:parseInt(i,10),timestamp:n,location:a?.trim()??""}}function k(l){return Uint8Array.from(x(l),t=>t.charCodeAt(0))}function Mt(l,t){if(l.length<6)throw new Error(`${t}: RDATA too short: ${l}`);const e=k(l),s=e[0]<<8|e[1];let i=2;const n=[];for(;;){const a=e[i];if(i+=1,a===0)break;n.push(Lt.decode(e.subarray(i,i+a))),i+=a}return{priority:s,targetName:`${n.join(".")}.`,params:Lt.decode(e.subarray(i))}}function _t(l){if(l.constructor.tinydnsType){const e=l.getFields("rdata").map(s=>l.isFqdnField(s)?l.getTinyFQDN(s):l.get(s)).join(":");return`${l.constructor.tinydnsType}${l.getTinyFQDN("owner")}:${e}:${l.getTinydnsPostamble()} +`}return l.getTinydnsGeneric(ae(l.getWireRdata()))}function te(l,{tinyline:t}){const e=l.getFields("rdata"),{owner:s,rdata:i,ttl:n,timestamp:a,location:o}=Jt(t,e.length),r={owner:l.fullyQualify(s),type:l.constructor.typeName,ttl:parseInt(n,10),timestamp:a,location:o};for(let c=0;c{e+=l.test(s)?se(s):s}),e}function x(l){return l.replace(Ot,t=>String.fromCharCode(parseInt(t.slice(1),8)))}function Pt(l){return l.replace(Ot,t=>parseInt(t.slice(1),8).toString(16).padStart(2,0))}function E(l){return parseInt(l.slice(1,4),8)&255}function B(l){return parseInt(l.slice(1,4),8)<<8|parseInt(l.slice(5,8),8)}function gt(l){const t=parseInt(l.slice(1,4),8),e=parseInt(l.slice(5,8),8),s=parseInt(l.slice(9,12),8),i=parseInt(l.slice(13,16),8);return(t<<24|e<<16|s<<8|i)>>>0}function Bt(l){return l.match(/(.{1,255})/g).map(t=>`${y(t.length)}${t}`).join("")}function ee(l){const t=Uint8Array.from(x(l.toString()),a=>a.charCodeAt(0)),e=new TextDecoder,s=[];let i=0,n;for(;(n=t[i])&&(i++,s.push(e.decode(t.subarray(i,i+n))),i=+(i+n),!(i>=t.length)););return s}function N(l){const t=new RegExp(/[^A-Za-z0-9-.]/,"g");let e="";return l.split(".").forEach(s=>{s===void 0||!s.length||(e+=y(s.length),e+=I(t,s))}),e+="\\000",e}function U(l){let t=0,e=0;const s=[],i=()=>{if(t>=l.length)return null;let a;return l[t]==="\\"?(a=parseInt(l.slice(t+1,t+4),8),t+=4):a=l.charCodeAt(t++),e++,a};let n;for(;(n=i())&&n!==0;){let a="";for(let o=0;o255)throw new Error(`UInt8toOctal: value ${l} exceeds 255 \u2014 tinydns encoders require Latin-1/byte input (code points <= 0xFF)`);return`\\${parseInt(l,10).toString(8).padStart(3,0)}`}function A(l){return y(l>>>8&255)+y(l&255)}function P(l){return y(l>>>24&255)+y(l>>>16&255)+y(l>>>8&255)+y(l&255)}function qt(l){return P(l.split`.`.reduce((t,e)=>t*256+ +e))}function ie(l){const t=gt(l);return[24,16,8,0].map(e=>t>>e&255).join(".")}function Rt(l,t=":"){const e=l.match(/:/g);return e?.length<7&&(l=l.replace(/::/,":".repeat(9-e.length))),l.split(":").map(s=>s.padStart(4,"0")).join(t).toLowerCase()}function ne(l){return O(Rt(l,""))}function re(l){return Pt(l).match(/(.{4})/g).join(":")}function W(l){const t=atob(l);let e="";for(let s=0;sparseInt(l.slice(e*2,e*2+2),16))}function R(l){return[...l].map(t=>t.toString(16).padStart(2,"0")).join("")}function G(l){return btoa([...l].map(t=>String.fromCharCode(t)).join(""))}function L(l){return Uint8Array.from(atob(l),t=>t.charCodeAt(0))}const q={A:1,NS:2,MD:3,MF:4,CNAME:5,SOA:6,MB:7,MG:8,MR:9,NULL:10,WKS:11,PTR:12,HINFO:13,MINFO:14,MX:15,TXT:16,RP:17,AFSDB:18,X25:19,ISDN:20,RT:21,NSAP:22,NSAP_PTR:23,SIG:24,KEY:25,PX:26,GPOS:27,AAAA:28,LOC:29,NXT:30,EID:31,NIMLOC:32,SRV:33,ATMA:34,NAPTR:35,KX:36,CERT:37,A6:38,DNAME:39,SINK:40,OPT:41,APL:42,DS:43,SSHFP:44,IPSECKEY:45,RRSIG:46,NSEC:47,DNSKEY:48,DHCID:49,NSEC3:50,NSEC3PARAM:51,TLSA:52,SMIMEA:53,HIP:55,NINFO:56,RKEY:57,TALINK:58,CDS:59,CDNSKEY:60,OPENPGPKEY:61,CSYNC:62,ZONEMD:63,SVCB:64,HTTPS:65,SPF:99,UINFO:100,UID:101,GID:102,UNSPEC:103,NID:104,L32:105,L64:106,LP:107,EUI48:108,EUI64:109,TKEY:249,TSIG:250,IXFR:251,AXFR:252,MAILB:253,MAILA:254,ANY:255,URI:256,CAA:257,AVC:258,DOA:259,AMTRELAY:260,TA:32768,DLV:32769};function Ut(l,t=0){const e=[];let s=t;for(;sn.length>0).map(n=>{const a=t.encode(n);if(a.length>63)throw new Error(`DNS label exceeds 63 bytes: ${n}`);return a}),s=new Uint8Array(e.reduce((n,a)=>n+a.length+1,1));let i=0;for(const n of e)s[i++]=n.length,s.set(n,i),i+=n.length;return s[i]=0,s}function oe(l){const t=l.toTinydns();if(!t.startsWith(":"))throw new Error(`${l.get("type")}: getWireRdata() not implemented. Override in rr/${l.get("type").toLowerCase()}.js`);const e=t.split(":")[3];return l.octalToUint8Array(e??"")}function ce(l,t){const e=l.getWireRdata(),s=V(l.get("owner")),i=new Uint8Array(s.length+10+e.length);i.set(s,0);const n=new DataView(i.buffer,s.length,10);return n.setUint16(0,l.getTypeId()),n.setUint16(2,t[l.get("class")]??1),n.setUint32(4,l.get("ttl")),n.setUint16(8,e.length),i.set(e,s.length+10),i}function le(l,t,e){const s=new l(null),i=t instanceof Uint8Array?t:new Uint8Array(t),{fqdn:n,end:a}=e(i,0),o=new DataView(i.buffer,i.byteOffset),r=o.getUint16(a+2),c={IN:1,CS:2,CH:3,HS:4,NONE:254,ANY:255},p=Object.keys(c).find(u=>c[u]===r)??"IN",h=o.getUint32(a+4),d=o.getUint16(a+8),g=i.slice(a+10,a+10+d);return s.fromWire({owner:n,cls:p,ttl:h,rdata:g})}function he(l,{owner:t,cls:e,ttl:s,rdata:i}){const n={owner:t,ttl:s,class:e,type:l.constructor.typeName},a=l.constructor.rdataFields??[],o=new DataView(i.buffer,i.byteOffset);let r=0;for(let c=0;ci.length)throw new Error("fromWireGeneric: truncated character-string in rdata");g.push(new TextDecoder().decode(i.subarray(r,r+u))),r+=u}n[h]=g.length>1?g:g[0]??"";break}case"svcparams":n[h]=ge(i.subarray(r)),r=i.length;break;case"ipv4":n[h]=[...i.subarray(r,r+4)].join("."),r+=4;break;case"ipv6":{const g=[];for(let u=0;u<16;u+=2)g.push(o.getUint16(r+u).toString(16).padStart(4,"0"));n[h]=g.join(":"),r+=16;break}default:n[h]=i[r++];break}}return new l.constructor(n)}const pe={mandatory:0,alpn:1,"no-default-alpn":2,port:3,ipv4hint:4,ech:5,ipv6hint:6};function Vt(l){if(!l||!l.trim())return new Uint8Array(0);const t=[],e=/([^\s=]+)(?:=(?:"([^"]*)"|(\S*)))?(?=\s|$)/g;let s;for(;(s=e.exec(l.trim()))!==null;){const o=s[1].toLowerCase(),r=s[2]??s[3]??"",c=pe[o];if(c===void 0)continue;let p;if(c===1){const d=new TextEncoder,g=r.split(",").map(b=>d.encode(b.trim())),u=g.reduce((b,w)=>b+1+w.length,0);p=new Uint8Array(u);let m=0;for(const b of g)p[m++]=b.length,p.set(b,m),m+=b.length}else if(c===2)p=new Uint8Array(0);else if(c===3)p=new Uint8Array(2),new DataView(p.buffer).setUint16(0,parseInt(r,10));else if(c===4){const d=r.split(",").map(g=>g.trim().split(".").map(Number));p=new Uint8Array(d.length*4),d.forEach((g,u)=>g.forEach((m,b)=>p[u*4+b]=m))}else if(c===5)p=L(r);else if(c===6){const d=r.split(",").map(g=>F(Rt(g.trim(),"")));p=new Uint8Array(d.length*16),d.forEach((g,u)=>p.set(g,u*16))}else p=new TextEncoder().encode(r);const h=new Uint8Array(4+p.length);new DataView(h.buffer).setUint16(0,c),new DataView(h.buffer).setUint16(2,p.length),h.set(p,4),t.push(h)}t.sort((o,r)=>new DataView(o.buffer).getUint16(0)-new DataView(r.buffer).getUint16(0));const i=t.reduce((o,r)=>o+r.length,0),n=new Uint8Array(i);let a=0;for(const o of t)n.set(o,a),a+=o.length;return n}const de={0:"mandatory",1:"alpn",2:"no-default-alpn",3:"port",4:"ipv4hint",5:"ech",6:"ipv6hint"};function ge(l){if(!l||l.length===0)return"";const t=[];let e=0;for(;e+4<=l.length;){const s=new DataView(l.buffer,l.byteOffset+e),i=s.getUint16(0),n=s.getUint16(2),a=l.subarray(e+4,e+4+n);e+=4+n;const o=de[i]??`key${i}`;if(i===1){const r=[];let c=0;for(;cString.fromCharCode(r)).join(""))}`);else if(i===6){const r=[];for(let c=0;cr.toString(16).padStart(2,"0")).join("")}`)}return t.join(" ")}function ue(l,t){const e={class:"IN",type:"",rdata:[]};let s="",i=!1;for(let a=0;a0;){const a=n[0].toUpperCase();if(t[a]){e.class=n.shift().toUpperCase();continue}if(/^\d+$/.test(a)){e.ttl=parseInt(n.shift(),10);continue}e.type=n.shift().toUpperCase();break}return e.rdata=n,e}function ye(l,t){const{owner:e,ttl:s,cls:i,rdata:n}=t,a={owner:e,ttl:s,class:i,type:l.constructor.typeName},o=l.getFields("rdata"),r=l.constructor.rdataFields??[];for(let c=0;cm.replace(/^"|"$/g,"")),g=r[c],u=Array.isArray(g)?g[1]:null;a[o[c]]=u==="charstrs"&&d.length>1?d:d.join("");break}let h=n[c];l.isQuotedField(o[c])?h=h?.replace(/^"|"$/g,""):/^\d+$/.test(h)&&(h=parseInt(h,10)),a[o[c]]=h}return new l.constructor(a)}function fe(l,t){const s=l.getFields("rdata").map(i=>l.isFqdnField(i)?l.getFQDN(i,t):l.getQuoted(i)).join(" ");return`${l.getPrefix(t)} ${s} +`}const me=Symbol.for("nodejs.util.inspect.custom");class f{static CLASSES={IN:1,CS:2,CH:3,HS:4,NONE:254,ANY:255};static typeId;static RFCs=[];static tags=[];constructor(t){if(t!==null){t?.default&&(this.default=t.default),this.setLocation(t?.location),this.setTimestamp(t?.timestamp),this.setOwner(t?.owner),this.setType(t?.type),this.setTtl(t?.ttl),this.setClass(t?.class);for(const e of this.constructor.rdataFields??[]){const s=f.fieldName(e),i=Array.isArray(e)?e[1]:null,n=`set${this.ucFirst(s)}`;typeof this[n]=="function"?this[n](t?.[s]):i?this.setTypedValue(i,s,t?.[s]):this.set(s,t?.[s])}t?.comment&&this.set("comment",t.comment)}}static fromBind(t,e={}){const s=new this(null);e.default!==void 0&&(s.default=e.default);const i=this.parseBindLine(t);return i?s.fromBind({...e,...i,bindline:t}):null}fromBind(t){return ye(this,t)}static parseBindLine(t){return ue(t,f.CLASSES)}static fromTinydns(t,e={}){const s=new this(null);return e.default!==void 0&&(s.default=e.default),s.fromTinydns({...e,tinyline:t})}fromTinydns(t){return te(this,t)}static fromWire(t){return le(this,t,Ut)}fromWire(t){return he(this,t)}static#t=["__proto__","constructor","prototype"];get(t){if(f.#t.includes(t))throw new Error(`Invalid field name: ${t}`);return this[t]}set(t,e){if(f.#t.includes(t))throw new Error(`Invalid field name: ${t}`);return this[t]=e,this}toJSON(){const t=[...this.getFields(),"location","timestamp","comment"],e={};for(const s of t){const i=this.get(s);i!==void 0&&(e[s]=i)}return e}[me](t,e,s){return`${this.type} ${s(this.toJSON(),e)}`}ucFirst(t){return t&&t.split(/\s/).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join("")}setClass(t){if([void 0,null,""].includes(t)){this.set("class","IN");return}if(f.CLASSES[t.toUpperCase()]){this.set("class",t.toUpperCase());return}this.throwHelp(`invalid class ${t}`)}setLocation(t){t!==void 0&&this.set("location",t)}setTimestamp(t){t!==void 0&&this.set("timestamp",t)}setOwner(t){t===void 0&&this.throwHelp("owner is required"),(t.length<1||t.length>255)&&this.throwHelp("Domain names must have 1-255 octets (characters): RFC 2181"),this.isFullyQualified(this.constructor.typeName??this.constructor.name,"owner",t),this.hasValidLabels(t),/\*/.test(t)&&!/^\*\./.test(t)&&!/\.\*\./.test(t)&&this.throwHelp("only *.something or * (by itself) is a valid wildcard"),this.set("owner",t.toLowerCase())}setTtl(t){if(t=t??this.default?.ttl,t===void 0){if(["SOA","SSHFP","RRSIG"].includes(this.get("type")))return;this.throwHelp("TTL is required, no default available")}typeof t!="number"&&this.throwHelp(`TTL must be numeric (${typeof t})`),this.is32bitInt(this.get("type"),"TTL",t),this.set("ttl",t)}setType(t){[void 0,""].includes(t)&&(t=this.constructor.typeName),t===void 0&&this.throwHelp("type is required"),t.toUpperCase()!==this.constructor.typeName&&this.throwHelp(`type ${t} doesn't match ${this.constructor.typeName}`),this.set("type",t.toUpperCase())}throwHelp(t){if(!this.constructor.typeName)throw new Error(t);const e=this.constructor.typeName,s=this.getCanonical?`Example ${e}: ${JSON.stringify(this.getCanonical(),null," ")} `:`${e} records have the fields: ${this.getFields().join(", ")} @@ -9,18 +9,18 @@ ${JSON.stringify(this.getCanonical(),null," ")} ${s}${this.citeRFC()} `)}citeRFC(){return`see RFC${this.getRFCs().length>1?"s":""} ${this.getRFCs()}`}fullyQualify(t,e){return t&&(t==="@"&&e&&(t=e),t.endsWith(".")?t.toLowerCase():e?`${t}.${e}`.toLowerCase():`${t}.`)}getPrefix(t={}){const e=t.hide?.class?"":this.get("class");let s=this.get("ttl");t.hide?.ttl&&s===t.ttl&&(s="");let i=this.get("owner");return t.hide?.sameOwner&&t.previousOwner===i?i="":i=this.getFQDN("owner",t),`${i} ${s} ${e} ${this.get("type")}`}getEmpty(t){return this.get(t)??""}getComment(t){const e=this.get("comment");return!e||!e[t]?"":e[t]}getQuoted(t){return this.isQuotedField(t)?/['"]/.test(this.get(t)[0])?this.get(t):`"${this.get(t)}"`:this.get(t)}static fieldName(t){return Array.isArray(t)?t[0]:t}static fieldType(t){return Array.isArray(t)?t[1]:null}getRdataFields(){return(this.constructor.rdataFields??[]).map(t=>f.fieldName(t))}getTags(){return this.constructor.tags??[]}getRFCs(){return this.constructor.RFCs??[]}getTypeId(){const t=this.constructor.typeId;return t===void 0&&this.throwHelp(`${this.constructor.typeName}: missing static typeId`),t}static getTypeId(){return this.typeId}getFields(t){const e=["owner","ttl","class","type"];Object.freeze(e);const s=this.getRdataFields();switch(t){case"common":return e;case"rdata":return s;default:return e.concat(s)}}getFQDN(t,e={}){let s=this.get(t);if(s||this.throwHelp(`empty value for field ${t}`),s.endsWith(".")||(s+="."),e.hide?.origin&&e.origin){if(s===e.origin)return"@";if(s.endsWith(e.origin))return s.slice(0,s.length-e.origin.length-1)}return s}getTinyFQDN(t){const e=this.get(t);return e===""||e==="."?e:e.endsWith(".")?e.slice(0,-1):e}getTinydnsGeneric(t){return`:${this.getTinyFQDN("owner")}:${this.getTypeId()}:${t}:${this.getTinydnsPostamble()} -`}getTinydnsPostamble(){return["ttl","timestamp","location"].map(t=>this.getEmpty(t)).join(":")}hasValidLabels(t){const e=t.endsWith(".")?t.slice(0,-1):t;for(const s of e.split("."))(s.length<1||s.length>63)&&this.throwHelp("Labels must have 1-63 octets (characters), RFC 2181")}is8bitInt(t,e,s){if(Number.isInteger(s)&&s>=0&&s<=255)return!0;this.throwHelp(`${t} ${e} must be a 8-bit integer (in the range 0-255)`)}is16bitInt(t,e,s){if(Number.isInteger(s)&&s>=0&&s<=65535)return!0;this.throwHelp(`${t} ${e} must be a 16-bit integer (in the range 0-65535)`)}is32bitInt(t,e,s){if(Number.isInteger(s)&&s>=0&&s<=4294967295)return!0;this.throwHelp(`${t} ${e} must be a 32-bit integer (in the range 0-4294967295)`)}isBase64(t,e,s){if(typeof s=="string"&&s.length>0&&s.length%4===0&&/^[A-Za-z0-9+/]*={0,2}$/.test(s))return!0;this.throwHelp(`${t} ${e} must be a valid base64 string`)}isQuoted(t){return/^["']/.test(t)&&/["']$/.test(t)}setFqdnValue(t,e,s){s||this.throwHelp(`${t}: ${e} is required`),(this.isIPv4(s)||this.isIPv6(s))&&this.throwHelp(`${t}: ${e} must be a domain name`),this.isFullyQualified(t,e,s),this.isValidHostname(t,e,s),this.set(e,s.toLowerCase())}setTypedValue(t,e,s){const i=this.constructor.typeName;switch(t){case"u8":this.is8bitInt(i,e,s),this.set(e,parseInt(s,10));break;case"u16":this.is16bitInt(i,e,s),this.set(e,parseInt(s,10));break;case"certtype":{if((s==null||s==="")&&this.throwHelp(`${i}: ${e} is required`),typeof s=="string"&&!/^[0-9]+$/.test(s)){const n=this.constructor.CERT_TYPES;(!n||!Object.hasOwn(n,s))&&this.throwHelp(`${i}: unknown cert type mnemonic: ${s}`),this.set(e,s);break}this.is16bitInt(i,e,s),this.set(e,parseInt(s,10));break}case"u32":this.is32bitInt(i,e,s),this.set(e,parseInt(s,10));break;case"fqdn":this.setFqdnValue(i,e,s);break;case"base64":this.isBase64(i,e,s),this.set(e,s);break;case"hex":/^[0-9a-fA-F]*$/.test(s)||this.throwHelp(`${i}: ${e} must be hexadecimal`),this.set(e,s);break;case"str":s||this.throwHelp(`${i}: ${e} is required`),this.set(e,s);break;case"qstr":s==null&&this.throwHelp(`${i}: ${e} is required`),this.set(e,s);break;case"charstr":{s==null&&this.throwHelp(`${i}: ${e} is required`);const n=String(s);new TextEncoder().encode(n).length>255&&this.throwHelp(`${i}: ${e} must be <=255 bytes`),this.set(e,n);break}case"qcharstr":{s==null&&this.throwHelp(`${i}: ${e} is required`);const n=String(s);new TextEncoder().encode(n).length>255&&this.throwHelp(`${i}: ${e} must be <=255 bytes`),this.set(e,n);break}case"charstrs":s==null&&this.throwHelp(`${i}: ${e} is required`),this.set(e,s);break;case"svcparams":s==null&&this.throwHelp(`${i}: ${e} is required`),this.set(e,s);break;case"ipv4":this.isIPv4(s)||this.throwHelp(`${i}: ${e} must be a valid IPv4 address`),this.set(e,s);break;case"ipv6":this.isIPv6(s)||this.throwHelp(`${i}: ${e} must be a valid IPv6 address`),this.set(e,this.expandIPv6(s.toLowerCase()));break}}isFullyQualified(t,e,s){if(s.endsWith("."))return!0;this.throwHelp(`${t}: ${e} must be fully qualified`)}isValidHostname(t,e,s){const i=new RegExp(/[^a-zA-Z0-9\-._/\\]/);if(!i.test(s))return!0;const n=i.exec(s);this.throwHelp(`${t}, ${e} has invalid hostname character (${n[0]})`)}isIPv4(t){return/^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}$/.test(t)}isIPv6(t){return/^(?:(?:[a-fA-F\d]{1,4}:){7}(?:[a-fA-F\d]{1,4}|:)|(?:[a-fA-F\d]{1,4}:){6}(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|:[a-fA-F\d]{1,4}|:)|(?:[a-fA-F\d]{1,4}:){5}(?::(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,2}|:)|(?:[a-fA-F\d]{1,4}:){4}(?:(?::[a-fA-F\d]{1,4}){0,1}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,3}|:)|(?:[a-fA-F\d]{1,4}:){3}(?:(?::[a-fA-F\d]{1,4}){0,2}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,4}|:)|(?:[a-fA-F\d]{1,4}:){2}(?:(?::[a-fA-F\d]{1,4}){0,3}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,5}|:)|(?:[a-fA-F\d]{1,4}:){1}(?:(?::[a-fA-F\d]{1,4}){0,4}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,6}|:)|(?::(?:(?::[a-fA-F\d]{1,4}){0,5}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,7}|:)))(?:%[0-9a-zA-Z]{1,})?$/gm.test(t)}expandIPv6(t,e){return Rt(t,e)}compressIPv6(t){const e=t.toLowerCase().split(":").map(c=>c.replace(/^0+/,"")||"0");let s=-1,i=0,n=-1,a=0;for(let c=0;ci&&(i=a,s=n)):(n=-1,a=0);if(i<2)return e.join(":");const o=e.slice(0,s).join(":"),r=e.slice(s+i).join(":");return`${o}::${r}`}octalToUint8Array(t){const e=x(t);return Uint8Array.from(e,s=>s.charCodeAt(0))}wireUnpackDomain(t,e=0){return Ut(t,e)}wirePackDomain(t){return W(t)}getWireRdata(){return ae(this)}toWire(){return oe(this,f.CLASSES)}toBind(t){return ye(this,t)}parseTinydnsLine(t){const e=Jt(t);return{...e,owner:this.fullyQualify(e.owner)}}toTinydns(){return Zt(this)}isFqdnField(t){return(this.constructor.rdataFields??[]).some(e=>f.fieldName(e)===t&&f.fieldType(e)==="fqdn")||!1}isQuotedField(t){const e=new Set(["qstr","qcharstr","charstrs"]);return(this.constructor.rdataFields??[]).some(s=>f.fieldName(s)===t&&e.has(f.fieldType(s)))||!1}toMaraDNS(){const t=this.get("type");return"A PTR MX AAAA SRV NAPTR NS SOA TXT SPF RAW FQDN4 FQDN6 CNAME HINFO WKS LOC".split(/\s+/g).includes(t)?`${this.get("owner")} +${this.get("ttl")} ${t} ${this.getFields("rdata").map(s=>this.getQuoted(s)).join(" ")} ~ +`}getTinydnsPostamble(){return["ttl","timestamp","location"].map(t=>this.getEmpty(t)).join(":")}hasValidLabels(t){const e=t.endsWith(".")?t.slice(0,-1):t;for(const s of e.split("."))(s.length<1||s.length>63)&&this.throwHelp("Labels must have 1-63 octets (characters), RFC 2181")}is8bitInt(t,e,s){if(Number.isInteger(s)&&s>=0&&s<=255)return!0;this.throwHelp(`${t} ${e} must be a 8-bit integer (in the range 0-255)`)}is16bitInt(t,e,s){if(Number.isInteger(s)&&s>=0&&s<=65535)return!0;this.throwHelp(`${t} ${e} must be a 16-bit integer (in the range 0-65535)`)}is32bitInt(t,e,s){if(Number.isInteger(s)&&s>=0&&s<=4294967295)return!0;this.throwHelp(`${t} ${e} must be a 32-bit integer (in the range 0-4294967295)`)}isBase64(t,e,s){if(typeof s=="string"&&s.length>0&&s.length%4===0&&/^[A-Za-z0-9+/]*={0,2}$/.test(s))return!0;this.throwHelp(`${t} ${e} must be a valid base64 string`)}isQuoted(t){return/^["']/.test(t)&&/["']$/.test(t)}setFqdnValue(t,e,s){s||this.throwHelp(`${t}: ${e} is required`),(this.isIPv4(s)||this.isIPv6(s))&&this.throwHelp(`${t}: ${e} must be a domain name`),this.isFullyQualified(t,e,s),this.isValidHostname(t,e,s),this.set(e,s.toLowerCase())}setTypedValue(t,e,s){const i=this.constructor.typeName;switch(t){case"u8":this.is8bitInt(i,e,s),this.set(e,parseInt(s,10));break;case"u16":this.is16bitInt(i,e,s),this.set(e,parseInt(s,10));break;case"certtype":{if((s==null||s==="")&&this.throwHelp(`${i}: ${e} is required`),typeof s=="string"&&!/^[0-9]+$/.test(s)){const n=this.constructor.CERT_TYPES;(!n||!Object.hasOwn(n,s))&&this.throwHelp(`${i}: unknown cert type mnemonic: ${s}`),this.set(e,s);break}this.is16bitInt(i,e,s),this.set(e,parseInt(s,10));break}case"u32":this.is32bitInt(i,e,s),this.set(e,parseInt(s,10));break;case"fqdn":this.setFqdnValue(i,e,s);break;case"base64":this.isBase64(i,e,s),this.set(e,s);break;case"hex":/^[0-9a-fA-F]*$/.test(s)||this.throwHelp(`${i}: ${e} must be hexadecimal`),this.set(e,s);break;case"str":s||this.throwHelp(`${i}: ${e} is required`),this.set(e,s);break;case"qstr":s==null&&this.throwHelp(`${i}: ${e} is required`),this.set(e,s);break;case"charstr":{s==null&&this.throwHelp(`${i}: ${e} is required`);const n=String(s);new TextEncoder().encode(n).length>255&&this.throwHelp(`${i}: ${e} must be <=255 bytes`),this.set(e,n);break}case"qcharstr":{s==null&&this.throwHelp(`${i}: ${e} is required`);const n=String(s);new TextEncoder().encode(n).length>255&&this.throwHelp(`${i}: ${e} must be <=255 bytes`),this.set(e,n);break}case"charstrs":s==null&&this.throwHelp(`${i}: ${e} is required`),this.set(e,s);break;case"svcparams":s==null&&this.throwHelp(`${i}: ${e} is required`),this.set(e,s);break;case"ipv4":this.isIPv4(s)||this.throwHelp(`${i}: ${e} must be a valid IPv4 address`),this.set(e,s);break;case"ipv6":this.isIPv6(s)||this.throwHelp(`${i}: ${e} must be a valid IPv6 address`),this.set(e,this.expandIPv6(s.toLowerCase()));break}}isFullyQualified(t,e,s){if(s.endsWith("."))return!0;this.throwHelp(`${t}: ${e} must be fully qualified`)}isValidHostname(t,e,s){const i=new RegExp(/[^a-zA-Z0-9\-._/\\]/);if(!i.test(s))return!0;const n=i.exec(s);this.throwHelp(`${t}, ${e} has invalid hostname character (${n[0]})`)}isIPv4(t){return/^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}$/.test(t)}isIPv6(t){return/^(?:(?:[a-fA-F\d]{1,4}:){7}(?:[a-fA-F\d]{1,4}|:)|(?:[a-fA-F\d]{1,4}:){6}(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|:[a-fA-F\d]{1,4}|:)|(?:[a-fA-F\d]{1,4}:){5}(?::(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,2}|:)|(?:[a-fA-F\d]{1,4}:){4}(?:(?::[a-fA-F\d]{1,4}){0,1}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,3}|:)|(?:[a-fA-F\d]{1,4}:){3}(?:(?::[a-fA-F\d]{1,4}){0,2}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,4}|:)|(?:[a-fA-F\d]{1,4}:){2}(?:(?::[a-fA-F\d]{1,4}){0,3}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,5}|:)|(?:[a-fA-F\d]{1,4}:){1}(?:(?::[a-fA-F\d]{1,4}){0,4}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,6}|:)|(?::(?:(?::[a-fA-F\d]{1,4}){0,5}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,7}|:)))(?:%[0-9a-zA-Z]{1,})?$/gm.test(t)}expandIPv6(t,e){return Rt(t,e)}compressIPv6(t){const e=t.toLowerCase().split(":").map(c=>c.replace(/^0+/,"")||"0");let s=-1,i=0,n=-1,a=0;for(let c=0;ci&&(i=a,s=n)):(n=-1,a=0);if(i<2)return e.join(":");const o=e.slice(0,s).join(":"),r=e.slice(s+i).join(":");return`${o}::${r}`}octalToUint8Array(t){const e=x(t);return Uint8Array.from(e,s=>s.charCodeAt(0))}wireUnpackDomain(t,e=0){return Ut(t,e)}wirePackDomain(t){return V(t)}getWireRdata(){return oe(this)}toWire(){return ce(this,f.CLASSES)}toBind(t){return fe(this,t)}parseTinydnsLine(t){const e=Zt(t);return{...e,owner:this.fullyQualify(e.owner)}}toTinydns(){return _t(this)}isFqdnField(t){return(this.constructor.rdataFields??[]).some(e=>f.fieldName(e)===t&&f.fieldType(e)==="fqdn")||!1}isQuotedField(t){const e=new Set(["qstr","qcharstr","charstrs"]);return(this.constructor.rdataFields??[]).some(s=>f.fieldName(s)===t&&e.has(f.fieldType(s)))||!1}toMaraDNS(){const t=this.get("type");return"A PTR MX AAAA SRV NAPTR NS SOA TXT SPF RAW FQDN4 FQDN6 CNAME HINFO WKS LOC".split(/\s+/g).includes(t)?`${this.get("owner")} +${this.get("ttl")} ${t} ${this.getFields("rdata").map(s=>this.getQuoted(s)).join(" ")} ~ `:this.toMaraGeneric()}toMaraGeneric(){return`${this.get("owner")} +${this.get("ttl")} RAW ${this.getTypeId()} '${this.getFields("rdata").map(t=>this.getQuoted(t)).join(" ")}' ~ -`}}class Gt extends f{static typeName="A";static typeId=1;static RFCs=[1035];static tinydnsType="+";static rdataFields=[["address","ipv4"]];static tags=["common"];constructor(t){super(t)}setAddress(t){t||this.throwHelp("A: address is required"),this.isIPv4(t)||this.throwHelp("A address must be IPv4"),this.set("address",t)}getDescription(){return"Address"}getCanonical(){return{owner:"host.example.com.",class:"IN",ttl:3600,type:"A",address:"192.0.2.127"}}getWireRdata(){return new Uint8Array(this.get("address").split(".").map(Number))}}class yt extends f{static typeName="AAAA";static typeId=28;static RFCs=[3596,5952];static rdataFields=[["address","ipv6"]];static tags=["common"];constructor(t){super(t)}setAddress(t){t||this.throwHelp("AAAA: address is required"),this.isIPv6(t)||this.throwHelp(`AAAA: address must be IPv6 (${t})`),this.set("address",this.expandIPv6(t.toLowerCase()))}getCompressed(t){return this.compressIPv6(t??this.get("address"))}getDescription(){return"Address IPv6"}getCanonical(){return{owner:"host.example.com.",address:"2001:0db8:0020:000a:0000:0000:0000:0004",class:"IN",ttl:3600,type:"AAAA"}}fromTinydns({tinyline:t}){const e=t;let s,i,n,a,o,r,c;switch(e[0]){case":":[s,n,a,o,r,c]=e.slice(1).split(":"),n!=28&&this.throwHelp("AAAA fromTinydns, invalid n"),i=Pt(a).match(/([0-9a-fA-F]{4})/g).join(":");break;case"3":case"6":[s,a,o,r,c]=e.slice(1).split(":"),i=a.match(/(.{4})/g).join(":");break}return new yt({owner:this.fullyQualify(s),ttl:parseInt(o,10),type:"AAAA",address:i,timestamp:r,location:c?.trim()??""})}getWireRdata(){const t=this.expandIPv6(this.get("address"),""),e=new Uint8Array(t.length/2);for(let s=0;sp.charCodeAt(0)),c=[];let h=0;for(;h{const e=t.startsWith("!"),s=e?t.slice(1):t,i=s.indexOf(":"),n=parseInt(s.slice(0,i),10),a=s.slice(i+1),o=a.lastIndexOf("/"),r=a.slice(0,o),c=parseInt(a.slice(o+1),10);let h;if(n===1)h=new Uint8Array(r.split(".").map(y=>parseInt(y,10)));else{const y=r.indexOf("::");let m;if(y!==-1){const w=r.slice(0,y).split(":").filter(D=>D!==""),T=r.slice(y+2).split(":").filter(D=>D!=="");m=[...w,...Array(8-w.length-T.length).fill("0000"),...T]}else m=r.split(":");const b=m.map(w=>w.padStart(4,"0")).join("");h=Uint8Array.from({length:b.length/2},(w,T)=>parseInt(b.slice(T*2,T*2+2),16))}let p=h.length;for(;p>0&&h[p-1]===0;)p--;const d=h.slice(0,p);let g=A(n);g+=u(c),g+=u((e?128:0)|d.length);for(const y of d)g+=u(y);return g}).join(""))}getWireRdata(){const t=this.get("apl rdata").split(/\s+/),e=[];for(const a of t){const o=a.startsWith("!"),r=o?a.slice(1):a,c=r.indexOf(":"),h=parseInt(r.slice(0,c),10),p=r.slice(c+1),d=p.lastIndexOf("/"),g=p.slice(0,d),y=parseInt(p.slice(d+1),10);let m;if(h===1)m=new Uint8Array(g.split(".").map(C=>parseInt(C,10)));else{const C=g.indexOf("::");let S;if(C!==-1){const _=g.slice(0,C).split(":").filter(Dt=>Dt!==""),tt=g.slice(C+2).split(":").filter(Dt=>Dt!=="");S=[..._,...Array(8-_.length-tt.length).fill("0000"),...tt]}else S=g.split(":");const kt=S.map(_=>_.padStart(4,"0")).join("");m=Uint8Array.from({length:kt.length/2},(_,tt)=>parseInt(kt.slice(tt*2,tt*2+2),16))}let b=m.length;for(;b>0&&m[b-1]===0;)b--;const w=m.slice(0,b),T=new Uint8Array(4+w.length);new DataView(T.buffer,T.byteOffset).setUint16(0,h),T[2]=y,T[3]=(o?128:0)|w.length,T.set(w,4),e.push(T)}const s=e.reduce((a,o)=>a+o.length,0),i=new Uint8Array(s);let n=0;for(const a of e)i.set(a,n),n+=a.length;return i}}class ft extends f{static typeName="CAA";static typeId=257;static RFCs=[6844,8659,9619];static rdataFields=[["flags","u8"],["tag","charstr"],["value","qstr"]];static tags=["security"];constructor(t){super(t)}setFlags(t){this.is8bitInt("CAA","flags",t),this.getFlagsOptions().has(t)||this.throwHelp(`CAA flags ${t} not recognized`),this.set("flags",t)}getFlagsOptions(){return new Map([[0,"Non Critical"],[128,"Critical"]])}setTag(t){(typeof t!="string"||t.length<1||/[^a-z0-9]/.test(t))&&this.throwHelp("CAA tag must be a sequence of ASCII letters and numbers in lowercase"),this.getTagOptions().has(t)||this.throwHelp(`CAA tag ${t} not recognized`),this.set("tag",t)}getTagOptions(){return new Map([["issue"],["issuewild"],["iodef"]])}setValue(t){this.isQuoted(t)&&(t=t.replace(/^["']|["']$/g,"")),this.get("tag")==="iodef"&&(["mailto:","http:","https:"].filter(s=>t.startsWith(s)).length||this.throwHelp("CAA value must have valid iodefScheme prefix")),this.set("value",t)}getDescription(){return"Certification Authority Authorization"}getCanonical(){return{owner:"example.com.",ttl:3600,class:"IN",type:"CAA",flags:0,tag:"issue",value:"http://letsencrypt.org"}}fromTinydns({tinyline:t}){const{owner:e,typeId:s,rdata:i,ttl:n,timestamp:a,location:o}=this.parseTinydnsLine(t);s!=this.getTypeId()&&this.throwHelp("CAA fromTinydns, invalid typeId");const r=E(i.slice(0,4)),c=E(i.slice(4,8)),h=x(i.slice(8)),p=h.slice(0,c),d=h.slice(c);return new ft({owner:e,ttl:n,type:"CAA",flags:r,tag:p,value:d,timestamp:a,location:o})}getWireRdata(){const t=new TextEncoder().encode(this.get("tag")),e=new TextEncoder().encode(this.get("value")),s=new Uint8Array(2+t.length+e.length);return s[0]=this.get("flags"),s[1]=t.length,s.set(t,2),s.set(e,2+t.length),s}toTinydns(){return this.getTinydnsGeneric(u(this.get("flags"))+u(this.get("tag").length)+I(/[\r\n\t:\\/]/,this.get("tag"))+I(/[\r\n\t:\\/]/,this.get("value")))}}class $ extends f{static typeName="CERT";static typeId=37;static RFCs=[2538,4398];static rdataFields=[["cert type","certtype"],["key tag","u16"],["algorithm","u8"],["certificate","base64"]];static CERT_TYPES={PKIX:1,SPKI:2,PGP:3,IPKIX:4,ISPKI:5,IPGP:6,ACPKIX:7,IACPKIX:8,URI:253,OID:254};static CERT_TYPES_REVERSE=Object.fromEntries(Object.entries($.CERT_TYPES).map(([t,e])=>[e,t]));constructor(t){super(t)}setCertType(t){(t==null||t==="")&&this.throwHelp("cert type is required"),typeof t=="string"&&!/^[0-9]+$/.test(t)?Object.hasOwn($.CERT_TYPES,t)||this.throwHelp(`CERT: unknown cert type mnemonic: ${t}`):this.is16bitInt("CERT","cert type",t),this.set("cert type",t)}getCertTypeValue(t){if(typeof t=="number")return t;if(/^[0-9]+$/.test(t))return parseInt(t,10);if(Object.hasOwn($.CERT_TYPES,t))return $.CERT_TYPES[t];this.throwHelp(`CERT: unknown cert type mnemonic: ${t}`)}setCertificate(t){(t==null||t==="")&&this.throwHelp("certificate is required and cannot be empty"),this.isBase64("CERT","certificate",t.replace(/[\s()]/g,"")),this.set("certificate",t)}getDescription(){return"Certificate"}getCanonical(){return{owner:"mail.example.com.",ttl:3600,class:"IN",type:"CERT","cert type":"PGP","key tag":0,algorithm:0,certificate:"AQIDBA=="}}fromTinydns({tinyline:t}){const{owner:e,typeId:s,rdata:i,ttl:n,timestamp:a,location:o}=this.parseTinydnsLine(t);s!=this.getTypeId()&&this.throwHelp("CERT fromTinydns, invalid n");const r=H(i),c=r[0]<<8|r[1],h=$.CERT_TYPES_REVERSE[c]??c;return new $({owner:e,ttl:n,type:"CERT","cert type":h,"key tag":r[2]<<8|r[3],algorithm:r[4],certificate:V(r.subarray(5)),timestamp:a,location:o})}fromBind({bindline:t}){const[e,s,i,n,a,o,r,c]=t.split(/\s+/);return new $({owner:e,ttl:parseInt(s,10),class:i,type:n,"cert type":/^[0-9]+$/.test(a)?parseInt(a,10):a,"key tag":parseInt(o,10),algorithm:parseInt(r,10),certificate:c})}toTinydns(){return this.getTinydnsGeneric(A(this.getCertTypeValue(this.get("cert type")))+A(this.get("key tag"))+u(this.get("algorithm"))+G(this.get("certificate").replace(/[\s()]/g,"")))}getWireRdata(){const t=L(this.get("certificate").replace(/[\s()]/g,"")),e=new Uint8Array(5+t.length),s=new DataView(e.buffer,e.byteOffset);return s.setUint16(0,this.getCertTypeValue(this.get("cert type"))),s.setUint16(2,this.get("key tag")),e[4]=this.get("algorithm"),e.set(t,5),e}}class Vt extends f{static typeName="CNAME";static typeId=5;static RFCs=[1035,2181];static tinydnsType="C";static rdataFields=[["cname","fqdn"]];static tags=["common"];constructor(t){super(t)}getDescription(){return"Canonical Name"}getCanonical(){return{owner:"www.example.com.",ttl:3600,class:"IN",type:"CNAME",cname:"web.example.com."}}getWireRdata(){return this.wirePackDomain(this.get("cname"))}}class mt extends f{static typeName="DHCID";static typeId=49;static RFCs=[4701];static rdataFields=[["data","base64"]];constructor(t){super(t)}setData(t){t||this.throwHelp("DHCID: data is required"),this.isBase64("DHCID","data",t),this.set("data",t)}getDescription(){return"DHCP Identifier"}getCanonical(){return{owner:"host.example.com.",ttl:3600,class:"IN",type:"DHCID",data:"AAIBY2/AuCccgoJbsaxcQc9TUapptP69lOjxfNuVAA2kjEA="}}fromTinydns({tinyline:t}){const{owner:e,typeId:s,rdata:i,ttl:n,timestamp:a,location:o}=this.parseTinydnsLine(t);return s!=this.getTypeId()&&this.throwHelp("DHCID fromTinydns, invalid n"),new mt({owner:e,ttl:n,type:"DHCID",data:ut(i),timestamp:a,location:o})}getWireRdata(){return new Uint8Array(atob(this.get("data")).split("").map(t=>t.charCodeAt(0)))}toTinydns(){return this.getTinydnsGeneric(G(this.get("data")))}}class wt extends f{static typeName="DNAME";static typeId=39;static RFCs=[2672,6672];static rdataFields=[["target","fqdn"]];constructor(t){super(t)}getDescription(){return"Delegation Name"}getCanonical(){return{owner:"example.com.",ttl:3600,class:"IN",type:"DNAME",target:"example.net."}}fromTinydns({tinyline:t}){const[e,s,i,n,a,o]=t.slice(1).split(":");return s!=39&&this.throwHelp("DNAME fromTinydns, invalid n"),new wt({type:"DNAME",owner:this.fullyQualify(e),target:U(i)[0],ttl:parseInt(n,10),timestamp:a,location:o?.trim()??""})}getWireRdata(){return this.wirePackDomain(this.get("target"))}toTinydns(){const t=N(this.get("target"));return this.getTinydnsGeneric(t)}}class et extends f{static typeName="DNSKEY";static typeId=48;static RFCs=[4034,6014,8624,9619,9905];static rdataFields=[["flags","u16"],["protocol","u8"],["algorithm","u8"],["publickey","base64"]];static tags=["dnssec"];constructor(t){super(t)}setFlags(t){this.is16bitInt("DNSKEY","flags",t),this.getFlagsOptions().has(t)||this.throwHelp(`DNSKEY: flags must be in the set: ${this.getFlagsOptions()}`),this.set("flags",t)}getFlagsOptions(){return new Map([[0],[256],[257]])}setProtocol(t){this.is8bitInt("DNSKEY","protocol",t),this.getProtocolOptions().has(t)||this.throwHelp("DNSKEY: protocol invalid"),this.set("protocol",t)}getProtocolOptions(){return new Map([[3]])}setAlgorithm(t){this.is8bitInt("DNSKEY","algorithm",t),this.getAlgorithmOptions().has(t)||console.error(`DNSKEY: algorithm (${t}) not recognized`),this.set("algorithm",t)}getAlgorithmOptions(){return new Map([[1,"RSA/MD5 (DEPRECATED)"],[2,"DH"],[3,"DSA/SHA-1"],[4,"EC"],[5,"RSA/SHA-1"],[6,"DSA-NSEC3-SHA1"],[7,"RSASHA1-NSEC3-SHA1"],[8,"RSA/SHA-256"],[9,""],[10,"RSA/SHA-512"],[13,"ECDSA Curve P-256 with SHA-256"],[14,"ECDSA Curve P-384 with SHA-384"],[15,"Ed25519"],[16,"Ed448"],[253],[254]])}setPublickey(t){t||this.throwHelp("DNSKEY: publickey is required"),this.isBase64("DNSKEY","publickey",t.replace(/[\s()]/g,"")),this.set("publickey",t)}getDescription(){return"DNS Public Key"}getCanonical(){return{owner:"example.com.",ttl:3600,class:"IN",type:"DNSKEY",flags:256,protocol:3,algorithm:5,publickey:"AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwIXAqcOTiW7iHnQt5hwVAAAAA=="}}fromBind({bindline:t}){const e=/^(?\S+)\s+(?\d+)\s+(?\w+)\s+(?DNSKEY)\s+(?\d+)\s+(?\d+)\s+(?\d+)\s+(?\S.*)$/i,s=t.trim().match(e);s||this.throwHelp(`unable to parse DNSKEY: ${t}`);const{owner:i,ttl:n,c:a,type:o,flags:r,protocol:c,algorithm:h,publickey:p}=s.groups;return new et({owner:i,ttl:parseInt(n,10),class:a,type:o,flags:parseInt(r,10),protocol:parseInt(c,10),algorithm:parseInt(h,10),publickey:p})}fromTinydns({tinyline:t}){const{owner:e,typeId:s,rdata:i,ttl:n,timestamp:a,location:o}=this.parseTinydnsLine(t);s!=this.getTypeId()&&this.throwHelp("DNSKEY fromTinydns, invalid n");const r=H(i);return new et({owner:e,ttl:n,type:"DNSKEY",flags:r[0]<<8|r[1],protocol:r[2],algorithm:r[3],publickey:V(r.subarray(4)),timestamp:a,location:o})}toTinydns(){return this.getTinydnsGeneric(A(this.get("flags"))+u(this.get("protocol"))+u(this.get("algorithm"))+G(this.get("publickey").replace(/[\s()]/g,"")))}getWireRdata(){const t=L(this.get("publickey").replace(/[\s()]/g,"")),e=new Uint8Array(4+t.length);return new DataView(e.buffer,e.byteOffset).setUint16(0,this.get("flags")),e[2]=this.get("protocol"),e[3]=this.get("algorithm"),e.set(t,4),e}}class st extends f{static typeName="DS";static typeId=43;static RFCs=[4034,4509,9619];static rdataFields=[["key tag","u16"],"algorithm","digest type",["digest","str"]];static tags=["dnssec"];constructor(t){super(t)}setAlgorithm(t){this.getAlgorithmOptions().has(t)||this.throwHelp("DS: algorithm invalid"),this.set("algorithm",t)}getAlgorithmOptions(){return new Map([[1,"RSA/MD5"],[2,"DH"],[3,"DSA/SHA-1"],[4,"EC"],[5,"RSA/SHA-1"],[253,""],[254,""]])}setDigestType(t){[1,2].includes(t)||this.throwHelp("DS: digest type invalid"),this.set("digest type",t)}getDescription(){return"Delegation Signer"}getCanonical(){return{owner:"example.com.",ttl:3600,class:"IN",type:"DS","key tag":12345,algorithm:5,"digest type":1,digest:"ABCDEF123..."}}fromTinydns(t){const{tinyline:e}=t,{owner:s,typeId:i,rdata:n,ttl:a,timestamp:o,location:r}=this.parseTinydnsLine(e);i!=this.getTypeId()&&this.throwHelp("DS fromTinydns, invalid n");const c=H(n);return new st({owner:s,ttl:a,type:"DS","key tag":c[0]<<8|c[1],algorithm:c[2],"digest type":c[3],digest:R(c.subarray(4)).toUpperCase(),timestamp:o,location:r})}fromWire({owner:t,cls:e,ttl:s,rdata:i}){const n=new DataView(i.buffer,i.byteOffset);return new st({owner:t,ttl:s,class:e,type:"DS","key tag":n.getUint16(0),algorithm:i[2],"digest type":i[3],digest:R(i.subarray(4)).toUpperCase()})}toTinydns(){return this.getTinydnsGeneric(A(this.get("key tag"))+u(this.get("algorithm"))+u(this.get("digest type"))+O(this.get("digest").replace(/\s+/g,"")))}getWireRdata(){const t=F(this.get("digest").replace(/\s+/g,"")),e=new Uint8Array(4+t.length);return new DataView(e.buffer,e.byteOffset).setUint16(0,this.get("key tag")),e[2]=this.get("algorithm"),e[3]=this.get("digest type"),e.set(t,4),e}}class jt extends f{static typeName="HINFO";static typeId=13;static RFCs=[1034,1035,8482];static rdataFields=[["cpu","qcharstr"],["os","qcharstr"]];static tags=["obsolete"];constructor(t){super(t)}setCpu(t){t.length>255&&this.throwHelp("HINFO cpu cannot exceed 255 chars"),this.set("cpu",t.replace(/^["']|["']$/g,""))}setOs(t){t.length>255&&this.throwHelp("HINFO os cannot exceed 255 chars"),this.set("os",t.replace(/^["']|["']$/g,""))}getDescription(){return"Host Info"}getCanonical(){return{owner:"test.example.com.",ttl:3600,class:"IN",type:"HINFO",cpu:"DEC-2060",os:"TOPS20"}}fromTinydns({tinyline:t}){const[e,,s,i,n,a]=t.slice(1).split(":"),[o,r]=[...te(s)];return new this.constructor({owner:this.fullyQualify(e),ttl:parseInt(i,10),type:"HINFO",cpu:o,os:r,timestamp:n,location:a?.trim()??""})}getWireRdata(){const t=new TextEncoder().encode(this.get("cpu")),e=new TextEncoder().encode(this.get("os")),s=new Uint8Array(2+t.length+e.length);return s[0]=t.length,s.set(t,1),s[1+t.length]=e.length,s.set(e,2+t.length),s}toTinydns(){return this.getTinydnsGeneric([Bt(this.get("cpu")),Bt(this.get("os"))].join(""))}}class K extends f{static typeName="HIP";static typeId=55;static RFCs=[8005];static rdataFields=["pk algorithm","hit","public key","rendezvous servers"];constructor(t){super(t)}setPkAlgorithm(t){t===void 0&&this.throwHelp("HIP: pk algorithm is required"),this.is8bitInt("HIP","pk algorithm",t),this.set("pk algorithm",t)}setHit(t){t||this.throwHelp("HIP: hit is required"),this.set("hit",t)}setPublicKey(t){t||this.throwHelp("HIP: public key is required"),this.set("public key",t)}setRendezvousServers(t){this.set("rendezvous servers",t??"")}getDescription(){return"Host Identity Protocol"}getCanonical(){return{owner:"example.com.",ttl:3600,class:"IN",type:"HIP","pk algorithm":2,hit:"200100107B1A74DF365639CC39F1D578","public key":"AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwIXAqcOTiW7iHnQt5hwVAAAAA==","rendezvous servers":""}}fromTinydns({tinyline:t}){const[e,s,i,n,a,o]=t.slice(1).split(":");s!=55&&this.throwHelp("HIP fromTinydns, invalid n");const r=Uint8Array.from(x(i),b=>b.charCodeAt(0)),c=r[0],h=r[1],p=r[2]<<8|r[3],d=R(r.subarray(4,4+c)).toUpperCase(),g=V(r.subarray(4+c,4+c+p)),y=[];let m=4+c+p;for(;mT<32||T>126?u(T):String.fromCharCode(T)).join(""));m+=w,b!=="."&&y.push(b)}return new K({owner:this.fullyQualify(e),ttl:parseInt(n,10),type:"HIP","pk algorithm":h,hit:d,"public key":g,"rendezvous servers":y.join(" "),timestamp:a,location:o?.trim()??""})}fromBind({bindline:t}){const e=t.split(/\s+/),[s,i,n,a,o,r]=e,c=e.slice(6),h=[],p=[];for(const d of c)/^[A-Za-z0-9+/=]+$/.test(d)?h.push(d):p.push(d);return new K({owner:s,ttl:parseInt(i,10),class:n,type:a,"pk algorithm":parseInt(o,10),hit:r,"public key":h.join(""),"rendezvous servers":p.join(" ").trim()})}fromWire({owner:t,cls:e,ttl:s,rdata:i}){const n=new DataView(i.buffer,i.byteOffset),a=i[0],o=i[1],r=n.getUint16(2),c=R(i.subarray(4,4+a)).toUpperCase(),h=V(i.subarray(4+a,4+a+r)),p=[];let d=4+a+r;for(;dW(d)),o=a.reduce((d,g)=>d+g.length,0),r=4+e.length+s.length+o,c=new Uint8Array(r),h=new DataView(c.buffer,c.byteOffset);let p=0;c[p++]=e.length,c[p++]=this.get("pk algorithm"),h.setUint16(p,s.length),p+=2,c.set(e,p),p+=e.length,c.set(s,p),p+=s.length;for(const d of a)c.set(d,p),p+=d.length;return c}}class it extends f{static typeName="HTTPS";static typeId=65;static RFCs=[9460];static tags=["common"];static rdataFields=[["priority","u16"],["target name","fqdn"],["params","svcparams"]];constructor(t){super(t)}setPriority(t){this.is16bitInt("HTTPS","priority",t),this.set("priority",t)}setTargetName(t){this.set("target name",t.toLowerCase())}setParams(t){this.set("params",t)}getDescription(){return"HTTP Semantics"}getCanonical(){return{owner:"example.com.",ttl:3600,class:"IN",type:"HTTPS",priority:1,"target name":"example.com.",params:'alpn="h2,h3"'}}fromBind({bindline:t}){const[e,s,i,n,a,o]=t.split(/\s+/);return new it({owner:e,ttl:parseInt(s,10),class:i,type:n,priority:parseInt(a,10),"target name":o,params:t.split(/\s+/).slice(6).join(" ").trim()})}fromTinydns({tinyline:t}){const{owner:e,typeId:s,rdata:i,ttl:n,timestamp:a,location:o}=this.parseTinydnsLine(t);s!=this.getTypeId()&&this.throwHelp("HTTPS fromTinydns, invalid n");const{priority:r,targetName:c,params:h}=Mt(i,"HTTPS");return new it({owner:e,ttl:n,type:"HTTPS",priority:r,"target name":c,params:h,timestamp:a,location:o})}toTinydns(){const t=new RegExp(/[\r\n\t:\\/]/,"g");return this.getTinydnsGeneric(A(this.get("priority"))+N(this.get("target name"))+I(t,this.get("params")))}getWireRdata(){const t=this.wirePackDomain(this.get("target name")),e=Wt(this.get("params")),s=new Uint8Array(2+t.length+e.length);return new DataView(s.buffer).setUint16(0,this.get("priority")),s.set(t,2),s.set(e,2+t.length),s}}class Q extends f{static typeName="IPSECKEY";static typeId=45;static RFCs=[4025];static rdataFields=["precedence","gateway type","algorithm","gateway","publickey"];static tags=["security"];constructor(t){super(t)}setPrecedence(t){this.is8bitInt("IPSECKEY","precedence",t),this.set("precedence",t)}setGatewayType(t){this.getGatewayTypeOptions().has(t)||this.throwHelp("IPSECKEY: Gateway Type is invalid"),this.set("gateway type",t)}getGatewayTypeOptions(){return new Map([[0,"none"],[1,"4-byte IPv4"],[2,"16-byte IPv6"],[3,"wire encoded domain name"]])}setAlgorithm(t){this.getAlgorithmOptions().has(t)||this.throwHelp("IPSECKEY: Algorithm invalid"),this.set("algorithm",t)}getAlgorithmOptions(){return new Map([[1,"DSA"],[2,"RSA"]])}setGateway(t){const e=this.get("gateway type"),s=new Error(`IPSECKEY: gateway invalid (${t}) for type ${e}`);switch(e){case 0:if(t!==".")throw s;break;case 1:if(!this.isIPv4(t))throw s;break;case 2:if(!this.isIPv6(t))throw s;break}this.set("gateway",t)}setPublickey(t){t&&this.isBase64("IPSECKEY","publickey",t),this.set("publickey",t)}getDescription(){return"IPsec Keying"}getCanonical(){return{owner:"38.2.0.192.in-addr.arpa.",ttl:7200,class:"IN",type:"IPSECKEY",precedence:10,"gateway type":1,algorithm:2,gateway:"192.0.2.38",publickey:"AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ=="}}fromBind({bindline:t}){const[e,s,i,n,a,o,r,c,h]=t.split(/\s+/);return new Q({owner:e,ttl:parseInt(s,10),class:i,type:n,precedence:parseInt(a,10),"gateway type":parseInt(o,10),algorithm:parseInt(r,10),gateway:c,publickey:h})}fromTinydns({tinyline:t}){const[e,s,i,n,a,o]=t.slice(1).split(":");s!=45&&this.throwHelp("IPSECKEY fromTinydns, invalid n");const r=E(i.slice(0,4)),c=E(i.slice(4,8)),h=E(i.slice(8,12));let p,d,g;switch(c){case 0:d=i.slice(12,13),g=i.slice(13);break;case 1:d=se(i.slice(12,28)),g=i.slice(28);break;case 2:d=ne(i.slice(12,76)),g=i.slice(76);break;case 3:[d,p]=U(i.slice(12)),g=i.slice(12+p);break}return new Q({owner:this.fullyQualify(e),ttl:parseInt(n,10),type:"IPSECKEY",precedence:r,"gateway type":c,algorithm:h,gateway:d,publickey:ut(g),timestamp:a,location:o?.trim()??""})}fromWire({owner:t,cls:e,ttl:s,rdata:i}){const n=i[0],a=i[1],o=i[2];let r,c;switch(a){case 0:r=".",c=3;break;case 1:r=[...i.subarray(3,7)].join("."),c=7;break;case 2:{const p=new DataView(i.buffer,i.byteOffset+3),d=[];for(let g=0;g<16;g+=2)d.push(p.getUint16(g).toString(16).padStart(4,"0"));r=d.join(":"),c=19;break}case 3:{const{fqdn:p,end:d}=this.wireUnpackDomain(i,3);r=p,c=d;break}}const h=V(i.subarray(c));return new Q({owner:t,ttl:s,class:e,type:"IPSECKEY",precedence:n,"gateway type":a,algorithm:o,gateway:r,publickey:h})}toTinydns(){const t=new RegExp(/[\r\n\t:\\/]/,"g");let e="";switch(e+=u(this.get("precedence")),e+=u(this.get("gateway type")),e+=u(this.get("algorithm")),this.get("gateway type")){case 0:e+=I(t,".");break;case 1:e+=qt(this.get("gateway"));break;case 2:e+=ie(this.get("gateway"));break;case 3:e+=N(this.get("gateway"));break}return e+=G(this.get("publickey")),this.getTinydnsGeneric(e)}getWireRdata(){const t=L(this.get("publickey")),e=this.get("gateway type");let s;switch(e){case 0:s=new Uint8Array(0);break;case 1:s=new Uint8Array(4),this.get("gateway").split(".").forEach((n,a)=>{s[a]=parseInt(n,10)});break;case 2:s=new Uint8Array(16);{const n=this.get("gateway").split(":");let a=0;for(const o of n){if(o==="")continue;const r=parseInt(o,16);s[a++]=r>>>8&255,s[a++]=r&255}}break;case 3:s=W(this.get("gateway"));break}const i=new Uint8Array(3+s.length+t.length);return i[0]=this.get("precedence"),i[1]=e,i[2]=this.get("algorithm"),i.set(s,3),i.set(t,3+s.length),i}}class nt extends f{static typeName="KEY";static typeId=25;static RFCs=[2535,3445,4034,6840];static rdataFields=[["flags","u16"],["protocol","u8"],["algorithm","u8"],["publickey","base64"]];static tags=["obsolete"];constructor(t){super(t)}setFlags(t){this.is16bitInt("KEY","flags",t),this.set("flags",t)}setProtocol(t){this.is8bitInt("KEY","protocol",t),this.set("protocol",t)}setAlgorithm(t){this.getAlgorithmOptions().has(t)||this.throwHelp("KEY: algorithm invalid"),this.set("algorithm",t)}getAlgorithmOptions(){return new Map([[1,"RSA/MD5"],[2,"DH"],[3,"DSA/SHA-1"],[4,"EC"],[5,"RSA/SHA-1"],[253,""],[254,""]])}setPublickey(t){t||this.throwHelp("KEY: publickey is required"),this.isBase64("KEY","publickey",t.replace(/[\s()]/g,"")),this.set("publickey",t)}getDescription(){return"DNS Public Key"}getCanonical(){return{owner:"example.com.",ttl:3600,class:"IN",type:"KEY",flags:256,protocol:3,algorithm:5,publickey:"AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwIXAqcOTiW7iHnQt5hwVAAAAA=="}}fromBind({bindline:t}){const[e,s,i,n,a,o,r]=t.split(/\s+/);return new nt({owner:e,ttl:parseInt(s,10),class:i,type:n,flags:parseInt(a,10),protocol:parseInt(o,10),algorithm:parseInt(r,10),publickey:t.split(/\s+/).slice(7).join(" ").trim()})}fromTinydns({tinyline:t}){const{owner:e,rdata:s,ttl:i,timestamp:n,location:a}=this.parseTinydnsLine(t);return s.length<16&&this.throwHelp(`KEY: RDATA too short: ${s}`),new nt({owner:e,ttl:i,type:"KEY",flags:B(s.slice(0,8)),protocol:E(s.slice(8,12)),algorithm:E(s.slice(12,16)),publickey:ut(s.slice(16)),timestamp:n,location:a})}toTinydns(){return this.getTinydnsGeneric(A(this.get("flags"))+u(this.get("protocol"))+u(this.get("algorithm"))+G(this.get("publickey").replace(/[\s()]/g,"")))}getWireRdata(){const t=L(this.get("publickey").replace(/[\s()]/g,"")),e=new Uint8Array(4+t.length);return new DataView(e.buffer,e.byteOffset).setUint16(0,this.get("flags")),e[2]=this.get("protocol"),e[3]=this.get("algorithm"),e.set(t,4),e}}class bt extends f{static typeName="KX";static typeId=36;static RFCs=[2230];static rdataFields=[["preference","u16"],["exchanger","fqdn"]];constructor(t){super(t)}setPreference(t){t===void 0&&this.throwHelp("KX: preference is required"),this.is16bitInt("KX","preference",t),this.set("preference",t)}setExchanger(t){t||this.throwHelp("KX: exchanger is required"),this.isFullyQualified("KX","exchanger",t),this.isValidHostname("KX","exchanger",t),this.set("exchanger",t.toLowerCase())}getDescription(){return"Key Exchanger"}getCanonical(){return{owner:"example.com.",ttl:3600,class:"IN",type:"KX",preference:10,exchanger:"kx.example.com."}}fromTinydns({tinyline:t}){const[e,s,i,n,a,o]=t.slice(1).split(":");return s!=36&&this.throwHelp("KX fromTinydns, invalid n"),new bt({owner:this.fullyQualify(e),ttl:parseInt(n,10),type:"KX",preference:B(i.slice(0,8)),exchanger:U(i.slice(8))[0],timestamp:a,location:o?.trim()??""})}getWireRdata(){const t=this.wirePackDomain(this.get("exchanger")),e=new Uint8Array(2+t.length);return new DataView(e.buffer).setUint16(0,this.get("preference")),e.set(t,2),e}toTinydns(){return this.getTinydnsGeneric(A(this.get("preference"))+N(this.get("exchanger")))}}const M={LATLON:2**31,ALTITUDE:1e5*100},k={sec:1e3,min:60*1e3,deg:3600*1e3};class Y extends f{static typeName="LOC";static typeId=29;static RFCs=[1876];static rdataFields=["address"];constructor(t){super(t)}setAddress(t){t||this.throwHelp("LOC: address is required"),this.parseLoc(t),this.set("address",t)}getDescription(){return"Location"}getCanonical(){return{owner:"example.com.",ttl:3600,class:"IN",type:"LOC",address:"52 22 23.000 N 4 53 32.000 E 10m 100m 10m 2m"}}parseLoc(t){const e="(\\d+)\\s+(?:(\\d+)\\s+)?(?:([\\d.]+)\\s+)?",s="(-?[\\d.]+)m?(?:\\s+([\\d.]+)m?)?(?:\\s+([\\d.]+)m?)?(?:\\s+([\\d.]+)m?)?",i=new RegExp(`^${e}(N|S)\\s+${e}(E|W)\\s+${s}`,"i"),n=t.match(i);return n||this.throwHelp("LOC address: invalid format, see RFC 1876"),{latitude:{degrees:n[1],minutes:n[2],seconds:n[3],hemisphere:n[4].toUpperCase()},longitude:{degrees:n[5],minutes:n[6],seconds:n[7],hemisphere:n[8].toUpperCase()},altitude:n[9]*100,size:n[10]*100,precision:{horizontal:n[11]*100,vertical:n[12]*100}}}fromTinydns({tinyline:t}){const[e,s,i,n,a,o]=t.slice(1).split(":");s!=29&&this.throwHelp("LOC fromTinydns, invalid n");const r={version:E(i.slice(0,4)),size:this.fromExponent(E(i.slice(4,8))),precision:{horizontal:this.fromExponent(E(i.slice(8,12))),vertical:this.fromExponent(E(i.slice(12,16)))},latitude:this.arcSecToDMS(gt(i.slice(16,32)),"lat"),longitude:this.arcSecToDMS(gt(i.slice(32,48)),"lon"),altitude:gt(i.slice(48,64))-M.ALTITUDE};return new Y({type:"LOC",owner:this.fullyQualify(e),address:this.toHuman(r),ttl:parseInt(n,10),timestamp:a,location:o?.trim()??""})}fromBind({bindline:t}){const[e,s,i,n]=t.split(/\s+/);return new Y({owner:e,ttl:parseInt(s,10),class:i,type:n,address:t.split(/\s+/).slice(4).join(" ").trim()})}dmsToArcSec(t){let e=t.degrees*k.deg+(t.minutes??0)*k.min+(t.seconds??0)*k.sec;switch(t.hemisphere.toUpperCase()){case"W":case"S":e=-e;break}return e+=M.LATLON,e}arcSecToDMS(t,e){let s=Math.abs(t-M.LATLON);const i=Math.floor(s/k.deg);s-=i*k.deg;const n=Math.floor(s/k.min);s-=n*k.min;const a=Math.floor(s/k.sec);s-=a*k.sec;let o;switch(e){case"lat":o=t>=M.LATLON?"N":"S";break;case"lon":o=t>=M.LATLON?"E":"W";break;default:this.throwHelp("unknown or missing hemisphere")}return`${i} ${n} ${a}${s?"."+s:""} ${o}`}fromExponent(t){const e=(t>>4&15)%10,s=(t>>0&15)%10;return e*Math.pow(10,s)}toExponent(t){let e=0;for(;t>=10;)t/=10,++e;return parseInt(t)<<4|e&15}toHuman(t){let e=`${t.latitude} ${t.longitude} ${t.altitude/100}m`;return t.size&&(e+=` ${t.size/100}m`),t.precision.horizontal&&(e+=` ${t.precision.horizontal/100}m`),t.precision.vertical&&(e+=` ${t.precision.vertical/100}m`),e}fromWire({owner:t,cls:e,ttl:s,rdata:i}){const n=new DataView(i.buffer,i.byteOffset),a={size:this.fromExponent(i[1]),precision:{horizontal:this.fromExponent(i[2]),vertical:this.fromExponent(i[3])},latitude:this.arcSecToDMS(n.getUint32(4),"lat"),longitude:this.arcSecToDMS(n.getUint32(8),"lon"),altitude:n.getUint32(12)-M.ALTITUDE};return new Y({owner:t,ttl:s,class:e,type:"LOC",address:this.toHuman(a)})}toTinydns(){const t=this.parseLoc(this.get("address"));let e="";return e+=u(0),e+=u(this.toExponent(t.size)),e+=u(this.toExponent(t.precision.horizontal)),e+=u(this.toExponent(t.precision.vertical)),e+=P(this.dmsToArcSec(t.latitude)),e+=P(this.dmsToArcSec(t.longitude)),e+=P(t.altitude+M.ALTITUDE),this.getTinydnsGeneric(e)}getWireRdata(){const t=this.parseLoc(this.get("address")),e=new Uint8Array(16),s=new DataView(e.buffer,e.byteOffset);return e[0]=0,e[1]=this.toExponent(t.size),e[2]=this.toExponent(t.precision.horizontal),e[3]=this.toExponent(t.precision.vertical),s.setUint32(4,this.dmsToArcSec(t.latitude)),s.setUint32(8,this.dmsToArcSec(t.longitude)),s.setUint32(12,t.altitude+M.ALTITUDE),e}}class Tt extends f{static typeName="MX";static typeId=15;static RFCs=[1035,2181,7505];static tinydnsType="@";static rdataFields=[["preference","u16"],["exchange","fqdn"]];static tags=["common"];constructor(t){super(t)}setPreference(t){t===void 0&&(t=this?.default?.preference),t===void 0&&this.throwHelp("MX: preference is required"),this.is16bitInt("MX","preference",t),this.set("preference",t)}getDescription(){return"Mail Exchanger"}getCanonical(){return{owner:"example.com.",ttl:43200,class:"IN",type:"MX",preference:10,exchange:"mail.example.com."}}fromTinydns({tinyline:t}){const[e,s,i,n,a,o,r]=t.slice(1).split(":");return new Tt({type:"MX",owner:this.fullyQualify(e),exchange:this.fullyQualify(/\./.test(i)?i:`${i}.mx.${e}`),preference:parseInt(n,10)||0,ttl:parseInt(a,10),timestamp:o,location:r?.trim()??""})}getWireRdata(){const t=this.wirePackDomain(this.get("exchange")),e=new Uint8Array(2+t.length);return new DataView(e.buffer).setUint16(0,this.get("preference")),e.set(t,2),e}toTinydns(){return`@${this.getTinyFQDN("owner")}::${this.getTinyFQDN("exchange")}:${this.get("preference")}:${this.getTinydnsPostamble()} -`}}const Ft=/[\r\n\t:\\/]/;class rt extends f{static typeName="NAPTR";static typeId=35;static RFCs=[2915,3403,4848];static rdataFields=[["order","u16"],["preference","u16"],["flags","qcharstr"],["service","qcharstr"],["regexp","qcharstr"],["replacement","fqdn"]];constructor(t){super(t)}getDescription(){return"Naming Authority Pointer"}getCanonical(){return{owner:"cid.urn.arpa.",ttl:3600,class:"IN",type:"NAPTR",order:100,preference:10,flags:"S",service:"z3950+N2L+N2R",regexp:"",replacement:"gatekeeper.example.com."}}setOrder(t){this.is16bitInt("NAPTR","order",t),this.set("order",t)}setPreference(t){this.is16bitInt("NAPTR","preference",t),this.set("preference",t)}setFlags(t){this.getFlagsOptions().has(t.toUpperCase())||this.throwHelp("NAPTR flags are invalid"),this.set("flags",t.toUpperCase())}getFlagsOptions(){return new Map([[""],["S"],["A"],["U"],["P"]])}setService(t){this.set("service",t)}setRegexp(t){this.set("regexp",t)}setReplacement(t){this.set("replacement",t)}fromTinydns({tinyline:t}){const{owner:e,typeId:s,rdata:i,ttl:n,timestamp:a,location:o}=this.parseTinydnsLine(t);s!=this.getTypeId()&&this.throwHelp("NAPTR fromTinydns, invalid n");const r=H(i),c=new DataView(r.buffer,r.byteOffset,r.byteLength),h={type:"NAPTR",owner:e,ttl:n,timestamp:a,location:o,order:c.getUint16(0),preference:c.getUint16(2)};let p=4;const d=r[p];p++,h.flags=new TextDecoder().decode(r.subarray(p,p+d)),p+=d;const g=r[p];p++,h.service=new TextDecoder().decode(r.subarray(p,p+g)),p+=g;const y=r[p];p++,h.regexp=new TextDecoder().decode(r.subarray(p,p+y)),p+=y;const m=r[p];return p++,h.replacement=new TextDecoder().decode(r.subarray(p,p+m)),new rt(h)}fromBind({bindline:t}){const e=/^(?\S+)\s+(?\d+)\s+(?\S+)\s+(?NAPTR)\s+(?\d+)\s+(?\d+)\s+["'](?[^"']*)["']\s+["'](?[^"']*)["']\s+["'](?[^"']*)["']\s+(?\S+)$/,s=t.trim().match(e);if(!s)throw new Error(`Invalid NAPTR BIND line: ${t}`);const{owner:i,ttl:n,type:a,order:o,preference:r,flags:c,service:h,regexp:p,replacement:d}=s.groups;return new rt({owner:this.fullyQualify(i),ttl:parseInt(n,10),class:s.groups.class,type:a,order:parseInt(o,10),preference:parseInt(r,10),flags:c,service:h,regexp:p,replacement:d})}toTinydns(){let t=A(this.get("order"))+A(this.get("preference"))+u(this.get("flags").length)+this.get("flags")+u(this.get("service").length)+I(Ft,this.get("service"))+u(this.get("regexp").length)+I(Ft,this.get("regexp"));const e=this.get("replacement");return e!==""&&(t+=u(e.length),t+=I(Ft,e)),t+="\\000",this.getTinydnsGeneric(t)}getWireRdata(){const t=new TextEncoder,e=t.encode(this.get("flags")),s=t.encode(this.get("service")),i=t.encode(this.get("regexp")),n=this.wirePackDomain(this.get("replacement")),a=5+e.length+1+s.length+1+i.length+n.length,o=new Uint8Array(a),r=new DataView(o.buffer);let c=0;return r.setUint16(c,this.get("order")),c+=2,r.setUint16(c,this.get("preference")),c+=2,o[c++]=e.length,o.set(e,c),c+=e.length,o[c++]=s.length,o.set(s,c),c+=s.length,o[c++]=i.length,o.set(i,c),c+=i.length,o.set(n,c),o}}class At extends f{static typeName="NS";static typeId=2;static RFCs=[1035];static tinydnsType="&";static rdataFields=[["dname","fqdn"]];static tags=["common"];constructor(t){super(t)}setDname(t){t||this.throwHelp("NS: dname is required"),this.isFullyQualified("NS","dname",t),this.isValidHostname("NS","dname",t),this.set("dname",t.toLowerCase())}getDescription(){return"Name Server"}getCanonical(){return{owner:"example.com.",ttl:3600,class:"IN",type:"NS",dname:"ns1.example.com."}}fromTinydns({tinyline:t}){const[e,s,i,n,a,o]=t.slice(1).split(":");return new At({type:"NS",owner:this.fullyQualify(e),dname:this.fullyQualify(/\./.test(i)?i:`${i}.ns.${e}`),ttl:parseInt(n,10),timestamp:a,location:o?.trim()??""})}getWireRdata(){return this.wirePackDomain(this.get("dname"))}toTinydns(){return`&${this.getTinyFQDN("owner")}::${this.getTinyFQDN("dname")}:${this.getTinydnsPostamble()} -`}}class X extends f{static typeName="NSEC";static typeId=47;static RFCs=[4034];static rdataFields=["next domain","type bit maps"];static tags=["dnssec"];constructor(t){super(t)}setNextDomain(t){t||this.throwHelp("NSEC: 'next domain' is required:"),this.isFullyQualified("NSEC","next domain",t),this.isValidHostname("NSEC","next domain",t),this.set("next domain",t.toLowerCase())}setTypeBitMaps(t){t||this.throwHelp("NSEC: 'type bit maps' is required"),this.set("type bit maps",t)}getDescription(){return"Next Secure"}getCanonical(){return{owner:"alfa.example.com.",ttl:3600,class:"IN",type:"NSEC","next domain":"host.example.com.","type bit maps":"A MX RRSIG NSEC TYPE1234"}}fromTinydns({tinyline:t}){const[e,s,i,n,a,o]=t.slice(1).split(":"),r=Uint8Array.from(x(i),d=>d.charCodeAt(0)),[c,h,p]=U(i);return new X({owner:this.fullyQualify(e),ttl:parseInt(n,10),type:"NSEC","next domain":c,"type bit maps":new TextDecoder().decode(r.subarray(p)),timestamp:a,location:o?.trim()??""})}fromBind({bindline:t}){const[e,s,i,n,a]=t.split(/\s+/);return new X({owner:e,ttl:parseInt(s,10),class:i,type:n,"next domain":a,"type bit maps":t.split(/\s+/).slice(5).filter(me).join(" ").trim()})}fromWire({owner:t,cls:e,ttl:s,rdata:i}){const{fqdn:n,end:a}=this.wireUnpackDomain(i,0),o=we(i.subarray(a));return new X({owner:t,ttl:s,class:e,type:"NSEC","next domain":n,"type bit maps":o})}toTinydns(){const t=new RegExp(/[\r\n\t:\\/]/,"g");return this.getTinydnsGeneric(N(this.get("next domain"))+I(t,this.get("type bit maps")))}getWireRdata(){const t=this.wirePackDomain(this.get("next domain")),e=be(this.get("type bit maps")),s=new Uint8Array(t.length+e.length);return s.set(t),s.set(e,t.length),s}}const me=l=>!["(",")"].includes(l);function we(l){const t=Object.fromEntries(Object.entries(q).map(([i,n])=>[n,i])),e=[];let s=0;for(;s+2<=l.length;){const i=l[s],n=l[s+1];s+=2;for(let a=0;a>r){const c=i*256+a*8+r;e.push(t[c]??`TYPE${c}`)}}s+=n}return e.join(" ")}function be(l){const t=l.trim().split(/\s+/).map(o=>/^TYPE\d+$/i.test(o)?parseInt(o.slice(4),10):q[o.toUpperCase()]).filter(o=>o!==void 0&&o>=0),e=new Map;for(const o of t){const r=Math.floor(o/256);e.has(r)||e.set(r,[]),e.get(r).push(o%256)}const s=[];for(const[o,r]of[...e.entries()].sort((c,h)=>c[0]-h[0])){const c=Math.max(...r),h=Math.floor(c/8)+1,p=new Uint8Array(h);for(const d of r)p[Math.floor(d/8)]|=128>>d%8;s.push(new Uint8Array([o,h,...p]))}const i=s.reduce((o,r)=>o+r.length,0),n=new Uint8Array(i);let a=0;for(const o of s)n.set(o,a),a+=o.length;return n}class z extends f{static typeName="NSEC3";static typeId=50;static RFCs=[5155,9077];static rdataFields=["hash algorithm","flags","iterations","salt","next hashed owner name","type bit maps"];static tags=["dnssec"];constructor(t){super(t)}setHashAlgorithm(t){t||this.throwHelp("NSEC3: 'hash algorithm' is required"),this.is8bitInt("NSEC3","hash algorithm",t),this.set("hash algorithm",t)}setFlags(t){t||this.throwHelp("NSEC3: 'flags' is required"),this.is8bitInt("NSEC3","flags",t),this.set("flags",t)}setIterations(t){t||this.throwHelp("NSEC3: 'iterations' is required"),this.is16bitInt("NSEC3","flags",t),this.set("iterations",t)}setSalt(t){this.set("salt",t)}setNextHashedOwnerName(t){t||this.throwHelp("NSEC3: 'next hashed owner name' is required"),this.set("next hashed owner name",t)}setTypeBitMaps(t){t||this.throwHelp("NSEC3: 'type bit maps' is required"),this.set("type bit maps",t)}getDescription(){return"Next Secure"}getCanonical(){return{owner:"test.example.com.",ttl:3600,class:"IN",type:"NSEC3","hash algorithm":1,flags:1,iterations:12,salt:"aabbccdd","next hashed owner name":"2vptu5timamqttgl4luu9kg21e0aor3s","type bit maps":"A RRSIG"}}fromBind({bindline:t}){const[e,s,i,n,a,o,r,c]=t.split(/\s+/),h=t.includes("(")?t.split(/\(|\)/)[1]:t.split(/\s+/).slice(8).join(" ");return new z({owner:e,ttl:parseInt(s,10),class:i,type:n,"hash algorithm":parseInt(a,10),flags:parseInt(o,10),iterations:parseInt(r,10),salt:c,"next hashed owner name":h.trim().split(/\s+/)[0],"type bit maps":h.trim().split(/\s+/).slice(1).join(" ")})}fromTinydns({tinyline:t}){const[e,s,i,n,a,o]=t.slice(1).split(":");s!=50&&this.throwHelp("NSEC3 fromTinydns, invalid n");const r=Uint8Array.from(x(i),b=>b.charCodeAt(0)),c=new DataView(r.buffer,r.byteOffset,r.byteLength),h=r[0],p=r[1],d=c.getUint16(2),{salt:g,nextHashedOwnerName:y,typeBitMaps:m}=Kt(r);return new z({owner:this.fullyQualify(e),ttl:parseInt(n,10),type:"NSEC3","hash algorithm":h,flags:p,iterations:d,salt:g,"next hashed owner name":y,"type bit maps":m,timestamp:a,location:o?.trim()??""})}fromWire({owner:t,cls:e,ttl:s,rdata:i}){const n=new DataView(i.buffer,i.byteOffset),{salt:a,nextHashedOwnerName:o,typeBitMaps:r}=Kt(i);return new z({owner:t,ttl:s,class:e,type:"NSEC3","hash algorithm":i[0],flags:i[1],iterations:n.getUint16(2),salt:a,"next hashed owner name":o,"type bit maps":r})}toBind(t){return`${this.getFQDN("owner",t)} ${this.get("ttl")} ${this.get("class")} NSEC3${this.getRdataFields().slice(0,4).map(e=>" "+this.get(e)).join("")} (${this.getRdataFields().slice(4).map(e=>this.get(e)).join(" ")}) -`}toTinydns(){const t=new RegExp(/[\r\n\t:\\/]/,"g");return this.getTinydnsGeneric(u(this.get("hash algorithm"))+u(this.get("flags"))+A(this.get("iterations"))+I(t,this.get("salt"))+I(t,this.get("next hashed owner name"))+I(t,this.get("type bit maps")))}getWireRdata(){const t=`${this.get("salt")}${this.get("next hashed owner name")}${this.get("type bit maps")}`,e=new TextEncoder().encode(t),s=4+e.length,i=new Uint8Array(s),n=new DataView(i.buffer,i.byteOffset);let a=0;return i[a++]=this.get("hash algorithm"),i[a++]=this.get("flags"),n.setUint16(a,this.get("iterations")),a+=2,i.set(e,a),i}}function Kt(l){const t=new TextDecoder().decode(l.subarray(4)),e=l[0],s=e===1?32:e===2?52:32;let i="",n="",a="";const o=Math.min(64,t.length);for(let r=o;r>=1;r--){const c=t.slice(r,r+s);if(c.length!==s||!/^[0-9a-z]+$/.test(c))continue;const h=t.slice(0,r);if(/^[0-9A-Fa-f]+$/.test(h)){i=h,n=c,a=t.slice(r+s);break}}if(!n){const r=t.match(/^([0-9A-Fa-f]*)/);i=r?r[1]:"",n=t.slice(i.length),a=""}return{salt:i,nextHashedOwnerName:n,typeBitMaps:a}}class at extends f{static typeName="NSEC3PARAM";static typeId=51;static RFCs=[5155];static rdataFields=["hash algorithm","flags","iterations","salt"];static tags=["dnssec"];constructor(t){super(t)}setHashAlgorithm(t){t==null&&this.throwHelp("NSEC3PARAM: 'hash algorithm' is required"),this.is8bitInt("NSEC3PARAM","hash algorithm",t),this.set("hash algorithm",t)}setFlags(t){t==null&&this.throwHelp("NSEC3PARAM: 'flags' is required"),this.is8bitInt("NSEC3PARAM","flags",t),this.set("flags",t)}setIterations(t){t==null&&this.throwHelp("NSEC3PARAM: 'iterations' is required"),this.is16bitInt("NSEC3PARAM","iterations",t),this.set("iterations",t)}setSalt(t){if(t==="-"){this.set("salt",t);return}t!=null&&!/^[0-9A-Fa-f]*$/.test(t)&&this.throwHelp("NSEC3PARAM: 'salt' must be hex or '-'"),this.set("salt",t)}getDescription(){return"Next Secure Parameters"}getCanonical(){return{owner:"example.com.",ttl:3600,class:"IN",type:"NSEC3PARAM","hash algorithm":1,flags:1,iterations:12,salt:"aabbccdd"}}fromTinydns({tinyline:t}){const{owner:e,typeId:s,rdata:i,ttl:n,timestamp:a,location:o}=this.parseTinydnsLine(t);s!=this.getTypeId()&&this.throwHelp("NSEC3PARAM fromTinydns, invalid n"),i.length<4&&this.throwHelp(`NSEC3PARAM: RDATA too short: ${i}`);const r=H(i);return new at({owner:e,ttl:n,type:"NSEC3PARAM","hash algorithm":r[0],flags:r[1],iterations:r[2]<<8|r[3],salt:r[4]===0?"-":R(r.subarray(5,5+r[4])),timestamp:a,location:o})}fromWire({owner:t,cls:e,ttl:s,rdata:i}){const n=new DataView(i.buffer,i.byteOffset),a=i[4],o=a===0?"-":R(i.subarray(5,5+a));return new at({owner:t,ttl:s,class:e,type:"NSEC3PARAM","hash algorithm":i[0],flags:i[1],iterations:n.getUint16(2),salt:o})}toTinydns(){const t=this.get("salt"),e=t==="-"?u(0):u(t.length/2)+O(t);return this.getTinydnsGeneric(u(this.get("hash algorithm"))+u(this.get("flags"))+A(this.get("iterations"))+e)}getWireRdata(){const t=this.get("salt"),e=t==="-"?new Uint8Array(0):F(t),s=new Uint8Array(5+e.length),i=new DataView(s.buffer,s.byteOffset);return s[0]=this.get("hash algorithm"),s[1]=this.get("flags"),i.setUint16(2,this.get("iterations")),s[4]=e.length,s.set(e,5),s}}class v extends f{static typeName="NXT";static typeId=30;static RFCs=[2065];static rdataFields=["next domain","type bit map"];static tags=["obsolete"];constructor(t){super(t)}setNextDomain(t){t||this.throwHelp("NXT: 'next domain' is required"),this.isFullyQualified("NXT","next domain",t),this.isValidHostname("NXT","next domain",t),this.set("next domain",t.toLowerCase())}setTypeBitMap(t){t||this.throwHelp("NXT: 'type bit map' is required"),this.set("type bit map",t)}getDescription(){return"Next Secure"}getCanonical(){return{owner:"big.example.com.",ttl:3600,class:"IN",type:"NXT","next domain":"host.example.com.","type bit map":"A MX NXT"}}fromTinydns({tinyline:t}){const[e,s,i,n,a,o]=t.slice(1).split(":");parseInt(s,10)!==this.getTypeId()&&this.throwHelp("NXT fromTinydns, invalid n");const r=Uint8Array.from(x(i),d=>d.charCodeAt(0)),[c,h,p]=U(i);return new v({owner:this.fullyQualify(e),ttl:parseInt(n,10),type:"NXT","next domain":c,"type bit map":new TextDecoder().decode(r.subarray(p)),timestamp:a,location:o?.trim()??""})}fromBind({bindline:t}){const[e,s,i,n,a]=t.split(/\s+/);return new v({owner:e,ttl:parseInt(s,10),class:i,type:n,"next domain":a,"type bit map":t.split(/\s+/).slice(5).filter(Te).join(" ").trim()})}fromWire({owner:t,cls:e,ttl:s,rdata:i}){const{fqdn:n,end:a}=this.wireUnpackDomain(i,0),o=Ae(i.subarray(a));return new v({owner:t,ttl:s,class:e,type:"NXT","next domain":n,"type bit map":o})}toTinydns(){const t=new RegExp(/[\r\n\t:\\/]/,"g");return this.getTinydnsGeneric(N(this.get("next domain"))+I(t,this.get("type bit map")))}getWireRdata(){const t=this.wirePackDomain(this.get("next domain")),e=Ie(this.get("type bit map")),s=new Uint8Array(t.length+e.length);return s.set(t),s.set(e,t.length),s}}const Te=l=>!["(",")"].includes(l);function Ae(l){const t=Object.fromEntries(Object.entries(q).map(([s,i])=>[i,s])),e=[];for(let s=0;s>n){const a=s*8+n;e.push(t[a]??`TYPE${a}`)}}return e.join(" ")}function Ie(l){const t=new Uint8Array(16);for(const s of l.trim().split(/\s+/)){const i=/^TYPE\d+$/i.test(s)?parseInt(s.slice(4),10):q[s.toUpperCase()];i!==void 0&&i<128&&(t[Math.floor(i/8)]|=128>>i%8)}let e=t.length;for(;e>0&&t[e-1]===0;)e--;return t.slice(0,e)}class ot extends f{static typeName="OPENPGPKEY";static typeId=61;static RFCs=[4880,7929];static rdataFields=[["public key","base64"]];static tags=["security"];constructor(t){super(t)}setPublicKey(t){this.isBase64("OPENPGPKEY","public key",t),this.set("public key",t)}getDescription(){return"OpenPGP Public Key"}getCanonical(){return{owner:"matt.example.com.",ttl:3600,class:"IN",type:"OPENPGPKEY","public key":"AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwIXAqcOTiW7iHnQt5hwVAAAAA=="}}fromBind({bindline:t}){const e=/^(?\S+)\s+(?\d{1,10})\s+(?IN)\s+(?OPENPGPKEY)\s+(?\S[\s\S]*)$/i,s=t.trim().match(e);s||this.throwHelp(`unable to parse OPENPGPKEY: ${t}`);const{owner:i,ttl:n,class:a,type:o,publickey:r}=s.groups,c=r.trim().replace(/\s+/g,"");return new ot({owner:i,ttl:parseInt(n,10),class:a,type:o,"public key":c})}fromTinydns({tinyline:t}){const{owner:e,typeId:s,rdata:i,ttl:n,timestamp:a,location:o}=this.parseTinydnsLine(t);return s!=this.getTypeId()&&this.throwHelp("OPENPGPKEY fromTinydns, invalid n"),new ot({owner:e,ttl:n,type:"OPENPGPKEY","public key":ut(i),timestamp:a,location:o})}toTinydns(){return this.getTinydnsGeneric(G(this.get("public key")))}getWireRdata(){return L(this.get("public key"))}}class Qt extends f{static typeName="PTR";static typeId=12;static RFCs=[1035];static tinydnsType="^";static rdataFields=[["dname","fqdn"]];static tags=["common"];constructor(t){super(t)}setDname(t){this.isFullyQualified("PTR","dname",t),this.isValidHostname("PTR","dname",t),this.set("dname",t.toLowerCase())}getDescription(){return"Pointer"}getCanonical(){return{owner:"2.2.0.192.in-addr.arpa.",ttl:3600,class:"IN",type:"PTR",dname:"host.example.com."}}getWireRdata(){return this.wirePackDomain(this.get("dname"))}}class It extends f{static typeName="RP";static rdataFields=[["mbox","fqdn"],["txt","fqdn"]];constructor(t){super(t)}setMbox(t){t||this.throwHelp("RP: mbox is required"),this.isFullyQualified("RP","mbox",t),this.set("mbox",t.toLowerCase())}setTxt(t){t||this.throwHelp("RP: txt is required"),this.isFullyQualified("RP","txt",t),this.set("txt",t.toLowerCase())}getDescription(){return"Responsible Person"}static tags=["obsolete"];static RFCs=[1183];static typeId=17;getCanonical(){return{owner:"example.com.",ttl:3600,class:"IN",type:"RP",mbox:"admin.example.com.",txt:"info.example.com."}}fromTinydns({tinyline:t}){const[e,s,i,n,a,o]=t.slice(1).split(":"),[r,c]=U(i),h=U(i.slice(c))[0];return new It({owner:this.fullyQualify(e),ttl:parseInt(n,10),type:"RP",mbox:r,txt:h,timestamp:a,location:o?.trim()??""})}getWireRdata(){const t=this.wirePackDomain(this.get("mbox")),e=this.wirePackDomain(this.get("txt")),s=new Uint8Array(t.length+e.length);return s.set(t,0),s.set(e,t.length),s}toTinydns(){return this.getTinydnsGeneric(N(this.get("mbox"))+N(this.get("txt")))}}class ct extends f{static typeName="RRSIG";static typeId=46;static RFCs=[4034];static rdataFields=[["type covered","u16"],["algorithm","u8"],["labels","u8"],["original ttl","u32"],["signature expiration","u32"],["signature inception","u32"],["key tag","u16"],["signers name","fqdn"],["signature","str"]];static tags=["dnssec"];constructor(t){super(t)}setTypeCovered(t){if(!t&&t!==0&&this.throwHelp("RRSIG: 'type covered' is required"),typeof t=="string"){const e=t.match(/^TYPE(\d+)$/i);if(e)t=parseInt(e[1],10);else{const s=q[t.toUpperCase()];s===void 0&&this.throwHelp("RRSIG: 'type covered' is not a recognized type name"),t=s}}this.is16bitInt("RRSIG","type covered",t),this.set("type covered",t)}setAlgorithm(t){this.getAlgorithmOptions().has(t)||this.throwHelp("RRSIG: algorithm invalid"),this.set("algorithm",t)}getAlgorithmOptions(){return new Map([[1,"RSA/MD5"],[2,"DH"],[3,"RRSIGA/SHA-1"],[4,"EC"],[5,"RSA/SHA-1"],[253],[254]])}getDescription(){return"Resource Record Signature"}getCanonical(){return{owner:"example.com.",ttl:3600,class:"IN",type:"RRSIG","type covered":1,algorithm:5,labels:3,"original ttl":3600,"signature expiration":1045053120,"signature inception":1042461120,"key tag":12345,"signers name":"example.com.",signature:"ABCDEF..."}}fromBind({bindline:t}){const e=t.trim().split(/\s+/),s=e[4],i=s.match(/^TYPE(\d+)$/i),n=/^\d+$/.test(s)?parseInt(s,10):i?parseInt(i[1],10):q[s.toUpperCase()]??parseInt(s,10);return new ct({owner:e[0],ttl:parseInt(e[1],10),class:e[2],type:"RRSIG","type covered":n,algorithm:parseInt(e[5],10),labels:parseInt(e[6],10),"original ttl":parseInt(e[7],10),"signature expiration":parseInt(e[8],10),"signature inception":parseInt(e[9],10),"key tag":parseInt(e[10],10),"signers name":e[11],signature:e.slice(12).filter(a=>a!=="("&&a!==")").join(" ").trim()})}fromTinydns({tinyline:t}){const[e,s,i,n,a,o]=t.slice(1).split(":");parseInt(s,10)!==this.getTypeId()&&this.throwHelp("RRSIG fromTinydns, invalid n");const r=Uint8Array.from(x(i),S=>S.charCodeAt(0)),c=new DataView(r.buffer,r.byteOffset,r.byteLength),h=c.getUint16(0),p=r[2],d=r[3],g=c.getUint32(4),y=c.getUint32(8),m=c.getUint32(12),b=c.getUint16(16);let w=18;const T=[];for(;wn!=="("&&n!==")").join(" ").trim()})}toTinydns(){const t=new RegExp(/[\r\n\t:]/,"g");return this.getTinydnsGeneric(A(this.get("type covered"))+u(this.get("algorithm"))+u(this.get("labels"))+P(this.get("original ttl"))+P(this.get("signature expiration"))+P(this.get("signature inception"))+A(this.get("key tag"))+N(this.get("signers name"))+I(t,this.get("signature")))}getWireRdata(){const t=W(this.get("signers name")),e=new TextEncoder().encode(this.get("signature")),s=18+t.length+e.length,i=new Uint8Array(s),n=new DataView(i.buffer,i.byteOffset);let a=0;return n.setUint16(a,this.get("type covered")),a+=2,i[a++]=this.get("algorithm"),i[a++]=this.get("labels"),n.setUint32(a,this.get("original ttl")),a+=4,n.setUint32(a,this.get("signature expiration")),a+=4,n.setUint32(a,this.get("signature inception")),a+=4,n.setUint16(a,this.get("key tag")),a+=2,i.set(t,a),a+=t.length,i.set(e,a),i}fromTinydns({tinyline:t}){const{owner:e,typeId:s,rdata:i,ttl:n,timestamp:a,location:o}=this.parseTinydnsLine(t);parseInt(s,10)!==this.getTypeId()&&this.throwHelp("SIG fromTinydns, invalid n");const r=H(i),c=new DataView(r.buffer,r.byteOffset,r.byteLength),h=c.getUint16(0),p=r[2],d=r[3],g=c.getUint32(4),y=c.getUint32(8),m=c.getUint32(12),b=c.getUint16(16);let w=18;const T=[];for(;w" "+this.get(e)).join("")} ${this.getRdataFields().slice(4,8).map(e=>this.get(e)).join(" ")} ( ${this.get("signature")} )`}}class ht extends f{static typeName="SMIMEA";static typeId=53;static RFCs=[8162];static rdataFields=[["certificate usage","u8"],["selector","u8"],["matching type","u8"],["certificate association data","hex"]];static tags=["security"];constructor(t){super(t)}setCertificateUsage(t){this.getCertificateUsageOptions().has(t)||this.throwHelp("SMIMEA: certificate usage invalid"),this.set("certificate usage",t)}getCertificateUsageOptions(){return new Map([[0,"CA certificate"],[1,"an end entity certificate"],[2,"the trust anchor"],[3,"domain-issued certificate"]])}setSelector(t){this.getSelectorOptions().has(t)||this.throwHelp("SMIMEA: selector invalid"),this.set("selector",t)}getSelectorOptions(){return new Map([[0,"Full certificate"],[1,"SubjectPublicKeyInfo"]])}setMatchingType(t){this.getMatchingTypeOptions().has(t)||this.throwHelp("SMIMEA: matching type"),this.set("matching type",t)}getMatchingTypeOptions(){return new Map([[0,"Exact match"],[1,"SHA-256 hash"],[2,"SHA-512 hash"]])}setCertificateAssociationData(t){this.set("certificate association data",t)}getDescription(){return"S/MIME cert association"}getCanonical(){return{owner:"_443._tcp.www.example.com.",ttl:3600,class:"IN",type:"SMIMEA","certificate usage":0,selector:0,"matching type":1,"certificate association data":"ABCDEF..."}}fromBind({bindline:t}){const[e,s,i,n,a,o,r]=t.split(/\s+/);return new ht({owner:e,ttl:parseInt(s,10),class:i,type:n,"certificate usage":parseInt(a,10),selector:parseInt(o,10),"matching type":parseInt(r,10),"certificate association data":t.split(/\s+/).slice(7).join(" ").trim()})}fromTinydns({tinyline:t}){const{owner:e,rdata:s,ttl:i,timestamp:n,location:a}=this.parseTinydnsLine(t),o=H(s);return new ht({owner:e,ttl:i,type:"SMIMEA","certificate usage":o[0],selector:o[1],"matching type":o[2],"certificate association data":R(o.subarray(3)),timestamp:n,location:a})}toTinydns(){return this.getTinydnsGeneric(u(this.get("certificate usage"))+u(this.get("selector"))+u(this.get("matching type"))+O(this.get("certificate association data").replace(/[\s()]/g,"")))}getWireRdata(){const t=F(this.get("certificate association data").replace(/[\s()]/g,"")),e=new Uint8Array(3+t.length);return e[0]=this.get("certificate usage"),e[1]=this.get("selector"),e[2]=this.get("matching type"),e.set(t,3),e}}class St extends f{static typeName="SOA";static typeId=6;static RFCs=[1035,2308];static tinydnsType="Z";static rdataFields=[["mname","fqdn"],["rname","fqdn"],["serial","u32"],["refresh","u32"],["retry","u32"],["expire","u32"],["minimum","u32"]];static tags=["common"];constructor(t){super(t)}setMinimum(t){this.is32bitInt("SOA","minimum",t),this.set("minimum",t)}setMname(t){this.isValidHostname("SOA","MNAME",t),this.isFullyQualified("SOA","MNAME",t),this.set("mname",t.toLowerCase())}setRname(t){this.isValidHostname("SOA","RNAME",t),this.isFullyQualified("SOA","RNAME",t),/@/.test(t)&&this.throwHelp("SOA rname replaces @ with a . (dot)"),this.set("rname",t.toLowerCase())}setSerial(t){this.is32bitInt("SOA","serial",t),this.set("serial",t)}setRefresh(t){this.is32bitInt("SOA","refresh",t),this.set("refresh",t)}setRetry(t){this.is32bitInt("SOA","retry",t),this.set("retry",t)}setExpire(t){this.is32bitInt("SOA","expire",t),this.set("expire",t)}getDescription(){return"Start Of Authority"}getCanonical(){return{owner:"example.com.",ttl:3600,class:"IN",type:"SOA",mname:"ns1.example.com.",rname:"admin.example.com.",serial:2023051001,refresh:7200,retry:3600,expire:1209600,minimum:3600}}fromTinydns({tinyline:t}){const[e,s,i,n,a,o,r,c,h,p,d]=t.slice(1).split(":");return new St({owner:this.fullyQualify(e),ttl:parseInt(h,10),type:"SOA",mname:this.fullyQualify(s),rname:this.fullyQualify(i),serial:parseInt(n??this.default?.serial,10),refresh:parseInt(a,10)||16384,retry:parseInt(o,10)||2048,expire:parseInt(r,10)||1048576,minimum:parseInt(c,10)||2560,timestamp:parseInt(p)||"",location:d?.trim()??""})}toMaraDNS(){return`${this.get("owner")} SOA ${this.getFields("rdata").map(t=>this.getQuoted(t)).join(" ")} ~ +`}}class Wt extends f{static typeName="A";static typeId=1;static RFCs=[1035];static tinydnsType="+";static rdataFields=[["address","ipv4"]];static tags=["common"];constructor(t){super(t)}setAddress(t){t||this.throwHelp("A: address is required"),this.isIPv4(t)||this.throwHelp("A address must be IPv4"),this.set("address",t)}getDescription(){return"Address"}getCanonical(){return{owner:"host.example.com.",class:"IN",ttl:3600,type:"A",address:"192.0.2.127"}}getWireRdata(){return new Uint8Array(this.get("address").split(".").map(Number))}}class yt extends f{static typeName="AAAA";static typeId=28;static RFCs=[3596,5952];static rdataFields=[["address","ipv6"]];static tags=["common"];constructor(t){super(t)}setAddress(t){t||this.throwHelp("AAAA: address is required"),this.isIPv6(t)||this.throwHelp(`AAAA: address must be IPv6 (${t})`),this.set("address",this.expandIPv6(t.toLowerCase()))}getCompressed(t){return this.compressIPv6(t??this.get("address"))}getDescription(){return"Address IPv6"}getCanonical(){return{owner:"host.example.com.",address:"2001:0db8:0020:000a:0000:0000:0000:0004",class:"IN",ttl:3600,type:"AAAA"}}fromTinydns({tinyline:t}){const e=t;let s,i,n,a,o,r,c;switch(e[0]){case":":[s,n,a,o,r,c]=e.slice(1).split(":"),n!=28&&this.throwHelp("AAAA fromTinydns, invalid n"),i=Pt(a).match(/([0-9a-fA-F]{4})/g).join(":");break;case"3":case"6":[s,a,o,r,c]=e.slice(1).split(":"),i=a.match(/(.{4})/g).join(":");break}return new yt({owner:this.fullyQualify(s),ttl:parseInt(o,10),type:"AAAA",address:i,timestamp:r,location:c?.trim()??""})}getWireRdata(){const t=this.expandIPv6(this.get("address"),""),e=new Uint8Array(t.length/2);for(let s=0;sh.charCodeAt(0)),c=[];let p=0;for(;p{const e=t.startsWith("!"),s=e?t.slice(1):t,i=s.indexOf(":"),n=parseInt(s.slice(0,i),10),a=s.slice(i+1),o=a.lastIndexOf("/"),r=a.slice(0,o),c=parseInt(a.slice(o+1),10);let p;if(n===1)p=new Uint8Array(r.split(".").map(u=>parseInt(u,10)));else{const u=r.indexOf("::");let m;if(u!==-1){const w=r.slice(0,u).split(":").filter(D=>D!==""),T=r.slice(u+2).split(":").filter(D=>D!=="");m=[...w,...Array(8-w.length-T.length).fill("0000"),...T]}else m=r.split(":");const b=m.map(w=>w.padStart(4,"0")).join("");p=Uint8Array.from({length:b.length/2},(w,T)=>parseInt(b.slice(T*2,T*2+2),16))}let h=p.length;for(;h>0&&p[h-1]===0;)h--;const d=p.slice(0,h);let g=A(n);g+=y(c),g+=y((e?128:0)|d.length);for(const u of d)g+=y(u);return g}).join(""))}getWireRdata(){const t=this.get("apl rdata").split(/\s+/),e=[];for(const a of t){const o=a.startsWith("!"),r=o?a.slice(1):a,c=r.indexOf(":"),p=parseInt(r.slice(0,c),10),h=r.slice(c+1),d=h.lastIndexOf("/"),g=h.slice(0,d),u=parseInt(h.slice(d+1),10);let m;if(p===1)m=new Uint8Array(g.split(".").map(C=>parseInt(C,10)));else{const C=g.indexOf("::");let S;if(C!==-1){const _=g.slice(0,C).split(":").filter(Dt=>Dt!==""),tt=g.slice(C+2).split(":").filter(Dt=>Dt!=="");S=[..._,...Array(8-_.length-tt.length).fill("0000"),...tt]}else S=g.split(":");const $t=S.map(_=>_.padStart(4,"0")).join("");m=Uint8Array.from({length:$t.length/2},(_,tt)=>parseInt($t.slice(tt*2,tt*2+2),16))}let b=m.length;for(;b>0&&m[b-1]===0;)b--;const w=m.slice(0,b),T=new Uint8Array(4+w.length);new DataView(T.buffer,T.byteOffset).setUint16(0,p),T[2]=u,T[3]=(o?128:0)|w.length,T.set(w,4),e.push(T)}const s=e.reduce((a,o)=>a+o.length,0),i=new Uint8Array(s);let n=0;for(const a of e)i.set(a,n),n+=a.length;return i}}class ft extends f{static typeName="CAA";static typeId=257;static RFCs=[6844,8659,9619];static rdataFields=[["flags","u8"],["tag","charstr"],["value","qstr"]];static tags=["security"];constructor(t){super(t)}setFlags(t){this.is8bitInt("CAA","flags",t),this.getFlagsOptions().has(t)||this.throwHelp(`CAA flags ${t} not recognized`),this.set("flags",t)}getFlagsOptions(){return new Map([[0,"Non Critical"],[128,"Critical"]])}setTag(t){(typeof t!="string"||t.length<1||/[^a-z0-9]/.test(t))&&this.throwHelp("CAA tag must be a sequence of ASCII letters and numbers in lowercase"),this.getTagOptions().has(t)||this.throwHelp(`CAA tag ${t} not recognized`),this.set("tag",t)}getTagOptions(){return new Map([["issue"],["issuewild"],["iodef"]])}setValue(t){this.isQuoted(t)&&(t=t.replace(/^["']|["']$/g,"")),this.get("tag")==="iodef"&&(["mailto:","http:","https:"].filter(s=>t.startsWith(s)).length||this.throwHelp("CAA value must have valid iodefScheme prefix")),this.set("value",t)}getDescription(){return"Certification Authority Authorization"}getCanonical(){return{owner:"example.com.",ttl:3600,class:"IN",type:"CAA",flags:0,tag:"issue",value:"http://letsencrypt.org"}}fromTinydns({tinyline:t}){const{owner:e,typeId:s,rdata:i,ttl:n,timestamp:a,location:o}=this.parseTinydnsLine(t);s!=this.getTypeId()&&this.throwHelp("CAA fromTinydns, invalid typeId");const r=E(i.slice(0,4)),c=E(i.slice(4,8)),p=x(i.slice(8)),h=p.slice(0,c),d=p.slice(c);return new ft({owner:e,ttl:n,type:"CAA",flags:r,tag:h,value:d,timestamp:a,location:o})}getWireRdata(){const t=new TextEncoder().encode(this.get("tag")),e=new TextEncoder().encode(this.get("value")),s=new Uint8Array(2+t.length+e.length);return s[0]=this.get("flags"),s[1]=t.length,s.set(t,2),s.set(e,2+t.length),s}toTinydns(){return this.getTinydnsGeneric(y(this.get("flags"))+y(this.get("tag").length)+I(/[\r\n\t:\\/]/,this.get("tag"))+I(/[\r\n\t:\\/]/,this.get("value")))}}class H extends f{static typeName="CERT";static typeId=37;static RFCs=[2538,4398];static rdataFields=[["cert type","certtype"],["key tag","u16"],["algorithm","u8"],["certificate","base64"]];static CERT_TYPES={PKIX:1,SPKI:2,PGP:3,IPKIX:4,ISPKI:5,IPGP:6,ACPKIX:7,IACPKIX:8,URI:253,OID:254};static CERT_TYPES_REVERSE=Object.fromEntries(Object.entries(H.CERT_TYPES).map(([t,e])=>[e,t]));constructor(t){super(t)}setCertType(t){(t==null||t==="")&&this.throwHelp("cert type is required"),typeof t=="string"&&!/^[0-9]+$/.test(t)?Object.hasOwn(H.CERT_TYPES,t)||this.throwHelp(`CERT: unknown cert type mnemonic: ${t}`):this.is16bitInt("CERT","cert type",t),this.set("cert type",t)}getCertTypeValue(t){if(typeof t=="number")return t;if(/^[0-9]+$/.test(t))return parseInt(t,10);if(Object.hasOwn(H.CERT_TYPES,t))return H.CERT_TYPES[t];this.throwHelp(`CERT: unknown cert type mnemonic: ${t}`)}setKeyTag(t){this.setTypedValue("u16","key tag",t)}setAlgorithm(t){this.setTypedValue("u8","algorithm",t)}setCertificate(t){(t==null||t==="")&&this.throwHelp("certificate is required and cannot be empty"),this.isBase64("CERT","certificate",t.replace(/[\s()]/g,"")),this.set("certificate",t)}getDescription(){return"Certificate"}getCanonical(){return{owner:"mail.example.com.",ttl:3600,class:"IN",type:"CERT","cert type":"PGP","key tag":0,algorithm:0,certificate:"AQIDBA=="}}fromTinydns({tinyline:t}){const{owner:e,typeId:s,rdata:i,ttl:n,timestamp:a,location:o}=this.parseTinydnsLine(t);s!=this.getTypeId()&&this.throwHelp("CERT fromTinydns, invalid n");const r=k(i),c=r[0]<<8|r[1],p=H.CERT_TYPES_REVERSE[c]??c;return new H({owner:e,ttl:n,type:"CERT","cert type":p,"key tag":r[2]<<8|r[3],algorithm:r[4],certificate:G(r.subarray(5)),timestamp:a,location:o})}fromBind({bindline:t}){const[e,s,i,n,a,o,r,c]=t.split(/\s+/);return new H({owner:e,ttl:parseInt(s,10),class:i,type:n,"cert type":/^[0-9]+$/.test(a)?parseInt(a,10):a,"key tag":parseInt(o,10),algorithm:parseInt(r,10),certificate:c})}toTinydns(){return this.getTinydnsGeneric(A(this.getCertTypeValue(this.get("cert type")))+A(this.get("key tag"))+y(this.get("algorithm"))+W(this.get("certificate").replace(/[\s()]/g,"")))}getWireRdata(){const t=L(this.get("certificate").replace(/[\s()]/g,"")),e=new Uint8Array(5+t.length),s=new DataView(e.buffer,e.byteOffset);return s.setUint16(0,this.getCertTypeValue(this.get("cert type"))),s.setUint16(2,this.get("key tag")),e[4]=this.get("algorithm"),e.set(t,5),e}}class Gt extends f{static typeName="CNAME";static typeId=5;static RFCs=[1035,2181];static tinydnsType="C";static rdataFields=[["cname","fqdn"]];static tags=["common"];constructor(t){super(t)}setCname(t){this.setTypedValue("fqdn","cname",t)}getDescription(){return"Canonical Name"}getCanonical(){return{owner:"www.example.com.",ttl:3600,class:"IN",type:"CNAME",cname:"web.example.com."}}getWireRdata(){return this.wirePackDomain(this.get("cname"))}}class mt extends f{static typeName="DHCID";static typeId=49;static RFCs=[4701];static rdataFields=[["data","base64"]];constructor(t){super(t)}setData(t){t||this.throwHelp("DHCID: data is required"),this.isBase64("DHCID","data",t),this.set("data",t)}getDescription(){return"DHCP Identifier"}getCanonical(){return{owner:"host.example.com.",ttl:3600,class:"IN",type:"DHCID",data:"AAIBY2/AuCccgoJbsaxcQc9TUapptP69lOjxfNuVAA2kjEA="}}fromTinydns({tinyline:t}){const{owner:e,typeId:s,rdata:i,ttl:n,timestamp:a,location:o}=this.parseTinydnsLine(t);return s!=this.getTypeId()&&this.throwHelp("DHCID fromTinydns, invalid n"),new mt({owner:e,ttl:n,type:"DHCID",data:ut(i),timestamp:a,location:o})}getWireRdata(){return new Uint8Array(atob(this.get("data")).split("").map(t=>t.charCodeAt(0)))}toTinydns(){return this.getTinydnsGeneric(W(this.get("data")))}}class wt extends f{static typeName="DNAME";static typeId=39;static RFCs=[2672,6672];static rdataFields=[["target","fqdn"]];constructor(t){super(t)}setTarget(t){this.setTypedValue("fqdn","target",t)}getDescription(){return"Delegation Name"}getCanonical(){return{owner:"example.com.",ttl:3600,class:"IN",type:"DNAME",target:"example.net."}}fromTinydns({tinyline:t}){const[e,s,i,n,a,o]=t.slice(1).split(":");return s!=39&&this.throwHelp("DNAME fromTinydns, invalid n"),new wt({type:"DNAME",owner:this.fullyQualify(e),target:U(i)[0],ttl:parseInt(n,10),timestamp:a,location:o?.trim()??""})}getWireRdata(){return this.wirePackDomain(this.get("target"))}toTinydns(){const t=N(this.get("target"));return this.getTinydnsGeneric(t)}}class et extends f{static typeName="DNSKEY";static typeId=48;static RFCs=[4034,6014,8624,9619,9905];static rdataFields=[["flags","u16"],["protocol","u8"],["algorithm","u8"],["publickey","base64"]];static tags=["dnssec"];constructor(t){super(t)}setFlags(t){this.is16bitInt("DNSKEY","flags",t),this.getFlagsOptions().has(t)||this.throwHelp(`DNSKEY: flags must be in the set: ${this.getFlagsOptions()}`),this.set("flags",t)}getFlagsOptions(){return new Map([[0],[256],[257]])}setProtocol(t){this.is8bitInt("DNSKEY","protocol",t),this.getProtocolOptions().has(t)||this.throwHelp("DNSKEY: protocol invalid"),this.set("protocol",t)}getProtocolOptions(){return new Map([[3]])}setAlgorithm(t){this.is8bitInt("DNSKEY","algorithm",t),this.getAlgorithmOptions().has(t)||console.error(`DNSKEY: algorithm (${t}) not recognized`),this.set("algorithm",t)}getAlgorithmOptions(){return new Map([[1,"RSA/MD5 (DEPRECATED)"],[2,"DH"],[3,"DSA/SHA-1"],[4,"EC"],[5,"RSA/SHA-1"],[6,"DSA-NSEC3-SHA1"],[7,"RSASHA1-NSEC3-SHA1"],[8,"RSA/SHA-256"],[9,""],[10,"RSA/SHA-512"],[13,"ECDSA Curve P-256 with SHA-256"],[14,"ECDSA Curve P-384 with SHA-384"],[15,"Ed25519"],[16,"Ed448"],[253],[254]])}setPublickey(t){t||this.throwHelp("DNSKEY: publickey is required"),this.isBase64("DNSKEY","publickey",t.replace(/[\s()]/g,"")),this.set("publickey",t)}getDescription(){return"DNS Public Key"}getCanonical(){return{owner:"example.com.",ttl:3600,class:"IN",type:"DNSKEY",flags:256,protocol:3,algorithm:5,publickey:"AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwIXAqcOTiW7iHnQt5hwVAAAAA=="}}fromBind({bindline:t}){const e=/^(?\S+)\s+(?\d+)\s+(?\w+)\s+(?DNSKEY)\s+(?\d+)\s+(?\d+)\s+(?\d+)\s+(?\S.*)$/i,s=t.trim().match(e);s||this.throwHelp(`unable to parse DNSKEY: ${t}`);const{owner:i,ttl:n,c:a,type:o,flags:r,protocol:c,algorithm:p,publickey:h}=s.groups;return new et({owner:i,ttl:parseInt(n,10),class:a,type:o,flags:parseInt(r,10),protocol:parseInt(c,10),algorithm:parseInt(p,10),publickey:h})}fromTinydns({tinyline:t}){const{owner:e,typeId:s,rdata:i,ttl:n,timestamp:a,location:o}=this.parseTinydnsLine(t);s!=this.getTypeId()&&this.throwHelp("DNSKEY fromTinydns, invalid n");const r=k(i);return new et({owner:e,ttl:n,type:"DNSKEY",flags:r[0]<<8|r[1],protocol:r[2],algorithm:r[3],publickey:G(r.subarray(4)),timestamp:a,location:o})}toTinydns(){return this.getTinydnsGeneric(A(this.get("flags"))+y(this.get("protocol"))+y(this.get("algorithm"))+W(this.get("publickey").replace(/[\s()]/g,"")))}getWireRdata(){const t=L(this.get("publickey").replace(/[\s()]/g,"")),e=new Uint8Array(4+t.length);return new DataView(e.buffer,e.byteOffset).setUint16(0,this.get("flags")),e[2]=this.get("protocol"),e[3]=this.get("algorithm"),e.set(t,4),e}}class st extends f{static typeName="DS";static typeId=43;static RFCs=[4034,4509,9619];static rdataFields=[["key tag","u16"],"algorithm","digest type",["digest","str"]];static tags=["dnssec"];constructor(t){super(t)}setKeyTag(t){this.setTypedValue("u16","key tag",t)}setDigest(t){this.setTypedValue("str","digest",t)}setAlgorithm(t){this.getAlgorithmOptions().has(t)||this.throwHelp("DS: algorithm invalid"),this.set("algorithm",t)}getAlgorithmOptions(){return new Map([[1,"RSA/MD5"],[2,"DH"],[3,"DSA/SHA-1"],[4,"EC"],[5,"RSA/SHA-1"],[6,"DSA-NSEC3-SHA1"],[7,"RSASHA1-NSEC3-SHA1"],[8,"RSA/SHA-256"],[10,"RSA/SHA-512"],[13,"ECDSA P-256/SHA-256"],[14,"ECDSA P-384/SHA-384"],[15,"Ed25519"],[16,"Ed448"],[253,""],[254,""]])}setDigestType(t){[1,2,4].includes(t)||this.throwHelp("DS: digest type invalid"),this.set("digest type",t)}getDescription(){return"Delegation Signer"}getCanonical(){return{owner:"example.com.",ttl:3600,class:"IN",type:"DS","key tag":12345,algorithm:5,"digest type":1,digest:"ABCDEF123..."}}fromTinydns(t){const{tinyline:e}=t,{owner:s,typeId:i,rdata:n,ttl:a,timestamp:o,location:r}=this.parseTinydnsLine(e);i!=this.getTypeId()&&this.throwHelp("DS fromTinydns, invalid n");const c=k(n);return new st({owner:s,ttl:a,type:"DS","key tag":c[0]<<8|c[1],algorithm:c[2],"digest type":c[3],digest:R(c.subarray(4)).toUpperCase(),timestamp:o,location:r})}fromWire({owner:t,cls:e,ttl:s,rdata:i}){const n=new DataView(i.buffer,i.byteOffset);return new st({owner:t,ttl:s,class:e,type:"DS","key tag":n.getUint16(0),algorithm:i[2],"digest type":i[3],digest:R(i.subarray(4)).toUpperCase()})}toTinydns(){return this.getTinydnsGeneric(A(this.get("key tag"))+y(this.get("algorithm"))+y(this.get("digest type"))+O(this.get("digest").replace(/\s+/g,"")))}getWireRdata(){const t=F(this.get("digest").replace(/\s+/g,"")),e=new Uint8Array(4+t.length);return new DataView(e.buffer,e.byteOffset).setUint16(0,this.get("key tag")),e[2]=this.get("algorithm"),e[3]=this.get("digest type"),e.set(t,4),e}}class Kt extends f{static typeName="HINFO";static typeId=13;static RFCs=[1034,1035,8482];static rdataFields=[["cpu","qcharstr"],["os","qcharstr"]];static tags=["obsolete"];constructor(t){super(t)}setCpu(t){t.length>255&&this.throwHelp("HINFO cpu cannot exceed 255 chars"),this.set("cpu",t.replace(/^["']|["']$/g,""))}setOs(t){t.length>255&&this.throwHelp("HINFO os cannot exceed 255 chars"),this.set("os",t.replace(/^["']|["']$/g,""))}getDescription(){return"Host Info"}getCanonical(){return{owner:"test.example.com.",ttl:3600,class:"IN",type:"HINFO",cpu:"DEC-2060",os:"TOPS20"}}fromTinydns({tinyline:t}){const[e,,s,i,n,a]=t.slice(1).split(":"),[o,r]=[...ee(s)];return new this.constructor({owner:this.fullyQualify(e),ttl:parseInt(i,10),type:"HINFO",cpu:o,os:r,timestamp:n,location:a?.trim()??""})}getWireRdata(){const t=new TextEncoder().encode(this.get("cpu")),e=new TextEncoder().encode(this.get("os")),s=new Uint8Array(2+t.length+e.length);return s[0]=t.length,s.set(t,1),s[1+t.length]=e.length,s.set(e,2+t.length),s}toTinydns(){return this.getTinydnsGeneric([Bt(this.get("cpu")),Bt(this.get("os"))].join(""))}}class j extends f{static typeName="HIP";static typeId=55;static RFCs=[8005];static rdataFields=["pk algorithm","hit","public key","rendezvous servers"];constructor(t){super(t)}setPkAlgorithm(t){t===void 0&&this.throwHelp("HIP: pk algorithm is required"),this.is8bitInt("HIP","pk algorithm",t),this.set("pk algorithm",t)}setHit(t){t||this.throwHelp("HIP: hit is required"),this.set("hit",t)}setPublicKey(t){t||this.throwHelp("HIP: public key is required"),this.set("public key",t)}setRendezvousServers(t){this.set("rendezvous servers",t??"")}getDescription(){return"Host Identity Protocol"}getCanonical(){return{owner:"example.com.",ttl:3600,class:"IN",type:"HIP","pk algorithm":2,hit:"200100107B1A74DF365639CC39F1D578","public key":"AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwIXAqcOTiW7iHnQt5hwVAAAAA==","rendezvous servers":""}}fromTinydns({tinyline:t}){const[e,s,i,n,a,o]=t.slice(1).split(":");s!=55&&this.throwHelp("HIP fromTinydns, invalid n");const r=Uint8Array.from(x(i),b=>b.charCodeAt(0)),c=r[0],p=r[1],h=r[2]<<8|r[3],d=R(r.subarray(4,4+c)).toUpperCase(),g=G(r.subarray(4+c,4+c+h)),u=[];let m=4+c+h;for(;mT<32||T>126?y(T):String.fromCharCode(T)).join(""));m+=w,b!=="."&&u.push(b)}return new j({owner:this.fullyQualify(e),ttl:parseInt(n,10),type:"HIP","pk algorithm":p,hit:d,"public key":g,"rendezvous servers":u.join(" "),timestamp:a,location:o?.trim()??""})}fromBind({bindline:t}){const e=t.split(/\s+/),[s,i,n,a,o,r]=e,c=e.slice(6),p=[],h=[];for(const d of c)/^[A-Za-z0-9+/=]+$/.test(d)?p.push(d):h.push(d);return new j({owner:s,ttl:parseInt(i,10),class:n,type:a,"pk algorithm":parseInt(o,10),hit:r,"public key":p.join(""),"rendezvous servers":h.join(" ").trim()})}fromWire({owner:t,cls:e,ttl:s,rdata:i}){const n=new DataView(i.buffer,i.byteOffset),a=i[0],o=i[1],r=n.getUint16(2),c=R(i.subarray(4,4+a)).toUpperCase(),p=G(i.subarray(4+a,4+a+r)),h=[];let d=4+a+r;for(;dV(d)),o=a.reduce((d,g)=>d+g.length,0),r=4+e.length+s.length+o,c=new Uint8Array(r),p=new DataView(c.buffer,c.byteOffset);let h=0;c[h++]=e.length,c[h++]=this.get("pk algorithm"),p.setUint16(h,s.length),h+=2,c.set(e,h),h+=e.length,c.set(s,h),h+=s.length;for(const d of a)c.set(d,h),h+=d.length;return c}}class it extends f{static typeName="HTTPS";static typeId=65;static RFCs=[9460];static tags=["common"];static rdataFields=[["priority","u16"],["target name","fqdn"],["params","svcparams"]];constructor(t){super(t)}setPriority(t){this.is16bitInt("HTTPS","priority",t),this.set("priority",t)}setTargetName(t){this.set("target name",t.toLowerCase())}setParams(t){this.set("params",t)}getDescription(){return"HTTP Semantics"}getCanonical(){return{owner:"example.com.",ttl:3600,class:"IN",type:"HTTPS",priority:1,"target name":"example.com.",params:'alpn="h2,h3"'}}fromBind({bindline:t}){const[e,s,i,n,a,o]=t.split(/\s+/);return new it({owner:e,ttl:parseInt(s,10),class:i,type:n,priority:parseInt(a,10),"target name":o,params:t.split(/\s+/).slice(6).join(" ").trim()})}fromTinydns({tinyline:t}){const{owner:e,typeId:s,rdata:i,ttl:n,timestamp:a,location:o}=this.parseTinydnsLine(t);s!=this.getTypeId()&&this.throwHelp("HTTPS fromTinydns, invalid n");const{priority:r,targetName:c,params:p}=Mt(i,"HTTPS");return new it({owner:e,ttl:n,type:"HTTPS",priority:r,"target name":c,params:p,timestamp:a,location:o})}toTinydns(){const t=new RegExp(/[\r\n\t:\\/]/,"g");return this.getTinydnsGeneric(A(this.get("priority"))+N(this.get("target name"))+I(t,this.get("params")))}getWireRdata(){const t=this.wirePackDomain(this.get("target name")),e=Vt(this.get("params")),s=new Uint8Array(2+t.length+e.length);return new DataView(s.buffer).setUint16(0,this.get("priority")),s.set(t,2),s.set(e,2+t.length),s}}class Q extends f{static typeName="IPSECKEY";static typeId=45;static RFCs=[4025];static rdataFields=["precedence","gateway type","algorithm","gateway","publickey"];static tags=["security"];constructor(t){super(t)}setPrecedence(t){this.is8bitInt("IPSECKEY","precedence",t),this.set("precedence",t)}setGatewayType(t){this.getGatewayTypeOptions().has(t)||this.throwHelp("IPSECKEY: Gateway Type is invalid"),this.set("gateway type",t)}getGatewayTypeOptions(){return new Map([[0,"none"],[1,"4-byte IPv4"],[2,"16-byte IPv6"],[3,"wire encoded domain name"]])}setAlgorithm(t){this.getAlgorithmOptions().has(t)||this.throwHelp("IPSECKEY: Algorithm invalid"),this.set("algorithm",t)}getAlgorithmOptions(){return new Map([[1,"DSA"],[2,"RSA"]])}setGateway(t){const e=this.get("gateway type"),s=new Error(`IPSECKEY: gateway invalid (${t}) for type ${e}`);switch(e){case 0:if(t!==".")throw s;break;case 1:if(!this.isIPv4(t))throw s;break;case 2:if(!this.isIPv6(t))throw s;break}this.set("gateway",t)}setPublickey(t){t&&this.isBase64("IPSECKEY","publickey",t),this.set("publickey",t)}getDescription(){return"IPsec Keying"}getCanonical(){return{owner:"38.2.0.192.in-addr.arpa.",ttl:7200,class:"IN",type:"IPSECKEY",precedence:10,"gateway type":1,algorithm:2,gateway:"192.0.2.38",publickey:"AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ=="}}fromBind({bindline:t}){const[e,s,i,n,a,o,r,c,p]=t.split(/\s+/);return new Q({owner:e,ttl:parseInt(s,10),class:i,type:n,precedence:parseInt(a,10),"gateway type":parseInt(o,10),algorithm:parseInt(r,10),gateway:c,publickey:p})}fromTinydns({tinyline:t}){const[e,s,i,n,a,o]=t.slice(1).split(":");s!=45&&this.throwHelp("IPSECKEY fromTinydns, invalid n");const r=E(i.slice(0,4)),c=E(i.slice(4,8)),p=E(i.slice(8,12));let h,d,g;switch(c){case 0:d=i.slice(12,13),g=i.slice(13);break;case 1:d=ie(i.slice(12,28)),g=i.slice(28);break;case 2:d=re(i.slice(12,76)),g=i.slice(76);break;case 3:[d,h]=U(i.slice(12)),g=i.slice(12+h);break}return new Q({owner:this.fullyQualify(e),ttl:parseInt(n,10),type:"IPSECKEY",precedence:r,"gateway type":c,algorithm:p,gateway:d,publickey:ut(g),timestamp:a,location:o?.trim()??""})}fromWire({owner:t,cls:e,ttl:s,rdata:i}){const n=i[0],a=i[1],o=i[2];let r,c;switch(a){case 0:r=".",c=3;break;case 1:r=[...i.subarray(3,7)].join("."),c=7;break;case 2:{const h=new DataView(i.buffer,i.byteOffset+3),d=[];for(let g=0;g<16;g+=2)d.push(h.getUint16(g).toString(16).padStart(4,"0"));r=d.join(":"),c=19;break}case 3:{const{fqdn:h,end:d}=this.wireUnpackDomain(i,3);r=h,c=d;break}}const p=G(i.subarray(c));return new Q({owner:t,ttl:s,class:e,type:"IPSECKEY",precedence:n,"gateway type":a,algorithm:o,gateway:r,publickey:p})}toTinydns(){const t=new RegExp(/[\r\n\t:\\/]/,"g");let e="";switch(e+=y(this.get("precedence")),e+=y(this.get("gateway type")),e+=y(this.get("algorithm")),this.get("gateway type")){case 0:e+=I(t,".");break;case 1:e+=qt(this.get("gateway"));break;case 2:e+=ne(this.get("gateway"));break;case 3:e+=N(this.get("gateway"));break}return e+=W(this.get("publickey")),this.getTinydnsGeneric(e)}getWireRdata(){const t=L(this.get("publickey")),e=this.get("gateway type");let s;switch(e){case 0:s=new Uint8Array(0);break;case 1:s=new Uint8Array(4),this.get("gateway").split(".").forEach((n,a)=>{s[a]=parseInt(n,10)});break;case 2:s=new Uint8Array(16);{const n=this.get("gateway").split(":");let a=0;for(const o of n){if(o==="")continue;const r=parseInt(o,16);s[a++]=r>>>8&255,s[a++]=r&255}}break;case 3:s=V(this.get("gateway"));break}const i=new Uint8Array(3+s.length+t.length);return i[0]=this.get("precedence"),i[1]=e,i[2]=this.get("algorithm"),i.set(s,3),i.set(t,3+s.length),i}}class nt extends f{static typeName="KEY";static typeId=25;static RFCs=[2535,3445,4034,6840];static rdataFields=[["flags","u16"],["protocol","u8"],["algorithm","u8"],["publickey","base64"]];static tags=["obsolete"];constructor(t){super(t)}setFlags(t){this.is16bitInt("KEY","flags",t),this.set("flags",t)}setProtocol(t){this.is8bitInt("KEY","protocol",t),this.set("protocol",t)}setAlgorithm(t){this.getAlgorithmOptions().has(t)||this.throwHelp("KEY: algorithm invalid"),this.set("algorithm",t)}getAlgorithmOptions(){return new Map([[1,"RSA/MD5"],[2,"DH"],[3,"DSA/SHA-1"],[4,"EC"],[5,"RSA/SHA-1"],[253,""],[254,""]])}setPublickey(t){t||this.throwHelp("KEY: publickey is required"),this.isBase64("KEY","publickey",t.replace(/[\s()]/g,"")),this.set("publickey",t)}getDescription(){return"DNS Public Key"}getCanonical(){return{owner:"example.com.",ttl:3600,class:"IN",type:"KEY",flags:256,protocol:3,algorithm:5,publickey:"AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwIXAqcOTiW7iHnQt5hwVAAAAA=="}}fromBind({bindline:t}){const[e,s,i,n,a,o,r]=t.split(/\s+/);return new nt({owner:e,ttl:parseInt(s,10),class:i,type:n,flags:parseInt(a,10),protocol:parseInt(o,10),algorithm:parseInt(r,10),publickey:t.split(/\s+/).slice(7).join(" ").trim()})}fromTinydns({tinyline:t}){const{owner:e,rdata:s,ttl:i,timestamp:n,location:a}=this.parseTinydnsLine(t);return s.length<16&&this.throwHelp(`KEY: RDATA too short: ${s}`),new nt({owner:e,ttl:i,type:"KEY",flags:B(s.slice(0,8)),protocol:E(s.slice(8,12)),algorithm:E(s.slice(12,16)),publickey:ut(s.slice(16)),timestamp:n,location:a})}toTinydns(){return this.getTinydnsGeneric(A(this.get("flags"))+y(this.get("protocol"))+y(this.get("algorithm"))+W(this.get("publickey").replace(/[\s()]/g,"")))}getWireRdata(){const t=L(this.get("publickey").replace(/[\s()]/g,"")),e=new Uint8Array(4+t.length);return new DataView(e.buffer,e.byteOffset).setUint16(0,this.get("flags")),e[2]=this.get("protocol"),e[3]=this.get("algorithm"),e.set(t,4),e}}class bt extends f{static typeName="KX";static typeId=36;static RFCs=[2230];static rdataFields=[["preference","u16"],["exchanger","fqdn"]];constructor(t){super(t)}setPreference(t){t===void 0&&this.throwHelp("KX: preference is required"),this.is16bitInt("KX","preference",t),this.set("preference",t)}setExchanger(t){t||this.throwHelp("KX: exchanger is required"),this.isFullyQualified("KX","exchanger",t),this.isValidHostname("KX","exchanger",t),this.set("exchanger",t.toLowerCase())}getDescription(){return"Key Exchanger"}getCanonical(){return{owner:"example.com.",ttl:3600,class:"IN",type:"KX",preference:10,exchanger:"kx.example.com."}}fromTinydns({tinyline:t}){const[e,s,i,n,a,o]=t.slice(1).split(":");return s!=36&&this.throwHelp("KX fromTinydns, invalid n"),new bt({owner:this.fullyQualify(e),ttl:parseInt(n,10),type:"KX",preference:B(i.slice(0,8)),exchanger:U(i.slice(8))[0],timestamp:a,location:o?.trim()??""})}getWireRdata(){const t=this.wirePackDomain(this.get("exchanger")),e=new Uint8Array(2+t.length);return new DataView(e.buffer).setUint16(0,this.get("preference")),e.set(t,2),e}toTinydns(){return this.getTinydnsGeneric(A(this.get("preference"))+N(this.get("exchanger")))}}const M={LATLON:2**31,ALTITUDE:1e5*100},$={sec:1e3,min:60*1e3,deg:3600*1e3};class Y extends f{static typeName="LOC";static typeId=29;static RFCs=[1876];static rdataFields=["address"];constructor(t){super(t)}setAddress(t){t||this.throwHelp("LOC: address is required"),this.parseLoc(t),this.set("address",t)}getDescription(){return"Location"}getCanonical(){return{owner:"example.com.",ttl:3600,class:"IN",type:"LOC",address:"52 22 23.000 N 4 53 32.000 E 10m 100m 10m 2m"}}parseLoc(t){const e="(\\d+)\\s+(?:(\\d+)\\s+)?(?:([\\d.]+)\\s+)?",s="(-?[\\d.]+)m?(?:\\s+([\\d.]+)m?)?(?:\\s+([\\d.]+)m?)?(?:\\s+([\\d.]+)m?)?",i=new RegExp(`^${e}(N|S)\\s+${e}(E|W)\\s+${s}`,"i"),n=t.match(i);return n||this.throwHelp("LOC address: invalid format, see RFC 1876"),{latitude:{degrees:n[1],minutes:n[2],seconds:n[3],hemisphere:n[4].toUpperCase()},longitude:{degrees:n[5],minutes:n[6],seconds:n[7],hemisphere:n[8].toUpperCase()},altitude:n[9]*100,size:n[10]*100,precision:{horizontal:n[11]*100,vertical:n[12]*100}}}fromTinydns({tinyline:t}){const[e,s,i,n,a,o]=t.slice(1).split(":");s!=29&&this.throwHelp("LOC fromTinydns, invalid n");const r={version:E(i.slice(0,4)),size:this.fromExponent(E(i.slice(4,8))),precision:{horizontal:this.fromExponent(E(i.slice(8,12))),vertical:this.fromExponent(E(i.slice(12,16)))},latitude:this.arcSecToDMS(gt(i.slice(16,32)),"lat"),longitude:this.arcSecToDMS(gt(i.slice(32,48)),"lon"),altitude:gt(i.slice(48,64))-M.ALTITUDE};return new Y({type:"LOC",owner:this.fullyQualify(e),address:this.toHuman(r),ttl:parseInt(n,10),timestamp:a,location:o?.trim()??""})}fromBind({bindline:t}){const[e,s,i,n]=t.split(/\s+/);return new Y({owner:e,ttl:parseInt(s,10),class:i,type:n,address:t.split(/\s+/).slice(4).join(" ").trim()})}dmsToArcSec(t){let e=t.degrees*$.deg+(t.minutes??0)*$.min+(t.seconds??0)*$.sec;switch(t.hemisphere.toUpperCase()){case"W":case"S":e=-e;break}return e+=M.LATLON,e}arcSecToDMS(t,e){let s=Math.abs(t-M.LATLON);const i=Math.floor(s/$.deg);s-=i*$.deg;const n=Math.floor(s/$.min);s-=n*$.min;const a=Math.floor(s/$.sec);s-=a*$.sec;let o;switch(e){case"lat":o=t>=M.LATLON?"N":"S";break;case"lon":o=t>=M.LATLON?"E":"W";break;default:this.throwHelp("unknown or missing hemisphere")}return`${i} ${n} ${a}${s?"."+s:""} ${o}`}fromExponent(t){const e=(t>>4&15)%10,s=(t>>0&15)%10;return e*Math.pow(10,s)}toExponent(t){let e=0;for(;t>=10;)t/=10,++e;return parseInt(t)<<4|e&15}toHuman(t){let e=`${t.latitude} ${t.longitude} ${t.altitude/100}m`;return t.size&&(e+=` ${t.size/100}m`),t.precision.horizontal&&(e+=` ${t.precision.horizontal/100}m`),t.precision.vertical&&(e+=` ${t.precision.vertical/100}m`),e}fromWire({owner:t,cls:e,ttl:s,rdata:i}){const n=new DataView(i.buffer,i.byteOffset),a={size:this.fromExponent(i[1]),precision:{horizontal:this.fromExponent(i[2]),vertical:this.fromExponent(i[3])},latitude:this.arcSecToDMS(n.getUint32(4),"lat"),longitude:this.arcSecToDMS(n.getUint32(8),"lon"),altitude:n.getUint32(12)-M.ALTITUDE};return new Y({owner:t,ttl:s,class:e,type:"LOC",address:this.toHuman(a)})}toTinydns(){const t=this.parseLoc(this.get("address"));let e="";return e+=y(0),e+=y(this.toExponent(t.size)),e+=y(this.toExponent(t.precision.horizontal)),e+=y(this.toExponent(t.precision.vertical)),e+=P(this.dmsToArcSec(t.latitude)),e+=P(this.dmsToArcSec(t.longitude)),e+=P(t.altitude+M.ALTITUDE),this.getTinydnsGeneric(e)}getWireRdata(){const t=this.parseLoc(this.get("address")),e=new Uint8Array(16),s=new DataView(e.buffer,e.byteOffset);return e[0]=0,e[1]=this.toExponent(t.size),e[2]=this.toExponent(t.precision.horizontal),e[3]=this.toExponent(t.precision.vertical),s.setUint32(4,this.dmsToArcSec(t.latitude)),s.setUint32(8,this.dmsToArcSec(t.longitude)),s.setUint32(12,t.altitude+M.ALTITUDE),e}}class Tt extends f{static typeName="MX";static typeId=15;static RFCs=[1035,2181,7505];static tinydnsType="@";static rdataFields=[["preference","u16"],["exchange","fqdn"]];static tags=["common"];constructor(t){super(t)}setPreference(t){t===void 0&&(t=this?.default?.preference),t===void 0&&this.throwHelp("MX: preference is required"),this.is16bitInt("MX","preference",t),this.set("preference",t)}setExchange(t){this.setTypedValue("fqdn","exchange",t)}getDescription(){return"Mail Exchanger"}getCanonical(){return{owner:"example.com.",ttl:43200,class:"IN",type:"MX",preference:10,exchange:"mail.example.com."}}fromTinydns({tinyline:t}){const[e,s,i,n,a,o,r]=t.slice(1).split(":");return new Tt({type:"MX",owner:this.fullyQualify(e),exchange:this.fullyQualify(/\./.test(i)?i:`${i}.mx.${e}`),preference:parseInt(n,10)||0,ttl:parseInt(a,10),timestamp:o,location:r?.trim()??""})}getWireRdata(){const t=this.wirePackDomain(this.get("exchange")),e=new Uint8Array(2+t.length);return new DataView(e.buffer).setUint16(0,this.get("preference")),e.set(t,2),e}toTinydns(){return`@${this.getTinyFQDN("owner")}::${this.getTinyFQDN("exchange")}:${this.get("preference")}:${this.getTinydnsPostamble()} +`}}const Ft=/[\r\n\t:\\/]/;class rt extends f{static typeName="NAPTR";static typeId=35;static RFCs=[2915,3403,4848];static rdataFields=[["order","u16"],["preference","u16"],["flags","qcharstr"],["service","qcharstr"],["regexp","qcharstr"],["replacement","fqdn"]];constructor(t){super(t)}getDescription(){return"Naming Authority Pointer"}getCanonical(){return{owner:"cid.urn.arpa.",ttl:3600,class:"IN",type:"NAPTR",order:100,preference:10,flags:"S",service:"z3950+N2L+N2R",regexp:"",replacement:"gatekeeper.example.com."}}setOrder(t){this.is16bitInt("NAPTR","order",t),this.set("order",t)}setPreference(t){this.is16bitInt("NAPTR","preference",t),this.set("preference",t)}setFlags(t){this.getFlagsOptions().has(t.toUpperCase())||this.throwHelp("NAPTR flags are invalid"),this.set("flags",t.toUpperCase())}getFlagsOptions(){return new Map([[""],["S"],["A"],["U"],["P"]])}setService(t){this.set("service",t)}setRegexp(t){this.set("regexp",t)}setReplacement(t){this.set("replacement",t)}fromTinydns({tinyline:t}){const{owner:e,typeId:s,rdata:i,ttl:n,timestamp:a,location:o}=this.parseTinydnsLine(t);s!=this.getTypeId()&&this.throwHelp("NAPTR fromTinydns, invalid n");const r=k(i),c=new DataView(r.buffer,r.byteOffset,r.byteLength),p={type:"NAPTR",owner:e,ttl:n,timestamp:a,location:o,order:c.getUint16(0),preference:c.getUint16(2)};let h=4;const d=r[h];h++,p.flags=new TextDecoder().decode(r.subarray(h,h+d)),h+=d;const g=r[h];h++,p.service=new TextDecoder().decode(r.subarray(h,h+g)),h+=g;const u=r[h];h++,p.regexp=new TextDecoder().decode(r.subarray(h,h+u)),h+=u;const m=r[h];return h++,p.replacement=new TextDecoder().decode(r.subarray(h,h+m)),new rt(p)}fromBind({bindline:t}){const e=/^(?\S+)\s+(?\d+)\s+(?\S+)\s+(?NAPTR)\s+(?\d+)\s+(?\d+)\s+["'](?[^"']*)["']\s+["'](?[^"']*)["']\s+["'](?[^"']*)["']\s+(?\S+)$/,s=t.trim().match(e);if(!s)throw new Error(`Invalid NAPTR BIND line: ${t}`);const{owner:i,ttl:n,type:a,order:o,preference:r,flags:c,service:p,regexp:h,replacement:d}=s.groups;return new rt({owner:this.fullyQualify(i),ttl:parseInt(n,10),class:s.groups.class,type:a,order:parseInt(o,10),preference:parseInt(r,10),flags:c,service:p,regexp:h,replacement:d})}toTinydns(){let t=A(this.get("order"))+A(this.get("preference"))+y(this.get("flags").length)+this.get("flags")+y(this.get("service").length)+I(Ft,this.get("service"))+y(this.get("regexp").length)+I(Ft,this.get("regexp"));const e=this.get("replacement");return e!==""&&(t+=y(e.length),t+=I(Ft,e)),t+="\\000",this.getTinydnsGeneric(t)}getWireRdata(){const t=new TextEncoder,e=t.encode(this.get("flags")),s=t.encode(this.get("service")),i=t.encode(this.get("regexp")),n=this.wirePackDomain(this.get("replacement")),a=5+e.length+1+s.length+1+i.length+n.length,o=new Uint8Array(a),r=new DataView(o.buffer);let c=0;return r.setUint16(c,this.get("order")),c+=2,r.setUint16(c,this.get("preference")),c+=2,o[c++]=e.length,o.set(e,c),c+=e.length,o[c++]=s.length,o.set(s,c),c+=s.length,o[c++]=i.length,o.set(i,c),c+=i.length,o.set(n,c),o}}class At extends f{static typeName="NS";static typeId=2;static RFCs=[1035];static tinydnsType="&";static rdataFields=[["dname","fqdn"]];static tags=["common"];constructor(t){super(t)}setDname(t){t||this.throwHelp("NS: dname is required"),this.isFullyQualified("NS","dname",t),this.isValidHostname("NS","dname",t),this.set("dname",t.toLowerCase())}getDescription(){return"Name Server"}getCanonical(){return{owner:"example.com.",ttl:3600,class:"IN",type:"NS",dname:"ns1.example.com."}}fromTinydns({tinyline:t}){const[e,s,i,n,a,o]=t.slice(1).split(":");return new At({type:"NS",owner:this.fullyQualify(e),dname:this.fullyQualify(/\./.test(i)?i:`${i}.ns.${e}`),ttl:parseInt(n,10),timestamp:a,location:o?.trim()??""})}getWireRdata(){return this.wirePackDomain(this.get("dname"))}toTinydns(){return`&${this.getTinyFQDN("owner")}::${this.getTinyFQDN("dname")}:${this.getTinydnsPostamble()} +`}}class X extends f{static typeName="NSEC";static typeId=47;static RFCs=[4034];static rdataFields=["next domain","type bit maps"];static tags=["dnssec"];constructor(t){super(t)}setNextDomain(t){t||this.throwHelp("NSEC: 'next domain' is required:"),this.isFullyQualified("NSEC","next domain",t),this.isValidHostname("NSEC","next domain",t),this.set("next domain",t.toLowerCase())}setTypeBitMaps(t){t||this.throwHelp("NSEC: 'type bit maps' is required"),this.set("type bit maps",t)}getDescription(){return"Next Secure"}getCanonical(){return{owner:"alfa.example.com.",ttl:3600,class:"IN",type:"NSEC","next domain":"host.example.com.","type bit maps":"A MX RRSIG NSEC TYPE1234"}}fromTinydns({tinyline:t}){const[e,s,i,n,a,o]=t.slice(1).split(":"),r=Uint8Array.from(x(i),d=>d.charCodeAt(0)),[c,p,h]=U(i);return new X({owner:this.fullyQualify(e),ttl:parseInt(n,10),type:"NSEC","next domain":c,"type bit maps":new TextDecoder().decode(r.subarray(h)),timestamp:a,location:o?.trim()??""})}fromBind({bindline:t}){const[e,s,i,n,a]=t.split(/\s+/);return new X({owner:e,ttl:parseInt(s,10),class:i,type:n,"next domain":a,"type bit maps":t.split(/\s+/).slice(5).filter(we).join(" ").trim()})}fromWire({owner:t,cls:e,ttl:s,rdata:i}){const{fqdn:n,end:a}=this.wireUnpackDomain(i,0),o=be(i.subarray(a));return new X({owner:t,ttl:s,class:e,type:"NSEC","next domain":n,"type bit maps":o})}toTinydns(){const t=new RegExp(/[\r\n\t:\\/]/,"g");return this.getTinydnsGeneric(N(this.get("next domain"))+I(t,this.get("type bit maps")))}getWireRdata(){const t=this.wirePackDomain(this.get("next domain")),e=Te(this.get("type bit maps")),s=new Uint8Array(t.length+e.length);return s.set(t),s.set(e,t.length),s}}const we=l=>!["(",")"].includes(l);function be(l){const t=Object.fromEntries(Object.entries(q).map(([i,n])=>[n,i])),e=[];let s=0;for(;s+2<=l.length;){const i=l[s],n=l[s+1];s+=2;for(let a=0;a>r){const c=i*256+a*8+r;e.push(t[c]??`TYPE${c}`)}}s+=n}return e.join(" ")}function Te(l){const t=l.trim().split(/\s+/).map(o=>/^TYPE\d+$/i.test(o)?parseInt(o.slice(4),10):q[o.toUpperCase()]).filter(o=>o!==void 0&&o>=0),e=new Map;for(const o of t){const r=Math.floor(o/256);e.has(r)||e.set(r,[]),e.get(r).push(o%256)}const s=[];for(const[o,r]of[...e.entries()].sort((c,p)=>c[0]-p[0])){const c=Math.max(...r),p=Math.floor(c/8)+1,h=new Uint8Array(p);for(const d of r)h[Math.floor(d/8)]|=128>>d%8;s.push(new Uint8Array([o,p,...h]))}const i=s.reduce((o,r)=>o+r.length,0),n=new Uint8Array(i);let a=0;for(const o of s)n.set(o,a),a+=o.length;return n}class z extends f{static typeName="NSEC3";static typeId=50;static RFCs=[5155,9077];static rdataFields=["hash algorithm","flags","iterations","salt","next hashed owner name","type bit maps"];static tags=["dnssec"];constructor(t){super(t)}setHashAlgorithm(t){t||this.throwHelp("NSEC3: 'hash algorithm' is required"),this.is8bitInt("NSEC3","hash algorithm",t),this.set("hash algorithm",t)}setFlags(t){t||this.throwHelp("NSEC3: 'flags' is required"),this.is8bitInt("NSEC3","flags",t),this.set("flags",t)}setIterations(t){t||this.throwHelp("NSEC3: 'iterations' is required"),this.is16bitInt("NSEC3","flags",t),this.set("iterations",t)}setSalt(t){this.set("salt",t)}setNextHashedOwnerName(t){t||this.throwHelp("NSEC3: 'next hashed owner name' is required"),this.set("next hashed owner name",t)}setTypeBitMaps(t){t||this.throwHelp("NSEC3: 'type bit maps' is required"),this.set("type bit maps",t)}getDescription(){return"Next Secure"}getCanonical(){return{owner:"test.example.com.",ttl:3600,class:"IN",type:"NSEC3","hash algorithm":1,flags:1,iterations:12,salt:"aabbccdd","next hashed owner name":"2vptu5timamqttgl4luu9kg21e0aor3s","type bit maps":"A RRSIG"}}fromBind({bindline:t}){const[e,s,i,n,a,o,r,c]=t.split(/\s+/),p=t.includes("(")?t.split(/\(|\)/)[1]:t.split(/\s+/).slice(8).join(" ");return new z({owner:e,ttl:parseInt(s,10),class:i,type:n,"hash algorithm":parseInt(a,10),flags:parseInt(o,10),iterations:parseInt(r,10),salt:c,"next hashed owner name":p.trim().split(/\s+/)[0],"type bit maps":p.trim().split(/\s+/).slice(1).join(" ")})}fromTinydns({tinyline:t}){const[e,s,i,n,a,o]=t.slice(1).split(":");s!=50&&this.throwHelp("NSEC3 fromTinydns, invalid n");const r=Uint8Array.from(x(i),b=>b.charCodeAt(0)),c=new DataView(r.buffer,r.byteOffset,r.byteLength),p=r[0],h=r[1],d=c.getUint16(2),{salt:g,nextHashedOwnerName:u,typeBitMaps:m}=jt(r);return new z({owner:this.fullyQualify(e),ttl:parseInt(n,10),type:"NSEC3","hash algorithm":p,flags:h,iterations:d,salt:g,"next hashed owner name":u,"type bit maps":m,timestamp:a,location:o?.trim()??""})}fromWire({owner:t,cls:e,ttl:s,rdata:i}){const n=new DataView(i.buffer,i.byteOffset),{salt:a,nextHashedOwnerName:o,typeBitMaps:r}=jt(i);return new z({owner:t,ttl:s,class:e,type:"NSEC3","hash algorithm":i[0],flags:i[1],iterations:n.getUint16(2),salt:a,"next hashed owner name":o,"type bit maps":r})}toBind(t){return`${this.getFQDN("owner",t)} ${this.get("ttl")} ${this.get("class")} NSEC3${this.getRdataFields().slice(0,4).map(e=>" "+this.get(e)).join("")} (${this.getRdataFields().slice(4).map(e=>this.get(e)).join(" ")}) +`}toTinydns(){const t=new RegExp(/[\r\n\t:\\/]/,"g");return this.getTinydnsGeneric(y(this.get("hash algorithm"))+y(this.get("flags"))+A(this.get("iterations"))+I(t,this.get("salt"))+I(t,this.get("next hashed owner name"))+I(t,this.get("type bit maps")))}getWireRdata(){const t=`${this.get("salt")}${this.get("next hashed owner name")}${this.get("type bit maps")}`,e=new TextEncoder().encode(t),s=4+e.length,i=new Uint8Array(s),n=new DataView(i.buffer,i.byteOffset);let a=0;return i[a++]=this.get("hash algorithm"),i[a++]=this.get("flags"),n.setUint16(a,this.get("iterations")),a+=2,i.set(e,a),i}}function jt(l){const t=new TextDecoder().decode(l.subarray(4)),e=l[0],s=e===1?32:e===2?52:32;let i="",n="",a="";const o=Math.min(64,t.length);for(let r=o;r>=1;r--){const c=t.slice(r,r+s);if(c.length!==s||!/^[0-9a-z]+$/.test(c))continue;const p=t.slice(0,r);if(/^[0-9A-Fa-f]+$/.test(p)){i=p,n=c,a=t.slice(r+s);break}}if(!n){const r=t.match(/^([0-9A-Fa-f]*)/);i=r?r[1]:"",n=t.slice(i.length),a=""}return{salt:i,nextHashedOwnerName:n,typeBitMaps:a}}class at extends f{static typeName="NSEC3PARAM";static typeId=51;static RFCs=[5155];static rdataFields=["hash algorithm","flags","iterations","salt"];static tags=["dnssec"];constructor(t){super(t)}setHashAlgorithm(t){t==null&&this.throwHelp("NSEC3PARAM: 'hash algorithm' is required"),this.is8bitInt("NSEC3PARAM","hash algorithm",t),this.set("hash algorithm",t)}setFlags(t){t==null&&this.throwHelp("NSEC3PARAM: 'flags' is required"),this.is8bitInt("NSEC3PARAM","flags",t),this.set("flags",t)}setIterations(t){t==null&&this.throwHelp("NSEC3PARAM: 'iterations' is required"),this.is16bitInt("NSEC3PARAM","iterations",t),this.set("iterations",t)}setSalt(t){if(t==="-"){this.set("salt",t);return}t!=null&&!/^[0-9A-Fa-f]*$/.test(t)&&this.throwHelp("NSEC3PARAM: 'salt' must be hex or '-'"),this.set("salt",t)}getDescription(){return"Next Secure Parameters"}getCanonical(){return{owner:"example.com.",ttl:3600,class:"IN",type:"NSEC3PARAM","hash algorithm":1,flags:1,iterations:12,salt:"aabbccdd"}}fromTinydns({tinyline:t}){const{owner:e,typeId:s,rdata:i,ttl:n,timestamp:a,location:o}=this.parseTinydnsLine(t);s!=this.getTypeId()&&this.throwHelp("NSEC3PARAM fromTinydns, invalid n"),i.length<4&&this.throwHelp(`NSEC3PARAM: RDATA too short: ${i}`);const r=k(i);return new at({owner:e,ttl:n,type:"NSEC3PARAM","hash algorithm":r[0],flags:r[1],iterations:r[2]<<8|r[3],salt:r[4]===0?"-":R(r.subarray(5,5+r[4])),timestamp:a,location:o})}fromWire({owner:t,cls:e,ttl:s,rdata:i}){const n=new DataView(i.buffer,i.byteOffset),a=i[4],o=a===0?"-":R(i.subarray(5,5+a));return new at({owner:t,ttl:s,class:e,type:"NSEC3PARAM","hash algorithm":i[0],flags:i[1],iterations:n.getUint16(2),salt:o})}toTinydns(){const t=this.get("salt"),e=t==="-"?y(0):y(t.length/2)+O(t);return this.getTinydnsGeneric(y(this.get("hash algorithm"))+y(this.get("flags"))+A(this.get("iterations"))+e)}getWireRdata(){const t=this.get("salt"),e=t==="-"?new Uint8Array(0):F(t),s=new Uint8Array(5+e.length),i=new DataView(s.buffer,s.byteOffset);return s[0]=this.get("hash algorithm"),s[1]=this.get("flags"),i.setUint16(2,this.get("iterations")),s[4]=e.length,s.set(e,5),s}}class v extends f{static typeName="NXT";static typeId=30;static RFCs=[2065];static rdataFields=["next domain","type bit map"];static tags=["obsolete"];constructor(t){super(t)}setNextDomain(t){t||this.throwHelp("NXT: 'next domain' is required"),this.isFullyQualified("NXT","next domain",t),this.isValidHostname("NXT","next domain",t),this.set("next domain",t.toLowerCase())}setTypeBitMap(t){t||this.throwHelp("NXT: 'type bit map' is required"),this.set("type bit map",t)}getDescription(){return"Next Secure"}getCanonical(){return{owner:"big.example.com.",ttl:3600,class:"IN",type:"NXT","next domain":"host.example.com.","type bit map":"A MX NXT"}}fromTinydns({tinyline:t}){const[e,s,i,n,a,o]=t.slice(1).split(":");parseInt(s,10)!==this.getTypeId()&&this.throwHelp("NXT fromTinydns, invalid n");const r=Uint8Array.from(x(i),d=>d.charCodeAt(0)),[c,p,h]=U(i);return new v({owner:this.fullyQualify(e),ttl:parseInt(n,10),type:"NXT","next domain":c,"type bit map":new TextDecoder().decode(r.subarray(h)),timestamp:a,location:o?.trim()??""})}fromBind({bindline:t}){const[e,s,i,n,a]=t.split(/\s+/);return new v({owner:e,ttl:parseInt(s,10),class:i,type:n,"next domain":a,"type bit map":t.split(/\s+/).slice(5).filter(Ae).join(" ").trim()})}fromWire({owner:t,cls:e,ttl:s,rdata:i}){const{fqdn:n,end:a}=this.wireUnpackDomain(i,0),o=Ie(i.subarray(a));return new v({owner:t,ttl:s,class:e,type:"NXT","next domain":n,"type bit map":o})}toTinydns(){const t=new RegExp(/[\r\n\t:\\/]/,"g");return this.getTinydnsGeneric(N(this.get("next domain"))+I(t,this.get("type bit map")))}getWireRdata(){const t=this.wirePackDomain(this.get("next domain")),e=Se(this.get("type bit map")),s=new Uint8Array(t.length+e.length);return s.set(t),s.set(e,t.length),s}}const Ae=l=>!["(",")"].includes(l);function Ie(l){const t=Object.fromEntries(Object.entries(q).map(([s,i])=>[i,s])),e=[];for(let s=0;s>n){const a=s*8+n;e.push(t[a]??`TYPE${a}`)}}return e.join(" ")}function Se(l){const t=new Uint8Array(16);for(const s of l.trim().split(/\s+/)){const i=/^TYPE\d+$/i.test(s)?parseInt(s.slice(4),10):q[s.toUpperCase()];i!==void 0&&i<128&&(t[Math.floor(i/8)]|=128>>i%8)}let e=t.length;for(;e>0&&t[e-1]===0;)e--;return t.slice(0,e)}class ot extends f{static typeName="OPENPGPKEY";static typeId=61;static RFCs=[4880,7929];static rdataFields=[["public key","base64"]];static tags=["security"];constructor(t){super(t)}setPublicKey(t){this.isBase64("OPENPGPKEY","public key",t),this.set("public key",t)}getDescription(){return"OpenPGP Public Key"}getCanonical(){return{owner:"matt.example.com.",ttl:3600,class:"IN",type:"OPENPGPKEY","public key":"AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwIXAqcOTiW7iHnQt5hwVAAAAA=="}}fromBind({bindline:t}){const e=/^(?\S+)\s+(?\d{1,10})\s+(?IN)\s+(?OPENPGPKEY)\s+(?\S[\s\S]*)$/i,s=t.trim().match(e);s||this.throwHelp(`unable to parse OPENPGPKEY: ${t}`);const{owner:i,ttl:n,class:a,type:o,publickey:r}=s.groups,c=r.trim().replace(/\s+/g,"");return new ot({owner:i,ttl:parseInt(n,10),class:a,type:o,"public key":c})}fromTinydns({tinyline:t}){const{owner:e,typeId:s,rdata:i,ttl:n,timestamp:a,location:o}=this.parseTinydnsLine(t);return s!=this.getTypeId()&&this.throwHelp("OPENPGPKEY fromTinydns, invalid n"),new ot({owner:e,ttl:n,type:"OPENPGPKEY","public key":ut(i),timestamp:a,location:o})}toTinydns(){return this.getTinydnsGeneric(W(this.get("public key")))}getWireRdata(){return L(this.get("public key"))}}class Qt extends f{static typeName="PTR";static typeId=12;static RFCs=[1035];static tinydnsType="^";static rdataFields=[["dname","fqdn"]];static tags=["common"];constructor(t){super(t)}setDname(t){this.isFullyQualified("PTR","dname",t),this.isValidHostname("PTR","dname",t),this.set("dname",t.toLowerCase())}getDescription(){return"Pointer"}getCanonical(){return{owner:"2.2.0.192.in-addr.arpa.",ttl:3600,class:"IN",type:"PTR",dname:"host.example.com."}}getWireRdata(){return this.wirePackDomain(this.get("dname"))}}class It extends f{static typeName="RP";static rdataFields=[["mbox","fqdn"],["txt","fqdn"]];constructor(t){super(t)}setMbox(t){t||this.throwHelp("RP: mbox is required"),this.isFullyQualified("RP","mbox",t),this.set("mbox",t.toLowerCase())}setTxt(t){t||this.throwHelp("RP: txt is required"),this.isFullyQualified("RP","txt",t),this.set("txt",t.toLowerCase())}getDescription(){return"Responsible Person"}static tags=["obsolete"];static RFCs=[1183];static typeId=17;getCanonical(){return{owner:"example.com.",ttl:3600,class:"IN",type:"RP",mbox:"admin.example.com.",txt:"info.example.com."}}fromTinydns({tinyline:t}){const[e,s,i,n,a,o]=t.slice(1).split(":"),[r,c]=U(i),p=U(i.slice(c))[0];return new It({owner:this.fullyQualify(e),ttl:parseInt(n,10),type:"RP",mbox:r,txt:p,timestamp:a,location:o?.trim()??""})}getWireRdata(){const t=this.wirePackDomain(this.get("mbox")),e=this.wirePackDomain(this.get("txt")),s=new Uint8Array(t.length+e.length);return s.set(t,0),s.set(e,t.length),s}toTinydns(){return this.getTinydnsGeneric(N(this.get("mbox"))+N(this.get("txt")))}}class ct extends f{static typeName="RRSIG";static typeId=46;static RFCs=[4034];static rdataFields=[["type covered","u16"],["algorithm","u8"],["labels","u8"],["original ttl","u32"],["signature expiration","u32"],["signature inception","u32"],["key tag","u16"],["signers name","fqdn"],["signature","str"]];static tags=["dnssec"];constructor(t){super(t)}setTypeCovered(t){if(!t&&t!==0&&this.throwHelp("RRSIG: 'type covered' is required"),typeof t=="string"){const e=t.match(/^TYPE(\d+)$/i);if(e)t=parseInt(e[1],10);else{const s=q[t.toUpperCase()];s===void 0&&this.throwHelp("RRSIG: 'type covered' is not a recognized type name"),t=s}}this.is16bitInt("RRSIG","type covered",t),this.set("type covered",t)}setAlgorithm(t){this.getAlgorithmOptions().has(t)||this.throwHelp("RRSIG: algorithm invalid"),this.set("algorithm",t)}setLabels(t){this.setTypedValue("u8","labels",t)}setOriginalTtl(t){this.setTypedValue("u32","original ttl",t)}setSignatureExpiration(t){this.setTypedValue("u32","signature expiration",t)}setSignatureInception(t){this.setTypedValue("u32","signature inception",t)}setKeyTag(t){this.setTypedValue("u16","key tag",t)}setSignersName(t){this.setTypedValue("fqdn","signers name",t)}setSignature(t){this.setTypedValue("str","signature",t)}getAlgorithmOptions(){return new Map([[1,"RSA/MD5"],[2,"DH"],[3,"DSA/SHA-1"],[4,"EC"],[5,"RSA/SHA-1"],[6,"DSA-NSEC3-SHA1"],[7,"RSASHA1-NSEC3-SHA1"],[8,"RSA/SHA-256"],[10,"RSA/SHA-512"],[13,"ECDSA P-256/SHA-256"],[14,"ECDSA P-384/SHA-384"],[15,"Ed25519"],[16,"Ed448"],[253],[254]])}getDescription(){return"Resource Record Signature"}getCanonical(){return{owner:"example.com.",ttl:3600,class:"IN",type:"RRSIG","type covered":1,algorithm:5,labels:3,"original ttl":3600,"signature expiration":1045053120,"signature inception":1042461120,"key tag":12345,"signers name":"example.com.",signature:"ABCDEF..."}}fromBind({bindline:t}){const e=t.trim().split(/\s+/),s=e[4],i=s.match(/^TYPE(\d+)$/i),n=/^\d+$/.test(s)?parseInt(s,10):i?parseInt(i[1],10):q[s.toUpperCase()]??parseInt(s,10);return new ct({owner:e[0],ttl:parseInt(e[1],10),class:e[2],type:"RRSIG","type covered":n,algorithm:parseInt(e[5],10),labels:parseInt(e[6],10),"original ttl":parseInt(e[7],10),"signature expiration":parseInt(e[8],10),"signature inception":parseInt(e[9],10),"key tag":parseInt(e[10],10),"signers name":e[11],signature:e.slice(12).filter(a=>a!=="("&&a!==")").join(" ").trim()})}fromTinydns({tinyline:t}){const[e,s,i,n,a,o]=t.slice(1).split(":");parseInt(s,10)!==this.getTypeId()&&this.throwHelp("RRSIG fromTinydns, invalid n");const r=Uint8Array.from(x(i),S=>S.charCodeAt(0)),c=new DataView(r.buffer,r.byteOffset,r.byteLength),p=c.getUint16(0),h=r[2],d=r[3],g=c.getUint32(4),u=c.getUint32(8),m=c.getUint32(12),b=c.getUint16(16);let w=18;const T=[];for(;wn!=="("&&n!==")").join(" ").trim()})}toTinydns(){const t=new RegExp(/[\r\n\t:]/,"g");return this.getTinydnsGeneric(A(this.get("type covered"))+y(this.get("algorithm"))+y(this.get("labels"))+P(this.get("original ttl"))+P(this.get("signature expiration"))+P(this.get("signature inception"))+A(this.get("key tag"))+N(this.get("signers name"))+I(t,this.get("signature")))}getWireRdata(){const t=V(this.get("signers name")),e=new TextEncoder().encode(this.get("signature")),s=18+t.length+e.length,i=new Uint8Array(s),n=new DataView(i.buffer,i.byteOffset);let a=0;return n.setUint16(a,this.get("type covered")),a+=2,i[a++]=this.get("algorithm"),i[a++]=this.get("labels"),n.setUint32(a,this.get("original ttl")),a+=4,n.setUint32(a,this.get("signature expiration")),a+=4,n.setUint32(a,this.get("signature inception")),a+=4,n.setUint16(a,this.get("key tag")),a+=2,i.set(t,a),a+=t.length,i.set(e,a),i}fromTinydns({tinyline:t}){const{owner:e,typeId:s,rdata:i,ttl:n,timestamp:a,location:o}=this.parseTinydnsLine(t);parseInt(s,10)!==this.getTypeId()&&this.throwHelp("SIG fromTinydns, invalid n");const r=k(i),c=new DataView(r.buffer,r.byteOffset,r.byteLength),p=c.getUint16(0),h=r[2],d=r[3],g=c.getUint32(4),u=c.getUint32(8),m=c.getUint32(12),b=c.getUint16(16);let w=18;const T=[];for(;w" "+this.get(e)).join("")} ${this.getRdataFields().slice(4,8).map(e=>this.get(e)).join(" ")} ( ${this.get("signature")} )`}}class ht extends f{static typeName="SMIMEA";static typeId=53;static RFCs=[8162];static rdataFields=[["certificate usage","u8"],["selector","u8"],["matching type","u8"],["certificate association data","hex"]];static tags=["security"];constructor(t){super(t)}setCertificateUsage(t){this.getCertificateUsageOptions().has(t)||this.throwHelp("SMIMEA: certificate usage invalid"),this.set("certificate usage",t)}getCertificateUsageOptions(){return new Map([[0,"CA certificate"],[1,"an end entity certificate"],[2,"the trust anchor"],[3,"domain-issued certificate"]])}setSelector(t){this.getSelectorOptions().has(t)||this.throwHelp("SMIMEA: selector invalid"),this.set("selector",t)}getSelectorOptions(){return new Map([[0,"Full certificate"],[1,"SubjectPublicKeyInfo"]])}setMatchingType(t){this.getMatchingTypeOptions().has(t)||this.throwHelp("SMIMEA: matching type"),this.set("matching type",t)}getMatchingTypeOptions(){return new Map([[0,"Exact match"],[1,"SHA-256 hash"],[2,"SHA-512 hash"]])}setCertificateAssociationData(t){this.set("certificate association data",t)}getDescription(){return"S/MIME cert association"}getCanonical(){return{owner:"_443._tcp.www.example.com.",ttl:3600,class:"IN",type:"SMIMEA","certificate usage":0,selector:0,"matching type":1,"certificate association data":"ABCDEF..."}}fromBind({bindline:t}){const[e,s,i,n,a,o,r]=t.split(/\s+/);return new ht({owner:e,ttl:parseInt(s,10),class:i,type:n,"certificate usage":parseInt(a,10),selector:parseInt(o,10),"matching type":parseInt(r,10),"certificate association data":t.split(/\s+/).slice(7).join(" ").trim()})}fromTinydns({tinyline:t}){const{owner:e,rdata:s,ttl:i,timestamp:n,location:a}=this.parseTinydnsLine(t),o=k(s);return new ht({owner:e,ttl:i,type:"SMIMEA","certificate usage":o[0],selector:o[1],"matching type":o[2],"certificate association data":R(o.subarray(3)),timestamp:n,location:a})}toTinydns(){return this.getTinydnsGeneric(y(this.get("certificate usage"))+y(this.get("selector"))+y(this.get("matching type"))+O(this.get("certificate association data").replace(/[\s()]/g,"")))}getWireRdata(){const t=F(this.get("certificate association data").replace(/[\s()]/g,"")),e=new Uint8Array(3+t.length);return e[0]=this.get("certificate usage"),e[1]=this.get("selector"),e[2]=this.get("matching type"),e.set(t,3),e}}class St extends f{static typeName="SOA";static typeId=6;static RFCs=[1035,2308];static tinydnsType="Z";static rdataFields=[["mname","fqdn"],["rname","fqdn"],["serial","u32"],["refresh","u32"],["retry","u32"],["expire","u32"],["minimum","u32"]];static tags=["common"];constructor(t){super(t)}setMinimum(t){this.is32bitInt("SOA","minimum",t),this.set("minimum",t)}setMname(t){this.isValidHostname("SOA","MNAME",t),this.isFullyQualified("SOA","MNAME",t),this.set("mname",t.toLowerCase())}setRname(t){this.isValidHostname("SOA","RNAME",t),this.isFullyQualified("SOA","RNAME",t),/@/.test(t)&&this.throwHelp("SOA rname replaces @ with a . (dot)"),this.set("rname",t.toLowerCase())}setSerial(t){this.is32bitInt("SOA","serial",t),this.set("serial",t)}setRefresh(t){this.is32bitInt("SOA","refresh",t),this.set("refresh",t)}setRetry(t){this.is32bitInt("SOA","retry",t),this.set("retry",t)}setExpire(t){this.is32bitInt("SOA","expire",t),this.set("expire",t)}getDescription(){return"Start Of Authority"}getCanonical(){return{owner:"example.com.",ttl:3600,class:"IN",type:"SOA",mname:"ns1.example.com.",rname:"admin.example.com.",serial:2023051001,refresh:7200,retry:3600,expire:1209600,minimum:3600}}fromTinydns({tinyline:t}){const[e,s,i,n,a,o,r,c,p,h,d]=t.slice(1).split(":");return new St({owner:this.fullyQualify(e),ttl:parseInt(p,10),type:"SOA",mname:this.fullyQualify(s),rname:this.fullyQualify(i),serial:parseInt(n??this.default?.serial,10),refresh:parseInt(a,10)||16384,retry:parseInt(o,10)||2048,expire:parseInt(r,10)||1048576,minimum:parseInt(c,10)||2560,timestamp:parseInt(h)||"",location:d?.trim()??""})}toMaraDNS(){return`${this.get("owner")} SOA ${this.getFields("rdata").map(t=>this.getQuoted(t)).join(" ")} ~ `}getWireRdata(){const t=this.wirePackDomain(this.get("mname")),e=this.wirePackDomain(this.get("rname")),s=new Uint8Array(t.length+e.length+20);let i=0;s.set(t,i),i+=t.length,s.set(e,i),i+=e.length;const n=new DataView(s.buffer,i);return n.setUint32(0,this.get("serial")),n.setUint32(4,this.get("refresh")),n.setUint32(8,this.get("retry")),n.setUint32(12,this.get("expire")),n.setUint32(16,this.get("minimum")),s}toTinydns(){return`Z${this.getTinyFQDN("owner")}:${this.getTinyFQDN("mname")}:${this.getTinyFQDN("rname")}:${this.getEmpty("serial")}:${this.getEmpty("refresh")}:${this.getEmpty("retry")}:${this.getEmpty("expire")}:${this.getEmpty("minimum")}:${this.getTinydnsPostamble()} -`}}class $t extends f{static typeName="TXT";static typeId=16;static RFCs=[1035,4408,7208,6376];static tinydnsType="'";static rdataFields=[["data","charstrs"]];static tags=["common"];constructor(t){super(t)}setData(t){this.set("data",t)}getDescription(){return"Text"}getCanonical(){return{owner:"example.com.",ttl:3600,class:"IN",type:"TXT",data:"v=spf1 mx -all"}}fromTinydns({tinyline:t}){const e=t;let s,i,n,a,o,r;return e[0]==="'"?([s,n,a,o,r]=e.slice(1).split(":"),i=x(n)):[s,i,a,o,r]=this.fromTinydnsGeneric(e),new this.constructor({owner:this.fullyQualify(s),ttl:parseInt(a,10),type:"TXT",data:i,timestamp:o,location:r?.trim()||""})}fromTinydnsGeneric(t){let[e,s,i,n,a,o]=t.slice(1).split(":");s!=16&&this.throwHelp("TXT fromTinydns, invalid n"),i=x(i);let r="",c=i[0].charCodeAt(0),h=1;for(;hi.length&&this.throwHelp("TXT fromTinydnsGeneric: truncated character-string in rdata"),r.push(i.slice(c,c+h)),c+=h}const p=r.length>1?r:r[0]??"";return[e,p,n,a,o]}toBind(t){return`${this.getPrefix(t)} "${Yt(this.get("data"))}" `}toMaraDNS(){const t=Yt(this.get("data")).replace(/"/g,"'");return`${this.get("owner")} +${this.get("ttl")} ${this.get("type")} '${t}' ~ -`}getWireRdata(){let t=this.get("data");return Array.isArray(t)&&(t=t.join("")),Se(t)}toTinydns(){let t=this.get("data");Array.isArray(t)&&(t=t.join(""));const e=I(new RegExp(/[\r\n\t:\\/]/,"g"),t);return`'${this.getTinyFQDN("owner")}:${e}:${this.getTinydnsPostamble()} -`}}function Yt(l){const t=new TextEncoder;return Array.isArray(l)?l.some(s=>t.encode(s).length>255)?Xt(l.join(""),255).join('" "'):l.join('" "'):t.encode(l).length<=255?l:Xt(l,255).join('" "')}function Xt(l,t){const e=new TextEncoder().encode(l),s=new TextDecoder,i=[];let n=0;for(;n\S+)\s+(?\d{1,10})\s+(?IN)\s+(?TLSA)\s+(?\d+)\s+(?\d+)\s+(?\d+)\s+(?\S.*)$/i,s=t.trim().match(e);s||this.throwHelp(`unable to parse TLSA: ${t}`);const{owner:i,ttl:n,cls:a,type:o,usage:r,selector:c,matchtype:h,cad:p}=s.groups;return new dt({owner:this.fullyQualify(i),ttl:parseInt(n,10),class:a.toUpperCase(),type:o.toUpperCase(),"certificate usage":parseInt(r,10),selector:parseInt(c,10),"matching type":parseInt(h,10),"certificate association data":p.trim()})}fromTinydns({tinyline:t}){const{owner:e,typeId:s,rdata:i,ttl:n,timestamp:a,location:o}=this.parseTinydnsLine(t);s!=this.getTypeId()&&this.throwHelp("TLSA fromTinydns, invalid n");const r=H(i);return new dt({owner:e,ttl:n,type:"TLSA","certificate usage":r[0],selector:r[1],"matching type":r[2],"certificate association data":R(r.subarray(3)),timestamp:a,location:o})}toTinydns(){return this.getTinydnsGeneric(u(this.get("certificate usage"))+u(this.get("selector"))+u(this.get("matching type"))+O(this.get("certificate association data").replace(/[\s()]/g,"")))}getWireRdata(){const t=F(this.get("certificate association data").replace(/[\s()]/g,"")),e=new Uint8Array(3+t.length);return e[0]=this.get("certificate usage"),e[1]=this.get("selector"),e[2]=this.get("matching type"),e.set(t,3),e}}class J extends f{static typeName="TSIG";static typeId=250;static RFCs=[2845,8945];static rdataFields=["algorithm name","time signed","fudge","mac","original id","error","other"];constructor(t){super(t)}getDescription(){return"Transaction Signature"}getCanonical(){return{owner:"test.example.",ttl:0,class:"ANY",type:"TSIG","algorithm name":"hmac-sha256.","time signed":162065e4,fudge:300,mac:"ABCDEF...","original id":12345,error:0,other:""}}setClass(t){t!=="ANY"&&this.throwHelp("TSIG: Class is required to be ANY"),this.set("class",t)}setTtl(t){t!==0&&this.throwHelp("TSIG: TTL is required to be 0"),this.set("ttl",t)}setAlgorithmName(t){t||this.throwHelp("TSIG: 'algorithm name' is required"),this.set("algorithm name",t)}setTimeSigned(t){t===void 0&&this.throwHelp("TSIG: 'time signed' is required"),this.set("time signed",t)}setFudge(t){this.is16bitInt("TSIG","fudge",t),this.set("fudge",t)}setMac(t){this.set("mac",t??"")}setOriginalId(t){this.is16bitInt("TSIG","original id",t),this.set("original id",t)}setError(t){this.is16bitInt("TSIG","error",t),this.set("error",t)}setOther(t){this.set("other",t??"")}fromBind({bindline:t}){const e=t.trimEnd().split(" "),[s,i,n,a,o,r,c,,h,p,d]=e;return new J({owner:s,ttl:parseInt(i,10),class:n,type:a.toUpperCase(),"algorithm name":o,"time signed":parseInt(r,10),fudge:parseInt(c,10),mac:h||"","original id":parseInt(p,10),error:parseInt(d,10),other:""})}fromTinydns({tinyline:t}){const[e,s,i,n,a,o]=t.slice(1).split(":"),r=U(i),c=r[2],h=Uint8Array.from(x(i),C=>C.charCodeAt(0)),p=new DataView(h.buffer,h.byteOffset,h.byteLength);let d=c;const g=p.getUint32(d);d+=4;const y=p.getUint16(d);d+=2;const m=p.getUint16(d);d+=2;const b=m>0?R(h.subarray(d,d+m)):"";d+=m;const w=p.getUint16(d);d+=2;const T=p.getUint16(d);d+=2;const D=d0?R(i.subarray(r,r+p)):"";r+=p;const g=o.getUint16(r);r+=2;const y=o.getUint16(r);r+=2;const m=r0?e.length:"",i=this.get("other")??"",n=i.length>0?i.length:0;return[this.getFQDN("owner",t),this.get("ttl"),this.get("class"),this.get("type"),this.get("algorithm name"),this.get("time signed"),this.get("fudge"),s,e,this.get("original id"),this.get("error"),n].join(" ")+` -`}getWireRdata(){const t=W(this.get("algorithm name")||""),e=this.get("mac")??"",s=e.length>0?F(e):new Uint8Array,i=this.get("other")??"",n=i.length>0?new TextEncoder().encode(i):new Uint8Array,a=new Uint8Array(t.length+4+2+2+s.length+2+2+n.length),o=new DataView(a.buffer,a.byteOffset);let r=0;return a.set(t,r),r+=t.length,o.setUint32(r,this.get("time signed")??0),r+=4,o.setUint16(r,this.get("fudge")??0),r+=2,o.setUint16(r,s.length),r+=2,s.length>0&&(a.set(s,r),r+=s.length),o.setUint16(r,this.get("original id")??0),r+=2,o.setUint16(r,this.get("error")??0),r+=2,n.length>0&&a.set(n,r),a}toTinydns(){const t=this.get("algorithm name")||"",e=this.get("mac")??"",s=e.length>0?e.length/2:0;return this.getTinydnsGeneric(N(t)+P(this.get("time signed")??0)+A(this.get("fudge"))+A(s)+(s>0?O(e):"")+A(this.get("original id")??0)+A(this.get("error")??0)+(this.get("other").length>0?I(new RegExp(/[\r\n\t:\\/]/,"g"),this.get("other")):""))}}class Et extends f{static typeName="URI";static typeId=256;static RFCs=[7553];static rdataFields=[["priority","u16"],["weight","u16"],["target","qstr"]];constructor(t){super(t)}setPriority(t){this.is16bitInt("URI","priority",t),this.set("priority",t)}setWeight(t){this.is16bitInt("URI","weight",t),this.set("weight",t)}setTarget(t){t||this.throwHelp("URI: target is required"),this.set("target",t)}fromTinydns({tinyline:t}){const[e,s,i,n,a,o]=t.slice(1).split(":");return s!=256&&this.throwHelp("URI fromTinydns, invalid n"),new Et({type:"URI",owner:this.fullyQualify(e),priority:B(i.slice(0,8)),weight:B(i.slice(8,16)),target:x(i.slice(16)),ttl:parseInt(n,10),timestamp:a,location:o?.trim()??""})}getDescription(){return"URI"}getCanonical(){return{owner:"www.example.com.",ttl:3600,class:"IN",type:"URI",priority:10,weight:10,target:"http://www.example.com/"}}getWireRdata(){const t=new TextEncoder().encode(this.get("target")),e=new Uint8Array(4+t.length),s=new DataView(e.buffer);return s.setUint16(0,this.get("priority")),s.setUint16(2,this.get("weight")),e.set(t,4),e}toTinydns(){const t=new RegExp(/[\r\n\t:\\/]/,"g");let e="";for(const s of["priority","weight"])e+=A(this.get(s));return e+=I(t,this.get("target")),this.getTinydnsGeneric(e)}}const zt={echo:7,discard:9,systat:11,daytime:13,netstat:15,ftp_data:20,ftp:21,ssh:22,telnet:23,smtp:25,time:37,rlp:39,nameserver:42,nicname:43,domain:53,mtp:57,bootps:67,bootpc:68,tftp:69,gopher:70,rje:77,finger:79,http:80,link:87,supdup:95,hostnames:101,iso_tsap:102,csnet_ns:105,pop_2:109,pop3:110,sunrpc:111,auth:113,sftp:115,uucp_path:117,nntp:119,ntp:123,netbios_ns:137,netbios_dgm:138,netbios_ssn:139,imap:143,sql_net:150,snmp:161,snmp_trap:162,cmip_man:163,cmip_agent:164,xdmcp:177,nextstep:178,bgp:179,prospero:191,irc:194,smux:199,at_rtmp:201,at_nbp:202,at_echo:204,at_zis:206,qmtp:209,z3950:210,ipx:213,imap3:220,ulistproc:372,https:443,snpp:444,microsoft_ds:445,kpasswd:464,urd:465,saft:487,isakmp:500,exec:512,biff:512,login:513,who:513,cmd:514,syslog:514,printer:515,talk:517,ntalk:518,route:520,timed:525,tempo:526,courier:530,netnews:532,netwall:533,uucp:540,remotefs:556,nntps:563,ldap:389};class Z extends f{static typeName="WKS";static typeId=11;static RFCs=[883,1035];static rdataFields=["address","protocol","bit map"];static tags=["obsolete"];constructor(t){super(t)}setAddress(t){t||this.throwHelp("WKS: address is required"),this.isIPv4(t)||this.throwHelp("WKS address must be IPv4"),this.set("address",t)}setProtocol(t){t||this.throwHelp("WKS: protocol is required");const e=typeof t=="string"?t.toUpperCase():t;["TCP","UDP",6,17].includes(e)||this.throwHelp("WKS protocol must be TCP or UDP"),this.set("protocol",e)}setBitMap(t){this.set("bit map",t??"")}getDescription(){return"Well Known Service"}getCanonical(){return{owner:"host.example.com.",ttl:3600,class:"IN",type:"WKS",address:"192.0.2.1",protocol:"TCP","bit map":"ftp smtp"}}fromBind({bindline:t}){const e=t.split(/\s+/),[s,i,n,a,o,r]=e;return new Z({owner:s,ttl:parseInt(i,10),class:n,type:a,address:o,protocol:r,"bit map":e.slice(6).join(" ").trim()})}fromTinydns({tinyline:t}){const[e,s,i,n,a,o]=t.slice(1).split(":"),r=Uint8Array.from(x(i),y=>y.charCodeAt(0)),c=[r[0],r[1],r[2],r[3]].join("."),h=r[4],d={6:"TCP",17:"UDP"}[h]??h,g=new TextDecoder().decode(r.subarray(5));return new Z({owner:this.fullyQualify(e),ttl:parseInt(n,10),type:"WKS",address:c,protocol:d,"bit map":g,timestamp:a,location:o?.trim()??""})}fromWire({owner:t,cls:e,ttl:s,rdata:i}){const n=[...i.subarray(0,4)].join("."),a=i[4],r={6:"TCP",17:"UDP"}[a]??String(a),c=Object.fromEntries(Object.entries(zt).map(([d,g])=>[g,d])),h=i.subarray(5),p=[];for(let d=0;d>g){const y=d*8+g;p.push(c[y]??String(y))}return new Z({owner:t,ttl:s,class:e,type:"WKS",address:n,protocol:r,"bit map":p.join(" ")})}toTinydns(){const t=new RegExp(/[\r\n\t:\\/]/,"g"),s={TCP:6,UDP:17,6:6,17:17}[this.get("protocol")];return this.getTinydnsGeneric(qt(this.get("address"))+u(s)+I(t,this.get("bit map")))}getWireRdata(){const t={TCP:6,UDP:17,6:6,17:17},e=this.get("address").split(".").map(Number),s=t[this.get("protocol")],i=this.get("bit map").trim().split(/\s+/).map(c=>/^\d+$/.test(c)?parseInt(c,10):zt[c.toLowerCase()]).filter(c=>c!==void 0);if(i.length===0)return new Uint8Array([...e,s]);const n=Math.max(...i),a=Math.floor(n/8)+1,o=new Uint8Array(a);for(const c of i)o[Math.floor(c/8)]|=128>>c%8;const r=new Uint8Array(5+a);return r.set(e),r[4]=s,r.set(o,5),r}}const Ht={},xe=[Gt,yt,j,ft,$,Vt,mt,wt,et,st,jt,K,it,Q,nt,bt,Y,Tt,rt,At,X,z,at,v,ot,Qt,It,ct,lt,ht,Nt,St,xt,Ct,pt,dt,J,$t,Et,Z];for(const l of xe){const t=l.getTypeId();Ht[t]=l.typeName,Ht[l.typeName]=t}export{Gt as A,yt as AAAA,j as APL,ft as CAA,$ as CERT,Vt as CNAME,mt as DHCID,wt as DNAME,et as DNSKEY,st as DS,jt as HINFO,K as HIP,it as HTTPS,Q as IPSECKEY,nt as KEY,bt as KX,Y as LOC,Tt as MX,rt as NAPTR,At as NS,X as NSEC,z as NSEC3,at as NSEC3PARAM,v as NXT,ot as OPENPGPKEY,Qt as PTR,It as RP,ct as RRSIG,lt as SIG,ht as SMIMEA,St as SOA,xt as SPF,Ct as SRV,Nt as SSHFP,pt as SVCB,dt as TLSA,J as TSIG,$t as TXT,Et as URI,Z as WKS,f as default,Ht as typeMap}; +`}getWireRdata(){const t=this.get("data");if(Array.isArray(t)){const e=new TextEncoder,s=t.map((o,r)=>(e.encode(o).length>255&&this.throwHelp(`TXT: array element ${r} exceeds 255 bytes; split it yourself or pass a single string to auto-chunk`),zt(o))),i=s.reduce((o,r)=>o+r.length,0),n=new Uint8Array(i);let a=0;for(const o of s)n.set(o,a),a+=o.length;return n}return zt(t)}toTinydns(){let t=this.get("data");Array.isArray(t)&&(t=t.join(""));const e=I(new RegExp(/[\r\n\t:\\/]/,"g"),t);return`'${this.getTinyFQDN("owner")}:${e}:${this.getTinydnsPostamble()} +`}}function Yt(l){const t=new TextEncoder;return Array.isArray(l)?l.some(s=>t.encode(s).length>255)?Xt(l.join(""),255).join('" "'):l.join('" "'):t.encode(l).length<=255?l:Xt(l,255).join('" "')}function Xt(l,t){const e=new TextEncoder().encode(l),s=new TextDecoder,i=[];let n=0;for(;n\S+)\s+(?\d{1,10})\s+(?IN)\s+(?TLSA)\s+(?\d+)\s+(?\d+)\s+(?\d+)\s+(?\S.*)$/i,s=t.trim().match(e);s||this.throwHelp(`unable to parse TLSA: ${t}`);const{owner:i,ttl:n,cls:a,type:o,usage:r,selector:c,matchtype:p,cad:h}=s.groups;return new dt({owner:this.fullyQualify(i),ttl:parseInt(n,10),class:a.toUpperCase(),type:o.toUpperCase(),"certificate usage":parseInt(r,10),selector:parseInt(c,10),"matching type":parseInt(p,10),"certificate association data":h.trim()})}fromTinydns({tinyline:t}){const{owner:e,typeId:s,rdata:i,ttl:n,timestamp:a,location:o}=this.parseTinydnsLine(t);s!=this.getTypeId()&&this.throwHelp("TLSA fromTinydns, invalid n");const r=k(i);return new dt({owner:e,ttl:n,type:"TLSA","certificate usage":r[0],selector:r[1],"matching type":r[2],"certificate association data":R(r.subarray(3)),timestamp:a,location:o})}toTinydns(){return this.getTinydnsGeneric(y(this.get("certificate usage"))+y(this.get("selector"))+y(this.get("matching type"))+O(this.get("certificate association data").replace(/[\s()]/g,"")))}getWireRdata(){const t=F(this.get("certificate association data").replace(/[\s()]/g,"")),e=new Uint8Array(3+t.length);return e[0]=this.get("certificate usage"),e[1]=this.get("selector"),e[2]=this.get("matching type"),e.set(t,3),e}}class J extends f{static typeName="TSIG";static typeId=250;static RFCs=[2845,8945];static rdataFields=["algorithm name","time signed","fudge","mac","original id","error","other"];constructor(t){super(t)}getDescription(){return"Transaction Signature"}getCanonical(){return{owner:"test.example.",ttl:0,class:"ANY",type:"TSIG","algorithm name":"hmac-sha256.","time signed":162065e4,fudge:300,mac:"ABCDEF...","original id":12345,error:0,other:""}}setClass(t){t!=="ANY"&&this.throwHelp("TSIG: Class is required to be ANY"),this.set("class",t)}setTtl(t){t!==0&&this.throwHelp("TSIG: TTL is required to be 0"),this.set("ttl",t)}setAlgorithmName(t){t||this.throwHelp("TSIG: 'algorithm name' is required"),this.set("algorithm name",t)}setTimeSigned(t){t===void 0&&this.throwHelp("TSIG: 'time signed' is required"),this.set("time signed",t)}setFudge(t){this.is16bitInt("TSIG","fudge",t),this.set("fudge",t)}setMac(t){this.set("mac",t??"")}setOriginalId(t){this.is16bitInt("TSIG","original id",t),this.set("original id",t)}setError(t){this.is16bitInt("TSIG","error",t),this.set("error",t)}setOther(t){this.set("other",t??"")}fromBind({bindline:t}){const e=t.trimEnd().split(" "),[s,i,n,a,o,r,c,,p,h,d]=e;return new J({owner:s,ttl:parseInt(i,10),class:n,type:a.toUpperCase(),"algorithm name":o,"time signed":parseInt(r,10),fudge:parseInt(c,10),mac:p||"","original id":parseInt(h,10),error:parseInt(d,10),other:""})}fromTinydns({tinyline:t}){const[e,s,i,n,a,o]=t.slice(1).split(":"),r=U(i),c=r[2],p=Uint8Array.from(x(i),C=>C.charCodeAt(0)),h=new DataView(p.buffer,p.byteOffset,p.byteLength);let d=c;const g=h.getUint32(d);d+=4;const u=h.getUint16(d);d+=2;const m=h.getUint16(d);d+=2;const b=m>0?R(p.subarray(d,d+m)):"";d+=m;const w=h.getUint16(d);d+=2;const T=h.getUint16(d);d+=2;const D=d0?R(i.subarray(r,r+h)):"";r+=h;const g=o.getUint16(r);r+=2;const u=o.getUint16(r);r+=2;const m=r0?e.length:"",i=this.get("other")??"",n=i.length>0?i.length:0;return[this.getFQDN("owner",t),this.get("ttl"),this.get("class"),this.get("type"),this.get("algorithm name"),this.get("time signed"),this.get("fudge"),s,e,this.get("original id"),this.get("error"),n].join(" ")+` +`}getWireRdata(){const t=V(this.get("algorithm name")||""),e=this.get("mac")??"",s=e.length>0?F(e):new Uint8Array,i=this.get("other")??"",n=i.length>0?new TextEncoder().encode(i):new Uint8Array,a=new Uint8Array(t.length+4+2+2+s.length+2+2+n.length),o=new DataView(a.buffer,a.byteOffset);let r=0;return a.set(t,r),r+=t.length,o.setUint32(r,this.get("time signed")??0),r+=4,o.setUint16(r,this.get("fudge")??0),r+=2,o.setUint16(r,s.length),r+=2,s.length>0&&(a.set(s,r),r+=s.length),o.setUint16(r,this.get("original id")??0),r+=2,o.setUint16(r,this.get("error")??0),r+=2,n.length>0&&a.set(n,r),a}toTinydns(){const t=this.get("algorithm name")||"",e=this.get("mac")??"",s=e.length>0?e.length/2:0;return this.getTinydnsGeneric(N(t)+P(this.get("time signed")??0)+A(this.get("fudge"))+A(s)+(s>0?O(e):"")+A(this.get("original id")??0)+A(this.get("error")??0)+(this.get("other").length>0?I(new RegExp(/[\r\n\t:\\/]/,"g"),this.get("other")):""))}}class Et extends f{static typeName="URI";static typeId=256;static RFCs=[7553];static rdataFields=[["priority","u16"],["weight","u16"],["target","qstr"]];constructor(t){super(t)}setPriority(t){this.is16bitInt("URI","priority",t),this.set("priority",t)}setWeight(t){this.is16bitInt("URI","weight",t),this.set("weight",t)}setTarget(t){t||this.throwHelp("URI: target is required"),this.set("target",t)}fromTinydns({tinyline:t}){const[e,s,i,n,a,o]=t.slice(1).split(":");return s!=256&&this.throwHelp("URI fromTinydns, invalid n"),new Et({type:"URI",owner:this.fullyQualify(e),priority:B(i.slice(0,8)),weight:B(i.slice(8,16)),target:x(i.slice(16)),ttl:parseInt(n,10),timestamp:a,location:o?.trim()??""})}getDescription(){return"URI"}getCanonical(){return{owner:"www.example.com.",ttl:3600,class:"IN",type:"URI",priority:10,weight:10,target:"http://www.example.com/"}}getWireRdata(){const t=new TextEncoder().encode(this.get("target")),e=new Uint8Array(4+t.length),s=new DataView(e.buffer);return s.setUint16(0,this.get("priority")),s.setUint16(2,this.get("weight")),e.set(t,4),e}toTinydns(){const t=new RegExp(/[\r\n\t:\\/]/,"g");let e="";for(const s of["priority","weight"])e+=A(this.get(s));return e+=I(t,this.get("target")),this.getTinydnsGeneric(e)}}const vt={echo:7,discard:9,systat:11,daytime:13,netstat:15,ftp_data:20,ftp:21,ssh:22,telnet:23,smtp:25,time:37,rlp:39,nameserver:42,nicname:43,domain:53,mtp:57,bootps:67,bootpc:68,tftp:69,gopher:70,rje:77,finger:79,http:80,link:87,supdup:95,hostnames:101,iso_tsap:102,csnet_ns:105,pop_2:109,pop3:110,sunrpc:111,auth:113,sftp:115,uucp_path:117,nntp:119,ntp:123,netbios_ns:137,netbios_dgm:138,netbios_ssn:139,imap:143,sql_net:150,snmp:161,snmp_trap:162,cmip_man:163,cmip_agent:164,xdmcp:177,nextstep:178,bgp:179,prospero:191,irc:194,smux:199,at_rtmp:201,at_nbp:202,at_echo:204,at_zis:206,qmtp:209,z3950:210,ipx:213,imap3:220,ulistproc:372,https:443,snpp:444,microsoft_ds:445,kpasswd:464,urd:465,saft:487,isakmp:500,exec:512,biff:512,login:513,who:513,cmd:514,syslog:514,printer:515,talk:517,ntalk:518,route:520,timed:525,tempo:526,courier:530,netnews:532,netwall:533,uucp:540,remotefs:556,nntps:563,ldap:389};class Z extends f{static typeName="WKS";static typeId=11;static RFCs=[883,1035];static rdataFields=["address","protocol","bit map"];static tags=["obsolete"];constructor(t){super(t)}setAddress(t){t||this.throwHelp("WKS: address is required"),this.isIPv4(t)||this.throwHelp("WKS address must be IPv4"),this.set("address",t)}setProtocol(t){t||this.throwHelp("WKS: protocol is required");const e=typeof t=="string"?t.toUpperCase():t;["TCP","UDP",6,17].includes(e)||this.throwHelp("WKS protocol must be TCP or UDP"),this.set("protocol",e)}setBitMap(t){this.set("bit map",t??"")}getDescription(){return"Well Known Service"}getCanonical(){return{owner:"host.example.com.",ttl:3600,class:"IN",type:"WKS",address:"192.0.2.1",protocol:"TCP","bit map":"ftp smtp"}}fromBind({bindline:t}){const e=t.split(/\s+/),[s,i,n,a,o,r]=e;return new Z({owner:s,ttl:parseInt(i,10),class:n,type:a,address:o,protocol:r,"bit map":e.slice(6).join(" ").trim()})}fromTinydns({tinyline:t}){const[e,s,i,n,a,o]=t.slice(1).split(":"),r=Uint8Array.from(x(i),u=>u.charCodeAt(0)),c=[r[0],r[1],r[2],r[3]].join("."),p=r[4],d={6:"TCP",17:"UDP"}[p]??p,g=new TextDecoder().decode(r.subarray(5));return new Z({owner:this.fullyQualify(e),ttl:parseInt(n,10),type:"WKS",address:c,protocol:d,"bit map":g,timestamp:a,location:o?.trim()??""})}fromWire({owner:t,cls:e,ttl:s,rdata:i}){const n=[...i.subarray(0,4)].join("."),a=i[4],r={6:"TCP",17:"UDP"}[a]??String(a),c=Object.fromEntries(Object.entries(vt).map(([d,g])=>[g,d])),p=i.subarray(5),h=[];for(let d=0;d>g){const u=d*8+g;h.push(c[u]??String(u))}return new Z({owner:t,ttl:s,class:e,type:"WKS",address:n,protocol:r,"bit map":h.join(" ")})}toTinydns(){const t=new RegExp(/[\r\n\t:\\/]/,"g"),s={TCP:6,UDP:17,6:6,17:17}[this.get("protocol")];return this.getTinydnsGeneric(qt(this.get("address"))+y(s)+I(t,this.get("bit map")))}getWireRdata(){const t={TCP:6,UDP:17,6:6,17:17},e=this.get("address").split(".").map(Number),s=t[this.get("protocol")],i=this.get("bit map").trim().split(/\s+/).map(c=>/^\d+$/.test(c)?parseInt(c,10):vt[c.toLowerCase()]).filter(c=>c!==void 0);if(i.length===0)return new Uint8Array([...e,s]);const n=Math.max(...i),a=Math.floor(n/8)+1,o=new Uint8Array(a);for(const c of i)o[Math.floor(c/8)]|=128>>c%8;const r=new Uint8Array(5+a);return r.set(e),r[4]=s,r.set(o,5),r}}const kt={},xe=[Wt,yt,K,ft,H,Gt,mt,wt,et,st,Kt,j,it,Q,nt,bt,Y,Tt,rt,At,X,z,at,v,ot,Qt,It,ct,lt,ht,Nt,St,xt,Ct,pt,dt,J,Ht,Et,Z];for(const l of xe){const t=l.getTypeId();kt[t]=l.typeName,kt[l.typeName]=t}export{Wt as A,yt as AAAA,K as APL,ft as CAA,H as CERT,Gt as CNAME,mt as DHCID,wt as DNAME,et as DNSKEY,st as DS,Kt as HINFO,j as HIP,it as HTTPS,Q as IPSECKEY,nt as KEY,bt as KX,Y as LOC,Tt as MX,rt as NAPTR,At as NS,X as NSEC,z as NSEC3,at as NSEC3PARAM,v as NXT,ot as OPENPGPKEY,Qt as PTR,It as RP,ct as RRSIG,lt as SIG,ht as SMIMEA,St as SOA,xt as SPF,Ct as SRV,Nt as SSHFP,pt as SVCB,dt as TLSA,J as TSIG,Ht as TXT,Et as URI,Z as WKS,f as default,kt as typeMap}; //# sourceMappingURL=dns-rr.min.js.map diff --git a/dist/dns-rr.min.js.map b/dist/dns-rr.min.js.map index ecf2b10..a79bbbb 100644 --- a/dist/dns-rr.min.js.map +++ b/dist/dns-rr.min.js.map @@ -1,7 +1,7 @@ { "version": 3, "sources": ["dns-rr.js"], - "sourcesContent": ["const octalRe = new RegExp(/\\\\(?:[1-7][0-7]{0,2}|[0-7]{2,3})/, 'g');\nconst textDecoder = new TextDecoder();\n\nfunction parseFields(tinyline, rdataCount) {\n const parts = tinyline.slice(1).split(':');\n const owner = parts[0];\n const rdata = parts.slice(1, 1 + rdataCount);\n const [ttl, timestamp, location] = parts.slice(1 + rdataCount);\n return { owner, rdata, ttl, timestamp, location: location?.trim() ?? '' }\n}\n\nfunction parseGenericLine(tinyline) {\n // Generic form: :owner:typeId:rdata:ttl:timestamp:location\n const [owner, typeId, rdata, ttl, timestamp, location] = tinyline.slice(1).split(':');\n return { owner, typeId, rdata, ttl: parseInt(ttl, 10), timestamp, location: location?.trim() ?? '' }\n}\n\nfunction octalRdataToBytes(rdata) {\n return Uint8Array.from(octalToChar(rdata), (c) => c.charCodeAt(0))\n}\n\nfunction parseSvcbLikeRdata(rdata, recordType) {\n if (rdata.length < 6) {\n throw new Error(`${recordType}: RDATA too short: ${rdata}`)\n }\n\n const binary = octalRdataToBytes(rdata);\n const priority = (binary[0] << 8) | binary[1];\n\n let pos = 2;\n const labels = [];\n while (true) {\n const len = binary[pos];\n pos += 1;\n if (len === 0) break\n labels.push(textDecoder.decode(binary.subarray(pos, pos + len)));\n pos += len;\n }\n\n return {\n priority,\n targetName: `${labels.join('.')}.`,\n params: textDecoder.decode(binary.subarray(pos)),\n }\n}\n\nfunction to(rrInstance) {\n if (rrInstance.constructor.tinydnsType) {\n const fields = rrInstance.getFields('rdata');\n const rdata = fields\n .map((f) => {\n if (rrInstance.isFqdnField(f)) return rrInstance.getTinyFQDN(f)\n return rrInstance.get(f)\n })\n .join(':');\n return `${rrInstance.constructor.tinydnsType}${rrInstance.getTinyFQDN('owner')}:${rdata}:${rrInstance.getTinydnsPostamble()}\\n`\n }\n return rrInstance.getTinydnsGeneric(bytesToOctalString(rrInstance.getWireRdata()))\n}\n\nfunction fromGeneric(rrInstance, { tinyline }) {\n const fields = rrInstance.getFields('rdata');\n const { owner, rdata, ttl, timestamp, location } = parseFields(tinyline, fields.length);\n\n const result = {\n owner: rrInstance.fullyQualify(owner),\n type: rrInstance.constructor.typeName,\n ttl: parseInt(ttl, 10),\n timestamp: timestamp,\n location: location,\n };\n\n for (let i = 0; i < fields.length; i++) {\n const val = rdata[i];\n result[fields[i]] = rrInstance.isFqdnField(fields[i]) ? rrInstance.fullyQualify(val) : val;\n }\n\n return new rrInstance.constructor(result)\n}\n\nfunction escapeOctal(re, str) {\n let escaped = '';\n str.split(/(.{1})/g).map((c) => {\n escaped += re.test(c) ? charToOctal(c) : c;\n });\n return escaped\n}\n\nfunction octalToChar(str) {\n // relace instances of \\NNN with ASCII\n return str.replace(octalRe, (o) => String.fromCharCode(parseInt(o.slice(1), 8)))\n}\n\nfunction octalToHex(str) {\n // relace instances of \\NNN with Hex\n return str.replace(octalRe, (o) => {\n // parseInt(n, 8) -> from octal to decimal\n // .toString(16) -> decimal to hex\n return parseInt(o.slice(1), 8).toString(16).padStart(2, 0)\n })\n}\n\nfunction octalToUInt8(str) {\n return parseInt(str.slice(1, 4), 8) & 0xff\n}\n\nfunction octalToUInt16(str) {\n return (parseInt(str.slice(1, 4), 8) << 8) | parseInt(str.slice(5, 8), 8)\n}\n\nfunction octalToUInt32(str) {\n const b0 = parseInt(str.slice(1, 4), 8);\n const b1 = parseInt(str.slice(5, 8), 8);\n const b2 = parseInt(str.slice(9, 12), 8);\n const b3 = parseInt(str.slice(13, 16), 8);\n return ((b0 << 24) | (b1 << 16) | (b2 << 8) | b3) >>> 0\n}\n\nfunction packString(str) {\n return str\n .match(/(.{1,255})/g)\n .map((s) => `${UInt8toOctal(s.length)}${s}`)\n .join('')\n}\n\nfunction unpackString(str) {\n const asBuf = Uint8Array.from(octalToChar(str.toString()), (c) => c.charCodeAt(0));\n const dec = new TextDecoder();\n const res = [];\n let pos = 0;\n let len;\n while ((len = asBuf[pos])) {\n // encoded length byte\n pos++;\n res.push(dec.decode(asBuf.subarray(pos, pos + len)));\n pos = +(pos + len);\n if (pos >= asBuf.length) break\n }\n return res\n}\n\nfunction packDomainName(fqdn) {\n const labelRegEx = new RegExp(/[^A-Za-z0-9-.]/, 'g');\n\n // RFC 1035, 3.3 Standard RRs\n // The standard wire format for DNS names. (1 octet length + octets)\n let packed = '';\n fqdn.split('.').forEach((label) => {\n if (label === undefined || !label.length) return\n\n packed += UInt8toOctal(label.length);\n\n packed += escapeOctal(labelRegEx, label);\n });\n packed += '\\\\000'; // terminates with a zero length label\n return packed\n}\n\nfunction unpackDomainName(escaped) {\n let pos = 0;\n let binaryLen = 0;\n const labels = [];\n\n // consume the next logical \"byte\" (char or octal escape)\n const getNextByte = () => {\n if (pos >= escaped.length) return null\n\n let value;\n if (escaped[pos] === '\\\\') {\n value = parseInt(escaped.slice(pos + 1, pos + 4), 8);\n pos += 4;\n } else {\n value = escaped.charCodeAt(pos++);\n }\n\n binaryLen++;\n return value\n };\n\n let lengthByte;\n while ((lengthByte = getNextByte()) && lengthByte !== 0) {\n let label = '';\n for (let i = 0; i < lengthByte; i++) {\n const char = getNextByte();\n if (char === null) break\n label += String.fromCharCode(char);\n }\n labels.push(label);\n }\n\n return [`${labels.join('.')}.`, pos, binaryLen]\n}\n\nfunction packHex(str) {\n let r = '';\n for (let i = 0; i < str.length; i = i + 2) {\n // nibble off 2 hex bytes, encode to octal\n r += UInt8toOctal(parseInt(str.slice(i, i + 2), 16));\n }\n return r\n}\n\nfunction charToOctal(c) {\n if (typeof c === 'number') return UInt8toOctal(c)\n\n return UInt8toOctal(c.charCodeAt(0))\n}\n\nfunction UInt8toOctal(n) {\n if (n > 255) {\n throw new Error(\n `UInt8toOctal: value ${n} exceeds 255 \u2014 tinydns encoders require Latin-1/byte input (code points <= 0xFF)`,\n )\n }\n\n return `\\\\${parseInt(n, 10).toString(8).padStart(3, 0)}`\n}\n\nfunction UInt16toOctal(n) {\n return UInt8toOctal((n >>> 8) & 0xff) + UInt8toOctal(n & 0xff)\n}\n\nfunction UInt32toOctal(n) {\n return (\n UInt8toOctal((n >>> 24) & 0xff) +\n UInt8toOctal((n >>> 16) & 0xff) +\n UInt8toOctal((n >>> 8) & 0xff) +\n UInt8toOctal(n & 0xff)\n )\n}\n\nfunction ipv4toOctal(ip) {\n return UInt32toOctal(ip.split`.`.reduce((int, value) => int * 256 + +value))\n}\n\nfunction octalToIPv4(str) {\n const asInt = octalToUInt32(str);\n return [24, 16, 8, 0].map((n) => (asInt >> n) & 0xff).join('.')\n}\n\nfunction expandIPv6(val, delimiter = ':') {\n const colons = val.match(/:/g);\n if (colons?.length < 7) {\n val = val.replace(/::/, ':'.repeat(9 - colons.length));\n }\n return val\n .split(':')\n .map((s) => s.padStart(4, '0'))\n .join(delimiter)\n .toLowerCase()\n}\n\nfunction ipv6toOctal(ip) {\n return packHex(expandIPv6(ip, ''))\n}\n\nfunction octalToIPv6(str) {\n return octalToHex(str)\n .match(/(.{4})/g)\n .join(':')\n}\n\nfunction base64toOctal(str) {\n const binary = atob(str);\n let escaped = '';\n for (let i = 0; i < binary.length; i++) {\n const b = binary.charCodeAt(i);\n escaped += /[A-Za-z0-9\\-.]/.test(binary[i]) ? binary[i] : UInt8toOctal(b);\n }\n return escaped\n}\n\nfunction octalToBase64(str) {\n return btoa(octalToChar(str))\n}\n\nfunction bytesToOctalString(bytes) {\n let result = '';\n for (const b of bytes) result += UInt8toOctal(b);\n return result\n}\n\nfunction hexToBytes(hex) {\n return Uint8Array.from({ length: hex.length / 2 }, (_, i) => parseInt(hex.slice(i * 2, i * 2 + 2), 16))\n}\n\nfunction bytesToHex(bytes) {\n return [...bytes].map((b) => b.toString(16).padStart(2, '0')).join('')\n}\n\nfunction bytesToBase64(bytes) {\n return btoa([...bytes].map((b) => String.fromCharCode(b)).join(''))\n}\n\nfunction base64ToBytes(b64) {\n return Uint8Array.from(atob(b64), (c) => c.charCodeAt(0))\n}\n\n// DNS type name \u2192 numeric type ID mapping (subset covering known RR types)\nconst DNS_TYPE_IDS = {\n A: 1,\n NS: 2,\n MD: 3,\n MF: 4,\n CNAME: 5,\n SOA: 6,\n MB: 7,\n MG: 8,\n MR: 9,\n NULL: 10,\n WKS: 11,\n PTR: 12,\n HINFO: 13,\n MINFO: 14,\n MX: 15,\n TXT: 16,\n RP: 17,\n AFSDB: 18,\n X25: 19,\n ISDN: 20,\n RT: 21,\n NSAP: 22,\n NSAP_PTR: 23,\n SIG: 24,\n KEY: 25,\n PX: 26,\n GPOS: 27,\n AAAA: 28,\n LOC: 29,\n NXT: 30,\n EID: 31,\n NIMLOC: 32,\n SRV: 33,\n ATMA: 34,\n NAPTR: 35,\n KX: 36,\n CERT: 37,\n A6: 38,\n DNAME: 39,\n SINK: 40,\n OPT: 41,\n APL: 42,\n DS: 43,\n SSHFP: 44,\n IPSECKEY: 45,\n RRSIG: 46,\n NSEC: 47,\n DNSKEY: 48,\n DHCID: 49,\n NSEC3: 50,\n NSEC3PARAM: 51,\n TLSA: 52,\n SMIMEA: 53,\n HIP: 55,\n NINFO: 56,\n RKEY: 57,\n TALINK: 58,\n CDS: 59,\n CDNSKEY: 60,\n OPENPGPKEY: 61,\n CSYNC: 62,\n ZONEMD: 63,\n SVCB: 64,\n HTTPS: 65,\n SPF: 99,\n UINFO: 100,\n UID: 101,\n GID: 102,\n UNSPEC: 103,\n NID: 104,\n L32: 105,\n L64: 106,\n LP: 107,\n EUI48: 108,\n EUI64: 109,\n TKEY: 249,\n TSIG: 250,\n IXFR: 251,\n AXFR: 252,\n MAILB: 253,\n MAILA: 254,\n ANY: 255,\n URI: 256,\n CAA: 257,\n AVC: 258,\n DOA: 259,\n AMTRELAY: 260,\n TA: 32768,\n DLV: 32769,\n};\n\n// \u2500\u2500 Uncompressed domain name decoding \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Decode a length-prefixed (uncompressed) DNS name from a Uint8Array.\n * Returns { fqdn: string, end: number } where end is the offset after the name.\n */\nfunction wireUnpackDomain(bytes, offset = 0) {\n const labels = [];\n let pos = offset;\n while (pos < bytes.length) {\n const len = bytes[pos];\n if (len === 0) {\n pos++;\n break\n }\n labels.push(new TextDecoder().decode(bytes.subarray(pos + 1, pos + 1 + len)));\n pos += 1 + len;\n }\n return { fqdn: labels.length ? labels.join('.') + '.' : '.', end: pos }\n}\n\n/**\n * Pack a fully qualified domain name into wire format (Uint8Array).\n * Domain labels are prefixed with their length; the name ends with a zero byte.\n */\nfunction wirePackDomain(fqdn) {\n if (fqdn === '.') return new Uint8Array([0])\n const enc = new TextEncoder();\n const labels = fqdn\n .split('.')\n .filter((p) => p.length > 0)\n .map((p) => {\n const b = enc.encode(p);\n if (b.length > 63) throw new Error(`DNS label exceeds 63 bytes: ${p}`)\n return b\n });\n\n const buf = new Uint8Array(labels.reduce((n, b) => n + b.length + 1, 1));\n let offset = 0;\n for (const b of labels) {\n buf[offset++] = b.length;\n buf.set(b, offset);\n offset += b.length;\n }\n buf[offset] = 0;\n return buf\n}\n\n/**\n * Get wire format rdata for an RR instance.\n * Derived classes should override this with direct RFC 1035 wire encoding.\n * Fallback uses toTinydns() as an intermediate (less efficient but works for all types).\n */\nfunction getWireRdata(rrInstance) {\n const line = rrInstance.toTinydns();\n if (!line.startsWith(':')) {\n throw new Error(\n `${rrInstance.get('type')}: getWireRdata() not implemented. Override in rr/${rrInstance.get('type').toLowerCase()}.js`,\n )\n }\n // line: :fqdn:typeId:rdata:ttl:ts:loc\\n\n // Extract octal-encoded rdata and decode\n const rdata = line.split(':')[3];\n return rrInstance.octalToUint8Array(rdata ?? '')\n}\n\n/**\n * Serialize an RR instance to DNS wire format (RFC 1035).\n * Combines owner name, type, class, TTL, and rdata.\n */\nfunction toWire(rrInstance, RRClasses) {\n const rdata = rrInstance.getWireRdata();\n const owner = wirePackDomain(rrInstance.get('owner'));\n const result = new Uint8Array(owner.length + 10 + rdata.length);\n result.set(owner, 0);\n const meta = new DataView(result.buffer, owner.length, 10);\n meta.setUint16(0, rrInstance.getTypeId());\n meta.setUint16(2, RRClasses[rrInstance.get('class')] ?? 1);\n meta.setUint32(4, rrInstance.get('ttl'));\n meta.setUint16(8, rdata.length);\n result.set(rdata, owner.length + 10);\n return result\n}\n\n/**\n * Deserialize wire format bytes into an RR instance.\n * Static method wrapper for RR.fromWire().\n */\nfunction fromWireBytes(RRConstructor, wireBytes, wireUnpackFn) {\n const instance = new RRConstructor(null);\n const bytes = wireBytes instanceof Uint8Array ? wireBytes : new Uint8Array(wireBytes);\n const { fqdn: owner, end } = wireUnpackFn(bytes, 0);\n const view = new DataView(bytes.buffer, bytes.byteOffset);\n const classNum = view.getUint16(end + 2);\n const RRClasses = { IN: 1, CS: 2, CH: 3, HS: 4, NONE: 254, ANY: 255 };\n const cls = Object.keys(RRClasses).find((k) => RRClasses[k] === classNum) ?? 'IN';\n const ttl = view.getUint32(end + 4);\n const rdlen = view.getUint16(end + 8);\n const rdata = bytes.slice(end + 10, end + 10 + rdlen);\n return instance.fromWire({ owner, cls, ttl, rdata })\n}\n\n/**\n * Generic fromWire decoder driven by rdataFields type annotations.\n * Supports u8, u16, u32, fqdn, hex, base64, str, qstr, charstr, qcharstr, charstrs, svcparams, ipv4, ipv6.\n * See rr/TEMPLATE.js for descriptions and example type usage.\n * Last typed field consumes all remaining bytes.\n */\nfunction fromWireGeneric(rrInstance, { owner, cls, ttl, rdata }) {\n const result = { owner, ttl, class: cls, type: rrInstance.constructor.typeName };\n const rdataFields = rrInstance.constructor.rdataFields ?? [];\n const dv = new DataView(rdata.buffer, rdata.byteOffset);\n let pos = 0;\n\n for (let i = 0; i < rdataFields.length; i++) {\n const entry = rdataFields[i];\n const fieldName = Array.isArray(entry) ? entry[0] : entry;\n const fieldType = Array.isArray(entry) ? entry[1] : null;\n\n switch (fieldType) {\n case 'u8':\n result[fieldName] = rdata[pos++];\n break\n case 'u16':\n result[fieldName] = dv.getUint16(pos);\n pos += 2;\n break\n case 'certtype': {\n const certTypeNum = dv.getUint16(pos);\n const reverse = rrInstance.constructor.CERT_TYPES_REVERSE;\n result[fieldName] = reverse?.[certTypeNum] ?? certTypeNum;\n pos += 2;\n break\n }\n case 'u32':\n result[fieldName] = dv.getUint32(pos);\n pos += 4;\n break\n case 'fqdn': {\n const { fqdn, end } = wireUnpackDomain(rdata, pos);\n result[fieldName] = fqdn;\n pos = end;\n break\n }\n case 'hex':\n result[fieldName] = bytesToHex(rdata.subarray(pos)).toUpperCase();\n pos = rdata.length;\n break\n case 'base64':\n result[fieldName] = bytesToBase64(rdata.subarray(pos));\n pos = rdata.length;\n break\n case 'str':\n result[fieldName] = new TextDecoder().decode(rdata.subarray(pos));\n pos = rdata.length;\n break\n case 'qstr':\n result[fieldName] = new TextDecoder().decode(rdata.subarray(pos));\n pos = rdata.length;\n break\n case 'charstr': {\n const strLen = rdata[pos++];\n result[fieldName] = new TextDecoder().decode(rdata.subarray(pos, pos + strLen));\n pos += strLen;\n break\n }\n case 'qcharstr': {\n const strLen = rdata[pos++];\n result[fieldName] = new TextDecoder().decode(rdata.subarray(pos, pos + strLen));\n pos += strLen;\n break\n }\n case 'charstrs': {\n const parts = [];\n while (pos < rdata.length) {\n const strLen = rdata[pos++];\n parts.push(new TextDecoder().decode(rdata.subarray(pos, pos + strLen)));\n pos += strLen;\n }\n result[fieldName] = parts.join('');\n break\n }\n case 'svcparams':\n result[fieldName] = svcParamsFromWire(rdata.subarray(pos));\n pos = rdata.length;\n break\n case 'ipv4':\n result[fieldName] = [...rdata.subarray(pos, pos + 4)].join('.');\n pos += 4;\n break\n case 'ipv6': {\n const parts = [];\n for (let j = 0; j < 16; j += 2) {\n parts.push(\n dv\n .getUint16(pos + j)\n .toString(16)\n .padStart(4, '0'),\n );\n }\n result[fieldName] = parts.join(':');\n pos += 16;\n break\n }\n default:\n result[fieldName] = rdata[pos++];\n break\n }\n }\n\n return new rrInstance.constructor(result)\n}\n\n// \u2500\u2500 SVCB/HTTPS parameter encoding (RFC 9460) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst SVCPARAM_KEYS = {\n mandatory: 0,\n alpn: 1,\n 'no-default-alpn': 2,\n port: 3,\n ipv4hint: 4,\n ech: 5,\n ipv6hint: 6,\n};\n\n/**\n * Encode SVCB/HTTPS params string (e.g. 'alpn=\"h2,h3\" port=\"8443\"') to wire bytes.\n */\nfunction svcParamsToWire(paramsStr) {\n if (!paramsStr || !paramsStr.trim()) return new Uint8Array(0)\n\n const parts = [];\n // Match: key, key=unquoted, or key=\"quoted\" tokens\n const re = /([^\\s=]+)(?:=(?:\"([^\"]*)\"|(\\S*)))?(?=\\s|$)/g;\n let m;\n while ((m = re.exec(paramsStr.trim())) !== null) {\n const key = m[1].toLowerCase();\n const val = m[2] ?? m[3] ?? '';\n const keyId = SVCPARAM_KEYS[key];\n if (keyId === undefined) continue\n\n let valBytes;\n if (keyId === 1) {\n // alpn: comma-separated list, each entry length-prefixed\n const enc = new TextEncoder();\n const entries = val.split(',').map((e) => enc.encode(e.trim()));\n const total = entries.reduce((s, e) => s + 1 + e.length, 0);\n valBytes = new Uint8Array(total);\n let p = 0;\n for (const e of entries) {\n valBytes[p++] = e.length;\n valBytes.set(e, p);\n p += e.length;\n }\n } else if (keyId === 2) {\n // no-default-alpn: no value\n valBytes = new Uint8Array(0);\n } else if (keyId === 3) {\n // port: uint16\n valBytes = new Uint8Array(2);\n new DataView(valBytes.buffer).setUint16(0, parseInt(val, 10));\n } else if (keyId === 4) {\n // ipv4hint: one or more IPv4 addresses\n const addrs = val.split(',').map((a) => a.trim().split('.').map(Number));\n valBytes = new Uint8Array(addrs.length * 4);\n addrs.forEach((addr, i) => addr.forEach((b, j) => (valBytes[i * 4 + j] = b)));\n } else if (keyId === 5) {\n // ech: base64-encoded ECH config\n valBytes = base64ToBytes(val);\n } else if (keyId === 6) {\n // ipv6hint: one or more IPv6 addresses (expand compressed form before encoding)\n const addrs = val.split(',').map((a) => hexToBytes(expandIPv6(a.trim(), '')));\n valBytes = new Uint8Array(addrs.length * 16);\n addrs.forEach((addr, i) => valBytes.set(addr, i * 16));\n } else {\n valBytes = new TextEncoder().encode(val);\n }\n\n const param = new Uint8Array(4 + valBytes.length);\n new DataView(param.buffer).setUint16(0, keyId);\n new DataView(param.buffer).setUint16(2, valBytes.length);\n param.set(valBytes, 4);\n parts.push(param);\n }\n\n // Sort by key ID (SvcParams MUST be in ascending order per RFC 9460)\n parts.sort((a, b) => new DataView(a.buffer).getUint16(0) - new DataView(b.buffer).getUint16(0));\n\n const total = parts.reduce((s, p) => s + p.length, 0);\n const result = new Uint8Array(total);\n let pos = 0;\n for (const p of parts) {\n result.set(p, pos);\n pos += p.length;\n }\n return result\n}\n\nconst SVCPARAM_KEY_NAMES = {\n 0: 'mandatory',\n 1: 'alpn',\n 2: 'no-default-alpn',\n 3: 'port',\n 4: 'ipv4hint',\n 5: 'ech',\n 6: 'ipv6hint',\n};\n\n/**\n * Decode SVCB/HTTPS wire params bytes back to a human-readable params string.\n */\nfunction svcParamsFromWire(bytes) {\n if (!bytes || bytes.length === 0) return ''\n const parts = [];\n let pos = 0;\n while (pos + 4 <= bytes.length) {\n const dv = new DataView(bytes.buffer, bytes.byteOffset + pos);\n const keyId = dv.getUint16(0);\n const valLen = dv.getUint16(2);\n const val = bytes.subarray(pos + 4, pos + 4 + valLen);\n pos += 4 + valLen;\n\n const keyName = SVCPARAM_KEY_NAMES[keyId] ?? `key${keyId}`;\n if (keyId === 1) {\n // alpn: comma-separated length-prefixed entries\n const entries = [];\n let p = 0;\n while (p < val.length) {\n const len = val[p++];\n entries.push(new TextDecoder().decode(val.subarray(p, p + len)));\n p += len;\n }\n parts.push(`alpn=\"${entries.join(',')}\"`);\n } else if (keyId === 2) {\n parts.push('no-default-alpn');\n } else if (keyId === 3) {\n parts.push(`port=${new DataView(val.buffer, val.byteOffset).getUint16(0)}`);\n } else if (keyId === 4) {\n const addrs = [];\n for (let i = 0; i < val.length; i += 4) addrs.push([...val.subarray(i, i + 4)].join('.'));\n parts.push(`ipv4hint=${addrs.join(',')}`);\n } else if (keyId === 5) {\n parts.push(`ech=${btoa([...val].map((b) => String.fromCharCode(b)).join(''))}`);\n } else if (keyId === 6) {\n const addrs = [];\n for (let i = 0; i < val.length; i += 16) {\n const dv16 = new DataView(val.buffer, val.byteOffset + i);\n const groups = [];\n for (let j = 0; j < 16; j += 2) groups.push(dv16.getUint16(j).toString(16).padStart(4, '0'));\n addrs.push(groups.join(':'));\n }\n parts.push(`ipv6hint=${addrs.join(',')}`);\n } else {\n parts.push(`${keyName}=${[...val].map((b) => b.toString(16).padStart(2, '0')).join('')}`);\n }\n }\n return parts.join(' ')\n}\n\nfunction parseBindLine(line, RRClasses) {\n const res = {\n class: 'IN',\n type: '',\n rdata: [],\n };\n\n // 1. Strip comments (not inside quotes)\n let cleanLine = '';\n let inQuote = false;\n for (let i = 0; i < line.length; i++) {\n const c = line[i];\n if (c === '\"') inQuote = !inQuote;\n if (c === ';' && !inQuote) break\n cleanLine += c;\n }\n cleanLine = cleanLine.trim();\n if (!cleanLine) return null\n\n // 2. Tokenize, respecting quoted strings\n const tokens = cleanLine.match(/(\".*?\"|\\S+)/g) || [];\n if (tokens.length < 1) return null\n\n // 3. Owner handling\n if (!/^\\s/.test(line)) {\n res.owner = tokens.shift();\n }\n\n // 4. Extract TTL, Class, and Type\n while (tokens.length > 0) {\n const token = tokens[0].toUpperCase();\n\n if (RRClasses[token]) {\n res.class = tokens.shift().toUpperCase();\n continue\n }\n\n if (/^\\d+$/.test(token)) {\n res.ttl = parseInt(tokens.shift(), 10);\n continue\n }\n\n // If it's not a Class or TTL, it must be the RR Type (A, MX, etc.)\n res.type = tokens.shift().toUpperCase();\n break\n }\n\n // 5. Remaining tokens are RDATA\n res.rdata = tokens;\n\n return res\n}\n\nfunction fromBind(rrInstance, opts) {\n const { owner, ttl, cls, rdata } = opts;\n const result = {\n owner,\n ttl,\n class: cls,\n type: rrInstance.constructor.typeName,\n };\n\n const fields = rrInstance.getFields('rdata');\n for (let i = 0; i < fields.length; i++) {\n const isLastField = i === fields.length - 1;\n if (isLastField && rrInstance.isQuotedField(fields[i])) {\n // Collect all remaining tokens for TXT/etc\n const val = rdata\n .slice(i)\n .map((s) => s.replace(/^\"|\"$/g, ''))\n .join('');\n result[fields[i]] = val;\n break\n }\n\n let val = rdata[i];\n if (rrInstance.isQuotedField(fields[i])) {\n val = val?.replace(/^\"|\"$/g, '');\n } else if (/^\\d+$/.test(val)) {\n val = parseInt(val, 10);\n }\n result[fields[i]] = val;\n }\n\n return new rrInstance.constructor(result)\n}\n\nfunction toBind(rrInstance, zone_opts) {\n const fields = rrInstance.getFields('rdata');\n const rdata = fields\n .map((f) => (rrInstance.isFqdnField(f) ? rrInstance.getFQDN(f, zone_opts) : rrInstance.getQuoted(f)))\n .join('\\t');\n return `${rrInstance.getPrefix(zone_opts)}\\t${rdata}\\n`\n}\n\nconst customInspect = Symbol.for('nodejs.util.inspect.custom');\n\nclass RR {\n static CLASSES = { IN: 1, CS: 2, CH: 3, HS: 4, NONE: 254, ANY: 255 }\n static typeId\n static RFCs = []\n static tags = []\n\n constructor(opts) {\n if (opts === null) return\n\n if (opts?.default) this.default = opts.default;\n\n // tinydns specific\n this.setLocation(opts?.location);\n this.setTimestamp(opts?.timestamp);\n\n this.setOwner(opts?.owner);\n this.setType(opts?.type);\n this.setTtl(opts?.ttl);\n this.setClass(opts?.class);\n\n for (const entry of this.constructor.rdataFields ?? []) {\n const f = RR.fieldName(entry);\n const fieldType = Array.isArray(entry) ? entry[1] : null;\n const fnName = `set${this.ucFirst(f)}`;\n if (typeof this[fnName] === 'function') {\n this[fnName](opts?.[f]);\n } else if (fieldType) {\n this.setTypedValue(fieldType, f, opts?.[f]);\n } else {\n this.set(f, opts?.[f]);\n }\n }\n\n if (opts?.comment) this.set('comment', opts.comment);\n }\n\n static fromBind(line, opts = {}) {\n const instance = new this(null);\n if (opts.default !== undefined) instance.default = opts.default;\n const parsed = this.parseBindLine(line);\n if (!parsed) return null\n return instance.fromBind({ ...opts, ...parsed, bindline: line })\n }\n\n fromBind(opts) {\n return fromBind(this, opts)\n }\n\n static parseBindLine(line) {\n return parseBindLine(line, RR.CLASSES)\n }\n\n static fromTinydns(line, opts = {}) {\n const instance = new this(null);\n if (opts.default !== undefined) instance.default = opts.default;\n return instance.fromTinydns({ ...opts, tinyline: line })\n }\n\n fromTinydns(opts) {\n return fromGeneric(this, opts)\n }\n\n static fromWire(wireBytes) {\n return fromWireBytes(this, wireBytes, wireUnpackDomain)\n }\n\n fromWire(opts) {\n return fromWireGeneric(this, opts)\n }\n\n static #reserved = ['__proto__', 'constructor', 'prototype']\n\n get(key) {\n if (RR.#reserved.includes(key)) throw new Error(`Invalid field name: ${key}`)\n return this[key]\n }\n\n set(key, value) {\n if (RR.#reserved.includes(key)) throw new Error(`Invalid field name: ${key}`)\n this[key] = value;\n return this\n }\n\n toJSON() {\n const fields = [...this.getFields(), 'location', 'timestamp', 'comment'];\n const obj = {};\n for (const f of fields) {\n const v = this.get(f);\n if (v !== undefined) obj[f] = v;\n }\n return obj\n }\n\n [customInspect](depth, options, nextInspect) {\n // Returns a formatted string that looks like: A { ... }\n return `${this.type} ${nextInspect(this.toJSON(), options)}`\n }\n\n ucFirst(str) {\n if (!str) return str\n return str\n .split(/\\s/)\n .map((w) => w.charAt(0).toUpperCase() + w.slice(1))\n .join('')\n }\n\n setClass(c) {\n if ([undefined, null, ''].includes(c)) {\n this.set('class', 'IN');\n return\n }\n if (RR.CLASSES[c.toUpperCase()]) {\n this.set('class', c.toUpperCase());\n return\n }\n this.throwHelp(`invalid class ${c}`);\n }\n\n setLocation(l) {\n switch (l) {\n case undefined:\n return\n default:\n this.set('location', l);\n }\n }\n\n setTimestamp(l) {\n switch (l) {\n case undefined:\n return\n default:\n this.set('timestamp', l);\n }\n }\n\n setOwner(n) {\n if (n === undefined) this.throwHelp(`owner is required`);\n\n if (n.length < 1 || n.length > 255)\n this.throwHelp('Domain names must have 1-255 octets (characters): RFC 2181');\n\n this.isFullyQualified(this.constructor.typeName ?? this.constructor.name, 'owner', n);\n this.hasValidLabels(n);\n\n // wildcard records: RFC 1034, 4592\n if (/\\*/.test(n)) {\n if (!/^\\*\\./.test(n) && !/\\.\\*\\./.test(n))\n this.throwHelp('only *.something or * (by itself) is a valid wildcard');\n }\n\n this.set('owner', n.toLowerCase());\n }\n\n setTtl(t) {\n t = t ?? this.default?.ttl;\n if (t === undefined) {\n if (['SOA', 'SSHFP', 'RRSIG'].includes(this.get('type'))) return\n this.throwHelp('TTL is required, no default available');\n }\n\n if (typeof t !== 'number') this.throwHelp(`TTL must be numeric (${typeof t})`);\n\n // RFC 1035, 2181\n this.is32bitInt(this.get('type'), 'TTL', t);\n\n this.set('ttl', t);\n }\n\n setType(t) {\n if ([undefined, ''].includes(t)) t = this.constructor.typeName;\n\n if (t === undefined) this.throwHelp(`type is required`);\n\n if (t.toUpperCase() !== this.constructor.typeName)\n this.throwHelp(`type ${t} doesn't match ${this.constructor.typeName}`);\n\n this.set('type', t.toUpperCase());\n }\n\n throwHelp(e) {\n if (!this.constructor.typeName) throw new Error(e)\n\n const typeName = this.constructor.typeName;\n const example = this.getCanonical\n ? `Example ${typeName}:\\n${JSON.stringify(this.getCanonical(), null, '\\t')}\\n\\n`\n : `${typeName} records have the fields: ${this.getFields().join(', ')}\\n\\n`;\n\n throw new Error(`${e}\\n\\n${example}${this.citeRFC()}\\n`)\n }\n\n citeRFC() {\n return `see RFC${this.getRFCs().length > 1 ? 's' : ''} ${this.getRFCs()}`\n }\n\n fullyQualify(hostname, origin) {\n if (!hostname) return hostname\n if (hostname === '@' && origin) hostname = origin;\n if (hostname.endsWith('.')) return hostname.toLowerCase()\n if (origin) return `${hostname}.${origin}`.toLowerCase()\n return `${hostname}.`\n }\n\n getPrefix(zone_opts = {}) {\n const classVal = zone_opts.hide?.class ? '' : this.get('class');\n\n let rrTTL = this.get('ttl');\n if (zone_opts.hide?.ttl && rrTTL === zone_opts.ttl) rrTTL = '';\n\n let owner = this.get('owner');\n if (zone_opts.hide?.sameOwner && zone_opts.previousOwner === owner) {\n owner = '';\n } else {\n owner = this.getFQDN('owner', zone_opts);\n }\n\n return `${owner}\\t${rrTTL}\\t${classVal}\\t${this.get('type')}`\n }\n\n getEmpty(prop) {\n return this.get(prop) ?? ''\n }\n\n getComment(prop) {\n const c = this.get('comment');\n if (!c || !c[prop]) return ''\n return c[prop]\n }\n\n getQuoted(prop) {\n // if prop is not a quoted string field, return bare\n if (!this.isQuotedField(prop)) return this.get(prop)\n\n // if it's already quoted, return as-is\n if (/['\"]/.test(this.get(prop)[0])) return this.get(prop)\n\n return `\"${this.get(prop)}\"` // add double quotes\n }\n\n static fieldName(entry) {\n return Array.isArray(entry) ? entry[0] : entry\n }\n\n static fieldType(entry) {\n return Array.isArray(entry) ? entry[1] : null\n }\n\n getRdataFields() {\n return (this.constructor.rdataFields ?? []).map((e) => RR.fieldName(e))\n }\n\n getTags() {\n return this.constructor.tags ?? []\n }\n\n getRFCs() {\n return this.constructor.RFCs ?? []\n }\n\n getTypeId() {\n const typeId = this.constructor.typeId;\n if (typeId === undefined) this.throwHelp(`${this.constructor.typeName}: missing static typeId`);\n return typeId\n }\n\n static getTypeId() {\n return this.typeId\n }\n\n getFields(arg) {\n const commonFields = ['owner', 'ttl', 'class', 'type'];\n Object.freeze(commonFields);\n\n const rdataFields = this.getRdataFields();\n\n switch (arg) {\n case 'common':\n return commonFields\n case 'rdata':\n return rdataFields\n default:\n return commonFields.concat(rdataFields)\n }\n }\n\n getFQDN(field, zone_opts = {}) {\n let fqdn = this.get(field);\n if (!fqdn) this.throwHelp(`empty value for field ${field}`);\n if (!fqdn.endsWith('.')) fqdn += '.';\n\n if (zone_opts.hide?.origin && zone_opts.origin) {\n if (fqdn === zone_opts.origin) return '@'\n if (fqdn.endsWith(zone_opts.origin)) return fqdn.slice(0, fqdn.length - zone_opts.origin.length - 1)\n }\n\n return fqdn\n }\n\n getTinyFQDN(field) {\n const val = this.get(field);\n if (val === '') return val // empty\n if (val === '.') return val // null MX\n\n // strip off trailing ., tinydns doesn't require it for FQDN\n if (val.endsWith('.')) return val.slice(0, -1)\n\n return val\n }\n\n getTinydnsGeneric(rdata) {\n return `:${this.getTinyFQDN('owner')}:${this.getTypeId()}:${rdata}:${this.getTinydnsPostamble()}\\n`\n }\n\n getTinydnsPostamble() {\n return ['ttl', 'timestamp', 'location'].map((f) => this.getEmpty(f)).join(':')\n }\n\n hasValidLabels(hostname) {\n // RFC 952 defined valid hostnames\n // RFC 1035 limited domain label chars to letters, digits, and hyphen\n // RFC 1123 allowed hostnames to start with a digit\n // RFC 2181 'any binary string can be used as the label'\n const fq = hostname.endsWith('.') ? hostname.slice(0, -1) : hostname;\n for (const label of fq.split('.')) {\n if (label.length < 1 || label.length > 63)\n this.throwHelp('Labels must have 1-63 octets (characters), RFC 2181');\n }\n }\n\n is8bitInt(type, field, value) {\n if (Number.isInteger(value) && value >= 0 && value <= 255) return true\n\n this.throwHelp(`${type} ${field} must be a 8-bit integer (in the range 0-255)`);\n }\n\n is16bitInt(type, field, value) {\n if (Number.isInteger(value) && value >= 0 && value <= 65535) return true\n\n this.throwHelp(`${type} ${field} must be a 16-bit integer (in the range 0-65535)`);\n }\n\n is32bitInt(type, field, value) {\n if (Number.isInteger(value) && value >= 0 && value <= 4294967295) return true\n\n this.throwHelp(`${type} ${field} must be a 32-bit integer (in the range 0-4294967295)`);\n }\n\n isBase64(type, field, value) {\n if (\n typeof value === 'string' &&\n value.length > 0 &&\n value.length % 4 === 0 &&\n /^[A-Za-z0-9+/]*={0,2}$/.test(value)\n )\n return true\n\n this.throwHelp(`${type} ${field} must be a valid base64 string`);\n }\n\n isQuoted(val) {\n return /^[\"']/.test(val) && /[\"']$/.test(val)\n }\n\n setFqdnValue(typeName, fieldName, val) {\n if (!val) this.throwHelp(`${typeName}: ${fieldName} is required`);\n if (this.isIPv4(val) || this.isIPv6(val))\n this.throwHelp(`${typeName}: ${fieldName} must be a domain name`);\n this.isFullyQualified(typeName, fieldName, val);\n this.isValidHostname(typeName, fieldName, val);\n this.set(fieldName, val.toLowerCase());\n }\n\n setTypedValue(type, fieldName, val) {\n const typeName = this.constructor.typeName;\n switch (type) {\n case 'u8':\n this.is8bitInt(typeName, fieldName, val);\n this.set(fieldName, parseInt(val, 10));\n break\n case 'u16':\n this.is16bitInt(typeName, fieldName, val);\n this.set(fieldName, parseInt(val, 10));\n break\n case 'certtype': {\n if (val === undefined || val === null || val === '')\n this.throwHelp(`${typeName}: ${fieldName} is required`);\n if (typeof val === 'string' && !/^[0-9]+$/.test(val)) {\n const certTypes = this.constructor.CERT_TYPES;\n if (!certTypes || !Object.hasOwn(certTypes, val)) {\n this.throwHelp(`${typeName}: unknown cert type mnemonic: ${val}`);\n }\n this.set(fieldName, val);\n break\n }\n this.is16bitInt(typeName, fieldName, val);\n this.set(fieldName, parseInt(val, 10));\n break\n }\n case 'u32':\n this.is32bitInt(typeName, fieldName, val);\n this.set(fieldName, parseInt(val, 10));\n break\n case 'fqdn':\n this.setFqdnValue(typeName, fieldName, val);\n break\n case 'base64':\n this.isBase64(typeName, fieldName, val);\n this.set(fieldName, val);\n break\n case 'hex':\n if (!/^[0-9a-fA-F]*$/.test(val)) this.throwHelp(`${typeName}: ${fieldName} must be hexadecimal`);\n this.set(fieldName, val);\n break\n case 'str':\n if (!val) this.throwHelp(`${typeName}: ${fieldName} is required`);\n this.set(fieldName, val);\n break\n case 'qstr':\n if (val === undefined || val === null) this.throwHelp(`${typeName}: ${fieldName} is required`);\n this.set(fieldName, val);\n break\n case 'charstr': {\n if (val === undefined || val === null) this.throwHelp(`${typeName}: ${fieldName} is required`);\n const value = String(val);\n const byteLen = new TextEncoder().encode(value).length;\n if (byteLen > 255) this.throwHelp(`${typeName}: ${fieldName} must be <=255 bytes`);\n this.set(fieldName, value);\n break\n }\n case 'qcharstr': {\n if (val === undefined || val === null) this.throwHelp(`${typeName}: ${fieldName} is required`);\n const value = String(val);\n const byteLen = new TextEncoder().encode(value).length;\n if (byteLen > 255) this.throwHelp(`${typeName}: ${fieldName} must be <=255 bytes`);\n this.set(fieldName, value);\n break\n }\n case 'charstrs':\n if (val === undefined || val === null) this.throwHelp(`${typeName}: ${fieldName} is required`);\n this.set(fieldName, val);\n break\n case 'svcparams':\n if (val === undefined || val === null) this.throwHelp(`${typeName}: ${fieldName} is required`);\n this.set(fieldName, val);\n break\n case 'ipv4':\n if (!this.isIPv4(val)) this.throwHelp(`${typeName}: ${fieldName} must be a valid IPv4 address`);\n this.set(fieldName, val);\n break\n case 'ipv6':\n if (!this.isIPv6(val)) this.throwHelp(`${typeName}: ${fieldName} must be a valid IPv6 address`);\n this.set(fieldName, this.expandIPv6(val.toLowerCase())); // lower case: RFC 5952\n break\n }\n }\n\n isFullyQualified(type, field, hostname) {\n if (hostname.endsWith('.')) return true\n\n this.throwHelp(`${type}: ${field} must be fully qualified`);\n }\n\n isValidHostname(type, field, hostname) {\n const allowed = new RegExp(/[^a-zA-Z0-9\\-._/\\\\]/);\n if (!allowed.test(hostname)) return true\n\n const matches = allowed.exec(hostname);\n this.throwHelp(`${type}, ${field} has invalid hostname character (${matches[0]})`);\n }\n\n isIPv4(string) {\n // https://stackoverflow.com/questions/5284147/validating-ipv4-addresses-with-regexp\n return /^((25[0-5]|(2[0-4]|1\\d|[1-9]|)\\d)\\.?\\b){4}$/.test(string)\n }\n\n isIPv6(string) {\n return /^(?:(?:[a-fA-F\\d]{1,4}:){7}(?:[a-fA-F\\d]{1,4}|:)|(?:[a-fA-F\\d]{1,4}:){6}(?:(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}|:[a-fA-F\\d]{1,4}|:)|(?:[a-fA-F\\d]{1,4}:){5}(?::(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}|(?::[a-fA-F\\d]{1,4}){1,2}|:)|(?:[a-fA-F\\d]{1,4}:){4}(?:(?::[a-fA-F\\d]{1,4}){0,1}:(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}|(?::[a-fA-F\\d]{1,4}){1,3}|:)|(?:[a-fA-F\\d]{1,4}:){3}(?:(?::[a-fA-F\\d]{1,4}){0,2}:(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}|(?::[a-fA-F\\d]{1,4}){1,4}|:)|(?:[a-fA-F\\d]{1,4}:){2}(?:(?::[a-fA-F\\d]{1,4}){0,3}:(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}|(?::[a-fA-F\\d]{1,4}){1,5}|:)|(?:[a-fA-F\\d]{1,4}:){1}(?:(?::[a-fA-F\\d]{1,4}){0,4}:(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}|(?::[a-fA-F\\d]{1,4}){1,6}|:)|(?::(?:(?::[a-fA-F\\d]{1,4}){0,5}:(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}|(?::[a-fA-F\\d]{1,4}){1,7}|:)))(?:%[0-9a-zA-Z]{1,})?$/gm.test(\n string,\n )\n }\n\n expandIPv6(val, delimiter) {\n return expandIPv6(val, delimiter)\n }\n\n compressIPv6(val) {\n // * RFC 5952\n // * 4.1. Leading zeros MUST be suppressed...A single 16-bit 0000 field MUST be represented as 0.\n // * 4.2.1 The use of the symbol \"::\" MUST be used to its maximum capability.\n // * 4.2.2 The symbol \"::\" MUST NOT be used to shorten just one 16-bit 0 field.\n // * 4.2.3 When choosing placement of a \"::\", the longest run...MUST be shortened\n // * 4.3 The characters a-f in an IPv6 address MUST be represented in lowercase.\n\n // 4.3 Lowercase and 4.1 remove leading zeros per segment\n const segments = val\n .toLowerCase()\n .split(':')\n .map((s) => s.replace(/^0+/, '') || '0');\n\n let bestStart = -1;\n let bestLen = 0;\n let curStart = -1;\n let curLen = 0;\n\n // 4.2.1 & 4.2.3 Find the longest consecutive run of '0'\n for (let i = 0; i < segments.length; i++) {\n if (segments[i] === '0') {\n if (curStart === -1) curStart = i;\n curLen++;\n if (curLen > bestLen) {\n bestLen = curLen;\n bestStart = curStart;\n }\n } else {\n curStart = -1;\n curLen = 0;\n }\n }\n\n // 4.2.2 Don't shorten a single 16-bit 0 field\n if (bestLen < 2) {\n return segments.join(':')\n }\n\n const head = segments.slice(0, bestStart).join(':');\n const tail = segments.slice(bestStart + bestLen).join(':');\n\n return `${head}::${tail}`\n }\n\n octalToUint8Array(octalStr) {\n const str = octalToChar(octalStr);\n return Uint8Array.from(str, (c) => c.charCodeAt(0))\n }\n\n wireUnpackDomain(bytes, offset = 0) {\n return wireUnpackDomain(bytes, offset)\n }\n\n wirePackDomain(fqdn) {\n return wirePackDomain(fqdn)\n }\n\n getWireRdata() {\n return getWireRdata(this)\n }\n\n toWire() {\n return toWire(this, RR.CLASSES)\n }\n\n toBind(zone_opts) {\n return toBind(this, zone_opts)\n }\n\n parseTinydnsLine(tinyline) {\n const parsed = parseGenericLine(tinyline);\n return { ...parsed, owner: this.fullyQualify(parsed.owner) }\n }\n\n toTinydns() {\n return to(this)\n }\n\n isFqdnField(field) {\n return (\n (this.constructor.rdataFields ?? []).some(\n (entry) => RR.fieldName(entry) === field && RR.fieldType(entry) === 'fqdn',\n ) || false\n )\n }\n\n isQuotedField(field) {\n const quotedTypes = new Set(['qstr', 'qcharstr', 'charstrs']);\n return (\n (this.constructor.rdataFields ?? []).some(\n (entry) => RR.fieldName(entry) === field && quotedTypes.has(RR.fieldType(entry)),\n ) || false\n )\n }\n\n toMaraDNS() {\n const type = this.get('type');\n const supportedTypes = 'A PTR MX AAAA SRV NAPTR NS SOA TXT SPF RAW FQDN4 FQDN6 CNAME HINFO WKS LOC'.split(\n /\\s+/g,\n );\n if (!supportedTypes.includes(type)) return this.toMaraGeneric()\n return `${this.get('owner')}\\t+${this.get('ttl')}\\t${type}\\t${this.getFields('rdata')\n .map((f) => this.getQuoted(f))\n .join('\\t')} ~\\n`\n }\n\n toMaraGeneric() {\n // this.throwHelp(`\\nMaraDNS does not support ${type} records yet and this package does not support MaraDNS generic records. Yet.\\n`)\n return `${this.get('owner')}\\t+${this.get('ttl')}\\tRAW ${this.getTypeId()}\\t'${this.getFields('rdata')\n .map((f) => this.getQuoted(f))\n .join(' ')}' ~\\n`\n }\n}\n\nclass A extends RR {\n static typeName = 'A'\n static typeId = 1\n static RFCs = [1035]\n static tinydnsType = '+'\n static rdataFields = [['address', 'ipv4']]\n static tags = ['common']\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setAddress(val) {\n if (!val) this.throwHelp('A: address is required');\n if (!this.isIPv4(val)) this.throwHelp('A address must be IPv4');\n this.set('address', val);\n }\n\n getDescription() {\n return 'Address'\n }\n\n getCanonical() {\n return {\n owner: 'host.example.com.',\n class: 'IN',\n ttl: 3600,\n type: 'A',\n address: '192.0.2.127',\n }\n }\n\n /****** EXPORTERS *******/\n getWireRdata() {\n return new Uint8Array(this.get('address').split('.').map(Number))\n }\n}\n\nclass AAAA extends RR {\n static typeName = 'AAAA'\n static typeId = 28\n static RFCs = [3596, 5952]\n static rdataFields = [['address', 'ipv6']]\n static tags = ['common']\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setAddress(val) {\n if (!val) this.throwHelp('AAAA: address is required');\n if (!this.isIPv6(val)) this.throwHelp(`AAAA: address must be IPv6 (${val})`);\n\n this.set('address', this.expandIPv6(val.toLowerCase())); // lower case: RFC 5952\n }\n\n getCompressed(val) {\n return this.compressIPv6(val ?? this.get('address'))\n }\n\n getDescription() {\n return 'Address IPv6'\n }\n\n getCanonical() {\n return {\n owner: 'host.example.com.',\n address: '2001:0db8:0020:000a:0000:0000:0000:0004',\n class: 'IN',\n ttl: 3600,\n type: 'AAAA',\n }\n }\n\n /****** IMPORTERS *******/\n fromTinydns({ tinyline }) {\n const str = tinyline;\n let fqdn, ip, n, rdata, ttl, ts, loc;\n\n switch (str[0]) {\n case ':':\n[fqdn, n, rdata, ttl, ts, loc] = str.slice(1).split(':');\n if (n != 28) this.throwHelp('AAAA fromTinydns, invalid n');\n ip = octalToHex(rdata)\n .match(/([0-9a-fA-F]{4})/g)\n .join(':');\n break\n case '3':\n case '6':\n[fqdn, rdata, ttl, ts, loc] = str.slice(1).split(':');\n ip = rdata.match(/(.{4})/g).join(':');\n break\n }\n\n return new AAAA({\n owner: this.fullyQualify(fqdn),\n ttl: parseInt(ttl, 10),\n type: 'AAAA',\n address: ip,\n timestamp: ts,\n location: loc?.trim() ?? '',\n })\n }\n\n /****** EXPORTERS *******/\n getWireRdata() {\n const hex = this.expandIPv6(this.get('address'), '');\n const arr = new Uint8Array(hex.length / 2);\n for (let i = 0; i < arr.length; i++) arr[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);\n return arr\n }\n\n toBind(zone_opts) {\n return `${this.getPrefix(zone_opts)}\\t${this.getCompressed()}\\n`\n }\n\n toTinydns() {\n // from AAAA notation (8 groups of 4 hex digits) to 16 escaped octals\n const rdata = packHex(this.expandIPv6(this.get('address'), ''));\n return this.getTinydnsGeneric(rdata)\n }\n}\n\nclass APL extends RR {\n static typeName = 'APL'\n static typeId = 42\n static RFCs = [3123]\n static rdataFields = ['apl rdata']\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setAplRdata(val) {\n if (!val) this.throwHelp('APL: apl rdata is required');\n this.set('apl rdata', val);\n }\n\n getDescription() {\n return 'Address Prefix List'\n }\n\n getCanonical() {\n return {\n owner: 'example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'APL',\n 'apl rdata': '1:192.0.2.1/24 !1:192.0.2.64/28 2:2001:db8::1/128',\n }\n }\n\n /****** IMPORTERS *******/\n fromTinydns({ tinyline }) {\n // APL via generic, :fqdn:42:rdata:ttl:timestamp:lo\n const [fqdn, n, rdata, ttl, ts, loc] = tinyline.slice(1).split(':');\n if (n != 42) this.throwHelp('APL fromTinydns, invalid n');\n\n const bytes = Uint8Array.from(octalToChar(rdata), (c) => c.charCodeAt(0));\n const items = [];\n let pos = 0;\n\n while (pos < bytes.length) {\n const afi = (bytes[pos] << 8) | bytes[pos + 1];\n pos += 2;\n const prefix = bytes[pos];\n pos++;\n const adfLenByte = bytes[pos];\n pos++;\n const neg = (adfLenByte & 0x80) !== 0;\n const addrLen = adfLenByte & 0x7f;\n const addrBytes = bytes.subarray(pos, pos + addrLen);\n pos += addrLen;\n\n let addr;\n if (afi === 1) {\n const padded = new Uint8Array(4);\n padded.set(addrBytes);\n addr = [...padded].join('.');\n } else {\n const padded = new Uint8Array(16);\n padded.set(addrBytes);\n const paddedDv = new DataView(padded.buffer);\n const groups = [];\n for (let i = 0; i < 16; i += 2) groups.push(paddedDv.getUint16(i).toString(16).padStart(4, '0'));\n addr = this.compressIPv6(groups.join(':'));\n }\n\n items.push(`${neg ? '!' : ''}${afi}:${addr}/${prefix}`);\n }\n\n return new APL({\n owner: this.fullyQualify(fqdn),\n ttl: parseInt(ttl, 10),\n type: 'APL',\n 'apl rdata': items.join(' '),\n timestamp: ts,\n location: loc?.trim() ?? '',\n })\n }\n\n fromBind({ bindline }) {\n // test.example.com 3600 IN APL {[!]afi:address/prefix}*\n const parts = bindline.split(/\\s+/);\n const [owner, ttl, c, type] = parts;\n return new APL({\n owner,\n ttl: parseInt(ttl, 10),\n class: c,\n type,\n 'apl rdata': parts.slice(4).join(' ').trim(),\n })\n }\n\n fromWire({ owner, cls, ttl, rdata }) {\n const items = [];\n let pos = 0;\n while (pos < rdata.length) {\n const afi = (rdata[pos] << 8) | rdata[pos + 1];\n pos += 2;\n const prefix = rdata[pos++];\n const adfLenByte = rdata[pos++];\n const neg = (adfLenByte & 0x80) !== 0;\n const addrLen = adfLenByte & 0x7f;\n const addrBytes = rdata.subarray(pos, pos + addrLen);\n pos += addrLen;\n\n let addr;\n if (afi === 1) {\n const padded = new Uint8Array(4);\n padded.set(addrBytes);\n addr = [...padded].join('.');\n } else {\n const padded = new Uint8Array(16);\n padded.set(addrBytes);\n const dv = new DataView(padded.buffer);\n const groups = [];\n for (let i = 0; i < 16; i += 2) groups.push(dv.getUint16(i).toString(16).padStart(4, '0'));\n addr = this.compressIPv6(groups.join(':'));\n }\n items.push(`${neg ? '!' : ''}${afi}:${addr}/${prefix}`);\n }\n return new APL({\n owner,\n ttl,\n class: cls,\n type: 'APL',\n 'apl rdata': items.join(' '),\n })\n }\n\n /****** EXPORTERS *******/\n toTinydns() {\n return this.getTinydnsGeneric(\n this.get('apl rdata')\n .split(/\\s+/)\n .map((item) => {\n const neg = item.startsWith('!');\n const bare = neg ? item.slice(1) : item;\n const colonIdx = bare.indexOf(':');\n const afi = parseInt(bare.slice(0, colonIdx), 10);\n const rest = bare.slice(colonIdx + 1);\n const slashIdx = rest.lastIndexOf('/');\n const addr = rest.slice(0, slashIdx);\n const prefix = parseInt(rest.slice(slashIdx + 1), 10);\n\n let addrBytes;\n if (afi === 1) {\n addrBytes = new Uint8Array(addr.split('.').map((n) => parseInt(n, 10)));\n } else {\n const dblIdx = addr.indexOf('::');\n let groups;\n if (dblIdx !== -1) {\n const left = addr\n .slice(0, dblIdx)\n .split(':')\n .filter((s) => s !== '');\n const right = addr\n .slice(dblIdx + 2)\n .split(':')\n .filter((s) => s !== '');\n groups = [...left, ...Array(8 - left.length - right.length).fill('0000'), ...right];\n } else {\n groups = addr.split(':');\n }\n const hexStr = groups.map((g) => g.padStart(4, '0')).join('');\n addrBytes = Uint8Array.from({ length: hexStr.length / 2 }, (_, i) =>\n parseInt(hexStr.slice(i * 2, i * 2 + 2), 16),\n );\n }\n\n let len = addrBytes.length;\n while (len > 0 && addrBytes[len - 1] === 0) len--;\n const afdPart = addrBytes.slice(0, len);\n\n let r = UInt16toOctal(afi);\n r += UInt8toOctal(prefix);\n r += UInt8toOctal((neg ? 0x80 : 0) | afdPart.length);\n for (const b of afdPart) r += UInt8toOctal(b);\n return r\n })\n .join(''),\n )\n }\n\n getWireRdata() {\n const items = this.get('apl rdata').split(/\\s+/);\n const rdata = [];\n\n for (const item of items) {\n const neg = item.startsWith('!');\n const bare = neg ? item.slice(1) : item;\n const colonIdx = bare.indexOf(':');\n const afi = parseInt(bare.slice(0, colonIdx), 10);\n const rest = bare.slice(colonIdx + 1);\n const slashIdx = rest.lastIndexOf('/');\n const addr = rest.slice(0, slashIdx);\n const prefix = parseInt(rest.slice(slashIdx + 1), 10);\n\n let addrBytes;\n if (afi === 1) {\n addrBytes = new Uint8Array(addr.split('.').map((n) => parseInt(n, 10)));\n } else {\n const dblIdx = addr.indexOf('::');\n let groups;\n if (dblIdx !== -1) {\n const left = addr\n .slice(0, dblIdx)\n .split(':')\n .filter((s) => s !== '');\n const right = addr\n .slice(dblIdx + 2)\n .split(':')\n .filter((s) => s !== '');\n groups = [...left, ...Array(8 - left.length - right.length).fill('0000'), ...right];\n } else {\n groups = addr.split(':');\n }\n const hexStr = groups.map((g) => g.padStart(4, '0')).join('');\n addrBytes = Uint8Array.from({ length: hexStr.length / 2 }, (_, i) =>\n parseInt(hexStr.slice(i * 2, i * 2 + 2), 16),\n );\n }\n\n let len = addrBytes.length;\n while (len > 0 && addrBytes[len - 1] === 0) len--;\n const afdPart = addrBytes.slice(0, len);\n\n const itemBytes = new Uint8Array(4 + afdPart.length);\n const dv = new DataView(itemBytes.buffer, itemBytes.byteOffset);\n dv.setUint16(0, afi);\n itemBytes[2] = prefix;\n itemBytes[3] = (neg ? 0x80 : 0) | afdPart.length;\n itemBytes.set(afdPart, 4);\n\n rdata.push(itemBytes);\n }\n\n const totalLen = rdata.reduce((sum, r) => sum + r.length, 0);\n const bytes = new Uint8Array(totalLen);\n let pos = 0;\n for (const r of rdata) {\n bytes.set(r, pos);\n pos += r.length;\n }\n\n return bytes\n }\n}\n\nclass CAA extends RR {\n static typeName = 'CAA'\n static typeId = 257\n static RFCs = [6844, 8659, 9619]\n static rdataFields = [\n ['flags', 'u8'],\n ['tag', 'charstr'],\n ['value', 'qstr'],\n ]\n static tags = ['security']\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setFlags(val) {\n this.is8bitInt('CAA', 'flags', val);\n\n if (!this.getFlagsOptions().has(val)) {\n this.throwHelp(`CAA flags ${val} not recognized`);\n }\n\n this.set('flags', val);\n }\n\n getFlagsOptions() {\n return new Map([\n [0, 'Non Critical'],\n [128, 'Critical'],\n ])\n }\n\n setTag(val) {\n if (typeof val !== 'string' || val.length < 1 || /[^a-z0-9]/.test(val))\n this.throwHelp(`CAA tag must be a sequence of ASCII letters and numbers in lowercase`);\n\n if (!this.getTagOptions().has(val)) {\n this.throwHelp(`CAA tag ${val} not recognized`);\n }\n this.set('tag', val);\n }\n\n getTagOptions() {\n return new Map([['issue'], ['issuewild'], ['iodef']])\n }\n\n setValue(val) {\n // either (2) a quoted string or\n // (1) a contiguous set of characters without interior spaces\n if (this.isQuoted(val)) {\n val = val.replace(/^[\"']|[\"']$/g, ''); // strip quotes\n }\n\n // check if val starts with one of iodefSchemes\n if (this.get('tag') === 'iodef') {\n const iodefSchemes = ['mailto:', 'http:', 'https:'];\n if (!iodefSchemes.filter((s) => val.startsWith(s)).length) {\n this.throwHelp(`CAA value must have valid iodefScheme prefix`);\n }\n }\n\n this.set('value', val);\n }\n\n getDescription() {\n return 'Certification Authority Authorization'\n }\n\n getCanonical() {\n return {\n owner: 'example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'CAA',\n flags: 0,\n tag: 'issue',\n value: 'http://letsencrypt.org',\n }\n }\n\n /****** IMPORTERS *******/\n fromTinydns({ tinyline }) {\n // CAA via generic, :fqdn:n:rdata:ttl:timestamp:lo\n const { owner, typeId, rdata, ttl, timestamp, location } = this.parseTinydnsLine(tinyline);\n if (typeId != this.getTypeId()) this.throwHelp('CAA fromTinydns, invalid typeId');\n\n const flags = octalToUInt8(rdata.slice(0, 4));\n const taglen = octalToUInt8(rdata.slice(4, 8));\n\n const unescaped = octalToChar(rdata.slice(8));\n const tag = unescaped.slice(0, taglen);\n const fingerprint = unescaped.slice(taglen);\n\n return new CAA({\n owner,\n ttl,\n type: 'CAA',\n flags,\n tag,\n value: fingerprint,\n timestamp,\n location,\n })\n }\n\n /****** EXPORTERS *******/\n\n getWireRdata() {\n const tag = new TextEncoder().encode(this.get('tag'));\n const value = new TextEncoder().encode(this.get('value'));\n const result = new Uint8Array(2 + tag.length + value.length);\n result[0] = this.get('flags');\n result[1] = tag.length;\n result.set(tag, 2);\n result.set(value, 2 + tag.length);\n return result\n }\n\n toTinydns() {\n return this.getTinydnsGeneric(\n UInt8toOctal(this.get('flags')) +\n UInt8toOctal(this.get('tag').length) +\n escapeOctal(/[\\r\\n\\t:\\\\/]/, this.get('tag')) +\n escapeOctal(/[\\r\\n\\t:\\\\/]/, this.get('value')),\n )\n }\n}\n\nclass CERT extends RR {\n static typeName = 'CERT'\n static typeId = 37\n static RFCs = [2538, 4398]\n static rdataFields = [\n ['cert type', 'certtype'],\n ['key tag', 'u16'],\n ['algorithm', 'u8'],\n ['certificate', 'base64'],\n ]\n\n static CERT_TYPES = {\n PKIX: 1,\n SPKI: 2,\n PGP: 3,\n IPKIX: 4,\n ISPKI: 5,\n IPGP: 6,\n ACPKIX: 7,\n IACPKIX: 8,\n URI: 253,\n OID: 254,\n }\n\n static CERT_TYPES_REVERSE = Object.fromEntries(Object.entries(CERT.CERT_TYPES).map(([k, v]) => [v, k]))\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setCertType(val) {\n // The type field is the certificate type\n // the type field as an unsigned decimal integer or as a mnemonic symbol\n if (val === undefined || val === null || val === '') {\n this.throwHelp('cert type is required');\n }\n // Accept both mnemonic and numeric, but validate mnemonic\n if (typeof val === 'string' && !/^[0-9]+$/.test(val)) {\n if (!Object.hasOwn(CERT.CERT_TYPES, val)) {\n this.throwHelp(`CERT: unknown cert type mnemonic: ${val}`);\n }\n } else {\n this.is16bitInt('CERT', 'cert type', val);\n }\n this.set('cert type', val);\n }\n\n getCertTypeValue(val) {\n if (typeof val === 'number') return val\n if (/^[0-9]+$/.test(val)) return parseInt(val, 10)\n if (Object.hasOwn(CERT.CERT_TYPES, val)) return CERT.CERT_TYPES[val]\n this.throwHelp(`CERT: unknown cert type mnemonic: ${val}`);\n }\n\n setCertificate(val) {\n // certificate/CRL portion is represented in base 64 [16] and may be\n // divided into any number of white-space-separated substrings\n if (val === undefined || val === null || val === '') {\n this.throwHelp('certificate is required and cannot be empty');\n }\n this.isBase64('CERT', 'certificate', val.replace(/[\\s()]/g, ''));\n this.set('certificate', val);\n }\n\n getDescription() {\n return 'Certificate'\n }\n\n getCanonical() {\n return {\n owner: 'mail.example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'CERT',\n 'cert type': 'PGP',\n 'key tag': 0,\n algorithm: 0,\n certificate: 'AQIDBA==',\n }\n }\n\n /****** IMPORTERS *******/\n\n fromTinydns({ tinyline }) {\n const { owner, typeId, rdata, ttl, timestamp, location } = this.parseTinydnsLine(tinyline);\n if (typeId != this.getTypeId()) this.throwHelp('CERT fromTinydns, invalid n');\n\n const bytes = octalRdataToBytes(rdata);\n const typeNum = (bytes[0] << 8) | bytes[1];\n\n const certType = CERT.CERT_TYPES_REVERSE[typeNum] ?? typeNum;\n\n return new CERT({\n owner,\n ttl,\n type: 'CERT',\n 'cert type': certType,\n 'key tag': (bytes[2] << 8) | bytes[3],\n algorithm: bytes[4],\n certificate: bytesToBase64(bytes.subarray(5)),\n timestamp,\n location,\n })\n }\n\n fromBind({ bindline }) {\n // test.example.com 3600 IN CERT certtype, keytag, algo, cert\n const [owner, ttl, c, type, certtype, keytag, algo, certificate] = bindline.split(/\\s+/);\n return new CERT({\n owner,\n ttl: parseInt(ttl, 10),\n class: c,\n type,\n 'cert type': /^[0-9]+$/.test(certtype) ? parseInt(certtype, 10) : certtype,\n 'key tag': parseInt(keytag, 10),\n algorithm: parseInt(algo, 10),\n certificate,\n })\n }\n\n /****** EXPORTERS *******/\n\n toTinydns() {\n return this.getTinydnsGeneric(\n UInt16toOctal(this.getCertTypeValue(this.get('cert type'))) +\n UInt16toOctal(this.get('key tag')) +\n UInt8toOctal(this.get('algorithm')) +\n base64toOctal(this.get('certificate').replace(/[\\s()]/g, '')),\n )\n }\n\n getWireRdata() {\n const certBytes = base64ToBytes(this.get('certificate').replace(/[\\s()]/g, ''));\n const bytes = new Uint8Array(5 + certBytes.length);\n const dv = new DataView(bytes.buffer, bytes.byteOffset);\n dv.setUint16(0, this.getCertTypeValue(this.get('cert type')));\n dv.setUint16(2, this.get('key tag'));\n bytes[4] = this.get('algorithm');\n bytes.set(certBytes, 5);\n return bytes\n }\n}\n\nclass CNAME extends RR {\n static typeName = 'CNAME'\n static typeId = 5\n static RFCs = [1035, 2181]\n static tinydnsType = 'C'\n static rdataFields = [['cname', 'fqdn']]\n static tags = ['common']\n\n constructor(opts) {\n super(opts);\n }\n\n getDescription() {\n return 'Canonical Name'\n }\n\n getCanonical() {\n return {\n owner: 'www.example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'CNAME',\n cname: 'web.example.com.',\n }\n }\n\n /****** EXPORTERS *******/\n getWireRdata() {\n return this.wirePackDomain(this.get('cname'))\n }\n}\n\nclass DHCID extends RR {\n static typeName = 'DHCID'\n static typeId = 49\n static RFCs = [4701]\n static rdataFields = [['data', 'base64']]\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setData(val) {\n if (!val) this.throwHelp('DHCID: data is required');\n this.isBase64('DHCID', 'data', val);\n this.set('data', val);\n }\n\n getDescription() {\n return 'DHCP Identifier'\n }\n\n getCanonical() {\n return {\n owner: 'host.example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'DHCID',\n data: 'AAIBY2/AuCccgoJbsaxcQc9TUapptP69lOjxfNuVAA2kjEA=',\n }\n }\n\n /****** IMPORTERS *******/\n fromTinydns({ tinyline }) {\n // DHCID via generic, :fqdn:49:rdata:ttl:timestamp:lo\n const { owner, typeId, rdata, ttl, timestamp, location } = this.parseTinydnsLine(tinyline);\n if (typeId != this.getTypeId()) this.throwHelp('DHCID fromTinydns, invalid n');\n\n return new DHCID({\n owner,\n ttl,\n type: 'DHCID',\n data: octalToBase64(rdata),\n timestamp,\n location,\n })\n }\n\n /****** EXPORTERS *******/\n\n getWireRdata() {\n return new Uint8Array(\n atob(this.get('data'))\n .split('')\n .map((c) => c.charCodeAt(0)),\n )\n }\n\n toTinydns() {\n return this.getTinydnsGeneric(base64toOctal(this.get('data')))\n }\n}\n\nclass DNAME extends RR {\n static typeName = 'DNAME'\n static typeId = 39\n static RFCs = [2672, 6672]\n static rdataFields = [['target', 'fqdn']]\n\n constructor(opts) {\n super(opts);\n }\n\n getDescription() {\n return 'Delegation Name'\n }\n\n getCanonical() {\n return {\n owner: 'example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'DNAME',\n target: 'example.net.',\n }\n }\n\n /****** IMPORTERS *******/\n fromTinydns({ tinyline }) {\n // DNAME via generic, :fqdn:n:rdata:ttl:timestamp:lo\n const [fqdn, n, rdata, ttl, ts, loc] = tinyline.slice(1).split(':');\n if (n != 39) this.throwHelp('DNAME fromTinydns, invalid n');\n\n return new DNAME({\n type: 'DNAME',\n owner: this.fullyQualify(fqdn),\n target: unpackDomainName(rdata)[0],\n ttl: parseInt(ttl, 10),\n timestamp: ts,\n location: loc?.trim() ?? '',\n })\n }\n\n /****** EXPORTERS *******/\n\n getWireRdata() {\n return this.wirePackDomain(this.get('target'))\n }\n\n toTinydns() {\n const rdata = packDomainName(this.get('target'));\n return this.getTinydnsGeneric(rdata)\n }\n}\n\nclass DNSKEY extends RR {\n static typeName = 'DNSKEY'\n static typeId = 48\n static RFCs = [4034, 6014, 8624, 9619, 9905]\n static rdataFields = [\n ['flags', 'u16'],\n ['protocol', 'u8'],\n ['algorithm', 'u8'],\n ['publickey', 'base64'],\n ]\n static tags = ['dnssec']\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setFlags(val) {\n // a 2 octet Flags Field\n this.is16bitInt('DNSKEY', 'flags', val);\n\n if (!this.getFlagsOptions().has(val)) {\n this.throwHelp(`DNSKEY: flags must be in the set: ${this.getFlagsOptions()}`);\n }\n\n this.set('flags', val);\n }\n\n // possible values are: 0, 256, and 257; RFC 4034\n getFlagsOptions() {\n return new Map([[0], [256], [257]])\n }\n\n setProtocol(val) {\n // 1 octet\n this.is8bitInt('DNSKEY', 'protocol', val);\n\n // The Protocol Field MUST be represented as an unsigned decimal integer with a value of 3.\n if (!this.getProtocolOptions().has(val)) this.throwHelp(`DNSKEY: protocol invalid`);\n\n this.set('protocol', val);\n }\n\n getProtocolOptions() {\n return new Map([[3]])\n }\n\n setAlgorithm(val) {\n // 1 octet\n this.is8bitInt('DNSKEY', 'algorithm', val);\n\n // https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml\n if (!this.getAlgorithmOptions().has(val)) console.error(`DNSKEY: algorithm (${val}) not recognized`);\n\n this.set('algorithm', val);\n }\n\n getAlgorithmOptions() {\n return new Map([\n [1, 'RSA/MD5 (DEPRECATED)'],\n [2, 'DH'],\n [3, 'DSA/SHA-1'],\n [4, 'EC'],\n [5, 'RSA/SHA-1'],\n [6, 'DSA-NSEC3-SHA1'],\n [7, 'RSASHA1-NSEC3-SHA1'],\n [8, 'RSA/SHA-256'],\n [9, ''],\n [10, 'RSA/SHA-512'],\n [13, 'ECDSA Curve P-256 with SHA-256'],\n [14, 'ECDSA Curve P-384 with SHA-384'],\n [15, 'Ed25519'],\n [16, 'Ed448'],\n [253],\n [254],\n ])\n }\n\n setPublickey(val) {\n if (!val) this.throwHelp(`DNSKEY: publickey is required`);\n this.isBase64('DNSKEY', 'publickey', val.replace(/[\\s()]/g, ''));\n this.set('publickey', val);\n }\n\n getDescription() {\n return 'DNS Public Key'\n }\n\n getCanonical() {\n return {\n owner: 'example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'DNSKEY',\n flags: 256,\n protocol: 3,\n algorithm: 5,\n publickey:\n 'AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwIXAqcOTiW7iHnQt5hwVAAAAA==',\n }\n }\n\n /****** IMPORTERS *******/\n\n fromBind({ bindline }) {\n // test.example.com 3600 IN DNSKEY Flags Protocol Algorithm PublicKey\n const regex =\n /^(?\\S+)\\s+(?\\d+)\\s+(?\\w+)\\s+(?DNSKEY)\\s+(?\\d+)\\s+(?\\d+)\\s+(?\\d+)\\s+(?\\S.*)$/i;\n\n const match = bindline.trim().match(regex);\n\n if (!match) {\n this.throwHelp(`unable to parse DNSKEY: ${bindline}`);\n }\n\n const { owner, ttl, c, type, flags, protocol, algorithm, publickey } = match.groups;\n\n return new DNSKEY({\n owner,\n ttl: parseInt(ttl, 10),\n class: c,\n type: type,\n flags: parseInt(flags, 10),\n protocol: parseInt(protocol, 10),\n algorithm: parseInt(algorithm, 10),\n publickey: publickey,\n })\n }\n\n fromTinydns({ tinyline }) {\n const { owner, typeId, rdata, ttl, timestamp, location } = this.parseTinydnsLine(tinyline);\n if (typeId != this.getTypeId()) this.throwHelp('DNSKEY fromTinydns, invalid n');\n\n const bytes = octalRdataToBytes(rdata);\n\n return new DNSKEY({\n owner,\n ttl,\n type: 'DNSKEY',\n flags: (bytes[0] << 8) | bytes[1],\n protocol: bytes[2],\n algorithm: bytes[3],\n publickey: bytesToBase64(bytes.subarray(4)),\n timestamp,\n location,\n })\n }\n\n /****** EXPORTERS *******/\n\n toTinydns() {\n return this.getTinydnsGeneric(\n UInt16toOctal(this.get('flags')) +\n UInt8toOctal(this.get('protocol')) +\n UInt8toOctal(this.get('algorithm')) +\n base64toOctal(this.get('publickey').replace(/[\\s()]/g, '')),\n )\n }\n\n getWireRdata() {\n const keyBytes = base64ToBytes(this.get('publickey').replace(/[\\s()]/g, ''));\n const bytes = new Uint8Array(4 + keyBytes.length);\n const dv = new DataView(bytes.buffer, bytes.byteOffset);\n dv.setUint16(0, this.get('flags'));\n bytes[2] = this.get('protocol');\n bytes[3] = this.get('algorithm');\n bytes.set(keyBytes, 4);\n return bytes\n }\n}\n\nclass DS extends RR {\n static typeName = 'DS'\n static typeId = 43\n static RFCs = [4034, 4509, 9619]\n static rdataFields = [['key tag', 'u16'], 'algorithm', 'digest type', ['digest', 'str']]\n static tags = ['dnssec']\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setAlgorithm(val) {\n if (!this.getAlgorithmOptions().has(val)) this.throwHelp(`DS: algorithm invalid`);\n\n this.set('algorithm', val);\n }\n\n getAlgorithmOptions() {\n return new Map([\n [1, 'RSA/MD5'],\n [2, 'DH'],\n [3, 'DSA/SHA-1'],\n [4, 'EC'],\n [5, 'RSA/SHA-1'],\n [253, ''],\n [254, ''],\n ])\n }\n\n setDigestType(val) {\n if (![1, 2].includes(val)) this.throwHelp(`DS: digest type invalid`);\n\n this.set('digest type', val);\n }\n\n getDescription() {\n return 'Delegation Signer'\n }\n\n getCanonical() {\n return {\n owner: 'example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'DS',\n 'key tag': 12345,\n algorithm: 5,\n 'digest type': 1,\n digest: 'ABCDEF123...',\n }\n }\n\n /****** IMPORTERS *******/\n\n fromTinydns(opts) {\n const { tinyline } = opts;\n const { owner, typeId, rdata, ttl, timestamp, location } = this.parseTinydnsLine(tinyline);\n if (typeId != this.getTypeId()) this.throwHelp('DS fromTinydns, invalid n');\n\n const binRdata = octalRdataToBytes(rdata);\n\n return new DS({\n owner,\n ttl,\n type: 'DS',\n 'key tag': (binRdata[0] << 8) | binRdata[1],\n algorithm: binRdata[2],\n 'digest type': binRdata[3],\n digest: bytesToHex(binRdata.subarray(4)).toUpperCase(),\n timestamp,\n location,\n })\n }\n\n fromWire({ owner, cls, ttl, rdata }) {\n const dv = new DataView(rdata.buffer, rdata.byteOffset);\n return new DS({\n owner,\n ttl,\n class: cls,\n type: 'DS',\n 'key tag': dv.getUint16(0),\n algorithm: rdata[2],\n 'digest type': rdata[3],\n digest: bytesToHex(rdata.subarray(4)).toUpperCase(),\n })\n }\n\n /****** EXPORTERS *******/\n\n toTinydns() {\n return this.getTinydnsGeneric(\n UInt16toOctal(this.get('key tag')) +\n UInt8toOctal(this.get('algorithm')) +\n UInt8toOctal(this.get('digest type')) +\n packHex(this.get('digest').replace(/\\s+/g, '')),\n )\n }\n\n getWireRdata() {\n const digestBytes = hexToBytes(this.get('digest').replace(/\\s+/g, ''));\n const bytes = new Uint8Array(4 + digestBytes.length);\n const dv = new DataView(bytes.buffer, bytes.byteOffset);\n dv.setUint16(0, this.get('key tag'));\n bytes[2] = this.get('algorithm');\n bytes[3] = this.get('digest type');\n bytes.set(digestBytes, 4);\n return bytes\n }\n}\n\nclass HINFO extends RR {\n static typeName = 'HINFO'\n static typeId = 13\n static RFCs = [1034, 1035, 8482]\n static rdataFields = [\n ['cpu', 'qcharstr'],\n ['os', 'qcharstr'],\n ]\n static tags = ['obsolete']\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setCpu(val) {\n if (val.length > 255) this.throwHelp('HINFO cpu cannot exceed 255 chars');\n this.set('cpu', val.replace(/^[\"']|[\"']$/g, ''));\n }\n\n setOs(val) {\n if (val.length > 255) this.throwHelp('HINFO os cannot exceed 255 chars');\n this.set('os', val.replace(/^[\"']|[\"']$/g, ''));\n }\n\n getDescription() {\n return 'Host Info'\n }\n\n getCanonical() {\n return {\n owner: 'test.example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'HINFO',\n cpu: 'DEC-2060',\n os: 'TOPS20',\n }\n }\n\n /****** IMPORTERS *******/\n fromTinydns({ tinyline }) {\n // HINFO via generic, :fqdn:n:rdata:ttl:timestamp:lo\n const [fqdn, , rdata, ttl, ts, loc] = tinyline.slice(1).split(':');\n const [cpu, os] = [...unpackString(rdata)];\n\n return new this.constructor({\n owner: this.fullyQualify(fqdn),\n ttl: parseInt(ttl, 10),\n type: 'HINFO',\n cpu,\n os,\n timestamp: ts,\n location: loc?.trim() ?? '',\n })\n }\n\n /****** EXPORTERS *******/\n\n getWireRdata() {\n const cpu = new TextEncoder().encode(this.get('cpu'));\n const os = new TextEncoder().encode(this.get('os'));\n const result = new Uint8Array(2 + cpu.length + os.length);\n result[0] = cpu.length;\n result.set(cpu, 1);\n result[1 + cpu.length] = os.length;\n result.set(os, 2 + cpu.length);\n return result\n }\n\n toTinydns() {\n return this.getTinydnsGeneric(\n [packString(this.get('cpu')), packString(this.get('os'))].join(''),\n )\n }\n}\n\nclass HIP extends RR {\n static typeName = 'HIP'\n static typeId = 55\n static RFCs = [8005]\n static rdataFields = ['pk algorithm', 'hit', 'public key', 'rendezvous servers']\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setPkAlgorithm(val) {\n if (val === undefined) this.throwHelp('HIP: pk algorithm is required');\n this.is8bitInt('HIP', 'pk algorithm', val);\n this.set('pk algorithm', val);\n }\n\n setHit(val) {\n if (!val) this.throwHelp('HIP: hit is required');\n this.set('hit', val);\n }\n\n setPublicKey(val) {\n if (!val) this.throwHelp('HIP: public key is required');\n this.set('public key', val);\n }\n\n setRendezvousServers(val) {\n this.set('rendezvous servers', val ?? '');\n }\n\n getDescription() {\n return 'Host Identity Protocol'\n }\n\n getCanonical() {\n return {\n owner: 'example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'HIP',\n 'pk algorithm': 2,\n hit: '200100107B1A74DF365639CC39F1D578',\n 'public key':\n 'AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwIXAqcOTiW7iHnQt5hwVAAAAA==',\n 'rendezvous servers': '',\n }\n }\n\n /****** IMPORTERS *******/\n fromTinydns({ tinyline }) {\n // HIP via generic, :fqdn:55:rdata:ttl:timestamp:lo\n const [fqdn, n, rdata, ttl, ts, loc] = tinyline.slice(1).split(':');\n if (n != 55) this.throwHelp('HIP fromTinydns, invalid n');\n\n const bytes = Uint8Array.from(octalToChar(rdata), (c) => c.charCodeAt(0));\n const hitLen = bytes[0];\n const pkAlgorithm = bytes[1];\n const pkLen = (bytes[2] << 8) | bytes[3];\n\n const hit = bytesToHex(bytes.subarray(4, 4 + hitLen)).toUpperCase();\n const publicKey = bytesToBase64(bytes.subarray(4 + hitLen, 4 + hitLen + pkLen));\n\n const rvsNames = [];\n let pos = 4 + hitLen + pkLen;\n while (pos < bytes.length) {\n const [name, newPos] = unpackDomainName(\n [...bytes.subarray(pos)]\n .map((b) => (b < 32 || b > 126 ? UInt8toOctal(b) : String.fromCharCode(b)))\n .join(''),\n );\n pos += newPos;\n if (name !== '.') rvsNames.push(name);\n }\n\n return new HIP({\n owner: this.fullyQualify(fqdn),\n ttl: parseInt(ttl, 10),\n type: 'HIP',\n 'pk algorithm': pkAlgorithm,\n hit,\n 'public key': publicKey,\n 'rendezvous servers': rvsNames.join(' '),\n timestamp: ts,\n location: loc?.trim() ?? '',\n })\n }\n\n fromBind({ bindline }) {\n // owner ttl IN HIP pk-algorithm HIT public-key [rendezvous-server...]\n // The public key may be split across multiple lines and joined with spaces\n // by the zone parser. Base64 chars are [A-Za-z0-9+/=]; domain names contain '.'.\n const parts = bindline.split(/\\s+/);\n const [owner, ttl, c, type, pkAlgorithm, hit] = parts;\n const rest = parts.slice(6);\n const keyParts = [];\n const rvsParts = [];\n for (const token of rest) {\n if (/^[A-Za-z0-9+/=]+$/.test(token)) {\n keyParts.push(token);\n } else {\n rvsParts.push(token);\n }\n }\n return new HIP({\n owner,\n ttl: parseInt(ttl, 10),\n class: c,\n type,\n 'pk algorithm': parseInt(pkAlgorithm, 10),\n hit,\n 'public key': keyParts.join(''),\n 'rendezvous servers': rvsParts.join(' ').trim(),\n })\n }\n\n fromWire({ owner, cls, ttl, rdata }) {\n const dv = new DataView(rdata.buffer, rdata.byteOffset);\n const hitLen = rdata[0];\n const pkAlgorithm = rdata[1];\n const pkLen = dv.getUint16(2);\n const hit = bytesToHex(rdata.subarray(4, 4 + hitLen)).toUpperCase();\n const publicKey = bytesToBase64(rdata.subarray(4 + hitLen, 4 + hitLen + pkLen));\n const rvsNames = [];\n let pos = 4 + hitLen + pkLen;\n while (pos < rdata.length) {\n const { fqdn, end } = this.wireUnpackDomain(rdata, pos);\n rvsNames.push(fqdn);\n pos = end;\n }\n return new HIP({\n owner,\n ttl,\n class: cls,\n type: 'HIP',\n 'pk algorithm': pkAlgorithm,\n hit,\n 'public key': publicKey,\n 'rendezvous servers': rvsNames.join(' '),\n })\n }\n\n /****** EXPORTERS *******/\n toBind(zone_opts) {\n const rs = this.get('rendezvous servers');\n const rsPart = rs ? `\\t${rs}` : '';\n return `${this.getPrefix(zone_opts)}\\t${this.get('pk algorithm')}\\t${this.get('hit')}\\t${this.get('public key')}${rsPart}\\n`\n }\n\n toTinydns() {\n const hitHex = this.get('hit');\n const hitBytes = hexToBytes(hitHex);\n const pkBytes = base64ToBytes(this.get('public key'));\n const rs = this.get('rendezvous servers');\n\n let rdata = '';\n rdata += UInt8toOctal(hitBytes.length);\n rdata += UInt8toOctal(this.get('pk algorithm'));\n rdata += UInt16toOctal(pkBytes.length);\n for (const b of hitBytes) rdata += UInt8toOctal(b);\n for (const b of pkBytes) rdata += UInt8toOctal(b);\n if (rs) {\n for (const name of rs.split(/\\s+/)) rdata += packDomainName(name);\n }\n\n return this.getTinydnsGeneric(rdata)\n }\n\n getWireRdata() {\n const hitHex = this.get('hit');\n const hitBytes = hexToBytes(hitHex);\n const pkBytes = base64ToBytes(this.get('public key'));\n const rs = this.get('rendezvous servers');\n\n const rsNames = rs ? rs.split(/\\s+/) : [];\n const rsDomains = rsNames.map((name) => wirePackDomain(name));\n const rsTotalLen = rsDomains.reduce((sum, b) => sum + b.length, 0);\n\n const totalLen = 1 + 1 + 2 + hitBytes.length + pkBytes.length + rsTotalLen;\n const bytes = new Uint8Array(totalLen);\n const dv = new DataView(bytes.buffer, bytes.byteOffset);\n\n let pos = 0;\n bytes[pos++] = hitBytes.length;\n bytes[pos++] = this.get('pk algorithm');\n dv.setUint16(pos, pkBytes.length);\n pos += 2;\n bytes.set(hitBytes, pos);\n pos += hitBytes.length;\n bytes.set(pkBytes, pos);\n pos += pkBytes.length;\n for (const rdomain of rsDomains) {\n bytes.set(rdomain, pos);\n pos += rdomain.length;\n }\n\n return bytes\n }\n}\n\nclass HTTPS extends RR {\n static typeName = 'HTTPS'\n static typeId = 65\n static RFCs = [9460]\n static tags = ['common']\n static rdataFields = [\n ['priority', 'u16'],\n ['target name', 'fqdn'],\n ['params', 'svcparams'],\n ]\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setPriority(val) {\n this.is16bitInt('HTTPS', 'priority', val);\n\n this.set('priority', val);\n }\n\n setTargetName(val) {\n // this.isFullyQualified('HTTPS', 'target name', val)\n // this.isValidHostname('HTTPS', 'target name', val)\n\n // RFC 4034: letters in the DNS names are lower cased\n this.set('target name', val.toLowerCase());\n }\n\n setParams(val) {\n // if (!val) this.throwHelp(`HTTPS: params is required`)\n\n this.set('params', val);\n }\n\n getDescription() {\n return 'HTTP Semantics'\n }\n\n getCanonical() {\n return {\n owner: 'example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'HTTPS',\n priority: 1,\n 'target name': 'example.com.',\n params: 'alpn=\"h2,h3\"',\n }\n }\n\n /****** IMPORTERS *******/\n\n fromBind({ bindline }) {\n // test.example.com 3600 IN HTTPS Priority TargetName Params\n const [owner, ttl, c, type, pri, fqdn] = bindline.split(/\\s+/);\n return new HTTPS({\n owner,\n ttl: parseInt(ttl, 10),\n class: c,\n type,\n priority: parseInt(pri, 10),\n 'target name': fqdn,\n params: bindline.split(/\\s+/).slice(6).join(' ').trim(),\n })\n }\n\n fromTinydns({ tinyline }) {\n const { owner, typeId, rdata, ttl, timestamp, location } = this.parseTinydnsLine(tinyline);\n if (typeId != this.getTypeId()) this.throwHelp('HTTPS fromTinydns, invalid n');\n const { priority, targetName, params } = parseSvcbLikeRdata(rdata, 'HTTPS');\n\n return new HTTPS({\n owner,\n ttl,\n type: 'HTTPS',\n priority,\n 'target name': targetName,\n params,\n timestamp,\n location,\n })\n }\n\n /****** EXPORTERS *******/\n\n toTinydns() {\n const dataRe = new RegExp(/[\\r\\n\\t:\\\\/]/, 'g');\n\n return this.getTinydnsGeneric(\n UInt16toOctal(this.get('priority')) +\n packDomainName(this.get('target name')) +\n escapeOctal(dataRe, this.get('params')),\n )\n }\n\n getWireRdata() {\n const targetBytes = this.wirePackDomain(this.get('target name'));\n const paramsBytes = svcParamsToWire(this.get('params'));\n const result = new Uint8Array(2 + targetBytes.length + paramsBytes.length);\n new DataView(result.buffer).setUint16(0, this.get('priority'));\n result.set(targetBytes, 2);\n result.set(paramsBytes, 2 + targetBytes.length);\n return result\n }\n}\n\nclass IPSECKEY extends RR {\n static typeName = 'IPSECKEY'\n static typeId = 45\n static RFCs = [4025]\n static rdataFields = ['precedence', 'gateway type', 'algorithm', 'gateway', 'publickey']\n static tags = ['security']\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setPrecedence(val) {\n // an 8-bit precedence for this record.\n this.is8bitInt('IPSECKEY', 'precedence', val);\n\n this.set('precedence', val);\n }\n\n setGatewayType(val) {\n if (!this.getGatewayTypeOptions().has(val)) this.throwHelp(`IPSECKEY: Gateway Type is invalid`);\n\n this.set('gateway type', val);\n }\n\n getGatewayTypeOptions() {\n return new Map([\n [0, 'none'],\n [1, '4-byte IPv4'],\n [2, '16-byte IPv6'],\n [3, 'wire encoded domain name'],\n ])\n }\n\n setAlgorithm(val) {\n if (!this.getAlgorithmOptions().has(val)) this.throwHelp(`IPSECKEY: Algorithm invalid`);\n\n this.set('algorithm', val);\n }\n\n getAlgorithmOptions() {\n return new Map([\n [1, 'DSA'],\n [2, 'RSA'],\n ])\n }\n\n setGateway(val) {\n const type = this.get('gateway type');\n const gwErr = new Error(`IPSECKEY: gateway invalid (${val}) for type ${type}`);\n switch (type) {\n case 0:\n if (val !== '.') throw gwErr\n break\n case 1:\n if (!this.isIPv4(val)) throw gwErr\n break\n case 2:\n if (!this.isIPv6(val)) throw gwErr\n break\n }\n\n this.set('gateway', val);\n }\n\n setPublickey(val) {\n if (val) this.isBase64('IPSECKEY', 'publickey', val);\n this.set('publickey', val);\n }\n\n getDescription() {\n return 'IPsec Keying'\n }\n\n getCanonical() {\n return {\n owner: '38.2.0.192.in-addr.arpa.',\n ttl: 7200,\n class: 'IN',\n type: 'IPSECKEY',\n precedence: 10,\n 'gateway type': 1,\n algorithm: 2,\n gateway: '192.0.2.38',\n publickey: 'AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==',\n }\n }\n\n /****** IMPORTERS *******/\n fromBind({ bindline }) {\n // FQDN TTL CLASS IPSECKEY Precedence GatewayType Algorithm Gateway PublicKey\n const [owner, ttl, c, type, prec, gwt, algo, gateway, publickey] = bindline.split(/\\s+/);\n return new IPSECKEY({\n owner,\n ttl: parseInt(ttl, 10),\n class: c,\n type,\n precedence: parseInt(prec, 10),\n 'gateway type': parseInt(gwt, 10),\n algorithm: parseInt(algo, 10),\n gateway,\n publickey,\n })\n }\n\n fromTinydns({ tinyline }) {\n const [fqdn, n, rdata, ttl, ts, loc] = tinyline.slice(1).split(':');\n if (n != 45) this.throwHelp('IPSECKEY fromTinydns, invalid n');\n\n const precedence = octalToUInt8(rdata.slice(0, 4));\n const gwType = octalToUInt8(rdata.slice(4, 8));\n const algorithm = octalToUInt8(rdata.slice(8, 12));\n\n let len, gateway, octalKey;\n\n switch (gwType) {\n case 0: // no gateway\n gateway = rdata.slice(12, 13); // should always be: '.'\n octalKey = rdata.slice(13);\n break\n case 1: // 4-byte IPv4 address\n gateway = octalToIPv4(rdata.slice(12, 28));\n octalKey = rdata.slice(28);\n break\n case 2: // 16-byte IPv6\n gateway = octalToIPv6(rdata.slice(12, 76));\n octalKey = rdata.slice(76);\n break\n case 3: // wire encoded domain name\n[gateway, len] = unpackDomainName(rdata.slice(12));\n octalKey = rdata.slice(12 + len);\n break\n }\n\n return new IPSECKEY({\n owner: this.fullyQualify(fqdn),\n ttl: parseInt(ttl, 10),\n type: 'IPSECKEY',\n precedence,\n 'gateway type': gwType,\n algorithm,\n gateway,\n publickey: octalToBase64(octalKey),\n timestamp: ts,\n location: loc?.trim() ?? '',\n })\n }\n\n fromWire({ owner, cls, ttl, rdata }) {\n const precedence = rdata[0];\n const gwType = rdata[1];\n const algorithm = rdata[2];\n let gateway, keyStart;\n switch (gwType) {\n case 0:\n gateway = '.';\n keyStart = 3;\n break\n case 1:\n gateway = [...rdata.subarray(3, 7)].join('.');\n keyStart = 7;\n break\n case 2: {\n const dv = new DataView(rdata.buffer, rdata.byteOffset + 3);\n const groups = [];\n for (let i = 0; i < 16; i += 2) groups.push(dv.getUint16(i).toString(16).padStart(4, '0'));\n gateway = groups.join(':');\n keyStart = 19;\n break\n }\n case 3: {\n const { fqdn, end } = this.wireUnpackDomain(rdata, 3);\n gateway = fqdn;\n keyStart = end;\n break\n }\n }\n const publickey = bytesToBase64(rdata.subarray(keyStart));\n return new IPSECKEY({\n owner,\n ttl,\n class: cls,\n type: 'IPSECKEY',\n precedence,\n 'gateway type': gwType,\n algorithm,\n gateway,\n publickey,\n })\n }\n\n /****** EXPORTERS *******/\n\n toTinydns() {\n const rdataRe = new RegExp(/[\\r\\n\\t:\\\\/]/, 'g');\n\n let rdata = '';\n rdata += UInt8toOctal(this.get('precedence'));\n rdata += UInt8toOctal(this.get('gateway type'));\n rdata += UInt8toOctal(this.get('algorithm'));\n\n switch (this.get('gateway type')) {\n case 0:\n rdata += escapeOctal(rdataRe, '.');\n break\n case 1:\n rdata += ipv4toOctal(this.get('gateway'));\n break\n case 2:\n rdata += ipv6toOctal(this.get('gateway'));\n break\n case 3:\n rdata += packDomainName(this.get('gateway'));\n break\n }\n\n rdata += base64toOctal(this.get('publickey'));\n\n return this.getTinydnsGeneric(rdata)\n }\n\n getWireRdata() {\n const pubkeyBytes = base64ToBytes(this.get('publickey'));\n const gwType = this.get('gateway type');\n\n let gwBytes;\n switch (gwType) {\n case 0:\n gwBytes = new Uint8Array(0);\n break\n case 1:\n gwBytes = new Uint8Array(4);\n this.get('gateway')\n .split('.')\n .forEach((part, i) => {\n gwBytes[i] = parseInt(part, 10);\n });\n break\n case 2:\n gwBytes = new Uint8Array(16);\n {\n const parts = this.get('gateway').split(':');\n let pos = 0;\n for (const part of parts) {\n if (part === '') continue\n const val = parseInt(part, 16);\n gwBytes[pos++] = (val >>> 8) & 0xff;\n gwBytes[pos++] = val & 0xff;\n }\n }\n break\n case 3:\n gwBytes = wirePackDomain(this.get('gateway'));\n break\n }\n\n const bytes = new Uint8Array(3 + gwBytes.length + pubkeyBytes.length);\n bytes[0] = this.get('precedence');\n bytes[1] = gwType;\n bytes[2] = this.get('algorithm');\n bytes.set(gwBytes, 3);\n bytes.set(pubkeyBytes, 3 + gwBytes.length);\n\n return bytes\n }\n}\n\nclass KEY extends RR {\n static typeName = 'KEY'\n static typeId = 25\n static RFCs = [2535, 3445, 4034, 6840]\n static rdataFields = [\n ['flags', 'u16'],\n ['protocol', 'u8'],\n ['algorithm', 'u8'],\n ['publickey', 'base64'],\n ]\n static tags = ['obsolete']\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setFlags(val) {\n // a 2 octet Flags Field\n this.is16bitInt('KEY', 'flags', val);\n\n this.set('flags', val);\n }\n\n setProtocol(val) {\n // 1 octet\n this.is8bitInt('KEY', 'protocol', val);\n\n this.set('protocol', val);\n }\n\n setAlgorithm(val) {\n // 1 octet\n\n if (!this.getAlgorithmOptions().has(val)) this.throwHelp(`KEY: algorithm invalid`);\n\n this.set('algorithm', val);\n }\n\n getAlgorithmOptions() {\n return new Map([\n [1, 'RSA/MD5'],\n [2, 'DH'],\n [3, 'DSA/SHA-1'],\n [4, 'EC'],\n [5, 'RSA/SHA-1'],\n [253, ''],\n [254, ''],\n ])\n }\n\n setPublickey(val) {\n if (!val) this.throwHelp(`KEY: publickey is required`);\n this.isBase64('KEY', 'publickey', val.replace(/[\\s()]/g, ''));\n this.set('publickey', val);\n }\n\n getDescription() {\n return 'DNS Public Key'\n }\n\n getCanonical() {\n return {\n owner: 'example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'KEY',\n flags: 256,\n protocol: 3,\n algorithm: 5,\n publickey:\n 'AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwIXAqcOTiW7iHnQt5hwVAAAAA==',\n }\n }\n\n /****** IMPORTERS *******/\n\n fromBind({ bindline }) {\n // test.example.com 3600 IN KEY Flags Protocol Algorithm PublicKey\n const [owner, ttl, c, type, flags, protocol, algorithm] = bindline.split(/\\s+/);\n return new KEY({\n owner,\n ttl: parseInt(ttl, 10),\n class: c,\n type: type,\n flags: parseInt(flags, 10),\n protocol: parseInt(protocol, 10),\n algorithm: parseInt(algorithm, 10),\n publickey: bindline.split(/\\s+/).slice(7).join(' ').trim(),\n })\n }\n\n fromTinydns({ tinyline }) {\n // RDATA format: Flags (8 octal chars) + Protocol (4 octal chars) + Algorithm (4 octal chars) + Public Key (escaped data)\n const { owner, rdata, ttl, timestamp, location } = this.parseTinydnsLine(tinyline);\n if (rdata.length < 16) {\n this.throwHelp(`KEY: RDATA too short: ${rdata}`);\n }\n\n return new KEY({\n owner,\n ttl,\n type: 'KEY',\n flags: octalToUInt16(rdata.slice(0, 8)),\n protocol: octalToUInt8(rdata.slice(8, 12)),\n algorithm: octalToUInt8(rdata.slice(12, 16)),\n publickey: octalToBase64(rdata.slice(16)),\n timestamp,\n location,\n })\n }\n\n /****** EXPORTERS *******/\n toTinydns() {\n return this.getTinydnsGeneric(\n UInt16toOctal(this.get('flags')) +\n UInt8toOctal(this.get('protocol')) +\n UInt8toOctal(this.get('algorithm')) +\n base64toOctal(this.get('publickey').replace(/[\\s()]/g, '')),\n )\n }\n\n getWireRdata() {\n const keyBytes = base64ToBytes(this.get('publickey').replace(/[\\s()]/g, ''));\n const bytes = new Uint8Array(4 + keyBytes.length);\n const dv = new DataView(bytes.buffer, bytes.byteOffset);\n dv.setUint16(0, this.get('flags'));\n bytes[2] = this.get('protocol');\n bytes[3] = this.get('algorithm');\n bytes.set(keyBytes, 4);\n return bytes\n }\n}\n\nclass KX extends RR {\n static typeName = 'KX'\n static typeId = 36\n static RFCs = [2230]\n static rdataFields = [\n ['preference', 'u16'],\n ['exchanger', 'fqdn'],\n ]\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setPreference(val) {\n if (val === undefined) this.throwHelp('KX: preference is required');\n this.is16bitInt('KX', 'preference', val);\n this.set('preference', val);\n }\n\n setExchanger(val) {\n if (!val) this.throwHelp('KX: exchanger is required');\n\n this.isFullyQualified('KX', 'exchanger', val);\n this.isValidHostname('KX', 'exchanger', val);\n\n this.set('exchanger', val.toLowerCase());\n }\n\n getDescription() {\n return 'Key Exchanger'\n }\n\n getCanonical() {\n return {\n owner: 'example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'KX',\n preference: 10,\n exchanger: 'kx.example.com.',\n }\n }\n\n /****** IMPORTERS *******/\n fromTinydns({ tinyline }) {\n // KX via generic, :fqdn:36:rdata:ttl:timestamp:lo\n const [fqdn, n, rdata, ttl, ts, loc] = tinyline.slice(1).split(':');\n if (n != 36) this.throwHelp('KX fromTinydns, invalid n');\n\n return new KX({\n owner: this.fullyQualify(fqdn),\n ttl: parseInt(ttl, 10),\n type: 'KX',\n preference: octalToUInt16(rdata.slice(0, 8)),\n exchanger: unpackDomainName(rdata.slice(8))[0],\n timestamp: ts,\n location: loc?.trim() ?? '',\n })\n }\n\n /****** EXPORTERS *******/\n\n getWireRdata() {\n const exchanger = this.wirePackDomain(this.get('exchanger'));\n const result = new Uint8Array(2 + exchanger.length);\n const dv = new DataView(result.buffer);\n dv.setUint16(0, this.get('preference'));\n result.set(exchanger, 2);\n return result\n }\n\n toTinydns() {\n return this.getTinydnsGeneric(\n UInt16toOctal(this.get('preference')) + packDomainName(this.get('exchanger')),\n )\n }\n}\n\nconst REF = {\n // RFC 1876\n LATLON: 2 ** 31, // LAT equator, LON prime meridian\n ALTITUDE: 100000 * 100, // reference spheroid used by GPS, in cm\n};\n\nconst CONV = {\n sec: 1000,\n min: 60 * 1000,\n deg: 60 * 60 * 1000,\n};\n\nclass LOC extends RR {\n static typeName = 'LOC'\n static typeId = 29\n static RFCs = [1876]\n static rdataFields = ['address']\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setAddress(val) {\n if (!val) this.throwHelp('LOC: address is required');\n\n /*\n ... LOC ( d1 [m1 [s1]] {\"N\"|\"S\"} d2 [m2 [s2]]\n {\"E\"|\"W\"} alt[\"m\"] [siz[\"m\"] [hp[\"m\"]\n [vp[\"m\"]]]] )\n */\n this.parseLoc(val);\n\n this.set('address', val);\n }\n\n getDescription() {\n return 'Location'\n }\n\n getCanonical() {\n return {\n owner: 'example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'LOC',\n address: '52 22 23.000 N 4 53 32.000 E 10m 100m 10m 2m',\n }\n }\n\n parseLoc(string) {\n // d1 [m1 [s1]]\n const dms = '(\\\\d+)\\\\s+(?:(\\\\d+)\\\\s+)?(?:([\\\\d.]+)\\\\s+)?';\n\n // alt[\"m\"] [siz[\"m\"] [hp[\"m\"] [vp[\"m\"]]]]\n const alt = '(-?[\\\\d.]+)m?(?:\\\\s+([\\\\d.]+)m?)?(?:\\\\s+([\\\\d.]+)m?)?(?:\\\\s+([\\\\d.]+)m?)?';\n\n // put them all together\n const locRe = new RegExp(`^${dms}(N|S)\\\\s+${dms}(E|W)\\\\s+${alt}`, 'i');\n const r = string.match(locRe);\n if (!r) this.throwHelp('LOC address: invalid format, see RFC 1876');\n\n const loc = {\n latitude: {\n degrees: r[1],\n minutes: r[2],\n seconds: r[3],\n hemisphere: r[4].toUpperCase(),\n },\n longitude: {\n degrees: r[5],\n minutes: r[6],\n seconds: r[7],\n hemisphere: r[8].toUpperCase(),\n },\n altitude: r[9] * 100, // m -> cm\n size: r[10] * 100,\n precision: {\n horizontal: r[11] * 100,\n vertical: r[12] * 100,\n },\n };\n\n return loc\n }\n\n /****** IMPORTERS *******/\n fromTinydns({ tinyline }) {\n // LOC via generic, :fqdn:n:rdata:ttl:timestamp:lo\n const [fqdn, n, rdata, ttl, ts, loc] = tinyline.slice(1).split(':');\n if (n != 29) this.throwHelp('LOC fromTinydns, invalid n');\n\n // divide by 100 is to convert cm to meters\n const l = {\n version: octalToUInt8(rdata.slice(0, 4)),\n size: this.fromExponent(octalToUInt8(rdata.slice(4, 8))),\n precision: {\n horizontal: this.fromExponent(octalToUInt8(rdata.slice(8, 12))),\n vertical: this.fromExponent(octalToUInt8(rdata.slice(12, 16))),\n },\n latitude: this.arcSecToDMS(octalToUInt32(rdata.slice(16, 32)), 'lat'),\n longitude: this.arcSecToDMS(octalToUInt32(rdata.slice(32, 48)), 'lon'),\n altitude: octalToUInt32(rdata.slice(48, 64)) - REF.ALTITUDE,\n };\n\n return new LOC({\n type: 'LOC',\n owner: this.fullyQualify(fqdn),\n address: this.toHuman(l),\n ttl: parseInt(ttl, 10),\n timestamp: ts,\n location: loc?.trim() ?? '',\n })\n }\n\n fromBind({ bindline }) {\n const [owner, ttl, c, type] = bindline.split(/\\s+/);\n\n return new LOC({\n owner,\n ttl: parseInt(ttl, 10),\n class: c,\n type: type,\n address: bindline.split(/\\s+/).slice(4).join(' ').trim(),\n })\n }\n\n dmsToArcSec(obj) {\n let retval = obj.degrees * CONV.deg + (obj.minutes ?? 0) * CONV.min + (obj.seconds ?? 0) * CONV.sec;\n switch (obj.hemisphere.toUpperCase()) {\n case 'W':\n case 'S':\n retval = -retval;\n break\n }\n retval += REF.LATLON;\n return retval\n }\n\n arcSecToDMS(rawmsec, latlon) {\n let msec = Math.abs(rawmsec - REF.LATLON);\n // console.log(`rawmsec: ${rawmsec}, abs msec: ${msec}`)\n\n const deg = Math.floor(msec / CONV.deg);\n msec -= deg * CONV.deg;\n\n const min = Math.floor(msec / CONV.min);\n msec -= min * CONV.min;\n\n const sec = Math.floor(msec / CONV.sec);\n msec -= sec * CONV.sec;\n\n let hem;\n switch (latlon) {\n case 'lat':\n hem = rawmsec >= REF.LATLON ? 'N' : 'S';\n break\n case 'lon':\n hem = rawmsec >= REF.LATLON ? 'E' : 'W';\n break\n default:\n this.throwHelp('unknown or missing hemisphere');\n }\n\n return `${deg} ${min} ${sec}${msec ? '.' + msec : ''} ${hem}`\n }\n\n fromExponent(prec) {\n const mantissa = ((prec >> 4) & 0x0f) % 10;\n const exponent = ((prec >> 0) & 0x0f) % 10;\n return mantissa * Math.pow(10, exponent)\n }\n\n toExponent(val) {\n /*\n RFC 1876, ... expressed as a pair of four-bit unsigned\n integers, each ranging from zero to nine, with the most\n significant four bits representing the base and the second\n number representing the power of ten by which to multiply\n the base.\n */\n let exponent = 0;\n while (val >= 10) {\n val /= 10;\n ++exponent;\n }\n return (parseInt(val) << 4) | (exponent & 0x0f)\n }\n\n toHuman(obj) {\n let r = `${obj.latitude} ${obj.longitude} ${obj.altitude / 100}m`;\n if (obj.size) r += ` ${obj.size / 100}m`;\n if (obj.precision.horizontal) r += ` ${obj.precision.horizontal / 100}m`;\n if (obj.precision.vertical) r += ` ${obj.precision.vertical / 100}m`;\n return r\n }\n\n fromWire({ owner, cls, ttl, rdata }) {\n const dv = new DataView(rdata.buffer, rdata.byteOffset);\n const l = {\n size: this.fromExponent(rdata[1]),\n precision: {\n horizontal: this.fromExponent(rdata[2]),\n vertical: this.fromExponent(rdata[3]),\n },\n latitude: this.arcSecToDMS(dv.getUint32(4), 'lat'),\n longitude: this.arcSecToDMS(dv.getUint32(8), 'lon'),\n altitude: dv.getUint32(12) - REF.ALTITUDE,\n };\n return new LOC({\n owner,\n ttl,\n class: cls,\n type: 'LOC',\n address: this.toHuman(l),\n })\n }\n\n /****** EXPORTERS *******/\n\n toTinydns() {\n const loc = this.parseLoc(this.get('address'));\n\n // LOC format declares in meters, tinydns uses cm (hence * 100)\n let rdata = '';\n rdata += UInt8toOctal(0); // version\n rdata += UInt8toOctal(this.toExponent(loc.size));\n rdata += UInt8toOctal(this.toExponent(loc.precision.horizontal));\n rdata += UInt8toOctal(this.toExponent(loc.precision.vertical));\n rdata += UInt32toOctal(this.dmsToArcSec(loc.latitude));\n rdata += UInt32toOctal(this.dmsToArcSec(loc.longitude));\n rdata += UInt32toOctal(loc.altitude + REF.ALTITUDE);\n\n return this.getTinydnsGeneric(rdata)\n }\n\n getWireRdata() {\n const loc = this.parseLoc(this.get('address'));\n const bytes = new Uint8Array(16);\n const dv = new DataView(bytes.buffer, bytes.byteOffset);\n\n bytes[0] = 0; // version\n bytes[1] = this.toExponent(loc.size);\n bytes[2] = this.toExponent(loc.precision.horizontal);\n bytes[3] = this.toExponent(loc.precision.vertical);\n dv.setUint32(4, this.dmsToArcSec(loc.latitude));\n dv.setUint32(8, this.dmsToArcSec(loc.longitude));\n dv.setUint32(12, loc.altitude + REF.ALTITUDE);\n\n return bytes\n }\n}\n\nclass MX extends RR {\n static typeName = 'MX'\n static typeId = 15\n static RFCs = [1035, 2181, 7505]\n static tinydnsType = '@'\n static rdataFields = [\n ['preference', 'u16'],\n ['exchange', 'fqdn'],\n ]\n static tags = ['common']\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setPreference(val) {\n if (val === undefined) val = this?.default?.preference;\n if (val === undefined) this.throwHelp('MX: preference is required');\n this.is16bitInt('MX', 'preference', val);\n this.set('preference', val);\n }\n\n getDescription() {\n return 'Mail Exchanger'\n }\n\n getCanonical() {\n return {\n owner: 'example.com.',\n ttl: 43200,\n class: 'IN',\n type: 'MX',\n preference: 10,\n exchange: 'mail.example.com.',\n }\n }\n\n /****** IMPORTERS *******/\n fromTinydns({ tinyline }) {\n // @fqdn:ip:x:dist:ttl:timestamp:lo\n const [owner, _ip, x, preference, ttl, ts, loc] = tinyline.slice(1).split(':');\n\n return new MX({\n type: 'MX',\n owner: this.fullyQualify(owner),\n exchange: this.fullyQualify(/\\./.test(x) ? x : `${x}.mx.${owner}`),\n preference: parseInt(preference, 10) || 0,\n ttl: parseInt(ttl, 10),\n timestamp: ts,\n location: loc?.trim() ?? '',\n })\n }\n\n /****** EXPORTERS *******/\n getWireRdata() {\n const domain = this.wirePackDomain(this.get('exchange'));\n const result = new Uint8Array(2 + domain.length);\n new DataView(result.buffer).setUint16(0, this.get('preference'));\n result.set(domain, 2);\n return result\n }\n\n toTinydns() {\n return `@${this.getTinyFQDN('owner')}::${this.getTinyFQDN('exchange')}:${this.get('preference')}:${this.getTinydnsPostamble()}\\n`\n }\n}\n\nconst rdataRe = /[\\r\\n\\t:\\\\/]/;\n\nclass NAPTR extends RR {\n static typeName = 'NAPTR'\n static typeId = 35\n static RFCs = [2915, 3403, 4848]\n static rdataFields = [\n ['order', 'u16'],\n ['preference', 'u16'],\n ['flags', 'qcharstr'],\n ['service', 'qcharstr'],\n ['regexp', 'qcharstr'],\n ['replacement', 'fqdn'],\n ]\n\n constructor(opts) {\n super(opts);\n }\n\n getDescription() {\n return 'Naming Authority Pointer'\n }\n\n getCanonical() {\n return {\n owner: 'cid.urn.arpa.',\n ttl: 3600,\n class: 'IN',\n type: 'NAPTR',\n order: 100,\n preference: 10,\n flags: 'S',\n service: 'z3950+N2L+N2R',\n regexp: '',\n replacement: 'gatekeeper.example.com.',\n }\n }\n\n /****** Resource record specific setters *******/\n setOrder(val) {\n this.is16bitInt('NAPTR', 'order', val);\n this.set('order', val);\n }\n\n setPreference(val) {\n this.is16bitInt('NAPTR', 'preference', val);\n this.set('preference', val);\n }\n\n setFlags(val) {\n if (!this.getFlagsOptions().has(val.toUpperCase())) this.throwHelp(`NAPTR flags are invalid`);\n\n this.set('flags', val.toUpperCase());\n }\n\n getFlagsOptions() {\n return new Map([[''], ['S'], ['A'], ['U'], ['P']])\n }\n\n setService(val) {\n this.set('service', val);\n }\n\n setRegexp(val) {\n this.set('regexp', val);\n }\n\n setReplacement(val) {\n this.set('replacement', val);\n }\n\n /****** IMPORTERS *******/\n fromTinydns({ tinyline }) {\n // NAPTR via generic, :fqdn:n:rdata:ttl:timestamp:lo\n const { owner, typeId, rdata, ttl, timestamp, location } = this.parseTinydnsLine(tinyline);\n if (typeId != this.getTypeId()) this.throwHelp('NAPTR fromTinydns, invalid n');\n\n const binRdata = octalRdataToBytes(rdata);\n const dv = new DataView(binRdata.buffer, binRdata.byteOffset, binRdata.byteLength);\n\n const rec = {\n type: 'NAPTR',\n owner,\n ttl,\n timestamp,\n location,\n order: dv.getUint16(0),\n preference: dv.getUint16(2),\n };\n\n let idx = 4;\n const flagsLength = binRdata[idx];\n idx++;\n rec.flags = new TextDecoder().decode(binRdata.subarray(idx, idx + flagsLength));\n idx += flagsLength;\n\n const serviceLen = binRdata[idx];\n idx++;\n rec.service = new TextDecoder().decode(binRdata.subarray(idx, idx + serviceLen));\n idx += serviceLen;\n\n const regexpLen = binRdata[idx];\n idx++;\n rec.regexp = new TextDecoder().decode(binRdata.subarray(idx, idx + regexpLen));\n idx += regexpLen;\n\n const replaceLen = binRdata[idx];\n idx++;\n rec.replacement = new TextDecoder().decode(binRdata.subarray(idx, idx + replaceLen));\n\n return new NAPTR(rec)\n }\n\n fromBind({ bindline }) {\n const regex =\n /^(?\\S+)\\s+(?\\d+)\\s+(?\\S+)\\s+(?NAPTR)\\s+(?\\d+)\\s+(?\\d+)\\s+[\"'](?[^\"']*)[\"']\\s+[\"'](?[^\"']*)[\"']\\s+[\"'](?[^\"']*)[\"']\\s+(?\\S+)$/;\n\n const match = bindline.trim().match(regex);\n\n if (!match) {\n throw new Error(`Invalid NAPTR BIND line: ${bindline}`)\n }\n\n const { owner, ttl, type, order, preference, flags, service, regexp, replacement } = match.groups;\n\n return new NAPTR({\n owner: this.fullyQualify(owner),\n ttl: parseInt(ttl, 10),\n class: match.groups.class,\n type,\n order: parseInt(order, 10),\n preference: parseInt(preference, 10),\n flags,\n service,\n regexp,\n replacement,\n })\n }\n\n /****** EXPORTERS *******/\n toTinydns() {\n let rdata =\n UInt16toOctal(this.get('order')) +\n UInt16toOctal(this.get('preference')) +\n UInt8toOctal(this.get('flags').length) +\n this.get('flags') +\n UInt8toOctal(this.get('service').length) +\n escapeOctal(rdataRe, this.get('service')) +\n UInt8toOctal(this.get('regexp').length) +\n escapeOctal(rdataRe, this.get('regexp'));\n\n const replacement = this.get('replacement');\n if (replacement !== '') {\n rdata += UInt8toOctal(replacement.length);\n rdata += escapeOctal(rdataRe, replacement);\n }\n rdata += '\\\\000';\n\n return this.getTinydnsGeneric(rdata)\n }\n\n getWireRdata() {\n const enc = new TextEncoder();\n const flags = enc.encode(this.get('flags'));\n const service = enc.encode(this.get('service'));\n const regexp = enc.encode(this.get('regexp'));\n const replacementBytes = this.wirePackDomain(this.get('replacement'));\n\n const len = 4 + 1 + flags.length + 1 + service.length + 1 + regexp.length + replacementBytes.length;\n const buf = new Uint8Array(len);\n const view = new DataView(buf.buffer);\n let pos = 0;\n view.setUint16(pos, this.get('order'));\n pos += 2;\n view.setUint16(pos, this.get('preference'));\n pos += 2;\n buf[pos++] = flags.length;\n buf.set(flags, pos);\n pos += flags.length;\n buf[pos++] = service.length;\n buf.set(service, pos);\n pos += service.length;\n buf[pos++] = regexp.length;\n buf.set(regexp, pos);\n pos += regexp.length;\n buf.set(replacementBytes, pos);\n return buf\n }\n}\n\nclass NS extends RR {\n static typeName = 'NS'\n static typeId = 2\n static RFCs = [1035]\n static tinydnsType = '&'\n static rdataFields = [['dname', 'fqdn']]\n static tags = ['common']\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setDname(val) {\n if (!val) this.throwHelp(`NS: dname is required`);\n\n this.isFullyQualified('NS', 'dname', val);\n this.isValidHostname('NS', 'dname', val);\n\n // RFC 4034: letters in the DNS names are lower cased\n this.set('dname', val.toLowerCase());\n }\n\n getDescription() {\n return 'Name Server'\n }\n\n getCanonical() {\n return {\n owner: 'example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'NS',\n dname: 'ns1.example.com.',\n }\n }\n\n /****** IMPORTERS *******/\n fromTinydns({ tinyline }) {\n // &fqdn:ip:x:ttl:timestamp:lo\n const [fqdn, _ip, dname, ttl, ts, loc] = tinyline.slice(1).split(':');\n\n return new NS({\n type: 'NS',\n owner: this.fullyQualify(fqdn),\n dname: this.fullyQualify(/\\./.test(dname) ? dname : `${dname}.ns.${fqdn}`),\n ttl: parseInt(ttl, 10),\n timestamp: ts,\n location: loc?.trim() ?? '',\n })\n }\n\n /****** EXPORTERS *******/\n getWireRdata() {\n return this.wirePackDomain(this.get('dname'))\n }\n\n toTinydns() {\n return `&${this.getTinyFQDN('owner')}::${this.getTinyFQDN('dname')}:${this.getTinydnsPostamble()}\\n`\n }\n}\n\nclass NSEC extends RR {\n static typeName = 'NSEC'\n static typeId = 47\n static RFCs = [4034]\n static rdataFields = ['next domain', 'type bit maps']\n static tags = ['dnssec']\n\n constructor(opts) {\n super(opts);\n if (opts === null) return\n }\n\n /****** Resource record specific setters *******/\n setNextDomain(val) {\n if (!val) this.throwHelp(`NSEC: 'next domain' is required:`);\n\n this.isFullyQualified('NSEC', 'next domain', val);\n this.isValidHostname('NSEC', 'next domain', val);\n\n // RFC 4034: letters in the DNS names are lower cased\n this.set('next domain', val.toLowerCase());\n }\n\n setTypeBitMaps(val) {\n if (!val) this.throwHelp(`NSEC: 'type bit maps' is required`);\n\n this.set('type bit maps', val);\n }\n\n getDescription() {\n return 'Next Secure'\n }\n\n getCanonical() {\n return {\n owner: 'alfa.example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'NSEC',\n 'next domain': 'host.example.com.',\n 'type bit maps': 'A MX RRSIG NSEC TYPE1234',\n }\n }\n\n /****** IMPORTERS *******/\n\n fromTinydns({ tinyline }) {\n const [owner, _typeId, rdata, ttl, ts, loc] = tinyline.slice(1).split(':');\n const binaryRdata = Uint8Array.from(octalToChar(rdata), (c) => c.charCodeAt(0));\n const [nextDomain, _escapedLen, binaryLen] = unpackDomainName(rdata);\n\n return new NSEC({\n owner: this.fullyQualify(owner),\n ttl: parseInt(ttl, 10),\n type: 'NSEC',\n 'next domain': nextDomain,\n 'type bit maps': new TextDecoder().decode(binaryRdata.subarray(binaryLen)),\n timestamp: ts,\n location: loc?.trim() ?? '',\n })\n }\n\n fromBind({ bindline }) {\n // test.example.com 3600 IN NSEC NextDomain TypeBitMaps\n const [owner, ttl, c, type, next] = bindline.split(/\\s+/);\n return new NSEC({\n owner,\n ttl: parseInt(ttl, 10),\n class: c,\n type: type,\n 'next domain': next,\n 'type bit maps': bindline.split(/\\s+/).slice(5).filter(removeParens$1).join(' ').trim(),\n })\n }\n\n fromWire({ owner, cls, ttl, rdata }) {\n const { fqdn: nextDomain, end } = this.wireUnpackDomain(rdata, 0);\n const typeBitMaps = nsecBitmapToTypes(rdata.subarray(end));\n return new NSEC({\n owner,\n ttl,\n class: cls,\n type: 'NSEC',\n 'next domain': nextDomain,\n 'type bit maps': typeBitMaps,\n })\n }\n\n /****** EXPORTERS *******/\n\n toTinydns() {\n const dataRe = new RegExp(/[\\r\\n\\t:\\\\/]/, 'g');\n\n return this.getTinydnsGeneric(\n packDomainName(this.get('next domain')) +\n escapeOctal(dataRe, this.get('type bit maps')),\n )\n }\n\n getWireRdata() {\n const nameBytes = this.wirePackDomain(this.get('next domain'));\n const bitmapBytes = typesToNsecBitmap(this.get('type bit maps'));\n const result = new Uint8Array(nameBytes.length + bitmapBytes.length);\n result.set(nameBytes);\n result.set(bitmapBytes, nameBytes.length);\n return result\n }\n}\n\nconst removeParens$1 = (a) => !['(', ')'].includes(a);\n\nfunction nsecBitmapToTypes(bitmap) {\n const DNS_TYPE_NAMES = Object.fromEntries(Object.entries(DNS_TYPE_IDS).map(([k, v]) => [v, k]));\n const types = [];\n let pos = 0;\n while (pos + 2 <= bitmap.length) {\n const windowNum = bitmap[pos];\n const bitmapLen = bitmap[pos + 1];\n pos += 2;\n for (let i = 0; i < bitmapLen; i++) {\n const byte = bitmap[pos + i];\n for (let bit = 0; bit < 8; bit++) {\n if (byte & (0x80 >> bit)) {\n const typeId = windowNum * 256 + i * 8 + bit;\n types.push(DNS_TYPE_NAMES[typeId] ?? `TYPE${typeId}`);\n }\n }\n }\n pos += bitmapLen;\n }\n return types.join(' ')\n}\n\nfunction typesToNsecBitmap(typeNamesStr) {\n const typeIds = typeNamesStr\n .trim()\n .split(/\\s+/)\n .map((t) => {\n if (/^TYPE\\d+$/i.test(t)) return parseInt(t.slice(4), 10)\n return DNS_TYPE_IDS[t.toUpperCase()]\n })\n .filter((id) => id !== undefined && id >= 0);\n\n const windows = new Map();\n for (const id of typeIds) {\n const w = Math.floor(id / 256);\n if (!windows.has(w)) windows.set(w, []);\n windows.get(w).push(id % 256);\n }\n\n const blocks = [];\n for (const [wNum, bits] of [...windows.entries()].sort((a, b) => a[0] - b[0])) {\n const maxBit = Math.max(...bits);\n const bitmapLen = Math.floor(maxBit / 8) + 1;\n const bitmap = new Uint8Array(bitmapLen);\n for (const b of bits) bitmap[Math.floor(b / 8)] |= 0x80 >> (b % 8);\n blocks.push(new Uint8Array([wNum, bitmapLen, ...bitmap]));\n }\n\n const total = blocks.reduce((s, b) => s + b.length, 0);\n const result = new Uint8Array(total);\n let pos = 0;\n for (const b of blocks) {\n result.set(b, pos);\n pos += b.length;\n }\n return result\n}\n\nclass NSEC3 extends RR {\n static typeName = 'NSEC3'\n static typeId = 50\n static RFCs = [5155, 9077]\n static rdataFields = [\n 'hash algorithm',\n 'flags',\n 'iterations',\n 'salt',\n 'next hashed owner name',\n 'type bit maps',\n ]\n static tags = ['dnssec']\n\n constructor(opts) {\n super(opts);\n if (opts === null) return\n }\n\n /****** Resource record specific setters *******/\n setHashAlgorithm(val) {\n // Hash Algorithm is a single octet.\n // The Hash Algorithm field is represented as an unsigned decimal integer.\n if (!val) this.throwHelp(`NSEC3: 'hash algorithm' is required`);\n\n this.is8bitInt('NSEC3', 'hash algorithm', val);\n\n this.set('hash algorithm', val);\n }\n\n setFlags(val) {\n // The Flags field is represented as an unsigned decimal integer.\n if (!val) this.throwHelp(`NSEC3: 'flags' is required`);\n\n this.is8bitInt('NSEC3', 'flags', val);\n\n this.set('flags', val);\n }\n\n setIterations(val) {\n // The Iterations field is represented as an unsigned decimal integer. 0-65535\n if (!val) this.throwHelp(`NSEC3: 'iterations' is required`);\n\n this.is16bitInt('NSEC3', 'flags', val);\n\n this.set('iterations', val);\n }\n\n setSalt(val) {\n // The Salt field is represented as a sequence of case-insensitive\n // hexadecimal digits. Whitespace is not allowed within the\n // sequence. The Salt field is represented as \"-\" (without the\n // quotes) when the Salt Length field has a value of 0\n this.set('salt', val);\n }\n\n setNextHashedOwnerName(val) {\n // The Next Hashed Owner Name field is represented as an unpadded\n // sequence of case-insensitive base32 digits, without whitespace\n if (!val) this.throwHelp(`NSEC3: 'next hashed owner name' is required`);\n\n this.set('next hashed owner name', val);\n }\n\n setTypeBitMaps(val) {\n // The Type Bit Maps field is represented as a sequence of RR type mnemonics.\n if (!val) this.throwHelp(`NSEC3: 'type bit maps' is required`);\n\n this.set('type bit maps', val);\n }\n\n getDescription() {\n return 'Next Secure'\n }\n\n getCanonical() {\n return {\n owner: 'test.example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'NSEC3',\n 'hash algorithm': 1,\n flags: 1,\n iterations: 12,\n salt: 'aabbccdd',\n 'next hashed owner name': '2vptu5timamqttgl4luu9kg21e0aor3s',\n 'type bit maps': 'A RRSIG',\n }\n }\n\n /****** IMPORTERS *******/\n\n fromBind({ bindline }) {\n // test.example.com. 3600 IN NSEC3 1 1 12 aabbccdd (2vptu5timamqttgl4luu9kg21e0aor3s A RRSIG)\n const [owner, ttl, c, type, ha, flags, iterations, salt] = bindline.split(/\\s+/);\n // rdata may be parenthesized or inline\n const rdataStr = bindline.includes('(')\n ? bindline.split(/\\(|\\)/)[1]\n : bindline.split(/\\s+/).slice(8).join(' ');\n\n return new NSEC3({\n owner,\n ttl: parseInt(ttl, 10),\n class: c,\n type: type,\n 'hash algorithm': parseInt(ha, 10),\n flags: parseInt(flags, 10),\n iterations: parseInt(iterations, 10),\n salt,\n 'next hashed owner name': rdataStr.trim().split(/\\s+/)[0],\n 'type bit maps': rdataStr.trim().split(/\\s+/).slice(1).join('\\t'),\n })\n }\n\n fromTinydns({ tinyline }) {\n const [fqdn, n, rdata, ttl, ts, loc] = tinyline.slice(1).split(':');\n if (n != 50) this.throwHelp('NSEC3 fromTinydns, invalid n');\n\n const bytes = Uint8Array.from(octalToChar(rdata), (c) => c.charCodeAt(0));\n const dv = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);\n\n const hashAlgorithm = bytes[0];\n const flags = bytes[1];\n const iterations = dv.getUint16(2);\n\n // The remaining bytes in the buffer contain:\n // Salt Length (1 octet)\n // Salt (variable length based on Salt Length)\n // Next Hashed Owner Name (variable length)\n // Type Bit Maps (variable length)\n const { salt, nextHashedOwnerName, typeBitMaps } = parseNSEC3Buffer(bytes);\n\n return new NSEC3({\n owner: this.fullyQualify(fqdn),\n ttl: parseInt(ttl, 10),\n type: 'NSEC3',\n 'hash algorithm': hashAlgorithm,\n flags: flags,\n iterations: iterations,\n salt: salt,\n 'next hashed owner name': nextHashedOwnerName,\n 'type bit maps': typeBitMaps,\n timestamp: ts,\n location: loc?.trim() ?? '',\n })\n }\n\n fromWire({ owner, cls, ttl, rdata }) {\n const dv = new DataView(rdata.buffer, rdata.byteOffset);\n const { salt, nextHashedOwnerName, typeBitMaps } = parseNSEC3Buffer(rdata);\n return new NSEC3({\n owner,\n ttl,\n class: cls,\n type: 'NSEC3',\n 'hash algorithm': rdata[0],\n flags: rdata[1],\n iterations: dv.getUint16(2),\n salt,\n 'next hashed owner name': nextHashedOwnerName,\n 'type bit maps': typeBitMaps,\n })\n }\n\n /****** EXPORTERS *******/\n\n toBind(zone_opts) {\n return `${this.getFQDN('owner', zone_opts)}\t${this.get('ttl')}\t${this.get('class')}\tNSEC3${this.getRdataFields()\n .slice(0, 4)\n .map((f) => '\t' + this.get(f))\n .join('')}\t(${this.getRdataFields()\n .slice(4)\n .map((f) => this.get(f))\n .join('\t')})\n`\n }\n\n toTinydns() {\n const dataRe = new RegExp(/[\\r\\n\\t:\\\\/]/, 'g');\n\n return this.getTinydnsGeneric(\n UInt8toOctal(this.get('hash algorithm')) +\n UInt8toOctal(this.get('flags')) +\n UInt16toOctal(this.get('iterations')) +\n escapeOctal(dataRe, this.get('salt')) +\n escapeOctal(dataRe, this.get('next hashed owner name')) +\n escapeOctal(dataRe, this.get('type bit maps')),\n )\n }\n\n getWireRdata() {\n const tail = `${this.get('salt')}${this.get('next hashed owner name')}${this.get('type bit maps')}`;\n const tailBytes = new TextEncoder().encode(tail);\n\n const totalLen = 4 + tailBytes.length;\n const bytes = new Uint8Array(totalLen);\n const dv = new DataView(bytes.buffer, bytes.byteOffset);\n\n let pos = 0;\n bytes[pos++] = this.get('hash algorithm');\n bytes[pos++] = this.get('flags');\n dv.setUint16(pos, this.get('iterations'));\n pos += 2;\n bytes.set(tailBytes, pos);\n\n return bytes\n }\n}\n\nfunction parseNSEC3Buffer(bytes) {\n // bytes is a Uint8Array containing the full RDATA binary (hash alg, flags, iterations, then ASCII salt + next-hashed + type bit maps)\n // Start after the first 4 bytes (hash alg, flags, iterations)\n const rest = new TextDecoder().decode(bytes.subarray(4));\n\n // determine expected next hashed owner name length from hash algorithm\n const hashAlgorithm = bytes[0];\n // common mapping: algorithm 1 => SHA-1 => 20 bytes => base32 length 32\n const expectedLen = hashAlgorithm === 1 ? 32 : hashAlgorithm === 2 ? 52 : 32;\n\n // salt length is ambiguous in this representation; try to find a split where\n // the following segment matches expected base32 length\n let salt = '';\n let nextHashedOwnerName = '';\n let typeBitMaps = '';\n\n const maxSl = Math.min(64, rest.length);\n for (let sl = maxSl; sl >= 1; sl--) {\n const candNext = rest.slice(sl, sl + expectedLen);\n if (candNext.length !== expectedLen) continue\n if (!/^[0-9a-z]+$/.test(candNext)) continue\n // candidate looks like a base32 name; accept and treat remainder as type bit maps\n const saltCandidate = rest.slice(0, sl);\n if (!/^[0-9A-Fa-f]+$/.test(saltCandidate)) continue\n salt = saltCandidate;\n nextHashedOwnerName = candNext;\n typeBitMaps = rest.slice(sl + expectedLen);\n break\n }\n\n // fallback: if we couldn't find a split, treat everything up to first non-hex as salt\n if (!nextHashedOwnerName) {\n const saltMatch = rest.match(/^([0-9A-Fa-f]*)/);\n salt = saltMatch ? saltMatch[1] : '';\n nextHashedOwnerName = rest.slice(salt.length);\n typeBitMaps = '';\n }\n\n return {\n salt,\n nextHashedOwnerName,\n typeBitMaps,\n }\n}\n\nclass NSEC3PARAM extends RR {\n static typeName = 'NSEC3PARAM'\n static typeId = 51\n static RFCs = [5155]\n static rdataFields = ['hash algorithm', 'flags', 'iterations', 'salt']\n static tags = ['dnssec']\n\n constructor(opts) {\n super(opts);\n if (opts === null) return\n }\n\n /****** Resource record specific setters *******/\n setHashAlgorithm(val) {\n // Hash Algorithm is a single octet.\n // The Hash Algorithm field is represented as an unsigned decimal integer.\n if (val === undefined || val === null) this.throwHelp(`NSEC3PARAM: 'hash algorithm' is required`);\n\n this.is8bitInt('NSEC3PARAM', 'hash algorithm', val);\n\n this.set('hash algorithm', val);\n }\n\n setFlags(val) {\n // The Flags field is represented as an unsigned decimal integer.\n if (val === undefined || val === null) this.throwHelp(`NSEC3PARAM: 'flags' is required`);\n\n this.is8bitInt('NSEC3PARAM', 'flags', val);\n\n this.set('flags', val);\n }\n\n setIterations(val) {\n // The Iterations field is represented as an unsigned decimal integer. 0-65535\n if (val === undefined || val === null) this.throwHelp(`NSEC3PARAM: 'iterations' is required`);\n\n this.is16bitInt('NSEC3PARAM', 'iterations', val);\n\n this.set('iterations', val);\n }\n\n setSalt(val) {\n // The Salt field is represented as a sequence of case-insensitive\n // hexadecimal digits. Whitespace is not allowed within the\n // sequence. The Salt field is represented as \"-\" (without the\n // quotes) when the Salt Length field has a value of 0\n if (val === '-') {\n this.set('salt', val);\n return\n }\n\n if (val !== undefined && val !== null && !/^[0-9A-Fa-f]*$/.test(val)) {\n this.throwHelp(`NSEC3PARAM: 'salt' must be hex or '-'`);\n }\n\n this.set('salt', val);\n }\n\n getDescription() {\n return 'Next Secure Parameters'\n }\n\n getCanonical() {\n return {\n owner: 'example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'NSEC3PARAM',\n 'hash algorithm': 1,\n flags: 1,\n iterations: 12,\n salt: 'aabbccdd',\n }\n }\n\n /****** IMPORTERS *******/\n\n fromTinydns({ tinyline }) {\n // RDATA format: Hash Algorithm (3 octal chars) + Flags (3 octal chars) + Iterations (6 octal chars) + Salt (escaped hex string)\n const { owner, typeId, rdata, ttl, timestamp, location } = this.parseTinydnsLine(tinyline);\n if (typeId != this.getTypeId()) this.throwHelp('NSEC3PARAM fromTinydns, invalid n');\n if (rdata.length < 4) {\n this.throwHelp(`NSEC3PARAM: RDATA too short: ${rdata}`);\n }\n\n // rd may contain actual binary characters (from JS string '\\\\001' -> char 0x01),\n // so convert via octalToChar and read bytes from a Uint8Array for robust parsing.\n const bytes = octalRdataToBytes(rdata);\n\n return new NSEC3PARAM({\n owner,\n ttl,\n type: 'NSEC3PARAM',\n 'hash algorithm': bytes[0],\n flags: bytes[1],\n iterations: (bytes[2] << 8) | bytes[3],\n salt: bytes[4] === 0 ? '-' : bytesToHex(bytes.subarray(5, 5 + bytes[4])),\n timestamp,\n location,\n })\n }\n\n fromWire({ owner, cls, ttl, rdata }) {\n const dv = new DataView(rdata.buffer, rdata.byteOffset);\n const saltLen = rdata[4];\n const salt = saltLen === 0 ? '-' : bytesToHex(rdata.subarray(5, 5 + saltLen));\n return new NSEC3PARAM({\n owner,\n ttl,\n class: cls,\n type: 'NSEC3PARAM',\n 'hash algorithm': rdata[0],\n flags: rdata[1],\n iterations: dv.getUint16(2),\n salt,\n })\n }\n\n /****** EXPORTERS *******/\n\n toTinydns() {\n const salt = this.get('salt');\n const saltOctal =\n salt === '-' ? UInt8toOctal(0) : UInt8toOctal(salt.length / 2) + packHex(salt);\n\n return this.getTinydnsGeneric(\n UInt8toOctal(this.get('hash algorithm')) +\n UInt8toOctal(this.get('flags')) +\n UInt16toOctal(this.get('iterations')) +\n saltOctal,\n )\n }\n\n getWireRdata() {\n const salt = this.get('salt');\n const saltBytes = salt === '-' ? new Uint8Array(0) : hexToBytes(salt);\n const bytes = new Uint8Array(4 + 1 + saltBytes.length);\n const dv = new DataView(bytes.buffer, bytes.byteOffset);\n\n bytes[0] = this.get('hash algorithm');\n bytes[1] = this.get('flags');\n dv.setUint16(2, this.get('iterations'));\n bytes[4] = saltBytes.length;\n bytes.set(saltBytes, 5);\n\n return bytes\n }\n}\n\nclass NXT extends RR {\n static typeName = 'NXT'\n static typeId = 30\n static RFCs = [2065]\n static rdataFields = ['next domain', 'type bit map']\n static tags = ['obsolete']\n\n constructor(opts) {\n super(opts);\n if (opts === null) return\n }\n\n /****** Resource record specific setters *******/\n setNextDomain(val) {\n if (!val) this.throwHelp(`NXT: 'next domain' is required`);\n\n this.isFullyQualified('NXT', 'next domain', val);\n this.isValidHostname('NXT', 'next domain', val);\n\n // RFC 4034: letters in the DNS names are lower cased\n this.set('next domain', val.toLowerCase());\n }\n\n setTypeBitMap(val) {\n if (!val) this.throwHelp(`NXT: 'type bit map' is required`);\n\n this.set('type bit map', val);\n }\n\n getDescription() {\n return 'Next Secure'\n }\n\n getCanonical() {\n return {\n owner: 'big.example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'NXT',\n 'next domain': 'host.example.com.',\n 'type bit map': 'A MX NXT',\n }\n }\n\n /****** IMPORTERS *******/\n\n fromTinydns({ tinyline }) {\n const [owner, n, rdata, ttl, ts, loc] = tinyline.slice(1).split(':');\n if (parseInt(n, 10) !== this.getTypeId()) this.throwHelp('NXT fromTinydns, invalid n');\n\n const binaryRdata = Uint8Array.from(octalToChar(rdata), (c) => c.charCodeAt(0));\n const [nextDomain, _escapedLen, binaryLen] = unpackDomainName(rdata);\n\n return new NXT({\n owner: this.fullyQualify(owner),\n ttl: parseInt(ttl, 10),\n type: 'NXT',\n 'next domain': nextDomain,\n 'type bit map': new TextDecoder().decode(binaryRdata.subarray(binaryLen)),\n timestamp: ts,\n location: loc?.trim() ?? '',\n })\n }\n\n fromBind({ bindline }) {\n // test.example.com 3600 IN NXT NextDomain TypeBitMap\n const [owner, ttl, c, type, next] = bindline.split(/\\s+/);\n return new NXT({\n owner,\n ttl: parseInt(ttl, 10),\n class: c,\n type: type,\n 'next domain': next,\n 'type bit map': bindline.split(/\\s+/).slice(5).filter(removeParens).join(' ').trim(),\n })\n }\n\n fromWire({ owner, cls, ttl, rdata }) {\n const { fqdn: nextDomain, end } = this.wireUnpackDomain(rdata, 0);\n const typeBitMap = nxtBitmapToTypes(rdata.subarray(end));\n return new NXT({\n owner,\n ttl,\n class: cls,\n type: 'NXT',\n 'next domain': nextDomain,\n 'type bit map': typeBitMap,\n })\n }\n\n /****** EXPORTERS *******/\n\n toTinydns() {\n const dataRe = new RegExp(/[\\r\\n\\t:\\\\/]/, 'g');\n\n return this.getTinydnsGeneric(\n packDomainName(this.get('next domain')) + escapeOctal(dataRe, this.get('type bit map')),\n )\n }\n\n getWireRdata() {\n const nameBytes = this.wirePackDomain(this.get('next domain'));\n const bitmapBytes = typesToNxtBitmap(this.get('type bit map'));\n const result = new Uint8Array(nameBytes.length + bitmapBytes.length);\n result.set(nameBytes);\n result.set(bitmapBytes, nameBytes.length);\n return result\n }\n}\n\nconst removeParens = (a) => !['(', ')'].includes(a);\n\nfunction nxtBitmapToTypes(bitmap) {\n const DNS_TYPE_NAMES = Object.fromEntries(Object.entries(DNS_TYPE_IDS).map(([k, v]) => [v, k]));\n const types = [];\n for (let i = 0; i < bitmap.length; i++) {\n const byte = bitmap[i];\n for (let bit = 0; bit < 8; bit++) {\n if (byte & (0x80 >> bit)) {\n const typeId = i * 8 + bit;\n types.push(DNS_TYPE_NAMES[typeId] ?? `TYPE${typeId}`);\n }\n }\n }\n return types.join(' ')\n}\n\nfunction typesToNxtBitmap(typeNamesStr) {\n const bitmap = new Uint8Array(16);\n for (const name of typeNamesStr.trim().split(/\\s+/)) {\n const id = /^TYPE\\d+$/i.test(name) ? parseInt(name.slice(4), 10) : DNS_TYPE_IDS[name.toUpperCase()];\n if (id !== undefined && id < 128) bitmap[Math.floor(id / 8)] |= 0x80 >> (id % 8);\n }\n let len = bitmap.length;\n while (len > 0 && bitmap[len - 1] === 0) len--;\n return bitmap.slice(0, len)\n}\n\nclass OPENPGPKEY extends RR {\n static typeName = 'OPENPGPKEY'\n static typeId = 61\n static RFCs = [4880, 7929]\n static rdataFields = [['public key', 'base64']]\n static tags = ['security']\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setPublicKey(val) {\n this.isBase64('OPENPGPKEY', 'public key', val);\n this.set('public key', val);\n }\n\n getDescription() {\n return 'OpenPGP Public Key'\n }\n\n getCanonical() {\n return {\n owner: 'matt.example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'OPENPGPKEY',\n 'public key':\n 'AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwIXAqcOTiW7iHnQt5hwVAAAAA==',\n }\n }\n\n /****** IMPORTERS *******/\n fromBind({ bindline: bindline }) {\n // test.example.com 3600 IN OPENPGPKEY \n const regex =\n /^(?\\S+)\\s+(?\\d{1,10})\\s+(?IN)\\s+(?OPENPGPKEY)\\s+(?\\S[\\s\\S]*)$/i;\n const match = bindline.trim().match(regex);\n if (!match) this.throwHelp(`unable to parse OPENPGPKEY: ${bindline}`);\n\n const { owner, ttl, class: c, type, publickey } = match.groups;\n const keyStr = publickey.trim().replace(/\\s+/g, '');\n\n return new OPENPGPKEY({\n owner,\n ttl: parseInt(ttl, 10),\n class: c,\n type: type,\n 'public key': keyStr,\n })\n }\n\n fromTinydns({ tinyline }) {\n const { owner, typeId, rdata, ttl, timestamp, location } = this.parseTinydnsLine(tinyline);\n if (typeId != this.getTypeId()) this.throwHelp('OPENPGPKEY fromTinydns, invalid n');\n return new OPENPGPKEY({\n owner,\n ttl,\n type: 'OPENPGPKEY',\n 'public key': octalToBase64(rdata),\n timestamp,\n location,\n })\n }\n\n /****** EXPORTERS *******/\n toTinydns() {\n return this.getTinydnsGeneric(base64toOctal(this.get('public key')))\n }\n\n getWireRdata() {\n return base64ToBytes(this.get('public key'))\n }\n}\n\nclass PTR extends RR {\n static typeName = 'PTR'\n static typeId = 12\n static RFCs = [1035]\n static tinydnsType = '^'\n static rdataFields = [['dname', 'fqdn']]\n static tags = ['common']\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setDname(val) {\n this.isFullyQualified('PTR', 'dname', val);\n this.isValidHostname('PTR', 'dname', val);\n\n // RFC 4034: letters in the DNS names are lower cased\n this.set('dname', val.toLowerCase());\n }\n\n getDescription() {\n return 'Pointer'\n }\n\n getCanonical() {\n return {\n owner: '2.2.0.192.in-addr.arpa.',\n ttl: 3600,\n class: 'IN',\n type: 'PTR',\n dname: 'host.example.com.',\n }\n }\n\n /****** EXPORTERS *******/\n getWireRdata() {\n return this.wirePackDomain(this.get('dname'))\n }\n}\n\nclass RP extends RR {\n static typeName = 'RP'\n static rdataFields = [\n ['mbox', 'fqdn'],\n ['txt', 'fqdn'],\n ]\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setMbox(val) {\n if (!val) this.throwHelp('RP: mbox is required');\n\n this.isFullyQualified('RP', 'mbox', val);\n\n this.set('mbox', val.toLowerCase());\n }\n\n setTxt(val) {\n if (!val) this.throwHelp('RP: txt is required');\n\n this.isFullyQualified('RP', 'txt', val);\n\n this.set('txt', val.toLowerCase());\n }\n\n getDescription() {\n return 'Responsible Person'\n }\n static tags = ['obsolete']\n static RFCs = [1183]\n static typeId = 17\n getCanonical() {\n return {\n owner: 'example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'RP',\n mbox: 'admin.example.com.',\n txt: 'info.example.com.',\n }\n }\n\n /****** IMPORTERS *******/\n fromTinydns({ tinyline }) {\n const [owner, _typeId, rdata, ttl, ts, loc] = tinyline.slice(1).split(':');\n\n const [mbox, consumed] = unpackDomainName(rdata);\n const txt = unpackDomainName(rdata.slice(consumed))[0];\n\n return new RP({\n owner: this.fullyQualify(owner),\n ttl: parseInt(ttl, 10),\n type: 'RP',\n mbox,\n txt,\n timestamp: ts,\n location: loc?.trim() ?? '',\n })\n }\n\n /****** EXPORTERS *******/\n\n getWireRdata() {\n const mbox = this.wirePackDomain(this.get('mbox'));\n const txt = this.wirePackDomain(this.get('txt'));\n const result = new Uint8Array(mbox.length + txt.length);\n result.set(mbox, 0);\n result.set(txt, mbox.length);\n return result\n }\n\n toTinydns() {\n return this.getTinydnsGeneric(\n packDomainName(this.get('mbox')) + packDomainName(this.get('txt')),\n )\n }\n}\n\nclass RRSIG extends RR {\n static typeName = 'RRSIG'\n static typeId = 46\n static RFCs = [4034]\n static rdataFields = [\n ['type covered', 'u16'],\n ['algorithm', 'u8'],\n ['labels', 'u8'],\n ['original ttl', 'u32'],\n ['signature expiration', 'u32'],\n ['signature inception', 'u32'],\n ['key tag', 'u16'],\n ['signers name', 'fqdn'],\n ['signature', 'str'],\n ]\n static tags = ['dnssec']\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setTypeCovered(val) {\n // a 16-bit Type Covered field (RFC 4034 \u00A73.1.1)\n if (!val && val !== 0) this.throwHelp(`RRSIG: 'type covered' is required`);\n if (typeof val === 'string') {\n const typeNN = val.match(/^TYPE(\\d+)$/i);\n if (typeNN) {\n val = parseInt(typeNN[1], 10);\n } else {\n const id = DNS_TYPE_IDS[val.toUpperCase()];\n if (id === undefined) this.throwHelp(`RRSIG: 'type covered' is not a recognized type name`);\n val = id;\n }\n }\n this.is16bitInt('RRSIG', 'type covered', val);\n this.set('type covered', val);\n }\n\n setAlgorithm(val) {\n // a 1 octet Algorithm field\n if (!this.getAlgorithmOptions().has(val)) this.throwHelp(`RRSIG: algorithm invalid`);\n\n this.set('algorithm', val);\n }\n\n getAlgorithmOptions() {\n return new Map([\n [1, 'RSA/MD5'],\n [2, 'DH'],\n [3, 'RRSIGA/SHA-1'],\n [4, 'EC'],\n [5, 'RSA/SHA-1'],\n [253],\n [254],\n ])\n }\n\n getDescription() {\n return 'Resource Record Signature'\n }\n\n getCanonical() {\n return {\n owner: 'example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'RRSIG',\n 'type covered': 1,\n algorithm: 5,\n labels: 3,\n 'original ttl': 3600,\n 'signature expiration': 1045053120,\n 'signature inception': 1042461120,\n 'key tag': 12345,\n 'signers name': 'example.com.',\n signature: 'ABCDEF...',\n }\n }\n\n /****** IMPORTERS *******/\n\n fromBind({ bindline }) {\n // example.com. 3600 IN RRSIG typecovered algorithm labels origttl sigexp siginc keytag signersname ( signature )\n const parts = bindline.trim().split(/\\s+/);\n const typeCoveredStr = parts[4];\n // type covered may be a type name ('A', 'MX'), TYPEnn (RFC 3597), or a numeric ID\n const typeNN = typeCoveredStr.match(/^TYPE(\\d+)$/i);\n const typeCovered = /^\\d+$/.test(typeCoveredStr)\n ? parseInt(typeCoveredStr, 10)\n : typeNN\n ? parseInt(typeNN[1], 10)\n : (DNS_TYPE_IDS[typeCoveredStr.toUpperCase()] ?? parseInt(typeCoveredStr, 10));\n return new RRSIG({\n owner: parts[0],\n ttl: parseInt(parts[1], 10),\n class: parts[2],\n type: 'RRSIG',\n 'type covered': typeCovered,\n algorithm: parseInt(parts[5], 10),\n labels: parseInt(parts[6], 10),\n 'original ttl': parseInt(parts[7], 10),\n 'signature expiration': parseInt(parts[8], 10),\n 'signature inception': parseInt(parts[9], 10),\n 'key tag': parseInt(parts[10], 10),\n 'signers name': parts[11],\n signature: parts\n .slice(12)\n .filter((a) => a !== '(' && a !== ')')\n .join(' ')\n .trim(),\n })\n }\n\n fromTinydns({ tinyline }) {\n const [fqdn, n, rdata, ttl, ts, loc] = tinyline.slice(1).split(':');\n if (parseInt(n, 10) !== this.getTypeId()) this.throwHelp('RRSIG fromTinydns, invalid n');\n\n const bytes = Uint8Array.from(octalToChar(rdata), (c) => c.charCodeAt(0));\n const dv = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);\n const typeCovered = dv.getUint16(0);\n const algorithm = bytes[2];\n const labels = bytes[3];\n const originalTtl = dv.getUint32(4);\n const signatureExpiration = dv.getUint32(8);\n const signatureInception = dv.getUint32(12);\n const keyTag = dv.getUint16(16);\n\n let pos = 18;\n const labelArr = [];\n while (pos < bytes.length) {\n const len = bytes[pos++];\n if (len === 0) break\n labelArr.push(new TextDecoder().decode(bytes.subarray(pos, pos + len)));\n pos += len;\n }\n const signersName = `${labelArr.join('.')}.`;\n const signature = new TextDecoder().decode(bytes.subarray(pos));\n\n return new RRSIG({\n owner: this.fullyQualify(fqdn),\n ttl: parseInt(ttl, 10),\n type: 'RRSIG',\n 'type covered': typeCovered,\n algorithm,\n labels,\n 'original ttl': originalTtl,\n 'signature expiration': signatureExpiration,\n 'signature inception': signatureInception,\n 'key tag': keyTag,\n 'signers name': signersName,\n signature,\n timestamp: ts,\n location: loc?.trim() ?? '',\n })\n }\n\n /****** EXPORTERS *******/\n\n toTinydns() {\n const dataRe = new RegExp(/[\\r\\n\\t:]/, 'g');\n return this.getTinydnsGeneric(\n UInt16toOctal(this.get('type covered')) +\n UInt8toOctal(this.get('algorithm')) +\n UInt8toOctal(this.get('labels')) +\n UInt32toOctal(this.get('original ttl')) +\n UInt32toOctal(this.get('signature expiration')) +\n UInt32toOctal(this.get('signature inception')) +\n UInt16toOctal(this.get('key tag')) +\n packDomainName(this.get('signers name')) +\n escapeOctal(dataRe, this.get('signature')),\n )\n }\n\n getWireRdata() {\n const signerBytes = wirePackDomain(this.get('signers name'));\n const sigBytes = new TextEncoder().encode(this.get('signature'));\n\n const totalLen = 2 + 1 + 1 + 4 + 4 + 4 + 2 + signerBytes.length + sigBytes.length;\n const bytes = new Uint8Array(totalLen);\n const dv = new DataView(bytes.buffer, bytes.byteOffset);\n\n let pos = 0;\n dv.setUint16(pos, this.get('type covered'));\n pos += 2;\n bytes[pos++] = this.get('algorithm');\n bytes[pos++] = this.get('labels');\n dv.setUint32(pos, this.get('original ttl'));\n pos += 4;\n dv.setUint32(pos, this.get('signature expiration'));\n pos += 4;\n dv.setUint32(pos, this.get('signature inception'));\n pos += 4;\n dv.setUint16(pos, this.get('key tag'));\n pos += 2;\n bytes.set(signerBytes, pos);\n pos += signerBytes.length;\n bytes.set(sigBytes, pos);\n\n return bytes\n }\n}\n\nclass SIG extends RR {\n static typeName = 'SIG'\n static typeId = 24\n static RFCs = [2535, 3755]\n static rdataFields = [\n ['type covered', 'u16'],\n ['algorithm', 'u8'],\n ['labels', 'u8'],\n ['original ttl', 'u32'],\n ['signature expiration', 'u32'],\n ['signature inception', 'u32'],\n ['key tag', 'u16'],\n ['signers name', 'fqdn'],\n ['signature', 'str'],\n ]\n static tags = ['obsolete']\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setTypeCovered(val) {\n // a 2 octet Type Covered field\n if (!val) this.throwHelp(`SIG: 'type covered' is required`);\n\n this.set('type covered', val);\n }\n\n setAlgorithm(val) {\n // a 1 octet Algorithm field\n this.is8bitInt('SIG', 'algorithm', val);\n\n this.set('algorithm', val);\n }\n\n setLabels(val) {\n // a 1 octet Labels field\n this.is8bitInt('SIG', 'labels', val);\n\n this.set('labels', val);\n }\n\n setOriginalTtl(val) {\n // a 4 octet Original TTL field\n this.is32bitInt('SIG', 'original ttl', val);\n\n this.set('original ttl', val);\n }\n\n setSignatureExpiration(val) {\n // a 4 octet Signature Expiration field\n this.set('signature expiration', val);\n }\n\n setSignatureInception(val) {\n // a 4 octet Signature Inception field\n this.set('signature inception', val);\n }\n\n setKeyTag(val) {\n // a 2 octet Key tag\n this.set('key tag', val);\n }\n\n setSignersName(val) {\n // the domain name of the signer generating the SIG RR\n\n // RFC 4034: letters in the DNS names are lower cased\n this.set('signers name', val.toLowerCase());\n }\n\n setSignature(val) {\n // the Signature field.\n\n this.set('signature', val);\n }\n\n getDescription() {\n return 'Signature'\n }\n\n getCanonical() {\n return {\n owner: 'example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'SIG',\n 'type covered': 1,\n algorithm: 5,\n labels: 3,\n 'original ttl': 3600,\n 'signature expiration': 1045053120,\n 'signature inception': 1042461120,\n 'key tag': 12345,\n 'signers name': 'example.com.',\n signature: 'ABCDEF...',\n }\n }\n\n /****** IMPORTERS *******/\n\n fromBind({ bindline }) {\n // example.com. 3600 IN SIG TypeCovered Algorithm Labels OrigTTL SigExpiration SigInception KeyTag SignersName ( Signature )\n const parts = bindline.trim().split(/\\s+/);\n const typeCoveredStr = parts[4];\n const typeCovered = /^\\d+$/.test(typeCoveredStr)\n ? parseInt(typeCoveredStr, 10)\n : (DNS_TYPE_IDS[typeCoveredStr.toUpperCase()] ?? parseInt(typeCoveredStr, 10));\n\n return new SIG({\n owner: parts[0],\n ttl: parseInt(parts[1], 10),\n class: parts[2],\n type: 'SIG',\n 'type covered': typeCovered,\n algorithm: parseInt(parts[5], 10),\n labels: parseInt(parts[6], 10),\n 'original ttl': parseInt(parts[7], 10),\n 'signature expiration': parseInt(parts[8], 10),\n 'signature inception': parseInt(parts[9], 10),\n 'key tag': parseInt(parts[10], 10),\n 'signers name': parts[11],\n signature: parts\n .slice(12)\n .filter((a) => a !== '(' && a !== ')')\n .join(' ')\n .trim(),\n })\n }\n\n /****** EXPORTERS *******/\n toTinydns() {\n const dataRe = new RegExp(/[\\r\\n\\t:]/, 'g');\n\n return this.getTinydnsGeneric(\n UInt16toOctal(this.get('type covered')) +\n UInt8toOctal(this.get('algorithm')) +\n UInt8toOctal(this.get('labels')) +\n UInt32toOctal(this.get('original ttl')) +\n UInt32toOctal(this.get('signature expiration')) +\n UInt32toOctal(this.get('signature inception')) +\n UInt16toOctal(this.get('key tag')) +\n packDomainName(this.get('signers name')) +\n escapeOctal(dataRe, this.get('signature')),\n )\n }\n\n getWireRdata() {\n const signerBytes = wirePackDomain(this.get('signers name'));\n const sigBytes = new TextEncoder().encode(this.get('signature'));\n\n const totalLen = 2 + 1 + 1 + 4 + 4 + 4 + 2 + signerBytes.length + sigBytes.length;\n const bytes = new Uint8Array(totalLen);\n const dv = new DataView(bytes.buffer, bytes.byteOffset);\n\n let pos = 0;\n dv.setUint16(pos, this.get('type covered'));\n pos += 2;\n bytes[pos++] = this.get('algorithm');\n bytes[pos++] = this.get('labels');\n dv.setUint32(pos, this.get('original ttl'));\n pos += 4;\n dv.setUint32(pos, this.get('signature expiration'));\n pos += 4;\n dv.setUint32(pos, this.get('signature inception'));\n pos += 4;\n dv.setUint16(pos, this.get('key tag'));\n pos += 2;\n bytes.set(signerBytes, pos);\n pos += signerBytes.length;\n bytes.set(sigBytes, pos);\n\n return bytes\n }\n\n fromTinydns({ tinyline }) {\n const { owner, typeId, rdata, ttl, timestamp, location } = this.parseTinydnsLine(tinyline);\n if (parseInt(typeId, 10) !== this.getTypeId()) this.throwHelp('SIG fromTinydns, invalid n');\n\n const bytes = octalRdataToBytes(rdata);\n const dv = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);\n\n const typeCovered = dv.getUint16(0);\n const algorithm = bytes[2];\n const labels = bytes[3];\n const originalTtl = dv.getUint32(4);\n const signatureExpiration = dv.getUint32(8);\n const signatureInception = dv.getUint32(12);\n const keyTag = dv.getUint16(16);\n\n // parse signers name from binary starting at offset 18\n let pos = 18;\n const labelsArr = [];\n while (pos < bytes.length) {\n const len = bytes[pos++];\n if (len === 0) break\n labelsArr.push(new TextDecoder().decode(bytes.subarray(pos, pos + len)));\n pos += len;\n }\n const signersName = `${labelsArr.join('.')}.`;\n\n const signature = new TextDecoder().decode(bytes.subarray(pos));\n\n return new SIG({\n owner,\n ttl,\n type: 'SIG',\n 'type covered': typeCovered,\n algorithm,\n labels,\n 'original ttl': originalTtl,\n 'signature expiration': signatureExpiration,\n 'signature inception': signatureInception,\n 'key tag': keyTag,\n 'signers name': signersName,\n signature,\n timestamp,\n location,\n })\n }\n\n toBind(zone_opts) {\n return `${this.getFQDN('owner', zone_opts)}\t${this.get('ttl')}\t${this.get('class')}\tSIG${this.getRdataFields()\n .slice(0, 4)\n .map((f) => '\t' + this.get(f))\n .join('')}\t${this.getRdataFields()\n .slice(4, 8)\n .map((f) => this.get(f))\n .join('\t')}\t( ${this.get('signature')} )`\n }\n}\n\nclass SMIMEA extends RR {\n static typeName = 'SMIMEA'\n static typeId = 53\n static RFCs = [8162]\n static rdataFields = [\n ['certificate usage', 'u8'],\n ['selector', 'u8'],\n ['matching type', 'u8'],\n ['certificate association data', 'hex'],\n ]\n static tags = ['security']\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setCertificateUsage(val) {\n if (!this.getCertificateUsageOptions().has(val)) this.throwHelp(`SMIMEA: certificate usage invalid`);\n\n this.set('certificate usage', val);\n }\n\n getCertificateUsageOptions() {\n return new Map([\n [0, 'CA certificate'],\n [1, 'an end entity certificate'],\n [2, 'the trust anchor'],\n [3, 'domain-issued certificate'],\n ])\n }\n\n setSelector(val) {\n if (!this.getSelectorOptions().has(val)) this.throwHelp(`SMIMEA: selector invalid`);\n\n this.set('selector', val);\n }\n\n getSelectorOptions() {\n return new Map([\n [0, 'Full certificate'],\n [1, 'SubjectPublicKeyInfo'],\n ])\n }\n\n setMatchingType(val) {\n if (!this.getMatchingTypeOptions().has(val)) this.throwHelp(`SMIMEA: matching type`);\n\n this.set('matching type', val);\n }\n\n getMatchingTypeOptions() {\n return new Map([\n [0, 'Exact match'],\n [1, 'SHA-256 hash'],\n [2, 'SHA-512 hash'],\n ])\n }\n\n setCertificateAssociationData(val) {\n this.set('certificate association data', val);\n }\n\n getDescription() {\n return 'S/MIME cert association'\n }\n\n getCanonical() {\n return {\n owner: '_443._tcp.www.example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'SMIMEA',\n 'certificate usage': 0,\n selector: 0,\n 'matching type': 1,\n 'certificate association data': 'ABCDEF...',\n }\n }\n\n /****** IMPORTERS *******/\n\n fromBind({ bindline }) {\n // test.example.com 3600 IN SMIMEA, usage, selector, match, data\n const [owner, ttl, c, type, usage, selector, match] = bindline.split(/\\s+/);\n return new SMIMEA({\n owner,\n ttl: parseInt(ttl, 10),\n class: c,\n type: type,\n 'certificate usage': parseInt(usage, 10),\n selector: parseInt(selector, 10),\n 'matching type': parseInt(match, 10),\n 'certificate association data': bindline.split(/\\s+/).slice(7).join(' ').trim(),\n })\n }\n\n fromTinydns({ tinyline }) {\n const { owner, rdata, ttl, timestamp, location } = this.parseTinydnsLine(tinyline);\n const binaryRdata = octalRdataToBytes(rdata);\n\n return new SMIMEA({\n owner,\n ttl,\n type: 'SMIMEA',\n 'certificate usage': binaryRdata[0],\n selector: binaryRdata[1],\n 'matching type': binaryRdata[2],\n 'certificate association data': bytesToHex(binaryRdata.subarray(3)),\n timestamp,\n location,\n })\n }\n\n /****** EXPORTERS *******/\n toTinydns() {\n return this.getTinydnsGeneric(\n UInt8toOctal(this.get('certificate usage')) +\n UInt8toOctal(this.get('selector')) +\n UInt8toOctal(this.get('matching type')) +\n packHex(this.get('certificate association data').replace(/[\\s()]/g, '')),\n )\n }\n\n getWireRdata() {\n const cadBytes = hexToBytes(this.get('certificate association data').replace(/[\\s()]/g, ''));\n const bytes = new Uint8Array(3 + cadBytes.length);\n bytes[0] = this.get('certificate usage');\n bytes[1] = this.get('selector');\n bytes[2] = this.get('matching type');\n bytes.set(cadBytes, 3);\n return bytes\n }\n}\n\nclass SOA extends RR {\n static typeName = 'SOA'\n static typeId = 6\n static RFCs = [1035, 2308]\n static tinydnsType = 'Z'\n static rdataFields = [\n ['mname', 'fqdn'],\n ['rname', 'fqdn'],\n ['serial', 'u32'],\n ['refresh', 'u32'],\n ['retry', 'u32'],\n ['expire', 'u32'],\n ['minimum', 'u32'],\n ]\n static tags = ['common']\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setMinimum(val) {\n // minimum (used for negative caching, since RFC 2308)\n // RFC 1912 sugggests 1-5 days\n // RIPE recommends 3600 (1 hour)\n this.is32bitInt('SOA', 'minimum', val);\n\n this.set('minimum', val);\n }\n\n setMname(val) {\n // MNAME (primary NS)\n this.isValidHostname('SOA', 'MNAME', val);\n this.isFullyQualified('SOA', 'MNAME', val);\n\n // RFC 4034: letters in the DNS names are lower cased\n this.set('mname', val.toLowerCase());\n }\n\n setRname(val) {\n // RNAME (email of admin) (escape . with \\)\n this.isValidHostname('SOA', 'RNAME', val);\n this.isFullyQualified('SOA', 'RNAME', val);\n if (/@/.test(val)) this.throwHelp(`SOA rname replaces @ with a . (dot)`);\n\n // RFC 4034: letters in the DNS names are lower cased\n this.set('rname', val.toLowerCase());\n }\n\n setSerial(val) {\n this.is32bitInt('SOA', 'serial', val);\n\n this.set('serial', val);\n }\n\n setRefresh(val) {\n // refresh (seconds after which to check with master for update)\n // RFC 1912 suggests 20 min to 12 hours\n // RIPE recommends 86400 (24 hours)\n this.is32bitInt('SOA', 'refresh', val);\n\n this.set('refresh', val);\n }\n\n setRetry(val) {\n // seconds after which to retry serial # update\n // RIPE recommends 7200 seconds (2 hours)\n\n this.is32bitInt('SOA', 'retry', val);\n\n this.set('retry', val);\n }\n\n setExpire(val) {\n // seconds after which secondary should drop zone if no master response\n // RFC 1912 suggests 2-4 weeks\n // RIPE suggests 3600000 (1,000 hours, 6 weeks)\n this.is32bitInt('SOA', 'expire', val);\n\n this.set('expire', val);\n }\n\n getDescription() {\n return 'Start Of Authority'\n }\n\n getCanonical() {\n return {\n owner: 'example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'SOA',\n mname: 'ns1.example.com.',\n rname: 'admin.example.com.',\n serial: 2023051001,\n refresh: 7200,\n retry: 3600,\n expire: 1209600,\n minimum: 3600,\n }\n }\n\n /****** IMPORTERS *******/\n fromTinydns({ tinyline }) {\n // Zfqdn:mname:rname:ser:ref:ret:exp:min:ttl:time:lo\n const [fqdn, mname, rname, ser, ref, ret, exp, min, ttl, ts, loc] = tinyline.slice(1).split(':');\n\n return new SOA({\n owner: this.fullyQualify(fqdn),\n ttl: parseInt(ttl, 10),\n type: 'SOA',\n mname: this.fullyQualify(mname),\n rname: this.fullyQualify(rname),\n serial: parseInt(ser ?? this.default?.serial, 10),\n refresh: parseInt(ref, 10) || 16384,\n retry: parseInt(ret, 10) || 2048,\n expire: parseInt(exp, 10) || 1048576,\n minimum: parseInt(min, 10) || 2560,\n timestamp: parseInt(ts) || '',\n location: loc?.trim() ?? '',\n })\n }\n\n /****** EXPORTERS *******/\n toMaraDNS() {\n return `${this.get('owner')}\\t SOA\\t${this.getFields('rdata')\n .map((f) => this.getQuoted(f))\n .join('\\t')} ~\\n`\n }\n\n getWireRdata() {\n const mname = this.wirePackDomain(this.get('mname'));\n const rname = this.wirePackDomain(this.get('rname'));\n const result = new Uint8Array(mname.length + rname.length + 20);\n let offset = 0;\n result.set(mname, offset);\n offset += mname.length;\n result.set(rname, offset);\n offset += rname.length;\n const view = new DataView(result.buffer, offset);\n view.setUint32(0, this.get('serial'));\n view.setUint32(4, this.get('refresh'));\n view.setUint32(8, this.get('retry'));\n view.setUint32(12, this.get('expire'));\n view.setUint32(16, this.get('minimum'));\n return result\n }\n\n toTinydns() {\n return `Z${this.getTinyFQDN('owner')}:${this.getTinyFQDN('mname')}:${this.getTinyFQDN('rname')}:${this.getEmpty('serial')}:${this.getEmpty('refresh')}:${this.getEmpty('retry')}:${this.getEmpty('expire')}:${this.getEmpty('minimum')}:${this.getTinydnsPostamble()}\\n`\n }\n}\n\nclass TXT extends RR {\n static typeName = 'TXT'\n static typeId = 16\n static RFCs = [1035, 4408, 7208, 6376]\n static tinydnsType = \"'\"\n static rdataFields = [['data', 'charstrs']]\n static tags = ['common']\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setData(val) {\n this.set('data', val);\n }\n\n getDescription() {\n return 'Text'\n }\n\n getCanonical() {\n return {\n owner: 'example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'TXT',\n data: 'v=spf1 mx -all',\n }\n }\n\n /****** IMPORTERS *******/\n fromTinydns({ tinyline }) {\n const str = tinyline;\n let fqdn, rdata, s, ttl, ts, loc;\n // 'fqdn:s:ttl:timestamp:lo\n if (str[0] === \"'\") {\n[fqdn, s, ttl, ts, loc] = str.slice(1).split(':');\n rdata = octalToChar(s);\n } else {\n[fqdn, rdata, ttl, ts, loc] = this.fromTinydnsGeneric(str);\n }\n\n return new this.constructor({\n owner: this.fullyQualify(fqdn),\n ttl: parseInt(ttl, 10),\n type: 'TXT',\n data: rdata,\n timestamp: ts,\n location: loc?.trim() || '',\n })\n }\n\n fromTinydnsGeneric(str) {\n // generic: :fqdn:n:rdata:ttl:timestamp:location\n // eslint-disable-next-line prefer-const\n let [fqdn, n, rdata, ttl, ts, loc] = str.slice(1).split(':');\n if (n != 16) this.throwHelp('TXT fromTinydns, invalid n');\n\n rdata = octalToChar(rdata);\n let s = '';\n let len = rdata[0].charCodeAt(0);\n let pos = 1;\n while (pos < rdata.length) {\n s += rdata.slice(pos, +(len + pos));\n pos = len + pos;\n len = rdata.charCodeAt(pos + 1);\n }\n return [fqdn, s, ttl, ts, loc]\n }\n\n /****** EXPORTERS *******/\n toBind(zone_opts) {\n return `${this.getPrefix(zone_opts)}\\t\"${asQuotedStrings(this.get('data'))}\"\\n`\n }\n\n toMaraDNS() {\n const data = asQuotedStrings(this.get('data')).replace(/\"/g, \"'\");\n return `${this.get('owner')}\\t+${this.get('ttl')}\\t${this.get('type')}\\t'${data}' ~\\n`\n }\n\n getWireRdata() {\n let data = this.get('data');\n if (Array.isArray(data)) data = data.join('');\n return packStringWire(data)\n }\n\n toTinydns() {\n let data = this.get('data');\n if (Array.isArray(data)) data = data.join('');\n const rdata = escapeOctal(new RegExp(/[\\r\\n\\t:\\\\/]/, 'g'), data);\n return `'${this.getTinyFQDN('owner')}:${rdata}:${this.getTinydnsPostamble()}\\n`\n }\n}\n\nfunction asQuotedStrings(data) {\n // RFC 1035 character-strings are 255 bytes max; chunk by UTF-8 bytes,\n // not JS chars, so non-ASCII TXT data doesn't overflow the 255-byte limit.\n const enc = new TextEncoder();\n\n if (Array.isArray(data)) {\n const anyTooLong = data.some((s) => enc.encode(s).length > 255);\n if (!anyTooLong) return data.join('\" \"')\n return chunkByBytes(data.join(''), 255).join('\" \"')\n }\n\n if (enc.encode(data).length <= 255) return data\n return chunkByBytes(data, 255).join('\" \"')\n}\n\nfunction chunkByBytes(str, maxBytes) {\n const bytes = new TextEncoder().encode(str);\n const dec = new TextDecoder();\n const chunks = [];\n let start = 0;\n while (start < bytes.length) {\n let end = Math.min(start + maxBytes, bytes.length);\n // back up to a UTF-8 codepoint boundary so decode() returns whole chars\n while (end < bytes.length && (bytes[end] & 0xc0) === 0x80) end--;\n chunks.push(dec.decode(bytes.subarray(start, end)));\n start = end;\n }\n return chunks\n}\n\nfunction packStringWire(str) {\n const encoded = new TextEncoder().encode(str);\n if (encoded.length === 0) return new Uint8Array([0])\n\n const chunks = [];\n for (let i = 0; i < encoded.length; i += 255) chunks.push(encoded.subarray(i, i + 255));\n\n const buf = new Uint8Array(encoded.length + chunks.length);\n let offset = 0;\n for (const chunk of chunks) {\n buf[offset++] = chunk.length;\n buf.set(chunk, offset);\n offset += chunk.length;\n }\n return buf\n}\n\n// obsoleted by RFC 7208\n\n\nclass SPF extends TXT {\n static typeName = 'SPF'\n static typeId = 99\n static RFCs = [4408, 7208]\n static rdataFields = [['data', 'charstrs']]\n static tags = ['obsolete']\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setData(val) {\n this.set('data', val);\n }\n\n getDescription() {\n return 'Sender Policy Framework'\n }\n getCanonical() {\n return {\n owner: 'example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'SPF',\n data: 'v=spf1 mx -all',\n }\n }\n\n /****** IMPORTERS *******/\n fromTinydns({ tinyline }) {\n // SPF via generic, :fqdn:n:rdata:ttl:timestamp:lo\n const [fqdn, n, rdata, ttl, ts, loc] = tinyline.slice(1).split(':');\n if (n != 99) this.throwHelp('SPF fromTinydns, invalid n');\n\n return new SPF({\n type: 'SPF',\n owner: this.fullyQualify(fqdn),\n data: octalToChar(rdata),\n ttl: parseInt(ttl, 10),\n timestamp: ts,\n location: loc?.trim() ?? '',\n })\n }\n\n /****** EXPORTERS *******/\n getWireRdata() {\n return super.getWireRdata()\n }\n\n toTinydns() {\n const rdata = escapeOctal(new RegExp(/[\\r\\n\\t:\\\\/]/, 'g'), this.get('data'));\n return this.getTinydnsGeneric(rdata)\n }\n}\n\nclass SRV extends RR {\n static typeName = 'SRV'\n static typeId = 33\n static RFCs = [2782]\n static rdataFields = [\n ['priority', 'u16'],\n ['weight', 'u16'],\n ['port', 'u16'],\n ['target', 'fqdn'],\n ]\n static tags = ['common']\n\n constructor(opts) {\n super(opts);\n }\n\n getDescription() {\n return 'Service'\n }\n\n getCanonical() {\n return {\n owner: '_imaps._tcp.example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'SRV',\n priority: 10,\n weight: 10,\n port: 993,\n target: 'mail.example.com.',\n }\n }\n\n /****** IMPORTERS *******/\n fromTinydns({ tinyline }) {\n const str = tinyline;\n let fqdn, addr, port, pri, weight, ttl, ts, loc, n, rdata;\n\n if (str[0] === 'S') {\n[fqdn, addr, port, pri, weight, ttl, ts, loc] = str.slice(1).split(':');\n } else {\n[fqdn, n, rdata, ttl, ts, loc] = str.slice(1).split(':');\n if (n != 33) this.throwHelp('SRV fromTinydns: invalid n');\n\n pri = octalToUInt16(rdata.slice(0, 8));\n weight = octalToUInt16(rdata.slice(8, 16));\n port = octalToUInt16(rdata.slice(16, 24));\n addr = unpackDomainName(rdata.slice(24))[0];\n }\n\n return new SRV({\n owner: this.fullyQualify(fqdn),\n ttl: parseInt(ttl, 10),\n type: 'SRV',\n priority: parseInt(pri, 10),\n weight: parseInt(weight, 10),\n port: parseInt(port, 10),\n target: this.fullyQualify(addr),\n timestamp: ts,\n location: loc?.trim() ?? '',\n })\n }\n\n /****** EXPORTERS *******/\n\n getWireRdata() {\n const target = this.wirePackDomain(this.get('target'));\n const result = new Uint8Array(6 + target.length);\n const dv = new DataView(result.buffer);\n dv.setUint16(0, this.get('priority'));\n dv.setUint16(2, this.get('weight'));\n dv.setUint16(4, this.get('port'));\n result.set(target, 6);\n return result\n }\n\n toTinydns() {\n let rdata = '';\n\n for (const e of ['priority', 'weight', 'port']) {\n rdata += UInt16toOctal(this.get(e));\n }\n\n rdata += packDomainName(this.get('target'));\n\n return this.getTinydnsGeneric(rdata)\n }\n}\n\nclass SSHFP extends RR {\n static typeName = 'SSHFP'\n static typeId = 44\n static RFCs = [4255, 7479, 8709]\n static rdataFields = [\n ['algorithm', 'u8'],\n ['fptype', 'u8'],\n ['fingerprint', 'hex'],\n ]\n static tags = ['security']\n\n constructor(opts) {\n super(opts);\n }\n\n getAlgorithmOptions() {\n return new Map([\n [0, 'reserved'],\n [1, 'RSA'],\n [2, 'DSA'],\n [3, 'ECDSA'],\n [4, 'Ed25519'],\n [6, 'Ed448'],\n ])\n }\n\n getFptypeOptions() {\n return new Map([\n [0, 'reserved'],\n [1, 'SHA-1'],\n [2, 'SHA-256'],\n ])\n }\n\n getDescription() {\n return 'Secure Shell Key Fingerprints'\n }\n\n getCanonical() {\n return {\n owner: 'mail.example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'SSHFP',\n algorithm: 2,\n fptype: 1,\n fingerprint: '123456789abcdef6789abcdf6789abdf6789abcd',\n }\n }\n\n /****** IMPORTERS *******/\n fromTinydns({ tinyline }) {\n // SSHFP via generic, :fqdn:n:rdata:ttl:timestamp:lo\n const { owner, typeId, rdata, ttl, timestamp, location } = this.parseTinydnsLine(tinyline);\n if (typeId != this.getTypeId()) this.throwHelp('SSHFP fromTinydns, invalid n');\n\n return new SSHFP({\n owner,\n ttl,\n type: 'SSHFP',\n algorithm: octalToUInt8(rdata.slice(0, 4)),\n fptype: octalToUInt8(rdata.slice(4, 8)),\n fingerprint: octalToHex(rdata.slice(8)),\n timestamp,\n location,\n })\n }\n\n /****** EXPORTERS *******/\n\n toTinydns() {\n return this.getTinydnsGeneric(\n UInt8toOctal(this.get('algorithm')) +\n UInt8toOctal(this.get('fptype')) +\n packHex(this.get('fingerprint')),\n )\n }\n\n getWireRdata() {\n const bytes = new Uint8Array(2 + hexToBytes(this.get('fingerprint')).length);\n bytes[0] = this.get('algorithm');\n bytes[1] = this.get('fptype');\n bytes.set(hexToBytes(this.get('fingerprint')), 2);\n return bytes\n }\n}\n\nclass SVCB extends RR {\n static typeName = 'SVCB'\n static typeId = 64\n static RFCs = [9460]\n static rdataFields = [\n ['priority', 'u16'],\n ['target name', 'fqdn'],\n ['params', 'svcparams'],\n ]\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setPriority(val) {\n this.is16bitInt('SVCB', 'priority', val);\n\n this.set('priority', val);\n }\n\n setTargetName(val) {\n // this.isFullyQualified('SVCB', 'target name', val)\n // this.isValidHostname('SVCB', 'target name', val)\n\n // RFC 4034: letters in the DNS names are lower cased\n this.set('target name', val.toLowerCase());\n }\n\n setParams(val) {\n // if (!val) throw new Error(`SVCB: params is required`)\n\n this.set('params', val);\n }\n\n getDescription() {\n return 'Service Binding'\n }\n\n getCanonical() {\n return {\n owner: '_8443._foo.api.example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'SVCB',\n priority: 1,\n 'target name': 'svc4.example.net.',\n params: 'alpn=\"h2,h3\"',\n }\n }\n\n /****** IMPORTERS *******/\n\n fromBind({ bindline }) {\n // test.example.com 3600 IN SVCB Priority TargetName Params\n // _8443._foo.api.example.com. 7200 IN SVCB 0 svc4.example.net.\n // svc4.example.net. 7200 IN SVCB 3 svc4.example.net. ( alpn=\"bar\" port=\"8004\" )\n const [owner, ttl, c, type, pri, fqdn] = bindline.split(/\\s+/);\n return new SVCB({\n owner,\n ttl: parseInt(ttl, 10),\n class: c,\n type,\n priority: parseInt(pri, 10),\n 'target name': fqdn,\n params: bindline.split(/\\s+/).slice(6).join(' ').trim(),\n })\n }\n\n fromTinydns({ tinyline }) {\n const { owner, typeId, rdata, ttl, timestamp, location } = this.parseTinydnsLine(tinyline);\n if (typeId != this.getTypeId()) this.throwHelp('SVCB fromTinydns, invalid n');\n const { priority, targetName, params } = parseSvcbLikeRdata(rdata, 'SVCB');\n\n return new SVCB({\n owner,\n ttl,\n type: 'SVCB',\n priority: priority,\n 'target name': targetName,\n params: params,\n timestamp,\n location,\n })\n }\n\n /****** EXPORTERS *******/\n\n toTinydns() {\n const dataRe = new RegExp(/[\\r\\n\\t:\\\\/]/, 'g');\n\n return this.getTinydnsGeneric(\n UInt16toOctal(this.get('priority')) +\n packDomainName(this.get('target name')) +\n escapeOctal(dataRe, this.get('params')),\n )\n }\n\n getWireRdata() {\n const targetBytes = this.wirePackDomain(this.get('target name'));\n const paramsBytes = svcParamsToWire(this.get('params'));\n const result = new Uint8Array(2 + targetBytes.length + paramsBytes.length);\n new DataView(result.buffer).setUint16(0, this.get('priority'));\n result.set(targetBytes, 2);\n result.set(paramsBytes, 2 + targetBytes.length);\n return result\n }\n}\n\nclass TLSA extends RR {\n static typeName = 'TLSA'\n static typeId = 52\n static RFCs = [6698, 7671]\n static rdataFields = [\n ['certificate usage', 'u8'],\n ['selector', 'u8'],\n ['matching type', 'u8'],\n ['certificate association data', 'hex'],\n ]\n static tags = ['security']\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setCertificateUsage(val) {\n if (!this.getCertificateUsageOptions().has(val)) this.throwHelp(`TLSA: certificate usage invalid`);\n\n this.set('certificate usage', val);\n }\n\n getCertificateUsageOptions() {\n return new Map([\n [0, 'CA certificate'],\n [1, 'an end entity certificate'],\n [2, 'the trust anchor'],\n [3, 'domain-issued certificate'],\n ])\n }\n\n setSelector(val) {\n if (!this.getSelectorOptions().has(val)) this.throwHelp(`TLSA: selector invalid`);\n\n this.set('selector', val);\n }\n\n getSelectorOptions() {\n return new Map([\n [0, 'Full certificate'],\n [1, 'SubjectPublicKeyInfo'],\n ])\n }\n\n setMatchingType(val) {\n if (!this.getMatchingTypeOptions().has(val)) this.throwHelp(`TLSA: matching type`);\n\n this.set('matching type', val);\n }\n\n getMatchingTypeOptions() {\n return new Map([\n [0, 'Exact match'],\n [1, 'SHA-256 hash'],\n [2, 'SHA-512 hash'],\n ])\n }\n\n setCertificateAssociationData(val) {\n this.set('certificate association data', val);\n }\n\n getDescription() {\n return 'TLSA certificate association'\n }\n\n getCanonical() {\n return {\n owner: '_443._tcp.www.example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'TLSA',\n 'certificate usage': 3,\n selector: 1,\n 'matching type': 1,\n 'certificate association data': 'ABCDEF...',\n }\n }\n\n /****** IMPORTERS *******/\n\n fromBind({ bindline }) {\n // test.example.com 3600 IN TLSA, usage, selector, match, data\n const regex =\n /^(?\\S+)\\s+(?\\d{1,10})\\s+(?IN)\\s+(?TLSA)\\s+(?\\d+)\\s+(?\\d+)\\s+(?\\d+)\\s+(?\\S.*)$/i;\n const match = bindline.trim().match(regex);\n if (!match) this.throwHelp(`unable to parse TLSA: ${bindline}`);\n const { owner, ttl, cls, type, usage, selector, matchtype, cad } = match.groups;\n\n return new TLSA({\n owner: this.fullyQualify(owner),\n ttl: parseInt(ttl, 10),\n class: cls.toUpperCase(),\n type: type.toUpperCase(),\n 'certificate usage': parseInt(usage, 10),\n selector: parseInt(selector, 10),\n 'matching type': parseInt(matchtype, 10),\n 'certificate association data': cad.trim(),\n })\n }\n\n fromTinydns({ tinyline }) {\n const { owner, typeId, rdata, ttl, timestamp, location } = this.parseTinydnsLine(tinyline);\n if (typeId != this.getTypeId()) this.throwHelp('TLSA fromTinydns, invalid n');\n\n const bytes = octalRdataToBytes(rdata);\n\n return new TLSA({\n owner,\n ttl,\n type: 'TLSA',\n 'certificate usage': bytes[0],\n selector: bytes[1],\n 'matching type': bytes[2],\n 'certificate association data': bytesToHex(bytes.subarray(3)),\n timestamp,\n location,\n })\n }\n\n /****** EXPORTERS *******/\n toTinydns() {\n return this.getTinydnsGeneric(\n UInt8toOctal(this.get('certificate usage')) +\n UInt8toOctal(this.get('selector')) +\n UInt8toOctal(this.get('matching type')) +\n packHex(this.get('certificate association data').replace(/[\\s()]/g, '')),\n )\n }\n\n getWireRdata() {\n const cadBytes = hexToBytes(this.get('certificate association data').replace(/[\\s()]/g, ''));\n const bytes = new Uint8Array(3 + cadBytes.length);\n bytes[0] = this.get('certificate usage');\n bytes[1] = this.get('selector');\n bytes[2] = this.get('matching type');\n bytes.set(cadBytes, 3);\n return bytes\n }\n}\n\nclass TSIG extends RR {\n static typeName = 'TSIG'\n static typeId = 250\n static RFCs = [2845, 8945]\n static rdataFields = ['algorithm name', 'time signed', 'fudge', 'mac', 'original id', 'error', 'other']\n\n constructor(opts) {\n super(opts);\n if (opts === null) return\n }\n\n /****** Resource record specific setters *******/\n\n getDescription() {\n return 'Transaction Signature'\n }\n\n getCanonical() {\n return {\n owner: 'test.example.',\n ttl: 0,\n class: 'ANY',\n type: 'TSIG',\n 'algorithm name': 'hmac-sha256.',\n 'time signed': 1620650000,\n fudge: 300,\n mac: 'ABCDEF...',\n 'original id': 12345,\n error: 0,\n other: '',\n }\n }\n\n setClass(t) {\n if (t !== 'ANY') this.throwHelp('TSIG: Class is required to be ANY');\n this.set('class', t);\n }\n\n setTtl(t) {\n if (t !== 0) this.throwHelp('TSIG: TTL is required to be 0');\n this.set('ttl', t);\n }\n\n setAlgorithmName(val) {\n if (!val) this.throwHelp(`TSIG: 'algorithm name' is required`);\n this.set('algorithm name', val);\n }\n\n setTimeSigned(val) {\n // a 48-bit unsigned integer, as seconds since the UNIX epoch\n if (val === undefined) this.throwHelp(`TSIG: 'time signed' is required`);\n this.set('time signed', val);\n }\n\n setFudge(val) {\n // 16-bit unsigned\n this.is16bitInt('TSIG', 'fudge', val);\n this.set('fudge', val);\n }\n\n setMac(val) {\n this.set('mac', val ?? '');\n }\n\n setOriginalId(val) {\n this.is16bitInt('TSIG', 'original id', val);\n this.set('original id', val);\n }\n\n setError(val) {\n this.is16bitInt('TSIG', 'error', val);\n this.set('error', val);\n }\n\n setOther(val) {\n this.set('other', val ?? '');\n }\n\n /****** IMPORTERS *******/\n\n fromBind({ bindline }) {\n // owner ttl ANY TSIG alg time fudge mac_size mac original_id error other_len\n const parts = bindline.trimEnd().split('\\t');\n const [owner, ttl, cls, type, alg, time, fudge, , mac, origId, error] = parts;\n\n return new TSIG({\n owner,\n ttl: parseInt(ttl, 10),\n class: cls,\n type: type.toUpperCase(),\n 'algorithm name': alg,\n 'time signed': parseInt(time, 10),\n fudge: parseInt(fudge, 10),\n mac: mac || '',\n 'original id': parseInt(origId, 10),\n error: parseInt(error, 10),\n other: '',\n })\n }\n\n fromTinydns({ tinyline }) {\n const [owner, _typeId, rdata, ttl, ts, loc] = tinyline.slice(1).split(':');\n\n const algUnpacked = unpackDomainName(rdata);\n const algBinaryLen = algUnpacked[2];\n\n const bytes = Uint8Array.from(octalToChar(rdata), (c) => c.charCodeAt(0));\n const dv = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);\n let bpos = algBinaryLen;\n\n const timeSigned = dv.getUint32(bpos);\n bpos += 4;\n const fudge = dv.getUint16(bpos);\n bpos += 2;\n const macSize = dv.getUint16(bpos);\n bpos += 2;\n const mac = macSize > 0 ? bytesToHex(bytes.subarray(bpos, bpos + macSize)) : '';\n bpos += macSize;\n const originalId = dv.getUint16(bpos);\n bpos += 2;\n const error = dv.getUint16(bpos);\n bpos += 2;\n const other = bpos < bytes.length ? new TextDecoder().decode(bytes.subarray(bpos)) : '';\n\n return new TSIG({\n owner: this.fullyQualify(owner),\n ttl: parseInt(ttl, 10),\n class: 'ANY',\n type: 'TSIG',\n 'algorithm name': algUnpacked[0],\n 'time signed': timeSigned,\n fudge,\n mac,\n 'original id': originalId,\n error,\n other,\n timestamp: ts,\n location: loc?.trim() ?? '',\n })\n }\n\n fromWire({ owner, cls, ttl, rdata }) {\n const { fqdn: algorithmName, end } = this.wireUnpackDomain(rdata, 0);\n const dv = new DataView(rdata.buffer, rdata.byteOffset);\n let pos = end;\n const timeSigned = dv.getUint32(pos);\n pos += 4;\n const fudge = dv.getUint16(pos);\n pos += 2;\n const macSize = dv.getUint16(pos);\n pos += 2;\n const mac = macSize > 0 ? bytesToHex(rdata.subarray(pos, pos + macSize)) : '';\n pos += macSize;\n const originalId = dv.getUint16(pos);\n pos += 2;\n const error = dv.getUint16(pos);\n pos += 2;\n const other = pos < rdata.length ? new TextDecoder().decode(rdata.subarray(pos)) : '';\n return new TSIG({\n owner,\n ttl: 0,\n class: 'ANY',\n type: 'TSIG',\n 'algorithm name': algorithmName,\n 'time signed': timeSigned,\n fudge,\n mac,\n 'original id': originalId,\n error,\n other,\n })\n }\n\n /****** EXPORTERS *******/\n toBind(zone_opts) {\n const mac = this.get('mac') ?? '';\n const macSize = mac.length > 0 ? mac.length : '';\n const other = this.get('other') ?? '';\n const otherLen = other.length > 0 ? other.length : 0;\n return (\n [\n this.getFQDN('owner', zone_opts),\n this.get('ttl'),\n this.get('class'),\n this.get('type'),\n this.get('algorithm name'),\n this.get('time signed'),\n this.get('fudge'),\n macSize,\n mac,\n this.get('original id'),\n this.get('error'),\n otherLen,\n ].join('\\t') + '\\n'\n )\n }\n\n getWireRdata() {\n const algWire = wirePackDomain(this.get('algorithm name') || '');\n const mac = this.get('mac') ?? '';\n const macBytes = mac.length > 0 ? hexToBytes(mac) : new Uint8Array();\n const other = this.get('other') ?? '';\n const otherBytes = other.length > 0 ? new TextEncoder().encode(other) : new Uint8Array();\n\n const bytes = new Uint8Array(algWire.length + 4 + 2 + 2 + macBytes.length + 2 + 2 + otherBytes.length);\n const dv = new DataView(bytes.buffer, bytes.byteOffset);\n let pos = 0;\n\n bytes.set(algWire, pos);\n pos += algWire.length;\n dv.setUint32(pos, this.get('time signed') ?? 0);\n pos += 4;\n dv.setUint16(pos, this.get('fudge') ?? 0);\n pos += 2;\n dv.setUint16(pos, macBytes.length);\n pos += 2;\n if (macBytes.length > 0) {\n bytes.set(macBytes, pos);\n pos += macBytes.length;\n }\n dv.setUint16(pos, this.get('original id') ?? 0);\n pos += 2;\n dv.setUint16(pos, this.get('error') ?? 0);\n pos += 2;\n if (otherBytes.length > 0) bytes.set(otherBytes, pos);\n\n return bytes\n }\n\n toTinydns() {\n const alg = this.get('algorithm name') || '';\n const mac = this.get('mac') ?? '';\n const macByteLen = mac.length > 0 ? mac.length / 2 : 0;\n\n return this.getTinydnsGeneric(\n packDomainName(alg) +\n UInt32toOctal(this.get('time signed') ?? 0) +\n UInt16toOctal(this.get('fudge')) +\n UInt16toOctal(macByteLen) +\n (macByteLen > 0 ? packHex(mac) : '') +\n UInt16toOctal(this.get('original id') ?? 0) +\n UInt16toOctal(this.get('error') ?? 0) +\n (this.get('other').length > 0\n ? escapeOctal(new RegExp(/[\\r\\n\\t:\\\\/]/, 'g'), this.get('other'))\n : ''),\n )\n }\n}\n\nclass URI extends RR {\n static typeName = 'URI'\n static typeId = 256\n static RFCs = [7553]\n static rdataFields = [\n ['priority', 'u16'],\n ['weight', 'u16'],\n ['target', 'qstr'],\n ]\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setPriority(val) {\n this.is16bitInt('URI', 'priority', val);\n\n this.set('priority', val);\n }\n\n setWeight(val) {\n this.is16bitInt('URI', 'weight', val);\n\n this.set('weight', val);\n }\n\n setTarget(val) {\n if (!val) this.throwHelp(`URI: target is required`);\n\n this.set('target', val);\n }\n\n /****** IMPORTERS *******/\n fromTinydns({ tinyline }) {\n // URI via generic, :fqdn:n:rdata:ttl:timestamp:lo\n const [fqdn, n, rdata, ttl, ts, loc] = tinyline.slice(1).split(':');\n if (n != 256) this.throwHelp('URI fromTinydns, invalid n');\n\n return new URI({\n type: 'URI',\n owner: this.fullyQualify(fqdn),\n priority: octalToUInt16(rdata.slice(0, 8)),\n weight: octalToUInt16(rdata.slice(8, 16)),\n target: octalToChar(rdata.slice(16)),\n ttl: parseInt(ttl, 10),\n timestamp: ts,\n location: loc?.trim() ?? '',\n })\n }\n\n /****** MISC *******/\n getDescription() {\n return 'URI'\n }\n\n getCanonical() {\n return {\n owner: 'www.example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'URI',\n priority: 10,\n weight: 10,\n target: 'http://www.example.com/',\n }\n }\n\n /****** EXPORTERS *******/\n\n getWireRdata() {\n const target = new TextEncoder().encode(this.get('target'));\n const result = new Uint8Array(4 + target.length);\n const dv = new DataView(result.buffer);\n dv.setUint16(0, this.get('priority'));\n dv.setUint16(2, this.get('weight'));\n result.set(target, 4);\n return result\n }\n\n toTinydns() {\n const dataRe = new RegExp(/[\\r\\n\\t:\\\\/]/, 'g');\n let rdata = '';\n\n for (const e of ['priority', 'weight']) {\n rdata += UInt16toOctal(this.get(e));\n }\n\n rdata += escapeOctal(dataRe, this.get('target'));\n return this.getTinydnsGeneric(rdata)\n }\n}\n\nconst WELL_KNOWN_PORTS = {\n echo: 7,\n discard: 9,\n systat: 11,\n daytime: 13,\n netstat: 15,\n ftp_data: 20,\n ftp: 21,\n ssh: 22,\n telnet: 23,\n smtp: 25,\n time: 37,\n rlp: 39,\n nameserver: 42,\n nicname: 43,\n domain: 53,\n mtp: 57,\n bootps: 67,\n bootpc: 68,\n tftp: 69,\n gopher: 70,\n rje: 77,\n finger: 79,\n http: 80,\n link: 87,\n supdup: 95,\n hostnames: 101,\n iso_tsap: 102,\n csnet_ns: 105,\n pop_2: 109,\n pop3: 110,\n sunrpc: 111,\n auth: 113,\n sftp: 115,\n uucp_path: 117,\n nntp: 119,\n ntp: 123,\n netbios_ns: 137,\n netbios_dgm: 138,\n netbios_ssn: 139,\n imap: 143,\n sql_net: 150,\n snmp: 161,\n snmp_trap: 162,\n cmip_man: 163,\n cmip_agent: 164,\n xdmcp: 177,\n nextstep: 178,\n bgp: 179,\n prospero: 191,\n irc: 194,\n smux: 199,\n at_rtmp: 201,\n at_nbp: 202,\n at_echo: 204,\n at_zis: 206,\n qmtp: 209,\n z3950: 210,\n ipx: 213,\n imap3: 220,\n ulistproc: 372,\n https: 443,\n snpp: 444,\n microsoft_ds: 445,\n kpasswd: 464,\n urd: 465,\n saft: 487,\n isakmp: 500,\n exec: 512,\n biff: 512,\n login: 513,\n who: 513,\n cmd: 514,\n syslog: 514,\n printer: 515,\n talk: 517,\n ntalk: 518,\n route: 520,\n timed: 525,\n tempo: 526,\n courier: 530,\n netnews: 532,\n netwall: 533,\n uucp: 540,\n remotefs: 556,\n nntps: 563,\n ldap: 389,\n};\n\nclass WKS extends RR {\n static typeName = 'WKS'\n static typeId = 11\n static RFCs = [883, 1035]\n static rdataFields = ['address', 'protocol', 'bit map']\n static tags = ['obsolete']\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setAddress(val) {\n if (!val) this.throwHelp('WKS: address is required');\n if (!this.isIPv4(val)) this.throwHelp('WKS address must be IPv4');\n this.set('address', val);\n }\n\n setProtocol(val) {\n if (!val) this.throwHelp('WKS: protocol is required');\n const upper = typeof val === 'string' ? val.toUpperCase() : val;\n if (!['TCP', 'UDP', 6, 17].includes(upper)) this.throwHelp('WKS protocol must be TCP or UDP');\n this.set('protocol', upper);\n }\n\n setBitMap(val) {\n this.set('bit map', val ?? '');\n }\n\n getDescription() {\n return 'Well Known Service'\n }\n\n getCanonical() {\n return {\n owner: 'host.example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'WKS',\n address: '192.0.2.1',\n protocol: 'TCP',\n 'bit map': 'ftp smtp',\n }\n }\n\n /****** IMPORTERS *******/\n\n fromBind({ bindline }) {\n // test.example.com 3600 IN WKS 192.168.1.1 TCP ftp smtp\n const parts = bindline.split(/\\s+/);\n const [owner, ttl, c, type, address, protocol] = parts;\n return new WKS({\n owner,\n ttl: parseInt(ttl, 10),\n class: c,\n type,\n address,\n protocol,\n 'bit map': parts.slice(6).join(' ').trim(),\n })\n }\n\n fromTinydns({ tinyline }) {\n const [owner, _typeId, rdata, ttl, ts, loc] = tinyline.slice(1).split(':');\n\n const binary = Uint8Array.from(octalToChar(rdata), (c) => c.charCodeAt(0));\n const address = [binary[0], binary[1], binary[2], binary[3]].join('.');\n const protoNum = binary[4];\n const protoMap = { 6: 'TCP', 17: 'UDP' };\n const protocol = protoMap[protoNum] ?? protoNum;\n const bitmap = new TextDecoder().decode(binary.subarray(5));\n\n return new WKS({\n owner: this.fullyQualify(owner),\n ttl: parseInt(ttl, 10),\n type: 'WKS',\n address,\n protocol,\n 'bit map': bitmap,\n timestamp: ts,\n location: loc?.trim() ?? '',\n })\n }\n\n fromWire({ owner, cls, ttl, rdata }) {\n const address = [...rdata.subarray(0, 4)].join('.');\n const protoNum = rdata[4];\n const protoMap = { 6: 'TCP', 17: 'UDP' };\n const protocol = protoMap[protoNum] ?? String(protoNum);\n const PORT_NAMES = Object.fromEntries(Object.entries(WELL_KNOWN_PORTS).map(([k, v]) => [v, k]));\n const bitmap = rdata.subarray(5);\n const ports = [];\n for (let i = 0; i < bitmap.length; i++) {\n for (let bit = 0; bit < 8; bit++) {\n if (bitmap[i] & (0x80 >> bit)) {\n const port = i * 8 + bit;\n ports.push(PORT_NAMES[port] ?? String(port));\n }\n }\n }\n return new WKS({\n owner,\n ttl,\n class: cls,\n type: 'WKS',\n address,\n protocol,\n 'bit map': ports.join(' '),\n })\n }\n\n /****** EXPORTERS *******/\n\n toTinydns() {\n const dataRe = new RegExp(/[\\r\\n\\t:\\\\/]/, 'g');\n const protoMap = { TCP: 6, UDP: 17, 6: 6, 17: 17 };\n const protoNum = protoMap[this.get('protocol')];\n\n return this.getTinydnsGeneric(\n ipv4toOctal(this.get('address')) +\n UInt8toOctal(protoNum) +\n escapeOctal(dataRe, this.get('bit map')),\n )\n }\n\n getWireRdata() {\n const protoMap = { TCP: 6, UDP: 17, 6: 6, 17: 17 };\n const addrBytes = this.get('address').split('.').map(Number);\n const protoNum = protoMap[this.get('protocol')];\n\n const portNums = this.get('bit map')\n .trim()\n .split(/\\s+/)\n .map((s) => {\n if (/^\\d+$/.test(s)) return parseInt(s, 10)\n return WELL_KNOWN_PORTS[s.toLowerCase()]\n })\n .filter((p) => p !== undefined);\n\n if (portNums.length === 0) return new Uint8Array([...addrBytes, protoNum])\n\n const maxPort = Math.max(...portNums);\n const bitmapLen = Math.floor(maxPort / 8) + 1;\n const bitmap = new Uint8Array(bitmapLen);\n for (const port of portNums) bitmap[Math.floor(port / 8)] |= 0x80 >> (port % 8);\n\n const result = new Uint8Array(5 + bitmapLen);\n result.set(addrBytes);\n result[4] = protoNum;\n result.set(bitmap, 5);\n return result\n }\n}\n\nconst typeMap = {};\nconst classes = [\n A,\n AAAA,\n APL,\n CAA,\n CERT,\n CNAME,\n DHCID,\n DNAME,\n DNSKEY,\n DS,\n HINFO,\n HIP,\n HTTPS,\n IPSECKEY,\n KEY,\n KX,\n LOC,\n MX,\n NAPTR,\n NS,\n NSEC,\n NSEC3,\n NSEC3PARAM,\n NXT,\n OPENPGPKEY,\n PTR,\n RP,\n RRSIG,\n SIG,\n SMIMEA,\n SSHFP,\n SOA,\n SPF,\n SRV,\n SVCB,\n TLSA,\n TSIG,\n TXT,\n URI,\n WKS,\n];\n\nfor (const c of classes) {\n const id = c.getTypeId();\n typeMap[id] = c.typeName;\n typeMap[c.typeName] = id;\n}\n\nexport { A, AAAA, APL, CAA, CERT, CNAME, DHCID, DNAME, DNSKEY, DS, HINFO, HIP, HTTPS, IPSECKEY, KEY, KX, LOC, MX, NAPTR, NS, NSEC, NSEC3, NSEC3PARAM, NXT, OPENPGPKEY, PTR, RP, RRSIG, SIG, SMIMEA, SOA, SPF, SRV, SSHFP, SVCB, TLSA, TSIG, TXT, URI, WKS, RR as default, typeMap };\n"], - "mappings": "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", - "names": ["octalRe", "textDecoder", "parseFields", "tinyline", "rdataCount", "parts", "owner", "rdata", "ttl", "timestamp", "location", "parseGenericLine", "typeId", "octalRdataToBytes", "octalToChar", "c", "parseSvcbLikeRdata", "recordType", "binary", "priority", "pos", "labels", "len", "to", "rrInstance", "f", "bytesToOctalString", "fromGeneric", "fields", "result", "i", "val", "escapeOctal", "re", "str", "escaped", "charToOctal", "o", "octalToHex", "octalToUInt8", "octalToUInt16", "octalToUInt32", "b0", "b1", "b2", "b3", "packString", "s", "UInt8toOctal", "unpackString", "asBuf", "dec", "res", "packDomainName", "fqdn", "labelRegEx", "packed", "label", "unpackDomainName", "binaryLen", "getNextByte", "value", "lengthByte", "char", "packHex", "r", "n", "UInt16toOctal", "UInt32toOctal", "ipv4toOctal", "ip", "int", "octalToIPv4", "asInt", "expandIPv6", "delimiter", "colons", "ipv6toOctal", "octalToIPv6", "base64toOctal", "b", "octalToBase64", "bytes", "hexToBytes", "hex", "_", "bytesToHex", "bytesToBase64", "base64ToBytes", "b64", "DNS_TYPE_IDS", "wireUnpackDomain", "offset", "wirePackDomain", "enc", "p", "buf", "getWireRdata", "line", "toWire", "RRClasses", "meta", "fromWireBytes", "RRConstructor", "wireBytes", "wireUnpackFn", "instance", "end", "view", "classNum", "cls", "k", "rdlen", "fromWireGeneric", "rdataFields", "dv", "entry", "fieldName", "certTypeNum", "reverse", "strLen", "svcParamsFromWire", "j", "SVCPARAM_KEYS", "svcParamsToWire", "paramsStr", "m", "key", "keyId", "valBytes", "entries", "e", "total", "addrs", "a", "addr", "param", "SVCPARAM_KEY_NAMES", "valLen", "keyName", "dv16", "groups", "parseBindLine", "cleanLine", "inQuote", "tokens", "token", "fromBind", "opts", "toBind", "zone_opts", "customInspect", "RR", "fieldType", "fnName", "parsed", "#reserved", "obj", "v", "depth", "options", "nextInspect", "w", "l", "typeName", "example", "hostname", "origin", "classVal", "rrTTL", "prop", "arg", "commonFields", "field", "fq", "type", "certTypes", "allowed", "matches", "string", "segments", "bestStart", "bestLen", "curStart", "curLen", "head", "tail", "octalStr", "quotedTypes", "A", "AAAA", "ts", "loc", "arr", "APL", "items", "afi", "prefix", "adfLenByte", "neg", "addrLen", "addrBytes", "padded", "paddedDv", "bindline", "item", "bare", "colonIdx", "rest", "slashIdx", "dblIdx", "left", "right", "hexStr", "g", "afdPart", "itemBytes", "totalLen", "sum", "CAA", "flags", "taglen", "unescaped", "tag", "fingerprint", "CERT", "typeNum", "certType", "certtype", "keytag", "algo", "certificate", "certBytes", "CNAME", "DHCID", "DNAME", "DNSKEY", "regex", "match", "protocol", "algorithm", "publickey", "keyBytes", "DS", "binRdata", "digestBytes", "HINFO", "cpu", "os", "HIP", "hitLen", "pkAlgorithm", "pkLen", "hit", "publicKey", "rvsNames", "name", "newPos", "keyParts", "rvsParts", "rs", "rsPart", "hitHex", "hitBytes", "pkBytes", "rsDomains", "rsTotalLen", "rdomain", "HTTPS", "pri", "targetName", "params", "dataRe", "targetBytes", "paramsBytes", "IPSECKEY", "gwErr", "prec", "gwt", "gateway", "precedence", "gwType", "octalKey", "keyStart", "rdataRe", "pubkeyBytes", "gwBytes", "part", "KEY", "KX", "exchanger", "REF", "CONV", "LOC", "dms", "alt", "locRe", "retval", "rawmsec", "latlon", "msec", "deg", "min", "sec", "hem", "mantissa", "exponent", "MX", "_ip", "x", "preference", "domain", "NAPTR", "rec", "idx", "flagsLength", "serviceLen", "regexpLen", "replaceLen", "order", "service", "regexp", "replacement", "replacementBytes", "NS", "dname", "NSEC", "_typeId", "binaryRdata", "nextDomain", "_escapedLen", "next", "removeParens$1", "typeBitMaps", "nsecBitmapToTypes", "nameBytes", "bitmapBytes", "typesToNsecBitmap", "bitmap", "DNS_TYPE_NAMES", "types", "windowNum", "bitmapLen", "byte", "bit", "typeNamesStr", "typeIds", "t", "id", "windows", "blocks", "wNum", "bits", "maxBit", "NSEC3", "ha", "iterations", "salt", "rdataStr", "hashAlgorithm", "nextHashedOwnerName", "parseNSEC3Buffer", "tailBytes", "expectedLen", "maxSl", "sl", "candNext", "saltCandidate", "saltMatch", "NSEC3PARAM", "saltLen", "saltOctal", "saltBytes", "NXT", "removeParens", "typeBitMap", "nxtBitmapToTypes", "typesToNxtBitmap", "OPENPGPKEY", "keyStr", "PTR", "RP", "mbox", "consumed", "txt", "RRSIG", "typeNN", "typeCoveredStr", "typeCovered", "originalTtl", "signatureExpiration", "signatureInception", "keyTag", "labelArr", "signersName", "signature", "signerBytes", "sigBytes", "SIG", "labelsArr", "SMIMEA", "usage", "selector", "cadBytes", "SOA", "mname", "rname", "ser", "ref", "ret", "exp", "TXT", "asQuotedStrings", "data", "packStringWire", "chunkByBytes", "maxBytes", "chunks", "start", "encoded", "chunk", "SPF", "SRV", "port", "weight", "target", "SSHFP", "SVCB", "TLSA", "matchtype", "cad", "TSIG", "alg", "time", "fudge", "mac", "origId", "error", "algUnpacked", "algBinaryLen", "bpos", "timeSigned", "macSize", "originalId", "other", "algorithmName", "otherLen", "algWire", "macBytes", "otherBytes", "macByteLen", "URI", "WELL_KNOWN_PORTS", "WKS", "upper", "address", "protoNum", "PORT_NAMES", "ports", "protoMap", "portNums", "maxPort", "typeMap", "classes"] + "sourcesContent": ["const octalRe = new RegExp(/\\\\(?:[1-7][0-7]{0,2}|[0-7]{2,3})/, 'g');\nconst textDecoder = new TextDecoder();\n\nfunction parseFields(tinyline, rdataCount) {\n const parts = tinyline.slice(1).split(':');\n const owner = parts[0];\n const rdata = parts.slice(1, 1 + rdataCount);\n const [ttl, timestamp, location] = parts.slice(1 + rdataCount);\n return { owner, rdata, ttl, timestamp, location: location?.trim() ?? '' }\n}\n\nfunction parseGenericLine(tinyline) {\n // Generic form: :owner:typeId:rdata:ttl:timestamp:location\n const [owner, typeId, rdata, ttl, timestamp, location] = tinyline.slice(1).split(':');\n return { owner, typeId, rdata, ttl: parseInt(ttl, 10), timestamp, location: location?.trim() ?? '' }\n}\n\nfunction octalRdataToBytes(rdata) {\n return Uint8Array.from(octalToChar(rdata), (c) => c.charCodeAt(0))\n}\n\nfunction parseSvcbLikeRdata(rdata, recordType) {\n if (rdata.length < 6) {\n throw new Error(`${recordType}: RDATA too short: ${rdata}`)\n }\n\n const binary = octalRdataToBytes(rdata);\n const priority = (binary[0] << 8) | binary[1];\n\n let pos = 2;\n const labels = [];\n while (true) {\n const len = binary[pos];\n pos += 1;\n if (len === 0) break\n labels.push(textDecoder.decode(binary.subarray(pos, pos + len)));\n pos += len;\n }\n\n return {\n priority,\n targetName: `${labels.join('.')}.`,\n params: textDecoder.decode(binary.subarray(pos)),\n }\n}\n\nfunction to(rrInstance) {\n if (rrInstance.constructor.tinydnsType) {\n const fields = rrInstance.getFields('rdata');\n const rdata = fields\n .map((f) => {\n if (rrInstance.isFqdnField(f)) return rrInstance.getTinyFQDN(f)\n return rrInstance.get(f)\n })\n .join(':');\n return `${rrInstance.constructor.tinydnsType}${rrInstance.getTinyFQDN('owner')}:${rdata}:${rrInstance.getTinydnsPostamble()}\\n`\n }\n return rrInstance.getTinydnsGeneric(bytesToOctalString(rrInstance.getWireRdata()))\n}\n\nfunction fromGeneric(rrInstance, { tinyline }) {\n const fields = rrInstance.getFields('rdata');\n const { owner, rdata, ttl, timestamp, location } = parseFields(tinyline, fields.length);\n\n const result = {\n owner: rrInstance.fullyQualify(owner),\n type: rrInstance.constructor.typeName,\n ttl: parseInt(ttl, 10),\n timestamp: timestamp,\n location: location,\n };\n\n for (let i = 0; i < fields.length; i++) {\n const val = rdata[i];\n result[fields[i]] = rrInstance.isFqdnField(fields[i]) ? rrInstance.fullyQualify(val) : val;\n }\n\n return new rrInstance.constructor(result)\n}\n\nfunction escapeOctal(re, str) {\n let escaped = '';\n str.split(/(.{1})/g).map((c) => {\n escaped += re.test(c) ? charToOctal(c) : c;\n });\n return escaped\n}\n\nfunction octalToChar(str) {\n // relace instances of \\NNN with ASCII\n return str.replace(octalRe, (o) => String.fromCharCode(parseInt(o.slice(1), 8)))\n}\n\nfunction octalToHex(str) {\n // relace instances of \\NNN with Hex\n return str.replace(octalRe, (o) => {\n // parseInt(n, 8) -> from octal to decimal\n // .toString(16) -> decimal to hex\n return parseInt(o.slice(1), 8).toString(16).padStart(2, 0)\n })\n}\n\nfunction octalToUInt8(str) {\n return parseInt(str.slice(1, 4), 8) & 0xff\n}\n\nfunction octalToUInt16(str) {\n return (parseInt(str.slice(1, 4), 8) << 8) | parseInt(str.slice(5, 8), 8)\n}\n\nfunction octalToUInt32(str) {\n const b0 = parseInt(str.slice(1, 4), 8);\n const b1 = parseInt(str.slice(5, 8), 8);\n const b2 = parseInt(str.slice(9, 12), 8);\n const b3 = parseInt(str.slice(13, 16), 8);\n return ((b0 << 24) | (b1 << 16) | (b2 << 8) | b3) >>> 0\n}\n\nfunction packString(str) {\n return str\n .match(/(.{1,255})/g)\n .map((s) => `${UInt8toOctal(s.length)}${s}`)\n .join('')\n}\n\nfunction unpackString(str) {\n const asBuf = Uint8Array.from(octalToChar(str.toString()), (c) => c.charCodeAt(0));\n const dec = new TextDecoder();\n const res = [];\n let pos = 0;\n let len;\n while ((len = asBuf[pos])) {\n // encoded length byte\n pos++;\n res.push(dec.decode(asBuf.subarray(pos, pos + len)));\n pos = +(pos + len);\n if (pos >= asBuf.length) break\n }\n return res\n}\n\nfunction packDomainName(fqdn) {\n const labelRegEx = new RegExp(/[^A-Za-z0-9-.]/, 'g');\n\n // RFC 1035, 3.3 Standard RRs\n // The standard wire format for DNS names. (1 octet length + octets)\n let packed = '';\n fqdn.split('.').forEach((label) => {\n if (label === undefined || !label.length) return\n\n packed += UInt8toOctal(label.length);\n\n packed += escapeOctal(labelRegEx, label);\n });\n packed += '\\\\000'; // terminates with a zero length label\n return packed\n}\n\nfunction unpackDomainName(escaped) {\n let pos = 0;\n let binaryLen = 0;\n const labels = [];\n\n // consume the next logical \"byte\" (char or octal escape)\n const getNextByte = () => {\n if (pos >= escaped.length) return null\n\n let value;\n if (escaped[pos] === '\\\\') {\n value = parseInt(escaped.slice(pos + 1, pos + 4), 8);\n pos += 4;\n } else {\n value = escaped.charCodeAt(pos++);\n }\n\n binaryLen++;\n return value\n };\n\n let lengthByte;\n while ((lengthByte = getNextByte()) && lengthByte !== 0) {\n let label = '';\n for (let i = 0; i < lengthByte; i++) {\n const char = getNextByte();\n if (char === null) break\n label += String.fromCharCode(char);\n }\n labels.push(label);\n }\n\n return [`${labels.join('.')}.`, pos, binaryLen]\n}\n\nfunction packHex(str) {\n let r = '';\n for (let i = 0; i < str.length; i = i + 2) {\n // nibble off 2 hex bytes, encode to octal\n r += UInt8toOctal(parseInt(str.slice(i, i + 2), 16));\n }\n return r\n}\n\nfunction charToOctal(c) {\n if (typeof c === 'number') return UInt8toOctal(c)\n\n return UInt8toOctal(c.charCodeAt(0))\n}\n\nfunction UInt8toOctal(n) {\n if (n > 255) {\n throw new Error(\n `UInt8toOctal: value ${n} exceeds 255 \u2014 tinydns encoders require Latin-1/byte input (code points <= 0xFF)`,\n )\n }\n\n return `\\\\${parseInt(n, 10).toString(8).padStart(3, 0)}`\n}\n\nfunction UInt16toOctal(n) {\n return UInt8toOctal((n >>> 8) & 0xff) + UInt8toOctal(n & 0xff)\n}\n\nfunction UInt32toOctal(n) {\n return (\n UInt8toOctal((n >>> 24) & 0xff) +\n UInt8toOctal((n >>> 16) & 0xff) +\n UInt8toOctal((n >>> 8) & 0xff) +\n UInt8toOctal(n & 0xff)\n )\n}\n\nfunction ipv4toOctal(ip) {\n return UInt32toOctal(ip.split`.`.reduce((int, value) => int * 256 + +value))\n}\n\nfunction octalToIPv4(str) {\n const asInt = octalToUInt32(str);\n return [24, 16, 8, 0].map((n) => (asInt >> n) & 0xff).join('.')\n}\n\nfunction expandIPv6(val, delimiter = ':') {\n const colons = val.match(/:/g);\n if (colons?.length < 7) {\n val = val.replace(/::/, ':'.repeat(9 - colons.length));\n }\n return val\n .split(':')\n .map((s) => s.padStart(4, '0'))\n .join(delimiter)\n .toLowerCase()\n}\n\nfunction ipv6toOctal(ip) {\n return packHex(expandIPv6(ip, ''))\n}\n\nfunction octalToIPv6(str) {\n return octalToHex(str)\n .match(/(.{4})/g)\n .join(':')\n}\n\nfunction base64toOctal(str) {\n const binary = atob(str);\n let escaped = '';\n for (let i = 0; i < binary.length; i++) {\n const b = binary.charCodeAt(i);\n escaped += /[A-Za-z0-9\\-.]/.test(binary[i]) ? binary[i] : UInt8toOctal(b);\n }\n return escaped\n}\n\nfunction octalToBase64(str) {\n return btoa(octalToChar(str))\n}\n\nfunction bytesToOctalString(bytes) {\n let result = '';\n for (const b of bytes) result += UInt8toOctal(b);\n return result\n}\n\nfunction hexToBytes(hex) {\n return Uint8Array.from({ length: hex.length / 2 }, (_, i) => parseInt(hex.slice(i * 2, i * 2 + 2), 16))\n}\n\nfunction bytesToHex(bytes) {\n return [...bytes].map((b) => b.toString(16).padStart(2, '0')).join('')\n}\n\nfunction bytesToBase64(bytes) {\n return btoa([...bytes].map((b) => String.fromCharCode(b)).join(''))\n}\n\nfunction base64ToBytes(b64) {\n return Uint8Array.from(atob(b64), (c) => c.charCodeAt(0))\n}\n\n// DNS type name \u2192 numeric type ID mapping (subset covering known RR types)\nconst DNS_TYPE_IDS = {\n A: 1,\n NS: 2,\n MD: 3,\n MF: 4,\n CNAME: 5,\n SOA: 6,\n MB: 7,\n MG: 8,\n MR: 9,\n NULL: 10,\n WKS: 11,\n PTR: 12,\n HINFO: 13,\n MINFO: 14,\n MX: 15,\n TXT: 16,\n RP: 17,\n AFSDB: 18,\n X25: 19,\n ISDN: 20,\n RT: 21,\n NSAP: 22,\n NSAP_PTR: 23,\n SIG: 24,\n KEY: 25,\n PX: 26,\n GPOS: 27,\n AAAA: 28,\n LOC: 29,\n NXT: 30,\n EID: 31,\n NIMLOC: 32,\n SRV: 33,\n ATMA: 34,\n NAPTR: 35,\n KX: 36,\n CERT: 37,\n A6: 38,\n DNAME: 39,\n SINK: 40,\n OPT: 41,\n APL: 42,\n DS: 43,\n SSHFP: 44,\n IPSECKEY: 45,\n RRSIG: 46,\n NSEC: 47,\n DNSKEY: 48,\n DHCID: 49,\n NSEC3: 50,\n NSEC3PARAM: 51,\n TLSA: 52,\n SMIMEA: 53,\n HIP: 55,\n NINFO: 56,\n RKEY: 57,\n TALINK: 58,\n CDS: 59,\n CDNSKEY: 60,\n OPENPGPKEY: 61,\n CSYNC: 62,\n ZONEMD: 63,\n SVCB: 64,\n HTTPS: 65,\n SPF: 99,\n UINFO: 100,\n UID: 101,\n GID: 102,\n UNSPEC: 103,\n NID: 104,\n L32: 105,\n L64: 106,\n LP: 107,\n EUI48: 108,\n EUI64: 109,\n TKEY: 249,\n TSIG: 250,\n IXFR: 251,\n AXFR: 252,\n MAILB: 253,\n MAILA: 254,\n ANY: 255,\n URI: 256,\n CAA: 257,\n AVC: 258,\n DOA: 259,\n AMTRELAY: 260,\n TA: 32768,\n DLV: 32769,\n};\n\n// \u2500\u2500 Uncompressed domain name decoding \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Decode a length-prefixed (uncompressed) DNS name from a Uint8Array.\n * Returns { fqdn: string, end: number } where end is the offset after the name.\n */\nfunction wireUnpackDomain(bytes, offset = 0) {\n const labels = [];\n let pos = offset;\n while (pos < bytes.length) {\n const len = bytes[pos];\n if (len === 0) {\n pos++;\n break\n }\n labels.push(new TextDecoder().decode(bytes.subarray(pos + 1, pos + 1 + len)));\n pos += 1 + len;\n }\n return { fqdn: labels.length ? labels.join('.') + '.' : '.', end: pos }\n}\n\n/**\n * Pack a fully qualified domain name into wire format (Uint8Array).\n * Domain labels are prefixed with their length; the name ends with a zero byte.\n */\nfunction wirePackDomain(fqdn) {\n if (fqdn === '.') return new Uint8Array([0])\n const enc = new TextEncoder();\n const labels = fqdn\n .split('.')\n .filter((p) => p.length > 0)\n .map((p) => {\n const b = enc.encode(p);\n if (b.length > 63) throw new Error(`DNS label exceeds 63 bytes: ${p}`)\n return b\n });\n\n const buf = new Uint8Array(labels.reduce((n, b) => n + b.length + 1, 1));\n let offset = 0;\n for (const b of labels) {\n buf[offset++] = b.length;\n buf.set(b, offset);\n offset += b.length;\n }\n buf[offset] = 0;\n return buf\n}\n\n/**\n * Get wire format rdata for an RR instance.\n * Derived classes should override this with direct RFC 1035 wire encoding.\n * Fallback uses toTinydns() as an intermediate (less efficient but works for all types).\n */\nfunction getWireRdata(rrInstance) {\n const line = rrInstance.toTinydns();\n if (!line.startsWith(':')) {\n throw new Error(\n `${rrInstance.get('type')}: getWireRdata() not implemented. Override in rr/${rrInstance.get('type').toLowerCase()}.js`,\n )\n }\n // line: :fqdn:typeId:rdata:ttl:ts:loc\\n\n // Extract octal-encoded rdata and decode\n const rdata = line.split(':')[3];\n return rrInstance.octalToUint8Array(rdata ?? '')\n}\n\n/**\n * Serialize an RR instance to DNS wire format (RFC 1035).\n * Combines owner name, type, class, TTL, and rdata.\n */\nfunction toWire(rrInstance, RRClasses) {\n const rdata = rrInstance.getWireRdata();\n const owner = wirePackDomain(rrInstance.get('owner'));\n const result = new Uint8Array(owner.length + 10 + rdata.length);\n result.set(owner, 0);\n const meta = new DataView(result.buffer, owner.length, 10);\n meta.setUint16(0, rrInstance.getTypeId());\n meta.setUint16(2, RRClasses[rrInstance.get('class')] ?? 1);\n meta.setUint32(4, rrInstance.get('ttl'));\n meta.setUint16(8, rdata.length);\n result.set(rdata, owner.length + 10);\n return result\n}\n\n/**\n * Deserialize wire format bytes into an RR instance.\n * Static method wrapper for RR.fromWire().\n */\nfunction fromWireBytes(RRConstructor, wireBytes, wireUnpackFn) {\n const instance = new RRConstructor(null);\n const bytes = wireBytes instanceof Uint8Array ? wireBytes : new Uint8Array(wireBytes);\n const { fqdn: owner, end } = wireUnpackFn(bytes, 0);\n const view = new DataView(bytes.buffer, bytes.byteOffset);\n const classNum = view.getUint16(end + 2);\n const RRClasses = { IN: 1, CS: 2, CH: 3, HS: 4, NONE: 254, ANY: 255 };\n const cls = Object.keys(RRClasses).find((k) => RRClasses[k] === classNum) ?? 'IN';\n const ttl = view.getUint32(end + 4);\n const rdlen = view.getUint16(end + 8);\n const rdata = bytes.slice(end + 10, end + 10 + rdlen);\n return instance.fromWire({ owner, cls, ttl, rdata })\n}\n\n/**\n * Generic fromWire decoder driven by rdataFields type annotations.\n * Supports u8, u16, u32, fqdn, hex, base64, str, qstr, charstr, qcharstr, charstrs, svcparams, ipv4, ipv6.\n * See rr/TEMPLATE.js for descriptions and example type usage.\n * Last typed field consumes all remaining bytes.\n */\nfunction fromWireGeneric(rrInstance, { owner, cls, ttl, rdata }) {\n const result = { owner, ttl, class: cls, type: rrInstance.constructor.typeName };\n const rdataFields = rrInstance.constructor.rdataFields ?? [];\n const dv = new DataView(rdata.buffer, rdata.byteOffset);\n let pos = 0;\n\n for (let i = 0; i < rdataFields.length; i++) {\n const entry = rdataFields[i];\n const fieldName = Array.isArray(entry) ? entry[0] : entry;\n const fieldType = Array.isArray(entry) ? entry[1] : null;\n\n switch (fieldType) {\n case 'u8':\n result[fieldName] = rdata[pos++];\n break\n case 'u16':\n result[fieldName] = dv.getUint16(pos);\n pos += 2;\n break\n case 'certtype': {\n const certTypeNum = dv.getUint16(pos);\n const reverse = rrInstance.constructor.CERT_TYPES_REVERSE;\n result[fieldName] = reverse?.[certTypeNum] ?? certTypeNum;\n pos += 2;\n break\n }\n case 'u32':\n result[fieldName] = dv.getUint32(pos);\n pos += 4;\n break\n case 'fqdn': {\n const { fqdn, end } = wireUnpackDomain(rdata, pos);\n result[fieldName] = fqdn;\n pos = end;\n break\n }\n case 'hex':\n result[fieldName] = bytesToHex(rdata.subarray(pos)).toUpperCase();\n pos = rdata.length;\n break\n case 'base64':\n result[fieldName] = bytesToBase64(rdata.subarray(pos));\n pos = rdata.length;\n break\n case 'str':\n result[fieldName] = new TextDecoder().decode(rdata.subarray(pos));\n pos = rdata.length;\n break\n case 'qstr':\n result[fieldName] = new TextDecoder().decode(rdata.subarray(pos));\n pos = rdata.length;\n break\n case 'charstr': {\n const strLen = rdata[pos++];\n result[fieldName] = new TextDecoder().decode(rdata.subarray(pos, pos + strLen));\n pos += strLen;\n break\n }\n case 'qcharstr': {\n const strLen = rdata[pos++];\n result[fieldName] = new TextDecoder().decode(rdata.subarray(pos, pos + strLen));\n pos += strLen;\n break\n }\n case 'charstrs': {\n // RFC 1035 \u00A73.3.14: each on the wire is len-prefixed.\n // Preserve multi-string boundaries by returning an array when >1.\n const parts = [];\n while (pos < rdata.length) {\n const strLen = rdata[pos++];\n if (pos + strLen > rdata.length) {\n throw new Error('fromWireGeneric: truncated character-string in rdata')\n }\n parts.push(new TextDecoder().decode(rdata.subarray(pos, pos + strLen)));\n pos += strLen;\n }\n result[fieldName] = parts.length > 1 ? parts : (parts[0] ?? '');\n break\n }\n case 'svcparams':\n result[fieldName] = svcParamsFromWire(rdata.subarray(pos));\n pos = rdata.length;\n break\n case 'ipv4':\n result[fieldName] = [...rdata.subarray(pos, pos + 4)].join('.');\n pos += 4;\n break\n case 'ipv6': {\n const parts = [];\n for (let j = 0; j < 16; j += 2) {\n parts.push(\n dv\n .getUint16(pos + j)\n .toString(16)\n .padStart(4, '0'),\n );\n }\n result[fieldName] = parts.join(':');\n pos += 16;\n break\n }\n default:\n result[fieldName] = rdata[pos++];\n break\n }\n }\n\n return new rrInstance.constructor(result)\n}\n\n// \u2500\u2500 SVCB/HTTPS parameter encoding (RFC 9460) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst SVCPARAM_KEYS = {\n mandatory: 0,\n alpn: 1,\n 'no-default-alpn': 2,\n port: 3,\n ipv4hint: 4,\n ech: 5,\n ipv6hint: 6,\n};\n\n/**\n * Encode SVCB/HTTPS params string (e.g. 'alpn=\"h2,h3\" port=\"8443\"') to wire bytes.\n */\nfunction svcParamsToWire(paramsStr) {\n if (!paramsStr || !paramsStr.trim()) return new Uint8Array(0)\n\n const parts = [];\n // Match: key, key=unquoted, or key=\"quoted\" tokens\n const re = /([^\\s=]+)(?:=(?:\"([^\"]*)\"|(\\S*)))?(?=\\s|$)/g;\n let m;\n while ((m = re.exec(paramsStr.trim())) !== null) {\n const key = m[1].toLowerCase();\n const val = m[2] ?? m[3] ?? '';\n const keyId = SVCPARAM_KEYS[key];\n if (keyId === undefined) continue\n\n let valBytes;\n if (keyId === 1) {\n // alpn: comma-separated list, each entry length-prefixed\n const enc = new TextEncoder();\n const entries = val.split(',').map((e) => enc.encode(e.trim()));\n const total = entries.reduce((s, e) => s + 1 + e.length, 0);\n valBytes = new Uint8Array(total);\n let p = 0;\n for (const e of entries) {\n valBytes[p++] = e.length;\n valBytes.set(e, p);\n p += e.length;\n }\n } else if (keyId === 2) {\n // no-default-alpn: no value\n valBytes = new Uint8Array(0);\n } else if (keyId === 3) {\n // port: uint16\n valBytes = new Uint8Array(2);\n new DataView(valBytes.buffer).setUint16(0, parseInt(val, 10));\n } else if (keyId === 4) {\n // ipv4hint: one or more IPv4 addresses\n const addrs = val.split(',').map((a) => a.trim().split('.').map(Number));\n valBytes = new Uint8Array(addrs.length * 4);\n addrs.forEach((addr, i) => addr.forEach((b, j) => (valBytes[i * 4 + j] = b)));\n } else if (keyId === 5) {\n // ech: base64-encoded ECH config\n valBytes = base64ToBytes(val);\n } else if (keyId === 6) {\n // ipv6hint: one or more IPv6 addresses (expand compressed form before encoding)\n const addrs = val.split(',').map((a) => hexToBytes(expandIPv6(a.trim(), '')));\n valBytes = new Uint8Array(addrs.length * 16);\n addrs.forEach((addr, i) => valBytes.set(addr, i * 16));\n } else {\n valBytes = new TextEncoder().encode(val);\n }\n\n const param = new Uint8Array(4 + valBytes.length);\n new DataView(param.buffer).setUint16(0, keyId);\n new DataView(param.buffer).setUint16(2, valBytes.length);\n param.set(valBytes, 4);\n parts.push(param);\n }\n\n // Sort by key ID (SvcParams MUST be in ascending order per RFC 9460)\n parts.sort((a, b) => new DataView(a.buffer).getUint16(0) - new DataView(b.buffer).getUint16(0));\n\n const total = parts.reduce((s, p) => s + p.length, 0);\n const result = new Uint8Array(total);\n let pos = 0;\n for (const p of parts) {\n result.set(p, pos);\n pos += p.length;\n }\n return result\n}\n\nconst SVCPARAM_KEY_NAMES = {\n 0: 'mandatory',\n 1: 'alpn',\n 2: 'no-default-alpn',\n 3: 'port',\n 4: 'ipv4hint',\n 5: 'ech',\n 6: 'ipv6hint',\n};\n\n/**\n * Decode SVCB/HTTPS wire params bytes back to a human-readable params string.\n */\nfunction svcParamsFromWire(bytes) {\n if (!bytes || bytes.length === 0) return ''\n const parts = [];\n let pos = 0;\n while (pos + 4 <= bytes.length) {\n const dv = new DataView(bytes.buffer, bytes.byteOffset + pos);\n const keyId = dv.getUint16(0);\n const valLen = dv.getUint16(2);\n const val = bytes.subarray(pos + 4, pos + 4 + valLen);\n pos += 4 + valLen;\n\n const keyName = SVCPARAM_KEY_NAMES[keyId] ?? `key${keyId}`;\n if (keyId === 1) {\n // alpn: comma-separated length-prefixed entries\n const entries = [];\n let p = 0;\n while (p < val.length) {\n const len = val[p++];\n entries.push(new TextDecoder().decode(val.subarray(p, p + len)));\n p += len;\n }\n parts.push(`alpn=\"${entries.join(',')}\"`);\n } else if (keyId === 2) {\n parts.push('no-default-alpn');\n } else if (keyId === 3) {\n parts.push(`port=${new DataView(val.buffer, val.byteOffset).getUint16(0)}`);\n } else if (keyId === 4) {\n const addrs = [];\n for (let i = 0; i < val.length; i += 4) addrs.push([...val.subarray(i, i + 4)].join('.'));\n parts.push(`ipv4hint=${addrs.join(',')}`);\n } else if (keyId === 5) {\n parts.push(`ech=${btoa([...val].map((b) => String.fromCharCode(b)).join(''))}`);\n } else if (keyId === 6) {\n const addrs = [];\n for (let i = 0; i < val.length; i += 16) {\n const dv16 = new DataView(val.buffer, val.byteOffset + i);\n const groups = [];\n for (let j = 0; j < 16; j += 2) groups.push(dv16.getUint16(j).toString(16).padStart(4, '0'));\n addrs.push(groups.join(':'));\n }\n parts.push(`ipv6hint=${addrs.join(',')}`);\n } else {\n parts.push(`${keyName}=${[...val].map((b) => b.toString(16).padStart(2, '0')).join('')}`);\n }\n }\n return parts.join(' ')\n}\n\nfunction parseBindLine(line, RRClasses) {\n const res = {\n class: 'IN',\n type: '',\n rdata: [],\n };\n\n // 1. Strip comments (not inside quotes)\n let cleanLine = '';\n let inQuote = false;\n for (let i = 0; i < line.length; i++) {\n const c = line[i];\n if (c === '\"') inQuote = !inQuote;\n if (c === ';' && !inQuote) break\n cleanLine += c;\n }\n cleanLine = cleanLine.trim();\n if (!cleanLine) return null\n\n // 2. Tokenize, respecting quoted strings\n const tokens = cleanLine.match(/(\".*?\"|\\S+)/g) || [];\n if (tokens.length < 1) return null\n\n // 3. Owner handling\n if (!/^\\s/.test(line)) {\n res.owner = tokens.shift();\n }\n\n // 4. Extract TTL, Class, and Type\n while (tokens.length > 0) {\n const token = tokens[0].toUpperCase();\n\n if (RRClasses[token]) {\n res.class = tokens.shift().toUpperCase();\n continue\n }\n\n if (/^\\d+$/.test(token)) {\n res.ttl = parseInt(tokens.shift(), 10);\n continue\n }\n\n // If it's not a Class or TTL, it must be the RR Type (A, MX, etc.)\n res.type = tokens.shift().toUpperCase();\n break\n }\n\n // 5. Remaining tokens are RDATA\n res.rdata = tokens;\n\n return res\n}\n\nfunction fromBind(rrInstance, opts) {\n const { owner, ttl, cls, rdata } = opts;\n const result = {\n owner,\n ttl,\n class: cls,\n type: rrInstance.constructor.typeName,\n };\n\n const fields = rrInstance.getFields('rdata');\n const rdataDefs = rrInstance.constructor.rdataFields ?? [];\n for (let i = 0; i < fields.length; i++) {\n const isLastField = i === fields.length - 1;\n if (isLastField && rrInstance.isQuotedField(fields[i])) {\n // Collect all remaining tokens for TXT/etc\n const tokens = rdata.slice(i).map((s) => s.replace(/^\"|\"$/g, ''));\n // For `charstrs` (TXT), preserve multi-string boundaries (RFC 1035 \u00A73.3.14).\n // For `qstr`/`qcharstr` (single character-string), join into one string.\n const def = rdataDefs[i];\n const fieldType = Array.isArray(def) ? def[1] : null;\n result[fields[i]] = fieldType === 'charstrs' && tokens.length > 1 ? tokens : tokens.join('');\n break\n }\n\n let val = rdata[i];\n if (rrInstance.isQuotedField(fields[i])) {\n val = val?.replace(/^\"|\"$/g, '');\n } else if (/^\\d+$/.test(val)) {\n val = parseInt(val, 10);\n }\n result[fields[i]] = val;\n }\n\n return new rrInstance.constructor(result)\n}\n\nfunction toBind(rrInstance, zone_opts) {\n const fields = rrInstance.getFields('rdata');\n const rdata = fields\n .map((f) => (rrInstance.isFqdnField(f) ? rrInstance.getFQDN(f, zone_opts) : rrInstance.getQuoted(f)))\n .join('\\t');\n return `${rrInstance.getPrefix(zone_opts)}\\t${rdata}\\n`\n}\n\nconst customInspect = Symbol.for('nodejs.util.inspect.custom');\n\nclass RR {\n static CLASSES = { IN: 1, CS: 2, CH: 3, HS: 4, NONE: 254, ANY: 255 }\n static typeId\n static RFCs = []\n static tags = []\n\n constructor(opts) {\n if (opts === null) return\n\n if (opts?.default) this.default = opts.default;\n\n // tinydns specific\n this.setLocation(opts?.location);\n this.setTimestamp(opts?.timestamp);\n\n this.setOwner(opts?.owner);\n this.setType(opts?.type);\n this.setTtl(opts?.ttl);\n this.setClass(opts?.class);\n\n for (const entry of this.constructor.rdataFields ?? []) {\n const f = RR.fieldName(entry);\n const fieldType = Array.isArray(entry) ? entry[1] : null;\n const fnName = `set${this.ucFirst(f)}`;\n if (typeof this[fnName] === 'function') {\n this[fnName](opts?.[f]);\n } else if (fieldType) {\n this.setTypedValue(fieldType, f, opts?.[f]);\n } else {\n this.set(f, opts?.[f]);\n }\n }\n\n if (opts?.comment) this.set('comment', opts.comment);\n }\n\n static fromBind(line, opts = {}) {\n const instance = new this(null);\n if (opts.default !== undefined) instance.default = opts.default;\n const parsed = this.parseBindLine(line);\n if (!parsed) return null\n return instance.fromBind({ ...opts, ...parsed, bindline: line })\n }\n\n fromBind(opts) {\n return fromBind(this, opts)\n }\n\n static parseBindLine(line) {\n return parseBindLine(line, RR.CLASSES)\n }\n\n static fromTinydns(line, opts = {}) {\n const instance = new this(null);\n if (opts.default !== undefined) instance.default = opts.default;\n return instance.fromTinydns({ ...opts, tinyline: line })\n }\n\n fromTinydns(opts) {\n return fromGeneric(this, opts)\n }\n\n static fromWire(wireBytes) {\n return fromWireBytes(this, wireBytes, wireUnpackDomain)\n }\n\n fromWire(opts) {\n return fromWireGeneric(this, opts)\n }\n\n static #reserved = ['__proto__', 'constructor', 'prototype']\n\n get(key) {\n if (RR.#reserved.includes(key)) throw new Error(`Invalid field name: ${key}`)\n return this[key]\n }\n\n set(key, value) {\n if (RR.#reserved.includes(key)) throw new Error(`Invalid field name: ${key}`)\n this[key] = value;\n return this\n }\n\n toJSON() {\n const fields = [...this.getFields(), 'location', 'timestamp', 'comment'];\n const obj = {};\n for (const f of fields) {\n const v = this.get(f);\n if (v !== undefined) obj[f] = v;\n }\n return obj\n }\n\n [customInspect](depth, options, nextInspect) {\n // Returns a formatted string that looks like: A { ... }\n return `${this.type} ${nextInspect(this.toJSON(), options)}`\n }\n\n ucFirst(str) {\n if (!str) return str\n return str\n .split(/\\s/)\n .map((w) => w.charAt(0).toUpperCase() + w.slice(1))\n .join('')\n }\n\n setClass(c) {\n if ([undefined, null, ''].includes(c)) {\n this.set('class', 'IN');\n return\n }\n if (RR.CLASSES[c.toUpperCase()]) {\n this.set('class', c.toUpperCase());\n return\n }\n this.throwHelp(`invalid class ${c}`);\n }\n\n setLocation(l) {\n switch (l) {\n case undefined:\n return\n default:\n this.set('location', l);\n }\n }\n\n setTimestamp(l) {\n switch (l) {\n case undefined:\n return\n default:\n this.set('timestamp', l);\n }\n }\n\n setOwner(n) {\n if (n === undefined) this.throwHelp(`owner is required`);\n\n if (n.length < 1 || n.length > 255)\n this.throwHelp('Domain names must have 1-255 octets (characters): RFC 2181');\n\n this.isFullyQualified(this.constructor.typeName ?? this.constructor.name, 'owner', n);\n this.hasValidLabels(n);\n\n // wildcard records: RFC 1034, 4592\n if (/\\*/.test(n)) {\n if (!/^\\*\\./.test(n) && !/\\.\\*\\./.test(n))\n this.throwHelp('only *.something or * (by itself) is a valid wildcard');\n }\n\n this.set('owner', n.toLowerCase());\n }\n\n setTtl(t) {\n t = t ?? this.default?.ttl;\n if (t === undefined) {\n if (['SOA', 'SSHFP', 'RRSIG'].includes(this.get('type'))) return\n this.throwHelp('TTL is required, no default available');\n }\n\n if (typeof t !== 'number') this.throwHelp(`TTL must be numeric (${typeof t})`);\n\n // RFC 1035, 2181\n this.is32bitInt(this.get('type'), 'TTL', t);\n\n this.set('ttl', t);\n }\n\n setType(t) {\n if ([undefined, ''].includes(t)) t = this.constructor.typeName;\n\n if (t === undefined) this.throwHelp(`type is required`);\n\n if (t.toUpperCase() !== this.constructor.typeName)\n this.throwHelp(`type ${t} doesn't match ${this.constructor.typeName}`);\n\n this.set('type', t.toUpperCase());\n }\n\n throwHelp(e) {\n if (!this.constructor.typeName) throw new Error(e)\n\n const typeName = this.constructor.typeName;\n const example = this.getCanonical\n ? `Example ${typeName}:\\n${JSON.stringify(this.getCanonical(), null, '\\t')}\\n\\n`\n : `${typeName} records have the fields: ${this.getFields().join(', ')}\\n\\n`;\n\n throw new Error(`${e}\\n\\n${example}${this.citeRFC()}\\n`)\n }\n\n citeRFC() {\n return `see RFC${this.getRFCs().length > 1 ? 's' : ''} ${this.getRFCs()}`\n }\n\n fullyQualify(hostname, origin) {\n if (!hostname) return hostname\n if (hostname === '@' && origin) hostname = origin;\n if (hostname.endsWith('.')) return hostname.toLowerCase()\n if (origin) return `${hostname}.${origin}`.toLowerCase()\n return `${hostname}.`\n }\n\n getPrefix(zone_opts = {}) {\n const classVal = zone_opts.hide?.class ? '' : this.get('class');\n\n let rrTTL = this.get('ttl');\n if (zone_opts.hide?.ttl && rrTTL === zone_opts.ttl) rrTTL = '';\n\n let owner = this.get('owner');\n if (zone_opts.hide?.sameOwner && zone_opts.previousOwner === owner) {\n owner = '';\n } else {\n owner = this.getFQDN('owner', zone_opts);\n }\n\n return `${owner}\\t${rrTTL}\\t${classVal}\\t${this.get('type')}`\n }\n\n getEmpty(prop) {\n return this.get(prop) ?? ''\n }\n\n getComment(prop) {\n const c = this.get('comment');\n if (!c || !c[prop]) return ''\n return c[prop]\n }\n\n getQuoted(prop) {\n // if prop is not a quoted string field, return bare\n if (!this.isQuotedField(prop)) return this.get(prop)\n\n // if it's already quoted, return as-is\n if (/['\"]/.test(this.get(prop)[0])) return this.get(prop)\n\n return `\"${this.get(prop)}\"` // add double quotes\n }\n\n static fieldName(entry) {\n return Array.isArray(entry) ? entry[0] : entry\n }\n\n static fieldType(entry) {\n return Array.isArray(entry) ? entry[1] : null\n }\n\n getRdataFields() {\n return (this.constructor.rdataFields ?? []).map((e) => RR.fieldName(e))\n }\n\n getTags() {\n return this.constructor.tags ?? []\n }\n\n getRFCs() {\n return this.constructor.RFCs ?? []\n }\n\n getTypeId() {\n const typeId = this.constructor.typeId;\n if (typeId === undefined) this.throwHelp(`${this.constructor.typeName}: missing static typeId`);\n return typeId\n }\n\n static getTypeId() {\n return this.typeId\n }\n\n getFields(arg) {\n const commonFields = ['owner', 'ttl', 'class', 'type'];\n Object.freeze(commonFields);\n\n const rdataFields = this.getRdataFields();\n\n switch (arg) {\n case 'common':\n return commonFields\n case 'rdata':\n return rdataFields\n default:\n return commonFields.concat(rdataFields)\n }\n }\n\n getFQDN(field, zone_opts = {}) {\n let fqdn = this.get(field);\n if (!fqdn) this.throwHelp(`empty value for field ${field}`);\n if (!fqdn.endsWith('.')) fqdn += '.';\n\n if (zone_opts.hide?.origin && zone_opts.origin) {\n if (fqdn === zone_opts.origin) return '@'\n if (fqdn.endsWith(zone_opts.origin)) return fqdn.slice(0, fqdn.length - zone_opts.origin.length - 1)\n }\n\n return fqdn\n }\n\n getTinyFQDN(field) {\n const val = this.get(field);\n if (val === '') return val // empty\n if (val === '.') return val // null MX\n\n // strip off trailing ., tinydns doesn't require it for FQDN\n if (val.endsWith('.')) return val.slice(0, -1)\n\n return val\n }\n\n getTinydnsGeneric(rdata) {\n return `:${this.getTinyFQDN('owner')}:${this.getTypeId()}:${rdata}:${this.getTinydnsPostamble()}\\n`\n }\n\n getTinydnsPostamble() {\n return ['ttl', 'timestamp', 'location'].map((f) => this.getEmpty(f)).join(':')\n }\n\n hasValidLabels(hostname) {\n // RFC 952 defined valid hostnames\n // RFC 1035 limited domain label chars to letters, digits, and hyphen\n // RFC 1123 allowed hostnames to start with a digit\n // RFC 2181 'any binary string can be used as the label'\n const fq = hostname.endsWith('.') ? hostname.slice(0, -1) : hostname;\n for (const label of fq.split('.')) {\n if (label.length < 1 || label.length > 63)\n this.throwHelp('Labels must have 1-63 octets (characters), RFC 2181');\n }\n }\n\n is8bitInt(type, field, value) {\n if (Number.isInteger(value) && value >= 0 && value <= 255) return true\n\n this.throwHelp(`${type} ${field} must be a 8-bit integer (in the range 0-255)`);\n }\n\n is16bitInt(type, field, value) {\n if (Number.isInteger(value) && value >= 0 && value <= 65535) return true\n\n this.throwHelp(`${type} ${field} must be a 16-bit integer (in the range 0-65535)`);\n }\n\n is32bitInt(type, field, value) {\n if (Number.isInteger(value) && value >= 0 && value <= 4294967295) return true\n\n this.throwHelp(`${type} ${field} must be a 32-bit integer (in the range 0-4294967295)`);\n }\n\n isBase64(type, field, value) {\n if (\n typeof value === 'string' &&\n value.length > 0 &&\n value.length % 4 === 0 &&\n /^[A-Za-z0-9+/]*={0,2}$/.test(value)\n )\n return true\n\n this.throwHelp(`${type} ${field} must be a valid base64 string`);\n }\n\n isQuoted(val) {\n return /^[\"']/.test(val) && /[\"']$/.test(val)\n }\n\n setFqdnValue(typeName, fieldName, val) {\n if (!val) this.throwHelp(`${typeName}: ${fieldName} is required`);\n if (this.isIPv4(val) || this.isIPv6(val))\n this.throwHelp(`${typeName}: ${fieldName} must be a domain name`);\n this.isFullyQualified(typeName, fieldName, val);\n this.isValidHostname(typeName, fieldName, val);\n this.set(fieldName, val.toLowerCase());\n }\n\n setTypedValue(type, fieldName, val) {\n const typeName = this.constructor.typeName;\n switch (type) {\n case 'u8':\n this.is8bitInt(typeName, fieldName, val);\n this.set(fieldName, parseInt(val, 10));\n break\n case 'u16':\n this.is16bitInt(typeName, fieldName, val);\n this.set(fieldName, parseInt(val, 10));\n break\n case 'certtype': {\n if (val === undefined || val === null || val === '')\n this.throwHelp(`${typeName}: ${fieldName} is required`);\n if (typeof val === 'string' && !/^[0-9]+$/.test(val)) {\n const certTypes = this.constructor.CERT_TYPES;\n if (!certTypes || !Object.hasOwn(certTypes, val)) {\n this.throwHelp(`${typeName}: unknown cert type mnemonic: ${val}`);\n }\n this.set(fieldName, val);\n break\n }\n this.is16bitInt(typeName, fieldName, val);\n this.set(fieldName, parseInt(val, 10));\n break\n }\n case 'u32':\n this.is32bitInt(typeName, fieldName, val);\n this.set(fieldName, parseInt(val, 10));\n break\n case 'fqdn':\n this.setFqdnValue(typeName, fieldName, val);\n break\n case 'base64':\n this.isBase64(typeName, fieldName, val);\n this.set(fieldName, val);\n break\n case 'hex':\n if (!/^[0-9a-fA-F]*$/.test(val)) this.throwHelp(`${typeName}: ${fieldName} must be hexadecimal`);\n this.set(fieldName, val);\n break\n case 'str':\n if (!val) this.throwHelp(`${typeName}: ${fieldName} is required`);\n this.set(fieldName, val);\n break\n case 'qstr':\n if (val === undefined || val === null) this.throwHelp(`${typeName}: ${fieldName} is required`);\n this.set(fieldName, val);\n break\n case 'charstr': {\n if (val === undefined || val === null) this.throwHelp(`${typeName}: ${fieldName} is required`);\n const value = String(val);\n const byteLen = new TextEncoder().encode(value).length;\n if (byteLen > 255) this.throwHelp(`${typeName}: ${fieldName} must be <=255 bytes`);\n this.set(fieldName, value);\n break\n }\n case 'qcharstr': {\n if (val === undefined || val === null) this.throwHelp(`${typeName}: ${fieldName} is required`);\n const value = String(val);\n const byteLen = new TextEncoder().encode(value).length;\n if (byteLen > 255) this.throwHelp(`${typeName}: ${fieldName} must be <=255 bytes`);\n this.set(fieldName, value);\n break\n }\n case 'charstrs':\n if (val === undefined || val === null) this.throwHelp(`${typeName}: ${fieldName} is required`);\n this.set(fieldName, val);\n break\n case 'svcparams':\n if (val === undefined || val === null) this.throwHelp(`${typeName}: ${fieldName} is required`);\n this.set(fieldName, val);\n break\n case 'ipv4':\n if (!this.isIPv4(val)) this.throwHelp(`${typeName}: ${fieldName} must be a valid IPv4 address`);\n this.set(fieldName, val);\n break\n case 'ipv6':\n if (!this.isIPv6(val)) this.throwHelp(`${typeName}: ${fieldName} must be a valid IPv6 address`);\n this.set(fieldName, this.expandIPv6(val.toLowerCase())); // lower case: RFC 5952\n break\n }\n }\n\n isFullyQualified(type, field, hostname) {\n if (hostname.endsWith('.')) return true\n\n this.throwHelp(`${type}: ${field} must be fully qualified`);\n }\n\n isValidHostname(type, field, hostname) {\n const allowed = new RegExp(/[^a-zA-Z0-9\\-._/\\\\]/);\n if (!allowed.test(hostname)) return true\n\n const matches = allowed.exec(hostname);\n this.throwHelp(`${type}, ${field} has invalid hostname character (${matches[0]})`);\n }\n\n isIPv4(string) {\n // https://stackoverflow.com/questions/5284147/validating-ipv4-addresses-with-regexp\n return /^((25[0-5]|(2[0-4]|1\\d|[1-9]|)\\d)\\.?\\b){4}$/.test(string)\n }\n\n isIPv6(string) {\n return /^(?:(?:[a-fA-F\\d]{1,4}:){7}(?:[a-fA-F\\d]{1,4}|:)|(?:[a-fA-F\\d]{1,4}:){6}(?:(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}|:[a-fA-F\\d]{1,4}|:)|(?:[a-fA-F\\d]{1,4}:){5}(?::(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}|(?::[a-fA-F\\d]{1,4}){1,2}|:)|(?:[a-fA-F\\d]{1,4}:){4}(?:(?::[a-fA-F\\d]{1,4}){0,1}:(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}|(?::[a-fA-F\\d]{1,4}){1,3}|:)|(?:[a-fA-F\\d]{1,4}:){3}(?:(?::[a-fA-F\\d]{1,4}){0,2}:(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}|(?::[a-fA-F\\d]{1,4}){1,4}|:)|(?:[a-fA-F\\d]{1,4}:){2}(?:(?::[a-fA-F\\d]{1,4}){0,3}:(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}|(?::[a-fA-F\\d]{1,4}){1,5}|:)|(?:[a-fA-F\\d]{1,4}:){1}(?:(?::[a-fA-F\\d]{1,4}){0,4}:(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}|(?::[a-fA-F\\d]{1,4}){1,6}|:)|(?::(?:(?::[a-fA-F\\d]{1,4}){0,5}:(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}|(?::[a-fA-F\\d]{1,4}){1,7}|:)))(?:%[0-9a-zA-Z]{1,})?$/gm.test(\n string,\n )\n }\n\n expandIPv6(val, delimiter) {\n return expandIPv6(val, delimiter)\n }\n\n compressIPv6(val) {\n // * RFC 5952\n // * 4.1. Leading zeros MUST be suppressed...A single 16-bit 0000 field MUST be represented as 0.\n // * 4.2.1 The use of the symbol \"::\" MUST be used to its maximum capability.\n // * 4.2.2 The symbol \"::\" MUST NOT be used to shorten just one 16-bit 0 field.\n // * 4.2.3 When choosing placement of a \"::\", the longest run...MUST be shortened\n // * 4.3 The characters a-f in an IPv6 address MUST be represented in lowercase.\n\n // 4.3 Lowercase and 4.1 remove leading zeros per segment\n const segments = val\n .toLowerCase()\n .split(':')\n .map((s) => s.replace(/^0+/, '') || '0');\n\n let bestStart = -1;\n let bestLen = 0;\n let curStart = -1;\n let curLen = 0;\n\n // 4.2.1 & 4.2.3 Find the longest consecutive run of '0'\n for (let i = 0; i < segments.length; i++) {\n if (segments[i] === '0') {\n if (curStart === -1) curStart = i;\n curLen++;\n if (curLen > bestLen) {\n bestLen = curLen;\n bestStart = curStart;\n }\n } else {\n curStart = -1;\n curLen = 0;\n }\n }\n\n // 4.2.2 Don't shorten a single 16-bit 0 field\n if (bestLen < 2) {\n return segments.join(':')\n }\n\n const head = segments.slice(0, bestStart).join(':');\n const tail = segments.slice(bestStart + bestLen).join(':');\n\n return `${head}::${tail}`\n }\n\n octalToUint8Array(octalStr) {\n const str = octalToChar(octalStr);\n return Uint8Array.from(str, (c) => c.charCodeAt(0))\n }\n\n wireUnpackDomain(bytes, offset = 0) {\n return wireUnpackDomain(bytes, offset)\n }\n\n wirePackDomain(fqdn) {\n return wirePackDomain(fqdn)\n }\n\n getWireRdata() {\n return getWireRdata(this)\n }\n\n toWire() {\n return toWire(this, RR.CLASSES)\n }\n\n toBind(zone_opts) {\n return toBind(this, zone_opts)\n }\n\n parseTinydnsLine(tinyline) {\n const parsed = parseGenericLine(tinyline);\n return { ...parsed, owner: this.fullyQualify(parsed.owner) }\n }\n\n toTinydns() {\n return to(this)\n }\n\n isFqdnField(field) {\n return (\n (this.constructor.rdataFields ?? []).some(\n (entry) => RR.fieldName(entry) === field && RR.fieldType(entry) === 'fqdn',\n ) || false\n )\n }\n\n isQuotedField(field) {\n const quotedTypes = new Set(['qstr', 'qcharstr', 'charstrs']);\n return (\n (this.constructor.rdataFields ?? []).some(\n (entry) => RR.fieldName(entry) === field && quotedTypes.has(RR.fieldType(entry)),\n ) || false\n )\n }\n\n toMaraDNS() {\n const type = this.get('type');\n const supportedTypes = 'A PTR MX AAAA SRV NAPTR NS SOA TXT SPF RAW FQDN4 FQDN6 CNAME HINFO WKS LOC'.split(\n /\\s+/g,\n );\n if (!supportedTypes.includes(type)) return this.toMaraGeneric()\n return `${this.get('owner')}\\t+${this.get('ttl')}\\t${type}\\t${this.getFields('rdata')\n .map((f) => this.getQuoted(f))\n .join('\\t')} ~\\n`\n }\n\n toMaraGeneric() {\n // this.throwHelp(`\\nMaraDNS does not support ${type} records yet and this package does not support MaraDNS generic records. Yet.\\n`)\n return `${this.get('owner')}\\t+${this.get('ttl')}\\tRAW ${this.getTypeId()}\\t'${this.getFields('rdata')\n .map((f) => this.getQuoted(f))\n .join(' ')}' ~\\n`\n }\n}\n\nclass A extends RR {\n static typeName = 'A'\n static typeId = 1\n static RFCs = [1035]\n static tinydnsType = '+'\n static rdataFields = [['address', 'ipv4']]\n static tags = ['common']\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setAddress(val) {\n if (!val) this.throwHelp('A: address is required');\n if (!this.isIPv4(val)) this.throwHelp('A address must be IPv4');\n this.set('address', val);\n }\n\n getDescription() {\n return 'Address'\n }\n\n getCanonical() {\n return {\n owner: 'host.example.com.',\n class: 'IN',\n ttl: 3600,\n type: 'A',\n address: '192.0.2.127',\n }\n }\n\n /****** EXPORTERS *******/\n getWireRdata() {\n return new Uint8Array(this.get('address').split('.').map(Number))\n }\n}\n\nclass AAAA extends RR {\n static typeName = 'AAAA'\n static typeId = 28\n static RFCs = [3596, 5952]\n static rdataFields = [['address', 'ipv6']]\n static tags = ['common']\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setAddress(val) {\n if (!val) this.throwHelp('AAAA: address is required');\n if (!this.isIPv6(val)) this.throwHelp(`AAAA: address must be IPv6 (${val})`);\n\n this.set('address', this.expandIPv6(val.toLowerCase())); // lower case: RFC 5952\n }\n\n getCompressed(val) {\n return this.compressIPv6(val ?? this.get('address'))\n }\n\n getDescription() {\n return 'Address IPv6'\n }\n\n getCanonical() {\n return {\n owner: 'host.example.com.',\n address: '2001:0db8:0020:000a:0000:0000:0000:0004',\n class: 'IN',\n ttl: 3600,\n type: 'AAAA',\n }\n }\n\n /****** IMPORTERS *******/\n fromTinydns({ tinyline }) {\n const str = tinyline;\n let fqdn, ip, n, rdata, ttl, ts, loc;\n\n switch (str[0]) {\n case ':':\n[fqdn, n, rdata, ttl, ts, loc] = str.slice(1).split(':');\n if (n != 28) this.throwHelp('AAAA fromTinydns, invalid n');\n ip = octalToHex(rdata)\n .match(/([0-9a-fA-F]{4})/g)\n .join(':');\n break\n case '3':\n case '6':\n[fqdn, rdata, ttl, ts, loc] = str.slice(1).split(':');\n ip = rdata.match(/(.{4})/g).join(':');\n break\n }\n\n return new AAAA({\n owner: this.fullyQualify(fqdn),\n ttl: parseInt(ttl, 10),\n type: 'AAAA',\n address: ip,\n timestamp: ts,\n location: loc?.trim() ?? '',\n })\n }\n\n /****** EXPORTERS *******/\n getWireRdata() {\n const hex = this.expandIPv6(this.get('address'), '');\n const arr = new Uint8Array(hex.length / 2);\n for (let i = 0; i < arr.length; i++) arr[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);\n return arr\n }\n\n toBind(zone_opts) {\n return `${this.getPrefix(zone_opts)}\\t${this.getCompressed()}\\n`\n }\n\n toTinydns() {\n // from AAAA notation (8 groups of 4 hex digits) to 16 escaped octals\n const rdata = packHex(this.expandIPv6(this.get('address'), ''));\n return this.getTinydnsGeneric(rdata)\n }\n}\n\nclass APL extends RR {\n static typeName = 'APL'\n static typeId = 42\n static RFCs = [3123]\n static rdataFields = ['apl rdata']\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setAplRdata(val) {\n if (!val) this.throwHelp('APL: apl rdata is required');\n this.set('apl rdata', val);\n }\n\n getDescription() {\n return 'Address Prefix List'\n }\n\n getCanonical() {\n return {\n owner: 'example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'APL',\n 'apl rdata': '1:192.0.2.1/24 !1:192.0.2.64/28 2:2001:db8::1/128',\n }\n }\n\n /****** IMPORTERS *******/\n fromTinydns({ tinyline }) {\n // APL via generic, :fqdn:42:rdata:ttl:timestamp:lo\n const [fqdn, n, rdata, ttl, ts, loc] = tinyline.slice(1).split(':');\n if (n != 42) this.throwHelp('APL fromTinydns, invalid n');\n\n const bytes = Uint8Array.from(octalToChar(rdata), (c) => c.charCodeAt(0));\n const items = [];\n let pos = 0;\n\n while (pos < bytes.length) {\n const afi = (bytes[pos] << 8) | bytes[pos + 1];\n pos += 2;\n const prefix = bytes[pos];\n pos++;\n const adfLenByte = bytes[pos];\n pos++;\n const neg = (adfLenByte & 0x80) !== 0;\n const addrLen = adfLenByte & 0x7f;\n const addrBytes = bytes.subarray(pos, pos + addrLen);\n pos += addrLen;\n\n let addr;\n if (afi === 1) {\n const padded = new Uint8Array(4);\n padded.set(addrBytes);\n addr = [...padded].join('.');\n } else {\n const padded = new Uint8Array(16);\n padded.set(addrBytes);\n const paddedDv = new DataView(padded.buffer);\n const groups = [];\n for (let i = 0; i < 16; i += 2) groups.push(paddedDv.getUint16(i).toString(16).padStart(4, '0'));\n addr = this.compressIPv6(groups.join(':'));\n }\n\n items.push(`${neg ? '!' : ''}${afi}:${addr}/${prefix}`);\n }\n\n return new APL({\n owner: this.fullyQualify(fqdn),\n ttl: parseInt(ttl, 10),\n type: 'APL',\n 'apl rdata': items.join(' '),\n timestamp: ts,\n location: loc?.trim() ?? '',\n })\n }\n\n fromBind({ bindline }) {\n // test.example.com 3600 IN APL {[!]afi:address/prefix}*\n const parts = bindline.split(/\\s+/);\n const [owner, ttl, c, type] = parts;\n return new APL({\n owner,\n ttl: parseInt(ttl, 10),\n class: c,\n type,\n 'apl rdata': parts.slice(4).join(' ').trim(),\n })\n }\n\n fromWire({ owner, cls, ttl, rdata }) {\n const items = [];\n let pos = 0;\n while (pos < rdata.length) {\n const afi = (rdata[pos] << 8) | rdata[pos + 1];\n pos += 2;\n const prefix = rdata[pos++];\n const adfLenByte = rdata[pos++];\n const neg = (adfLenByte & 0x80) !== 0;\n const addrLen = adfLenByte & 0x7f;\n const addrBytes = rdata.subarray(pos, pos + addrLen);\n pos += addrLen;\n\n let addr;\n if (afi === 1) {\n const padded = new Uint8Array(4);\n padded.set(addrBytes);\n addr = [...padded].join('.');\n } else {\n const padded = new Uint8Array(16);\n padded.set(addrBytes);\n const dv = new DataView(padded.buffer);\n const groups = [];\n for (let i = 0; i < 16; i += 2) groups.push(dv.getUint16(i).toString(16).padStart(4, '0'));\n addr = this.compressIPv6(groups.join(':'));\n }\n items.push(`${neg ? '!' : ''}${afi}:${addr}/${prefix}`);\n }\n return new APL({\n owner,\n ttl,\n class: cls,\n type: 'APL',\n 'apl rdata': items.join(' '),\n })\n }\n\n /****** EXPORTERS *******/\n toTinydns() {\n return this.getTinydnsGeneric(\n this.get('apl rdata')\n .split(/\\s+/)\n .map((item) => {\n const neg = item.startsWith('!');\n const bare = neg ? item.slice(1) : item;\n const colonIdx = bare.indexOf(':');\n const afi = parseInt(bare.slice(0, colonIdx), 10);\n const rest = bare.slice(colonIdx + 1);\n const slashIdx = rest.lastIndexOf('/');\n const addr = rest.slice(0, slashIdx);\n const prefix = parseInt(rest.slice(slashIdx + 1), 10);\n\n let addrBytes;\n if (afi === 1) {\n addrBytes = new Uint8Array(addr.split('.').map((n) => parseInt(n, 10)));\n } else {\n const dblIdx = addr.indexOf('::');\n let groups;\n if (dblIdx !== -1) {\n const left = addr\n .slice(0, dblIdx)\n .split(':')\n .filter((s) => s !== '');\n const right = addr\n .slice(dblIdx + 2)\n .split(':')\n .filter((s) => s !== '');\n groups = [...left, ...Array(8 - left.length - right.length).fill('0000'), ...right];\n } else {\n groups = addr.split(':');\n }\n const hexStr = groups.map((g) => g.padStart(4, '0')).join('');\n addrBytes = Uint8Array.from({ length: hexStr.length / 2 }, (_, i) =>\n parseInt(hexStr.slice(i * 2, i * 2 + 2), 16),\n );\n }\n\n let len = addrBytes.length;\n while (len > 0 && addrBytes[len - 1] === 0) len--;\n const afdPart = addrBytes.slice(0, len);\n\n let r = UInt16toOctal(afi);\n r += UInt8toOctal(prefix);\n r += UInt8toOctal((neg ? 0x80 : 0) | afdPart.length);\n for (const b of afdPart) r += UInt8toOctal(b);\n return r\n })\n .join(''),\n )\n }\n\n getWireRdata() {\n const items = this.get('apl rdata').split(/\\s+/);\n const rdata = [];\n\n for (const item of items) {\n const neg = item.startsWith('!');\n const bare = neg ? item.slice(1) : item;\n const colonIdx = bare.indexOf(':');\n const afi = parseInt(bare.slice(0, colonIdx), 10);\n const rest = bare.slice(colonIdx + 1);\n const slashIdx = rest.lastIndexOf('/');\n const addr = rest.slice(0, slashIdx);\n const prefix = parseInt(rest.slice(slashIdx + 1), 10);\n\n let addrBytes;\n if (afi === 1) {\n addrBytes = new Uint8Array(addr.split('.').map((n) => parseInt(n, 10)));\n } else {\n const dblIdx = addr.indexOf('::');\n let groups;\n if (dblIdx !== -1) {\n const left = addr\n .slice(0, dblIdx)\n .split(':')\n .filter((s) => s !== '');\n const right = addr\n .slice(dblIdx + 2)\n .split(':')\n .filter((s) => s !== '');\n groups = [...left, ...Array(8 - left.length - right.length).fill('0000'), ...right];\n } else {\n groups = addr.split(':');\n }\n const hexStr = groups.map((g) => g.padStart(4, '0')).join('');\n addrBytes = Uint8Array.from({ length: hexStr.length / 2 }, (_, i) =>\n parseInt(hexStr.slice(i * 2, i * 2 + 2), 16),\n );\n }\n\n let len = addrBytes.length;\n while (len > 0 && addrBytes[len - 1] === 0) len--;\n const afdPart = addrBytes.slice(0, len);\n\n const itemBytes = new Uint8Array(4 + afdPart.length);\n const dv = new DataView(itemBytes.buffer, itemBytes.byteOffset);\n dv.setUint16(0, afi);\n itemBytes[2] = prefix;\n itemBytes[3] = (neg ? 0x80 : 0) | afdPart.length;\n itemBytes.set(afdPart, 4);\n\n rdata.push(itemBytes);\n }\n\n const totalLen = rdata.reduce((sum, r) => sum + r.length, 0);\n const bytes = new Uint8Array(totalLen);\n let pos = 0;\n for (const r of rdata) {\n bytes.set(r, pos);\n pos += r.length;\n }\n\n return bytes\n }\n}\n\nclass CAA extends RR {\n static typeName = 'CAA'\n static typeId = 257\n static RFCs = [6844, 8659, 9619]\n static rdataFields = [\n ['flags', 'u8'],\n ['tag', 'charstr'],\n ['value', 'qstr'],\n ]\n static tags = ['security']\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setFlags(val) {\n this.is8bitInt('CAA', 'flags', val);\n\n if (!this.getFlagsOptions().has(val)) {\n this.throwHelp(`CAA flags ${val} not recognized`);\n }\n\n this.set('flags', val);\n }\n\n getFlagsOptions() {\n return new Map([\n [0, 'Non Critical'],\n [128, 'Critical'],\n ])\n }\n\n setTag(val) {\n if (typeof val !== 'string' || val.length < 1 || /[^a-z0-9]/.test(val))\n this.throwHelp(`CAA tag must be a sequence of ASCII letters and numbers in lowercase`);\n\n if (!this.getTagOptions().has(val)) {\n this.throwHelp(`CAA tag ${val} not recognized`);\n }\n this.set('tag', val);\n }\n\n getTagOptions() {\n return new Map([['issue'], ['issuewild'], ['iodef']])\n }\n\n setValue(val) {\n // either (2) a quoted string or\n // (1) a contiguous set of characters without interior spaces\n if (this.isQuoted(val)) {\n val = val.replace(/^[\"']|[\"']$/g, ''); // strip quotes\n }\n\n // check if val starts with one of iodefSchemes\n if (this.get('tag') === 'iodef') {\n const iodefSchemes = ['mailto:', 'http:', 'https:'];\n if (!iodefSchemes.filter((s) => val.startsWith(s)).length) {\n this.throwHelp(`CAA value must have valid iodefScheme prefix`);\n }\n }\n\n this.set('value', val);\n }\n\n getDescription() {\n return 'Certification Authority Authorization'\n }\n\n getCanonical() {\n return {\n owner: 'example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'CAA',\n flags: 0,\n tag: 'issue',\n value: 'http://letsencrypt.org',\n }\n }\n\n /****** IMPORTERS *******/\n fromTinydns({ tinyline }) {\n // CAA via generic, :fqdn:n:rdata:ttl:timestamp:lo\n const { owner, typeId, rdata, ttl, timestamp, location } = this.parseTinydnsLine(tinyline);\n if (typeId != this.getTypeId()) this.throwHelp('CAA fromTinydns, invalid typeId');\n\n const flags = octalToUInt8(rdata.slice(0, 4));\n const taglen = octalToUInt8(rdata.slice(4, 8));\n\n const unescaped = octalToChar(rdata.slice(8));\n const tag = unescaped.slice(0, taglen);\n const fingerprint = unescaped.slice(taglen);\n\n return new CAA({\n owner,\n ttl,\n type: 'CAA',\n flags,\n tag,\n value: fingerprint,\n timestamp,\n location,\n })\n }\n\n /****** EXPORTERS *******/\n\n getWireRdata() {\n const tag = new TextEncoder().encode(this.get('tag'));\n const value = new TextEncoder().encode(this.get('value'));\n const result = new Uint8Array(2 + tag.length + value.length);\n result[0] = this.get('flags');\n result[1] = tag.length;\n result.set(tag, 2);\n result.set(value, 2 + tag.length);\n return result\n }\n\n toTinydns() {\n return this.getTinydnsGeneric(\n UInt8toOctal(this.get('flags')) +\n UInt8toOctal(this.get('tag').length) +\n escapeOctal(/[\\r\\n\\t:\\\\/]/, this.get('tag')) +\n escapeOctal(/[\\r\\n\\t:\\\\/]/, this.get('value')),\n )\n }\n}\n\nclass CERT extends RR {\n static typeName = 'CERT'\n static typeId = 37\n static RFCs = [2538, 4398]\n static rdataFields = [\n ['cert type', 'certtype'],\n ['key tag', 'u16'],\n ['algorithm', 'u8'],\n ['certificate', 'base64'],\n ]\n\n static CERT_TYPES = {\n PKIX: 1,\n SPKI: 2,\n PGP: 3,\n IPKIX: 4,\n ISPKI: 5,\n IPGP: 6,\n ACPKIX: 7,\n IACPKIX: 8,\n URI: 253,\n OID: 254,\n }\n\n static CERT_TYPES_REVERSE = Object.fromEntries(Object.entries(CERT.CERT_TYPES).map(([k, v]) => [v, k]))\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setCertType(val) {\n // The type field is the certificate type\n // the type field as an unsigned decimal integer or as a mnemonic symbol\n if (val === undefined || val === null || val === '') {\n this.throwHelp('cert type is required');\n }\n // Accept both mnemonic and numeric, but validate mnemonic\n if (typeof val === 'string' && !/^[0-9]+$/.test(val)) {\n if (!Object.hasOwn(CERT.CERT_TYPES, val)) {\n this.throwHelp(`CERT: unknown cert type mnemonic: ${val}`);\n }\n } else {\n this.is16bitInt('CERT', 'cert type', val);\n }\n this.set('cert type', val);\n }\n\n getCertTypeValue(val) {\n if (typeof val === 'number') return val\n if (/^[0-9]+$/.test(val)) return parseInt(val, 10)\n if (Object.hasOwn(CERT.CERT_TYPES, val)) return CERT.CERT_TYPES[val]\n this.throwHelp(`CERT: unknown cert type mnemonic: ${val}`);\n }\n\n setKeyTag(val) {\n this.setTypedValue('u16', 'key tag', val);\n }\n\n setAlgorithm(val) {\n this.setTypedValue('u8', 'algorithm', val);\n }\n\n setCertificate(val) {\n // certificate/CRL portion is represented in base 64 [16] and may be\n // divided into any number of white-space-separated substrings\n if (val === undefined || val === null || val === '') {\n this.throwHelp('certificate is required and cannot be empty');\n }\n this.isBase64('CERT', 'certificate', val.replace(/[\\s()]/g, ''));\n this.set('certificate', val);\n }\n\n getDescription() {\n return 'Certificate'\n }\n\n getCanonical() {\n return {\n owner: 'mail.example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'CERT',\n 'cert type': 'PGP',\n 'key tag': 0,\n algorithm: 0,\n certificate: 'AQIDBA==',\n }\n }\n\n /****** IMPORTERS *******/\n\n fromTinydns({ tinyline }) {\n const { owner, typeId, rdata, ttl, timestamp, location } = this.parseTinydnsLine(tinyline);\n if (typeId != this.getTypeId()) this.throwHelp('CERT fromTinydns, invalid n');\n\n const bytes = octalRdataToBytes(rdata);\n const typeNum = (bytes[0] << 8) | bytes[1];\n\n const certType = CERT.CERT_TYPES_REVERSE[typeNum] ?? typeNum;\n\n return new CERT({\n owner,\n ttl,\n type: 'CERT',\n 'cert type': certType,\n 'key tag': (bytes[2] << 8) | bytes[3],\n algorithm: bytes[4],\n certificate: bytesToBase64(bytes.subarray(5)),\n timestamp,\n location,\n })\n }\n\n fromBind({ bindline }) {\n // test.example.com 3600 IN CERT certtype, keytag, algo, cert\n const [owner, ttl, c, type, certtype, keytag, algo, certificate] = bindline.split(/\\s+/);\n return new CERT({\n owner,\n ttl: parseInt(ttl, 10),\n class: c,\n type,\n 'cert type': /^[0-9]+$/.test(certtype) ? parseInt(certtype, 10) : certtype,\n 'key tag': parseInt(keytag, 10),\n algorithm: parseInt(algo, 10),\n certificate,\n })\n }\n\n /****** EXPORTERS *******/\n\n toTinydns() {\n return this.getTinydnsGeneric(\n UInt16toOctal(this.getCertTypeValue(this.get('cert type'))) +\n UInt16toOctal(this.get('key tag')) +\n UInt8toOctal(this.get('algorithm')) +\n base64toOctal(this.get('certificate').replace(/[\\s()]/g, '')),\n )\n }\n\n getWireRdata() {\n const certBytes = base64ToBytes(this.get('certificate').replace(/[\\s()]/g, ''));\n const bytes = new Uint8Array(5 + certBytes.length);\n const dv = new DataView(bytes.buffer, bytes.byteOffset);\n dv.setUint16(0, this.getCertTypeValue(this.get('cert type')));\n dv.setUint16(2, this.get('key tag'));\n bytes[4] = this.get('algorithm');\n bytes.set(certBytes, 5);\n return bytes\n }\n}\n\nclass CNAME extends RR {\n static typeName = 'CNAME'\n static typeId = 5\n static RFCs = [1035, 2181]\n static tinydnsType = 'C'\n static rdataFields = [['cname', 'fqdn']]\n static tags = ['common']\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setCname(val) {\n this.setTypedValue('fqdn', 'cname', val);\n }\n\n getDescription() {\n return 'Canonical Name'\n }\n\n getCanonical() {\n return {\n owner: 'www.example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'CNAME',\n cname: 'web.example.com.',\n }\n }\n\n /****** EXPORTERS *******/\n getWireRdata() {\n return this.wirePackDomain(this.get('cname'))\n }\n}\n\nclass DHCID extends RR {\n static typeName = 'DHCID'\n static typeId = 49\n static RFCs = [4701]\n static rdataFields = [['data', 'base64']]\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setData(val) {\n if (!val) this.throwHelp('DHCID: data is required');\n this.isBase64('DHCID', 'data', val);\n this.set('data', val);\n }\n\n getDescription() {\n return 'DHCP Identifier'\n }\n\n getCanonical() {\n return {\n owner: 'host.example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'DHCID',\n data: 'AAIBY2/AuCccgoJbsaxcQc9TUapptP69lOjxfNuVAA2kjEA=',\n }\n }\n\n /****** IMPORTERS *******/\n fromTinydns({ tinyline }) {\n // DHCID via generic, :fqdn:49:rdata:ttl:timestamp:lo\n const { owner, typeId, rdata, ttl, timestamp, location } = this.parseTinydnsLine(tinyline);\n if (typeId != this.getTypeId()) this.throwHelp('DHCID fromTinydns, invalid n');\n\n return new DHCID({\n owner,\n ttl,\n type: 'DHCID',\n data: octalToBase64(rdata),\n timestamp,\n location,\n })\n }\n\n /****** EXPORTERS *******/\n\n getWireRdata() {\n return new Uint8Array(\n atob(this.get('data'))\n .split('')\n .map((c) => c.charCodeAt(0)),\n )\n }\n\n toTinydns() {\n return this.getTinydnsGeneric(base64toOctal(this.get('data')))\n }\n}\n\nclass DNAME extends RR {\n static typeName = 'DNAME'\n static typeId = 39\n static RFCs = [2672, 6672]\n static rdataFields = [['target', 'fqdn']]\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setTarget(val) {\n this.setTypedValue('fqdn', 'target', val);\n }\n\n getDescription() {\n return 'Delegation Name'\n }\n\n getCanonical() {\n return {\n owner: 'example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'DNAME',\n target: 'example.net.',\n }\n }\n\n /****** IMPORTERS *******/\n fromTinydns({ tinyline }) {\n // DNAME via generic, :fqdn:n:rdata:ttl:timestamp:lo\n const [fqdn, n, rdata, ttl, ts, loc] = tinyline.slice(1).split(':');\n if (n != 39) this.throwHelp('DNAME fromTinydns, invalid n');\n\n return new DNAME({\n type: 'DNAME',\n owner: this.fullyQualify(fqdn),\n target: unpackDomainName(rdata)[0],\n ttl: parseInt(ttl, 10),\n timestamp: ts,\n location: loc?.trim() ?? '',\n })\n }\n\n /****** EXPORTERS *******/\n\n getWireRdata() {\n return this.wirePackDomain(this.get('target'))\n }\n\n toTinydns() {\n const rdata = packDomainName(this.get('target'));\n return this.getTinydnsGeneric(rdata)\n }\n}\n\nclass DNSKEY extends RR {\n static typeName = 'DNSKEY'\n static typeId = 48\n static RFCs = [4034, 6014, 8624, 9619, 9905]\n static rdataFields = [\n ['flags', 'u16'],\n ['protocol', 'u8'],\n ['algorithm', 'u8'],\n ['publickey', 'base64'],\n ]\n static tags = ['dnssec']\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setFlags(val) {\n // a 2 octet Flags Field\n this.is16bitInt('DNSKEY', 'flags', val);\n\n if (!this.getFlagsOptions().has(val)) {\n this.throwHelp(`DNSKEY: flags must be in the set: ${this.getFlagsOptions()}`);\n }\n\n this.set('flags', val);\n }\n\n // possible values are: 0, 256, and 257; RFC 4034\n getFlagsOptions() {\n return new Map([[0], [256], [257]])\n }\n\n setProtocol(val) {\n // 1 octet\n this.is8bitInt('DNSKEY', 'protocol', val);\n\n // The Protocol Field MUST be represented as an unsigned decimal integer with a value of 3.\n if (!this.getProtocolOptions().has(val)) this.throwHelp(`DNSKEY: protocol invalid`);\n\n this.set('protocol', val);\n }\n\n getProtocolOptions() {\n return new Map([[3]])\n }\n\n setAlgorithm(val) {\n // 1 octet\n this.is8bitInt('DNSKEY', 'algorithm', val);\n\n // https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml\n if (!this.getAlgorithmOptions().has(val)) console.error(`DNSKEY: algorithm (${val}) not recognized`);\n\n this.set('algorithm', val);\n }\n\n getAlgorithmOptions() {\n return new Map([\n [1, 'RSA/MD5 (DEPRECATED)'],\n [2, 'DH'],\n [3, 'DSA/SHA-1'],\n [4, 'EC'],\n [5, 'RSA/SHA-1'],\n [6, 'DSA-NSEC3-SHA1'],\n [7, 'RSASHA1-NSEC3-SHA1'],\n [8, 'RSA/SHA-256'],\n [9, ''],\n [10, 'RSA/SHA-512'],\n [13, 'ECDSA Curve P-256 with SHA-256'],\n [14, 'ECDSA Curve P-384 with SHA-384'],\n [15, 'Ed25519'],\n [16, 'Ed448'],\n [253],\n [254],\n ])\n }\n\n setPublickey(val) {\n if (!val) this.throwHelp(`DNSKEY: publickey is required`);\n this.isBase64('DNSKEY', 'publickey', val.replace(/[\\s()]/g, ''));\n this.set('publickey', val);\n }\n\n getDescription() {\n return 'DNS Public Key'\n }\n\n getCanonical() {\n return {\n owner: 'example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'DNSKEY',\n flags: 256,\n protocol: 3,\n algorithm: 5,\n publickey:\n 'AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwIXAqcOTiW7iHnQt5hwVAAAAA==',\n }\n }\n\n /****** IMPORTERS *******/\n\n fromBind({ bindline }) {\n // test.example.com 3600 IN DNSKEY Flags Protocol Algorithm PublicKey\n const regex =\n /^(?\\S+)\\s+(?\\d+)\\s+(?\\w+)\\s+(?DNSKEY)\\s+(?\\d+)\\s+(?\\d+)\\s+(?\\d+)\\s+(?\\S.*)$/i;\n\n const match = bindline.trim().match(regex);\n\n if (!match) {\n this.throwHelp(`unable to parse DNSKEY: ${bindline}`);\n }\n\n const { owner, ttl, c, type, flags, protocol, algorithm, publickey } = match.groups;\n\n return new DNSKEY({\n owner,\n ttl: parseInt(ttl, 10),\n class: c,\n type: type,\n flags: parseInt(flags, 10),\n protocol: parseInt(protocol, 10),\n algorithm: parseInt(algorithm, 10),\n publickey: publickey,\n })\n }\n\n fromTinydns({ tinyline }) {\n const { owner, typeId, rdata, ttl, timestamp, location } = this.parseTinydnsLine(tinyline);\n if (typeId != this.getTypeId()) this.throwHelp('DNSKEY fromTinydns, invalid n');\n\n const bytes = octalRdataToBytes(rdata);\n\n return new DNSKEY({\n owner,\n ttl,\n type: 'DNSKEY',\n flags: (bytes[0] << 8) | bytes[1],\n protocol: bytes[2],\n algorithm: bytes[3],\n publickey: bytesToBase64(bytes.subarray(4)),\n timestamp,\n location,\n })\n }\n\n /****** EXPORTERS *******/\n\n toTinydns() {\n return this.getTinydnsGeneric(\n UInt16toOctal(this.get('flags')) +\n UInt8toOctal(this.get('protocol')) +\n UInt8toOctal(this.get('algorithm')) +\n base64toOctal(this.get('publickey').replace(/[\\s()]/g, '')),\n )\n }\n\n getWireRdata() {\n const keyBytes = base64ToBytes(this.get('publickey').replace(/[\\s()]/g, ''));\n const bytes = new Uint8Array(4 + keyBytes.length);\n const dv = new DataView(bytes.buffer, bytes.byteOffset);\n dv.setUint16(0, this.get('flags'));\n bytes[2] = this.get('protocol');\n bytes[3] = this.get('algorithm');\n bytes.set(keyBytes, 4);\n return bytes\n }\n}\n\nclass DS extends RR {\n static typeName = 'DS'\n static typeId = 43\n static RFCs = [4034, 4509, 9619]\n static rdataFields = [['key tag', 'u16'], 'algorithm', 'digest type', ['digest', 'str']]\n static tags = ['dnssec']\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setKeyTag(val) {\n this.setTypedValue('u16', 'key tag', val);\n }\n\n setDigest(val) {\n this.setTypedValue('str', 'digest', val);\n }\n\n setAlgorithm(val) {\n if (!this.getAlgorithmOptions().has(val)) this.throwHelp(`DS: algorithm invalid`);\n\n this.set('algorithm', val);\n }\n\n getAlgorithmOptions() {\n // IANA DNSSEC Algorithm Numbers\n // https://www.iana.org/assignments/dns-sec-alg-numbers/\n return new Map([\n [1, 'RSA/MD5'],\n [2, 'DH'],\n [3, 'DSA/SHA-1'],\n [4, 'EC'],\n [5, 'RSA/SHA-1'],\n [6, 'DSA-NSEC3-SHA1'],\n [7, 'RSASHA1-NSEC3-SHA1'],\n [8, 'RSA/SHA-256'],\n [10, 'RSA/SHA-512'],\n [13, 'ECDSA P-256/SHA-256'],\n [14, 'ECDSA P-384/SHA-384'],\n [15, 'Ed25519'],\n [16, 'Ed448'],\n [253, ''],\n [254, ''],\n ])\n }\n\n setDigestType(val) {\n // 1=SHA-1 (RFC 4034), 2=SHA-256 (RFC 4509), 4=SHA-384 (RFC 6605)\n if (![1, 2, 4].includes(val)) this.throwHelp(`DS: digest type invalid`);\n\n this.set('digest type', val);\n }\n\n getDescription() {\n return 'Delegation Signer'\n }\n\n getCanonical() {\n return {\n owner: 'example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'DS',\n 'key tag': 12345,\n algorithm: 5,\n 'digest type': 1,\n digest: 'ABCDEF123...',\n }\n }\n\n /****** IMPORTERS *******/\n\n fromTinydns(opts) {\n const { tinyline } = opts;\n const { owner, typeId, rdata, ttl, timestamp, location } = this.parseTinydnsLine(tinyline);\n if (typeId != this.getTypeId()) this.throwHelp('DS fromTinydns, invalid n');\n\n const binRdata = octalRdataToBytes(rdata);\n\n return new DS({\n owner,\n ttl,\n type: 'DS',\n 'key tag': (binRdata[0] << 8) | binRdata[1],\n algorithm: binRdata[2],\n 'digest type': binRdata[3],\n digest: bytesToHex(binRdata.subarray(4)).toUpperCase(),\n timestamp,\n location,\n })\n }\n\n fromWire({ owner, cls, ttl, rdata }) {\n const dv = new DataView(rdata.buffer, rdata.byteOffset);\n return new DS({\n owner,\n ttl,\n class: cls,\n type: 'DS',\n 'key tag': dv.getUint16(0),\n algorithm: rdata[2],\n 'digest type': rdata[3],\n digest: bytesToHex(rdata.subarray(4)).toUpperCase(),\n })\n }\n\n /****** EXPORTERS *******/\n\n toTinydns() {\n return this.getTinydnsGeneric(\n UInt16toOctal(this.get('key tag')) +\n UInt8toOctal(this.get('algorithm')) +\n UInt8toOctal(this.get('digest type')) +\n packHex(this.get('digest').replace(/\\s+/g, '')),\n )\n }\n\n getWireRdata() {\n const digestBytes = hexToBytes(this.get('digest').replace(/\\s+/g, ''));\n const bytes = new Uint8Array(4 + digestBytes.length);\n const dv = new DataView(bytes.buffer, bytes.byteOffset);\n dv.setUint16(0, this.get('key tag'));\n bytes[2] = this.get('algorithm');\n bytes[3] = this.get('digest type');\n bytes.set(digestBytes, 4);\n return bytes\n }\n}\n\nclass HINFO extends RR {\n static typeName = 'HINFO'\n static typeId = 13\n static RFCs = [1034, 1035, 8482]\n static rdataFields = [\n ['cpu', 'qcharstr'],\n ['os', 'qcharstr'],\n ]\n static tags = ['obsolete']\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setCpu(val) {\n if (val.length > 255) this.throwHelp('HINFO cpu cannot exceed 255 chars');\n this.set('cpu', val.replace(/^[\"']|[\"']$/g, ''));\n }\n\n setOs(val) {\n if (val.length > 255) this.throwHelp('HINFO os cannot exceed 255 chars');\n this.set('os', val.replace(/^[\"']|[\"']$/g, ''));\n }\n\n getDescription() {\n return 'Host Info'\n }\n\n getCanonical() {\n return {\n owner: 'test.example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'HINFO',\n cpu: 'DEC-2060',\n os: 'TOPS20',\n }\n }\n\n /****** IMPORTERS *******/\n fromTinydns({ tinyline }) {\n // HINFO via generic, :fqdn:n:rdata:ttl:timestamp:lo\n const [fqdn, , rdata, ttl, ts, loc] = tinyline.slice(1).split(':');\n const [cpu, os] = [...unpackString(rdata)];\n\n return new this.constructor({\n owner: this.fullyQualify(fqdn),\n ttl: parseInt(ttl, 10),\n type: 'HINFO',\n cpu,\n os,\n timestamp: ts,\n location: loc?.trim() ?? '',\n })\n }\n\n /****** EXPORTERS *******/\n\n getWireRdata() {\n const cpu = new TextEncoder().encode(this.get('cpu'));\n const os = new TextEncoder().encode(this.get('os'));\n const result = new Uint8Array(2 + cpu.length + os.length);\n result[0] = cpu.length;\n result.set(cpu, 1);\n result[1 + cpu.length] = os.length;\n result.set(os, 2 + cpu.length);\n return result\n }\n\n toTinydns() {\n return this.getTinydnsGeneric(\n [packString(this.get('cpu')), packString(this.get('os'))].join(''),\n )\n }\n}\n\nclass HIP extends RR {\n static typeName = 'HIP'\n static typeId = 55\n static RFCs = [8005]\n static rdataFields = ['pk algorithm', 'hit', 'public key', 'rendezvous servers']\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setPkAlgorithm(val) {\n if (val === undefined) this.throwHelp('HIP: pk algorithm is required');\n this.is8bitInt('HIP', 'pk algorithm', val);\n this.set('pk algorithm', val);\n }\n\n setHit(val) {\n if (!val) this.throwHelp('HIP: hit is required');\n this.set('hit', val);\n }\n\n setPublicKey(val) {\n if (!val) this.throwHelp('HIP: public key is required');\n this.set('public key', val);\n }\n\n setRendezvousServers(val) {\n this.set('rendezvous servers', val ?? '');\n }\n\n getDescription() {\n return 'Host Identity Protocol'\n }\n\n getCanonical() {\n return {\n owner: 'example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'HIP',\n 'pk algorithm': 2,\n hit: '200100107B1A74DF365639CC39F1D578',\n 'public key':\n 'AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwIXAqcOTiW7iHnQt5hwVAAAAA==',\n 'rendezvous servers': '',\n }\n }\n\n /****** IMPORTERS *******/\n fromTinydns({ tinyline }) {\n // HIP via generic, :fqdn:55:rdata:ttl:timestamp:lo\n const [fqdn, n, rdata, ttl, ts, loc] = tinyline.slice(1).split(':');\n if (n != 55) this.throwHelp('HIP fromTinydns, invalid n');\n\n const bytes = Uint8Array.from(octalToChar(rdata), (c) => c.charCodeAt(0));\n const hitLen = bytes[0];\n const pkAlgorithm = bytes[1];\n const pkLen = (bytes[2] << 8) | bytes[3];\n\n const hit = bytesToHex(bytes.subarray(4, 4 + hitLen)).toUpperCase();\n const publicKey = bytesToBase64(bytes.subarray(4 + hitLen, 4 + hitLen + pkLen));\n\n const rvsNames = [];\n let pos = 4 + hitLen + pkLen;\n while (pos < bytes.length) {\n const [name, newPos] = unpackDomainName(\n [...bytes.subarray(pos)]\n .map((b) => (b < 32 || b > 126 ? UInt8toOctal(b) : String.fromCharCode(b)))\n .join(''),\n );\n pos += newPos;\n if (name !== '.') rvsNames.push(name);\n }\n\n return new HIP({\n owner: this.fullyQualify(fqdn),\n ttl: parseInt(ttl, 10),\n type: 'HIP',\n 'pk algorithm': pkAlgorithm,\n hit,\n 'public key': publicKey,\n 'rendezvous servers': rvsNames.join(' '),\n timestamp: ts,\n location: loc?.trim() ?? '',\n })\n }\n\n fromBind({ bindline }) {\n // owner ttl IN HIP pk-algorithm HIT public-key [rendezvous-server...]\n // The public key may be split across multiple lines and joined with spaces\n // by the zone parser. Base64 chars are [A-Za-z0-9+/=]; domain names contain '.'.\n const parts = bindline.split(/\\s+/);\n const [owner, ttl, c, type, pkAlgorithm, hit] = parts;\n const rest = parts.slice(6);\n const keyParts = [];\n const rvsParts = [];\n for (const token of rest) {\n if (/^[A-Za-z0-9+/=]+$/.test(token)) {\n keyParts.push(token);\n } else {\n rvsParts.push(token);\n }\n }\n return new HIP({\n owner,\n ttl: parseInt(ttl, 10),\n class: c,\n type,\n 'pk algorithm': parseInt(pkAlgorithm, 10),\n hit,\n 'public key': keyParts.join(''),\n 'rendezvous servers': rvsParts.join(' ').trim(),\n })\n }\n\n fromWire({ owner, cls, ttl, rdata }) {\n const dv = new DataView(rdata.buffer, rdata.byteOffset);\n const hitLen = rdata[0];\n const pkAlgorithm = rdata[1];\n const pkLen = dv.getUint16(2);\n const hit = bytesToHex(rdata.subarray(4, 4 + hitLen)).toUpperCase();\n const publicKey = bytesToBase64(rdata.subarray(4 + hitLen, 4 + hitLen + pkLen));\n const rvsNames = [];\n let pos = 4 + hitLen + pkLen;\n while (pos < rdata.length) {\n const { fqdn, end } = this.wireUnpackDomain(rdata, pos);\n rvsNames.push(fqdn);\n pos = end;\n }\n return new HIP({\n owner,\n ttl,\n class: cls,\n type: 'HIP',\n 'pk algorithm': pkAlgorithm,\n hit,\n 'public key': publicKey,\n 'rendezvous servers': rvsNames.join(' '),\n })\n }\n\n /****** EXPORTERS *******/\n toBind(zone_opts) {\n const rs = this.get('rendezvous servers');\n const rsPart = rs ? `\\t${rs}` : '';\n return `${this.getPrefix(zone_opts)}\\t${this.get('pk algorithm')}\\t${this.get('hit')}\\t${this.get('public key')}${rsPart}\\n`\n }\n\n toTinydns() {\n const hitHex = this.get('hit');\n const hitBytes = hexToBytes(hitHex);\n const pkBytes = base64ToBytes(this.get('public key'));\n const rs = this.get('rendezvous servers');\n\n let rdata = '';\n rdata += UInt8toOctal(hitBytes.length);\n rdata += UInt8toOctal(this.get('pk algorithm'));\n rdata += UInt16toOctal(pkBytes.length);\n for (const b of hitBytes) rdata += UInt8toOctal(b);\n for (const b of pkBytes) rdata += UInt8toOctal(b);\n if (rs) {\n for (const name of rs.split(/\\s+/)) rdata += packDomainName(name);\n }\n\n return this.getTinydnsGeneric(rdata)\n }\n\n getWireRdata() {\n const hitHex = this.get('hit');\n const hitBytes = hexToBytes(hitHex);\n const pkBytes = base64ToBytes(this.get('public key'));\n const rs = this.get('rendezvous servers');\n\n const rsNames = rs ? rs.split(/\\s+/) : [];\n const rsDomains = rsNames.map((name) => wirePackDomain(name));\n const rsTotalLen = rsDomains.reduce((sum, b) => sum + b.length, 0);\n\n const totalLen = 1 + 1 + 2 + hitBytes.length + pkBytes.length + rsTotalLen;\n const bytes = new Uint8Array(totalLen);\n const dv = new DataView(bytes.buffer, bytes.byteOffset);\n\n let pos = 0;\n bytes[pos++] = hitBytes.length;\n bytes[pos++] = this.get('pk algorithm');\n dv.setUint16(pos, pkBytes.length);\n pos += 2;\n bytes.set(hitBytes, pos);\n pos += hitBytes.length;\n bytes.set(pkBytes, pos);\n pos += pkBytes.length;\n for (const rdomain of rsDomains) {\n bytes.set(rdomain, pos);\n pos += rdomain.length;\n }\n\n return bytes\n }\n}\n\nclass HTTPS extends RR {\n static typeName = 'HTTPS'\n static typeId = 65\n static RFCs = [9460]\n static tags = ['common']\n static rdataFields = [\n ['priority', 'u16'],\n ['target name', 'fqdn'],\n ['params', 'svcparams'],\n ]\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setPriority(val) {\n this.is16bitInt('HTTPS', 'priority', val);\n\n this.set('priority', val);\n }\n\n setTargetName(val) {\n // this.isFullyQualified('HTTPS', 'target name', val)\n // this.isValidHostname('HTTPS', 'target name', val)\n\n // RFC 4034: letters in the DNS names are lower cased\n this.set('target name', val.toLowerCase());\n }\n\n setParams(val) {\n // if (!val) this.throwHelp(`HTTPS: params is required`)\n\n this.set('params', val);\n }\n\n getDescription() {\n return 'HTTP Semantics'\n }\n\n getCanonical() {\n return {\n owner: 'example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'HTTPS',\n priority: 1,\n 'target name': 'example.com.',\n params: 'alpn=\"h2,h3\"',\n }\n }\n\n /****** IMPORTERS *******/\n\n fromBind({ bindline }) {\n // test.example.com 3600 IN HTTPS Priority TargetName Params\n const [owner, ttl, c, type, pri, fqdn] = bindline.split(/\\s+/);\n return new HTTPS({\n owner,\n ttl: parseInt(ttl, 10),\n class: c,\n type,\n priority: parseInt(pri, 10),\n 'target name': fqdn,\n params: bindline.split(/\\s+/).slice(6).join(' ').trim(),\n })\n }\n\n fromTinydns({ tinyline }) {\n const { owner, typeId, rdata, ttl, timestamp, location } = this.parseTinydnsLine(tinyline);\n if (typeId != this.getTypeId()) this.throwHelp('HTTPS fromTinydns, invalid n');\n const { priority, targetName, params } = parseSvcbLikeRdata(rdata, 'HTTPS');\n\n return new HTTPS({\n owner,\n ttl,\n type: 'HTTPS',\n priority,\n 'target name': targetName,\n params,\n timestamp,\n location,\n })\n }\n\n /****** EXPORTERS *******/\n\n toTinydns() {\n const dataRe = new RegExp(/[\\r\\n\\t:\\\\/]/, 'g');\n\n return this.getTinydnsGeneric(\n UInt16toOctal(this.get('priority')) +\n packDomainName(this.get('target name')) +\n escapeOctal(dataRe, this.get('params')),\n )\n }\n\n getWireRdata() {\n const targetBytes = this.wirePackDomain(this.get('target name'));\n const paramsBytes = svcParamsToWire(this.get('params'));\n const result = new Uint8Array(2 + targetBytes.length + paramsBytes.length);\n new DataView(result.buffer).setUint16(0, this.get('priority'));\n result.set(targetBytes, 2);\n result.set(paramsBytes, 2 + targetBytes.length);\n return result\n }\n}\n\nclass IPSECKEY extends RR {\n static typeName = 'IPSECKEY'\n static typeId = 45\n static RFCs = [4025]\n static rdataFields = ['precedence', 'gateway type', 'algorithm', 'gateway', 'publickey']\n static tags = ['security']\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setPrecedence(val) {\n // an 8-bit precedence for this record.\n this.is8bitInt('IPSECKEY', 'precedence', val);\n\n this.set('precedence', val);\n }\n\n setGatewayType(val) {\n if (!this.getGatewayTypeOptions().has(val)) this.throwHelp(`IPSECKEY: Gateway Type is invalid`);\n\n this.set('gateway type', val);\n }\n\n getGatewayTypeOptions() {\n return new Map([\n [0, 'none'],\n [1, '4-byte IPv4'],\n [2, '16-byte IPv6'],\n [3, 'wire encoded domain name'],\n ])\n }\n\n setAlgorithm(val) {\n if (!this.getAlgorithmOptions().has(val)) this.throwHelp(`IPSECKEY: Algorithm invalid`);\n\n this.set('algorithm', val);\n }\n\n getAlgorithmOptions() {\n return new Map([\n [1, 'DSA'],\n [2, 'RSA'],\n ])\n }\n\n setGateway(val) {\n const type = this.get('gateway type');\n const gwErr = new Error(`IPSECKEY: gateway invalid (${val}) for type ${type}`);\n switch (type) {\n case 0:\n if (val !== '.') throw gwErr\n break\n case 1:\n if (!this.isIPv4(val)) throw gwErr\n break\n case 2:\n if (!this.isIPv6(val)) throw gwErr\n break\n }\n\n this.set('gateway', val);\n }\n\n setPublickey(val) {\n if (val) this.isBase64('IPSECKEY', 'publickey', val);\n this.set('publickey', val);\n }\n\n getDescription() {\n return 'IPsec Keying'\n }\n\n getCanonical() {\n return {\n owner: '38.2.0.192.in-addr.arpa.',\n ttl: 7200,\n class: 'IN',\n type: 'IPSECKEY',\n precedence: 10,\n 'gateway type': 1,\n algorithm: 2,\n gateway: '192.0.2.38',\n publickey: 'AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==',\n }\n }\n\n /****** IMPORTERS *******/\n fromBind({ bindline }) {\n // FQDN TTL CLASS IPSECKEY Precedence GatewayType Algorithm Gateway PublicKey\n const [owner, ttl, c, type, prec, gwt, algo, gateway, publickey] = bindline.split(/\\s+/);\n return new IPSECKEY({\n owner,\n ttl: parseInt(ttl, 10),\n class: c,\n type,\n precedence: parseInt(prec, 10),\n 'gateway type': parseInt(gwt, 10),\n algorithm: parseInt(algo, 10),\n gateway,\n publickey,\n })\n }\n\n fromTinydns({ tinyline }) {\n const [fqdn, n, rdata, ttl, ts, loc] = tinyline.slice(1).split(':');\n if (n != 45) this.throwHelp('IPSECKEY fromTinydns, invalid n');\n\n const precedence = octalToUInt8(rdata.slice(0, 4));\n const gwType = octalToUInt8(rdata.slice(4, 8));\n const algorithm = octalToUInt8(rdata.slice(8, 12));\n\n let len, gateway, octalKey;\n\n switch (gwType) {\n case 0: // no gateway\n gateway = rdata.slice(12, 13); // should always be: '.'\n octalKey = rdata.slice(13);\n break\n case 1: // 4-byte IPv4 address\n gateway = octalToIPv4(rdata.slice(12, 28));\n octalKey = rdata.slice(28);\n break\n case 2: // 16-byte IPv6\n gateway = octalToIPv6(rdata.slice(12, 76));\n octalKey = rdata.slice(76);\n break\n case 3: // wire encoded domain name\n[gateway, len] = unpackDomainName(rdata.slice(12));\n octalKey = rdata.slice(12 + len);\n break\n }\n\n return new IPSECKEY({\n owner: this.fullyQualify(fqdn),\n ttl: parseInt(ttl, 10),\n type: 'IPSECKEY',\n precedence,\n 'gateway type': gwType,\n algorithm,\n gateway,\n publickey: octalToBase64(octalKey),\n timestamp: ts,\n location: loc?.trim() ?? '',\n })\n }\n\n fromWire({ owner, cls, ttl, rdata }) {\n const precedence = rdata[0];\n const gwType = rdata[1];\n const algorithm = rdata[2];\n let gateway, keyStart;\n switch (gwType) {\n case 0:\n gateway = '.';\n keyStart = 3;\n break\n case 1:\n gateway = [...rdata.subarray(3, 7)].join('.');\n keyStart = 7;\n break\n case 2: {\n const dv = new DataView(rdata.buffer, rdata.byteOffset + 3);\n const groups = [];\n for (let i = 0; i < 16; i += 2) groups.push(dv.getUint16(i).toString(16).padStart(4, '0'));\n gateway = groups.join(':');\n keyStart = 19;\n break\n }\n case 3: {\n const { fqdn, end } = this.wireUnpackDomain(rdata, 3);\n gateway = fqdn;\n keyStart = end;\n break\n }\n }\n const publickey = bytesToBase64(rdata.subarray(keyStart));\n return new IPSECKEY({\n owner,\n ttl,\n class: cls,\n type: 'IPSECKEY',\n precedence,\n 'gateway type': gwType,\n algorithm,\n gateway,\n publickey,\n })\n }\n\n /****** EXPORTERS *******/\n\n toTinydns() {\n const rdataRe = new RegExp(/[\\r\\n\\t:\\\\/]/, 'g');\n\n let rdata = '';\n rdata += UInt8toOctal(this.get('precedence'));\n rdata += UInt8toOctal(this.get('gateway type'));\n rdata += UInt8toOctal(this.get('algorithm'));\n\n switch (this.get('gateway type')) {\n case 0:\n rdata += escapeOctal(rdataRe, '.');\n break\n case 1:\n rdata += ipv4toOctal(this.get('gateway'));\n break\n case 2:\n rdata += ipv6toOctal(this.get('gateway'));\n break\n case 3:\n rdata += packDomainName(this.get('gateway'));\n break\n }\n\n rdata += base64toOctal(this.get('publickey'));\n\n return this.getTinydnsGeneric(rdata)\n }\n\n getWireRdata() {\n const pubkeyBytes = base64ToBytes(this.get('publickey'));\n const gwType = this.get('gateway type');\n\n let gwBytes;\n switch (gwType) {\n case 0:\n gwBytes = new Uint8Array(0);\n break\n case 1:\n gwBytes = new Uint8Array(4);\n this.get('gateway')\n .split('.')\n .forEach((part, i) => {\n gwBytes[i] = parseInt(part, 10);\n });\n break\n case 2:\n gwBytes = new Uint8Array(16);\n {\n const parts = this.get('gateway').split(':');\n let pos = 0;\n for (const part of parts) {\n if (part === '') continue\n const val = parseInt(part, 16);\n gwBytes[pos++] = (val >>> 8) & 0xff;\n gwBytes[pos++] = val & 0xff;\n }\n }\n break\n case 3:\n gwBytes = wirePackDomain(this.get('gateway'));\n break\n }\n\n const bytes = new Uint8Array(3 + gwBytes.length + pubkeyBytes.length);\n bytes[0] = this.get('precedence');\n bytes[1] = gwType;\n bytes[2] = this.get('algorithm');\n bytes.set(gwBytes, 3);\n bytes.set(pubkeyBytes, 3 + gwBytes.length);\n\n return bytes\n }\n}\n\nclass KEY extends RR {\n static typeName = 'KEY'\n static typeId = 25\n static RFCs = [2535, 3445, 4034, 6840]\n static rdataFields = [\n ['flags', 'u16'],\n ['protocol', 'u8'],\n ['algorithm', 'u8'],\n ['publickey', 'base64'],\n ]\n static tags = ['obsolete']\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setFlags(val) {\n // a 2 octet Flags Field\n this.is16bitInt('KEY', 'flags', val);\n\n this.set('flags', val);\n }\n\n setProtocol(val) {\n // 1 octet\n this.is8bitInt('KEY', 'protocol', val);\n\n this.set('protocol', val);\n }\n\n setAlgorithm(val) {\n // 1 octet\n\n if (!this.getAlgorithmOptions().has(val)) this.throwHelp(`KEY: algorithm invalid`);\n\n this.set('algorithm', val);\n }\n\n getAlgorithmOptions() {\n return new Map([\n [1, 'RSA/MD5'],\n [2, 'DH'],\n [3, 'DSA/SHA-1'],\n [4, 'EC'],\n [5, 'RSA/SHA-1'],\n [253, ''],\n [254, ''],\n ])\n }\n\n setPublickey(val) {\n if (!val) this.throwHelp(`KEY: publickey is required`);\n this.isBase64('KEY', 'publickey', val.replace(/[\\s()]/g, ''));\n this.set('publickey', val);\n }\n\n getDescription() {\n return 'DNS Public Key'\n }\n\n getCanonical() {\n return {\n owner: 'example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'KEY',\n flags: 256,\n protocol: 3,\n algorithm: 5,\n publickey:\n 'AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwIXAqcOTiW7iHnQt5hwVAAAAA==',\n }\n }\n\n /****** IMPORTERS *******/\n\n fromBind({ bindline }) {\n // test.example.com 3600 IN KEY Flags Protocol Algorithm PublicKey\n const [owner, ttl, c, type, flags, protocol, algorithm] = bindline.split(/\\s+/);\n return new KEY({\n owner,\n ttl: parseInt(ttl, 10),\n class: c,\n type: type,\n flags: parseInt(flags, 10),\n protocol: parseInt(protocol, 10),\n algorithm: parseInt(algorithm, 10),\n publickey: bindline.split(/\\s+/).slice(7).join(' ').trim(),\n })\n }\n\n fromTinydns({ tinyline }) {\n // RDATA format: Flags (8 octal chars) + Protocol (4 octal chars) + Algorithm (4 octal chars) + Public Key (escaped data)\n const { owner, rdata, ttl, timestamp, location } = this.parseTinydnsLine(tinyline);\n if (rdata.length < 16) {\n this.throwHelp(`KEY: RDATA too short: ${rdata}`);\n }\n\n return new KEY({\n owner,\n ttl,\n type: 'KEY',\n flags: octalToUInt16(rdata.slice(0, 8)),\n protocol: octalToUInt8(rdata.slice(8, 12)),\n algorithm: octalToUInt8(rdata.slice(12, 16)),\n publickey: octalToBase64(rdata.slice(16)),\n timestamp,\n location,\n })\n }\n\n /****** EXPORTERS *******/\n toTinydns() {\n return this.getTinydnsGeneric(\n UInt16toOctal(this.get('flags')) +\n UInt8toOctal(this.get('protocol')) +\n UInt8toOctal(this.get('algorithm')) +\n base64toOctal(this.get('publickey').replace(/[\\s()]/g, '')),\n )\n }\n\n getWireRdata() {\n const keyBytes = base64ToBytes(this.get('publickey').replace(/[\\s()]/g, ''));\n const bytes = new Uint8Array(4 + keyBytes.length);\n const dv = new DataView(bytes.buffer, bytes.byteOffset);\n dv.setUint16(0, this.get('flags'));\n bytes[2] = this.get('protocol');\n bytes[3] = this.get('algorithm');\n bytes.set(keyBytes, 4);\n return bytes\n }\n}\n\nclass KX extends RR {\n static typeName = 'KX'\n static typeId = 36\n static RFCs = [2230]\n static rdataFields = [\n ['preference', 'u16'],\n ['exchanger', 'fqdn'],\n ]\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setPreference(val) {\n if (val === undefined) this.throwHelp('KX: preference is required');\n this.is16bitInt('KX', 'preference', val);\n this.set('preference', val);\n }\n\n setExchanger(val) {\n if (!val) this.throwHelp('KX: exchanger is required');\n\n this.isFullyQualified('KX', 'exchanger', val);\n this.isValidHostname('KX', 'exchanger', val);\n\n this.set('exchanger', val.toLowerCase());\n }\n\n getDescription() {\n return 'Key Exchanger'\n }\n\n getCanonical() {\n return {\n owner: 'example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'KX',\n preference: 10,\n exchanger: 'kx.example.com.',\n }\n }\n\n /****** IMPORTERS *******/\n fromTinydns({ tinyline }) {\n // KX via generic, :fqdn:36:rdata:ttl:timestamp:lo\n const [fqdn, n, rdata, ttl, ts, loc] = tinyline.slice(1).split(':');\n if (n != 36) this.throwHelp('KX fromTinydns, invalid n');\n\n return new KX({\n owner: this.fullyQualify(fqdn),\n ttl: parseInt(ttl, 10),\n type: 'KX',\n preference: octalToUInt16(rdata.slice(0, 8)),\n exchanger: unpackDomainName(rdata.slice(8))[0],\n timestamp: ts,\n location: loc?.trim() ?? '',\n })\n }\n\n /****** EXPORTERS *******/\n\n getWireRdata() {\n const exchanger = this.wirePackDomain(this.get('exchanger'));\n const result = new Uint8Array(2 + exchanger.length);\n const dv = new DataView(result.buffer);\n dv.setUint16(0, this.get('preference'));\n result.set(exchanger, 2);\n return result\n }\n\n toTinydns() {\n return this.getTinydnsGeneric(\n UInt16toOctal(this.get('preference')) + packDomainName(this.get('exchanger')),\n )\n }\n}\n\nconst REF = {\n // RFC 1876\n LATLON: 2 ** 31, // LAT equator, LON prime meridian\n ALTITUDE: 100000 * 100, // reference spheroid used by GPS, in cm\n};\n\nconst CONV = {\n sec: 1000,\n min: 60 * 1000,\n deg: 60 * 60 * 1000,\n};\n\nclass LOC extends RR {\n static typeName = 'LOC'\n static typeId = 29\n static RFCs = [1876]\n static rdataFields = ['address']\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setAddress(val) {\n if (!val) this.throwHelp('LOC: address is required');\n\n /*\n ... LOC ( d1 [m1 [s1]] {\"N\"|\"S\"} d2 [m2 [s2]]\n {\"E\"|\"W\"} alt[\"m\"] [siz[\"m\"] [hp[\"m\"]\n [vp[\"m\"]]]] )\n */\n this.parseLoc(val);\n\n this.set('address', val);\n }\n\n getDescription() {\n return 'Location'\n }\n\n getCanonical() {\n return {\n owner: 'example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'LOC',\n address: '52 22 23.000 N 4 53 32.000 E 10m 100m 10m 2m',\n }\n }\n\n parseLoc(string) {\n // d1 [m1 [s1]]\n const dms = '(\\\\d+)\\\\s+(?:(\\\\d+)\\\\s+)?(?:([\\\\d.]+)\\\\s+)?';\n\n // alt[\"m\"] [siz[\"m\"] [hp[\"m\"] [vp[\"m\"]]]]\n const alt = '(-?[\\\\d.]+)m?(?:\\\\s+([\\\\d.]+)m?)?(?:\\\\s+([\\\\d.]+)m?)?(?:\\\\s+([\\\\d.]+)m?)?';\n\n // put them all together\n const locRe = new RegExp(`^${dms}(N|S)\\\\s+${dms}(E|W)\\\\s+${alt}`, 'i');\n const r = string.match(locRe);\n if (!r) this.throwHelp('LOC address: invalid format, see RFC 1876');\n\n const loc = {\n latitude: {\n degrees: r[1],\n minutes: r[2],\n seconds: r[3],\n hemisphere: r[4].toUpperCase(),\n },\n longitude: {\n degrees: r[5],\n minutes: r[6],\n seconds: r[7],\n hemisphere: r[8].toUpperCase(),\n },\n altitude: r[9] * 100, // m -> cm\n size: r[10] * 100,\n precision: {\n horizontal: r[11] * 100,\n vertical: r[12] * 100,\n },\n };\n\n return loc\n }\n\n /****** IMPORTERS *******/\n fromTinydns({ tinyline }) {\n // LOC via generic, :fqdn:n:rdata:ttl:timestamp:lo\n const [fqdn, n, rdata, ttl, ts, loc] = tinyline.slice(1).split(':');\n if (n != 29) this.throwHelp('LOC fromTinydns, invalid n');\n\n // divide by 100 is to convert cm to meters\n const l = {\n version: octalToUInt8(rdata.slice(0, 4)),\n size: this.fromExponent(octalToUInt8(rdata.slice(4, 8))),\n precision: {\n horizontal: this.fromExponent(octalToUInt8(rdata.slice(8, 12))),\n vertical: this.fromExponent(octalToUInt8(rdata.slice(12, 16))),\n },\n latitude: this.arcSecToDMS(octalToUInt32(rdata.slice(16, 32)), 'lat'),\n longitude: this.arcSecToDMS(octalToUInt32(rdata.slice(32, 48)), 'lon'),\n altitude: octalToUInt32(rdata.slice(48, 64)) - REF.ALTITUDE,\n };\n\n return new LOC({\n type: 'LOC',\n owner: this.fullyQualify(fqdn),\n address: this.toHuman(l),\n ttl: parseInt(ttl, 10),\n timestamp: ts,\n location: loc?.trim() ?? '',\n })\n }\n\n fromBind({ bindline }) {\n const [owner, ttl, c, type] = bindline.split(/\\s+/);\n\n return new LOC({\n owner,\n ttl: parseInt(ttl, 10),\n class: c,\n type: type,\n address: bindline.split(/\\s+/).slice(4).join(' ').trim(),\n })\n }\n\n dmsToArcSec(obj) {\n let retval = obj.degrees * CONV.deg + (obj.minutes ?? 0) * CONV.min + (obj.seconds ?? 0) * CONV.sec;\n switch (obj.hemisphere.toUpperCase()) {\n case 'W':\n case 'S':\n retval = -retval;\n break\n }\n retval += REF.LATLON;\n return retval\n }\n\n arcSecToDMS(rawmsec, latlon) {\n let msec = Math.abs(rawmsec - REF.LATLON);\n // console.log(`rawmsec: ${rawmsec}, abs msec: ${msec}`)\n\n const deg = Math.floor(msec / CONV.deg);\n msec -= deg * CONV.deg;\n\n const min = Math.floor(msec / CONV.min);\n msec -= min * CONV.min;\n\n const sec = Math.floor(msec / CONV.sec);\n msec -= sec * CONV.sec;\n\n let hem;\n switch (latlon) {\n case 'lat':\n hem = rawmsec >= REF.LATLON ? 'N' : 'S';\n break\n case 'lon':\n hem = rawmsec >= REF.LATLON ? 'E' : 'W';\n break\n default:\n this.throwHelp('unknown or missing hemisphere');\n }\n\n return `${deg} ${min} ${sec}${msec ? '.' + msec : ''} ${hem}`\n }\n\n fromExponent(prec) {\n const mantissa = ((prec >> 4) & 0x0f) % 10;\n const exponent = ((prec >> 0) & 0x0f) % 10;\n return mantissa * Math.pow(10, exponent)\n }\n\n toExponent(val) {\n /*\n RFC 1876, ... expressed as a pair of four-bit unsigned\n integers, each ranging from zero to nine, with the most\n significant four bits representing the base and the second\n number representing the power of ten by which to multiply\n the base.\n */\n let exponent = 0;\n while (val >= 10) {\n val /= 10;\n ++exponent;\n }\n return (parseInt(val) << 4) | (exponent & 0x0f)\n }\n\n toHuman(obj) {\n let r = `${obj.latitude} ${obj.longitude} ${obj.altitude / 100}m`;\n if (obj.size) r += ` ${obj.size / 100}m`;\n if (obj.precision.horizontal) r += ` ${obj.precision.horizontal / 100}m`;\n if (obj.precision.vertical) r += ` ${obj.precision.vertical / 100}m`;\n return r\n }\n\n fromWire({ owner, cls, ttl, rdata }) {\n const dv = new DataView(rdata.buffer, rdata.byteOffset);\n const l = {\n size: this.fromExponent(rdata[1]),\n precision: {\n horizontal: this.fromExponent(rdata[2]),\n vertical: this.fromExponent(rdata[3]),\n },\n latitude: this.arcSecToDMS(dv.getUint32(4), 'lat'),\n longitude: this.arcSecToDMS(dv.getUint32(8), 'lon'),\n altitude: dv.getUint32(12) - REF.ALTITUDE,\n };\n return new LOC({\n owner,\n ttl,\n class: cls,\n type: 'LOC',\n address: this.toHuman(l),\n })\n }\n\n /****** EXPORTERS *******/\n\n toTinydns() {\n const loc = this.parseLoc(this.get('address'));\n\n // LOC format declares in meters, tinydns uses cm (hence * 100)\n let rdata = '';\n rdata += UInt8toOctal(0); // version\n rdata += UInt8toOctal(this.toExponent(loc.size));\n rdata += UInt8toOctal(this.toExponent(loc.precision.horizontal));\n rdata += UInt8toOctal(this.toExponent(loc.precision.vertical));\n rdata += UInt32toOctal(this.dmsToArcSec(loc.latitude));\n rdata += UInt32toOctal(this.dmsToArcSec(loc.longitude));\n rdata += UInt32toOctal(loc.altitude + REF.ALTITUDE);\n\n return this.getTinydnsGeneric(rdata)\n }\n\n getWireRdata() {\n const loc = this.parseLoc(this.get('address'));\n const bytes = new Uint8Array(16);\n const dv = new DataView(bytes.buffer, bytes.byteOffset);\n\n bytes[0] = 0; // version\n bytes[1] = this.toExponent(loc.size);\n bytes[2] = this.toExponent(loc.precision.horizontal);\n bytes[3] = this.toExponent(loc.precision.vertical);\n dv.setUint32(4, this.dmsToArcSec(loc.latitude));\n dv.setUint32(8, this.dmsToArcSec(loc.longitude));\n dv.setUint32(12, loc.altitude + REF.ALTITUDE);\n\n return bytes\n }\n}\n\nclass MX extends RR {\n static typeName = 'MX'\n static typeId = 15\n static RFCs = [1035, 2181, 7505]\n static tinydnsType = '@'\n static rdataFields = [\n ['preference', 'u16'],\n ['exchange', 'fqdn'],\n ]\n static tags = ['common']\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setPreference(val) {\n if (val === undefined) val = this?.default?.preference;\n if (val === undefined) this.throwHelp('MX: preference is required');\n this.is16bitInt('MX', 'preference', val);\n this.set('preference', val);\n }\n\n setExchange(val) {\n this.setTypedValue('fqdn', 'exchange', val);\n }\n\n getDescription() {\n return 'Mail Exchanger'\n }\n\n getCanonical() {\n return {\n owner: 'example.com.',\n ttl: 43200,\n class: 'IN',\n type: 'MX',\n preference: 10,\n exchange: 'mail.example.com.',\n }\n }\n\n /****** IMPORTERS *******/\n fromTinydns({ tinyline }) {\n // @fqdn:ip:x:dist:ttl:timestamp:lo\n const [owner, _ip, x, preference, ttl, ts, loc] = tinyline.slice(1).split(':');\n\n return new MX({\n type: 'MX',\n owner: this.fullyQualify(owner),\n exchange: this.fullyQualify(/\\./.test(x) ? x : `${x}.mx.${owner}`),\n preference: parseInt(preference, 10) || 0,\n ttl: parseInt(ttl, 10),\n timestamp: ts,\n location: loc?.trim() ?? '',\n })\n }\n\n /****** EXPORTERS *******/\n getWireRdata() {\n const domain = this.wirePackDomain(this.get('exchange'));\n const result = new Uint8Array(2 + domain.length);\n new DataView(result.buffer).setUint16(0, this.get('preference'));\n result.set(domain, 2);\n return result\n }\n\n toTinydns() {\n return `@${this.getTinyFQDN('owner')}::${this.getTinyFQDN('exchange')}:${this.get('preference')}:${this.getTinydnsPostamble()}\\n`\n }\n}\n\nconst rdataRe = /[\\r\\n\\t:\\\\/]/;\n\nclass NAPTR extends RR {\n static typeName = 'NAPTR'\n static typeId = 35\n static RFCs = [2915, 3403, 4848]\n static rdataFields = [\n ['order', 'u16'],\n ['preference', 'u16'],\n ['flags', 'qcharstr'],\n ['service', 'qcharstr'],\n ['regexp', 'qcharstr'],\n ['replacement', 'fqdn'],\n ]\n\n constructor(opts) {\n super(opts);\n }\n\n getDescription() {\n return 'Naming Authority Pointer'\n }\n\n getCanonical() {\n return {\n owner: 'cid.urn.arpa.',\n ttl: 3600,\n class: 'IN',\n type: 'NAPTR',\n order: 100,\n preference: 10,\n flags: 'S',\n service: 'z3950+N2L+N2R',\n regexp: '',\n replacement: 'gatekeeper.example.com.',\n }\n }\n\n /****** Resource record specific setters *******/\n setOrder(val) {\n this.is16bitInt('NAPTR', 'order', val);\n this.set('order', val);\n }\n\n setPreference(val) {\n this.is16bitInt('NAPTR', 'preference', val);\n this.set('preference', val);\n }\n\n setFlags(val) {\n if (!this.getFlagsOptions().has(val.toUpperCase())) this.throwHelp(`NAPTR flags are invalid`);\n\n this.set('flags', val.toUpperCase());\n }\n\n getFlagsOptions() {\n return new Map([[''], ['S'], ['A'], ['U'], ['P']])\n }\n\n setService(val) {\n this.set('service', val);\n }\n\n setRegexp(val) {\n this.set('regexp', val);\n }\n\n setReplacement(val) {\n this.set('replacement', val);\n }\n\n /****** IMPORTERS *******/\n fromTinydns({ tinyline }) {\n // NAPTR via generic, :fqdn:n:rdata:ttl:timestamp:lo\n const { owner, typeId, rdata, ttl, timestamp, location } = this.parseTinydnsLine(tinyline);\n if (typeId != this.getTypeId()) this.throwHelp('NAPTR fromTinydns, invalid n');\n\n const binRdata = octalRdataToBytes(rdata);\n const dv = new DataView(binRdata.buffer, binRdata.byteOffset, binRdata.byteLength);\n\n const rec = {\n type: 'NAPTR',\n owner,\n ttl,\n timestamp,\n location,\n order: dv.getUint16(0),\n preference: dv.getUint16(2),\n };\n\n let idx = 4;\n const flagsLength = binRdata[idx];\n idx++;\n rec.flags = new TextDecoder().decode(binRdata.subarray(idx, idx + flagsLength));\n idx += flagsLength;\n\n const serviceLen = binRdata[idx];\n idx++;\n rec.service = new TextDecoder().decode(binRdata.subarray(idx, idx + serviceLen));\n idx += serviceLen;\n\n const regexpLen = binRdata[idx];\n idx++;\n rec.regexp = new TextDecoder().decode(binRdata.subarray(idx, idx + regexpLen));\n idx += regexpLen;\n\n const replaceLen = binRdata[idx];\n idx++;\n rec.replacement = new TextDecoder().decode(binRdata.subarray(idx, idx + replaceLen));\n\n return new NAPTR(rec)\n }\n\n fromBind({ bindline }) {\n const regex =\n /^(?\\S+)\\s+(?\\d+)\\s+(?\\S+)\\s+(?NAPTR)\\s+(?\\d+)\\s+(?\\d+)\\s+[\"'](?[^\"']*)[\"']\\s+[\"'](?[^\"']*)[\"']\\s+[\"'](?[^\"']*)[\"']\\s+(?\\S+)$/;\n\n const match = bindline.trim().match(regex);\n\n if (!match) {\n throw new Error(`Invalid NAPTR BIND line: ${bindline}`)\n }\n\n const { owner, ttl, type, order, preference, flags, service, regexp, replacement } = match.groups;\n\n return new NAPTR({\n owner: this.fullyQualify(owner),\n ttl: parseInt(ttl, 10),\n class: match.groups.class,\n type,\n order: parseInt(order, 10),\n preference: parseInt(preference, 10),\n flags,\n service,\n regexp,\n replacement,\n })\n }\n\n /****** EXPORTERS *******/\n toTinydns() {\n let rdata =\n UInt16toOctal(this.get('order')) +\n UInt16toOctal(this.get('preference')) +\n UInt8toOctal(this.get('flags').length) +\n this.get('flags') +\n UInt8toOctal(this.get('service').length) +\n escapeOctal(rdataRe, this.get('service')) +\n UInt8toOctal(this.get('regexp').length) +\n escapeOctal(rdataRe, this.get('regexp'));\n\n const replacement = this.get('replacement');\n if (replacement !== '') {\n rdata += UInt8toOctal(replacement.length);\n rdata += escapeOctal(rdataRe, replacement);\n }\n rdata += '\\\\000';\n\n return this.getTinydnsGeneric(rdata)\n }\n\n getWireRdata() {\n const enc = new TextEncoder();\n const flags = enc.encode(this.get('flags'));\n const service = enc.encode(this.get('service'));\n const regexp = enc.encode(this.get('regexp'));\n const replacementBytes = this.wirePackDomain(this.get('replacement'));\n\n const len = 4 + 1 + flags.length + 1 + service.length + 1 + regexp.length + replacementBytes.length;\n const buf = new Uint8Array(len);\n const view = new DataView(buf.buffer);\n let pos = 0;\n view.setUint16(pos, this.get('order'));\n pos += 2;\n view.setUint16(pos, this.get('preference'));\n pos += 2;\n buf[pos++] = flags.length;\n buf.set(flags, pos);\n pos += flags.length;\n buf[pos++] = service.length;\n buf.set(service, pos);\n pos += service.length;\n buf[pos++] = regexp.length;\n buf.set(regexp, pos);\n pos += regexp.length;\n buf.set(replacementBytes, pos);\n return buf\n }\n}\n\nclass NS extends RR {\n static typeName = 'NS'\n static typeId = 2\n static RFCs = [1035]\n static tinydnsType = '&'\n static rdataFields = [['dname', 'fqdn']]\n static tags = ['common']\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setDname(val) {\n if (!val) this.throwHelp(`NS: dname is required`);\n\n this.isFullyQualified('NS', 'dname', val);\n this.isValidHostname('NS', 'dname', val);\n\n // RFC 4034: letters in the DNS names are lower cased\n this.set('dname', val.toLowerCase());\n }\n\n getDescription() {\n return 'Name Server'\n }\n\n getCanonical() {\n return {\n owner: 'example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'NS',\n dname: 'ns1.example.com.',\n }\n }\n\n /****** IMPORTERS *******/\n fromTinydns({ tinyline }) {\n // &fqdn:ip:x:ttl:timestamp:lo\n const [fqdn, _ip, dname, ttl, ts, loc] = tinyline.slice(1).split(':');\n\n return new NS({\n type: 'NS',\n owner: this.fullyQualify(fqdn),\n dname: this.fullyQualify(/\\./.test(dname) ? dname : `${dname}.ns.${fqdn}`),\n ttl: parseInt(ttl, 10),\n timestamp: ts,\n location: loc?.trim() ?? '',\n })\n }\n\n /****** EXPORTERS *******/\n getWireRdata() {\n return this.wirePackDomain(this.get('dname'))\n }\n\n toTinydns() {\n return `&${this.getTinyFQDN('owner')}::${this.getTinyFQDN('dname')}:${this.getTinydnsPostamble()}\\n`\n }\n}\n\nclass NSEC extends RR {\n static typeName = 'NSEC'\n static typeId = 47\n static RFCs = [4034]\n static rdataFields = ['next domain', 'type bit maps']\n static tags = ['dnssec']\n\n constructor(opts) {\n super(opts);\n if (opts === null) return\n }\n\n /****** Resource record specific setters *******/\n setNextDomain(val) {\n if (!val) this.throwHelp(`NSEC: 'next domain' is required:`);\n\n this.isFullyQualified('NSEC', 'next domain', val);\n this.isValidHostname('NSEC', 'next domain', val);\n\n // RFC 4034: letters in the DNS names are lower cased\n this.set('next domain', val.toLowerCase());\n }\n\n setTypeBitMaps(val) {\n if (!val) this.throwHelp(`NSEC: 'type bit maps' is required`);\n\n this.set('type bit maps', val);\n }\n\n getDescription() {\n return 'Next Secure'\n }\n\n getCanonical() {\n return {\n owner: 'alfa.example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'NSEC',\n 'next domain': 'host.example.com.',\n 'type bit maps': 'A MX RRSIG NSEC TYPE1234',\n }\n }\n\n /****** IMPORTERS *******/\n\n fromTinydns({ tinyline }) {\n const [owner, _typeId, rdata, ttl, ts, loc] = tinyline.slice(1).split(':');\n const binaryRdata = Uint8Array.from(octalToChar(rdata), (c) => c.charCodeAt(0));\n const [nextDomain, _escapedLen, binaryLen] = unpackDomainName(rdata);\n\n return new NSEC({\n owner: this.fullyQualify(owner),\n ttl: parseInt(ttl, 10),\n type: 'NSEC',\n 'next domain': nextDomain,\n 'type bit maps': new TextDecoder().decode(binaryRdata.subarray(binaryLen)),\n timestamp: ts,\n location: loc?.trim() ?? '',\n })\n }\n\n fromBind({ bindline }) {\n // test.example.com 3600 IN NSEC NextDomain TypeBitMaps\n const [owner, ttl, c, type, next] = bindline.split(/\\s+/);\n return new NSEC({\n owner,\n ttl: parseInt(ttl, 10),\n class: c,\n type: type,\n 'next domain': next,\n 'type bit maps': bindline.split(/\\s+/).slice(5).filter(removeParens$1).join(' ').trim(),\n })\n }\n\n fromWire({ owner, cls, ttl, rdata }) {\n const { fqdn: nextDomain, end } = this.wireUnpackDomain(rdata, 0);\n const typeBitMaps = nsecBitmapToTypes(rdata.subarray(end));\n return new NSEC({\n owner,\n ttl,\n class: cls,\n type: 'NSEC',\n 'next domain': nextDomain,\n 'type bit maps': typeBitMaps,\n })\n }\n\n /****** EXPORTERS *******/\n\n toTinydns() {\n const dataRe = new RegExp(/[\\r\\n\\t:\\\\/]/, 'g');\n\n return this.getTinydnsGeneric(\n packDomainName(this.get('next domain')) +\n escapeOctal(dataRe, this.get('type bit maps')),\n )\n }\n\n getWireRdata() {\n const nameBytes = this.wirePackDomain(this.get('next domain'));\n const bitmapBytes = typesToNsecBitmap(this.get('type bit maps'));\n const result = new Uint8Array(nameBytes.length + bitmapBytes.length);\n result.set(nameBytes);\n result.set(bitmapBytes, nameBytes.length);\n return result\n }\n}\n\nconst removeParens$1 = (a) => !['(', ')'].includes(a);\n\nfunction nsecBitmapToTypes(bitmap) {\n const DNS_TYPE_NAMES = Object.fromEntries(Object.entries(DNS_TYPE_IDS).map(([k, v]) => [v, k]));\n const types = [];\n let pos = 0;\n while (pos + 2 <= bitmap.length) {\n const windowNum = bitmap[pos];\n const bitmapLen = bitmap[pos + 1];\n pos += 2;\n for (let i = 0; i < bitmapLen; i++) {\n const byte = bitmap[pos + i];\n for (let bit = 0; bit < 8; bit++) {\n if (byte & (0x80 >> bit)) {\n const typeId = windowNum * 256 + i * 8 + bit;\n types.push(DNS_TYPE_NAMES[typeId] ?? `TYPE${typeId}`);\n }\n }\n }\n pos += bitmapLen;\n }\n return types.join(' ')\n}\n\nfunction typesToNsecBitmap(typeNamesStr) {\n const typeIds = typeNamesStr\n .trim()\n .split(/\\s+/)\n .map((t) => {\n if (/^TYPE\\d+$/i.test(t)) return parseInt(t.slice(4), 10)\n return DNS_TYPE_IDS[t.toUpperCase()]\n })\n .filter((id) => id !== undefined && id >= 0);\n\n const windows = new Map();\n for (const id of typeIds) {\n const w = Math.floor(id / 256);\n if (!windows.has(w)) windows.set(w, []);\n windows.get(w).push(id % 256);\n }\n\n const blocks = [];\n for (const [wNum, bits] of [...windows.entries()].sort((a, b) => a[0] - b[0])) {\n const maxBit = Math.max(...bits);\n const bitmapLen = Math.floor(maxBit / 8) + 1;\n const bitmap = new Uint8Array(bitmapLen);\n for (const b of bits) bitmap[Math.floor(b / 8)] |= 0x80 >> (b % 8);\n blocks.push(new Uint8Array([wNum, bitmapLen, ...bitmap]));\n }\n\n const total = blocks.reduce((s, b) => s + b.length, 0);\n const result = new Uint8Array(total);\n let pos = 0;\n for (const b of blocks) {\n result.set(b, pos);\n pos += b.length;\n }\n return result\n}\n\nclass NSEC3 extends RR {\n static typeName = 'NSEC3'\n static typeId = 50\n static RFCs = [5155, 9077]\n static rdataFields = [\n 'hash algorithm',\n 'flags',\n 'iterations',\n 'salt',\n 'next hashed owner name',\n 'type bit maps',\n ]\n static tags = ['dnssec']\n\n constructor(opts) {\n super(opts);\n if (opts === null) return\n }\n\n /****** Resource record specific setters *******/\n setHashAlgorithm(val) {\n // Hash Algorithm is a single octet.\n // The Hash Algorithm field is represented as an unsigned decimal integer.\n if (!val) this.throwHelp(`NSEC3: 'hash algorithm' is required`);\n\n this.is8bitInt('NSEC3', 'hash algorithm', val);\n\n this.set('hash algorithm', val);\n }\n\n setFlags(val) {\n // The Flags field is represented as an unsigned decimal integer.\n if (!val) this.throwHelp(`NSEC3: 'flags' is required`);\n\n this.is8bitInt('NSEC3', 'flags', val);\n\n this.set('flags', val);\n }\n\n setIterations(val) {\n // The Iterations field is represented as an unsigned decimal integer. 0-65535\n if (!val) this.throwHelp(`NSEC3: 'iterations' is required`);\n\n this.is16bitInt('NSEC3', 'flags', val);\n\n this.set('iterations', val);\n }\n\n setSalt(val) {\n // The Salt field is represented as a sequence of case-insensitive\n // hexadecimal digits. Whitespace is not allowed within the\n // sequence. The Salt field is represented as \"-\" (without the\n // quotes) when the Salt Length field has a value of 0\n this.set('salt', val);\n }\n\n setNextHashedOwnerName(val) {\n // The Next Hashed Owner Name field is represented as an unpadded\n // sequence of case-insensitive base32 digits, without whitespace\n if (!val) this.throwHelp(`NSEC3: 'next hashed owner name' is required`);\n\n this.set('next hashed owner name', val);\n }\n\n setTypeBitMaps(val) {\n // The Type Bit Maps field is represented as a sequence of RR type mnemonics.\n if (!val) this.throwHelp(`NSEC3: 'type bit maps' is required`);\n\n this.set('type bit maps', val);\n }\n\n getDescription() {\n return 'Next Secure'\n }\n\n getCanonical() {\n return {\n owner: 'test.example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'NSEC3',\n 'hash algorithm': 1,\n flags: 1,\n iterations: 12,\n salt: 'aabbccdd',\n 'next hashed owner name': '2vptu5timamqttgl4luu9kg21e0aor3s',\n 'type bit maps': 'A RRSIG',\n }\n }\n\n /****** IMPORTERS *******/\n\n fromBind({ bindline }) {\n // test.example.com. 3600 IN NSEC3 1 1 12 aabbccdd (2vptu5timamqttgl4luu9kg21e0aor3s A RRSIG)\n const [owner, ttl, c, type, ha, flags, iterations, salt] = bindline.split(/\\s+/);\n // rdata may be parenthesized or inline\n const rdataStr = bindline.includes('(')\n ? bindline.split(/\\(|\\)/)[1]\n : bindline.split(/\\s+/).slice(8).join(' ');\n\n return new NSEC3({\n owner,\n ttl: parseInt(ttl, 10),\n class: c,\n type: type,\n 'hash algorithm': parseInt(ha, 10),\n flags: parseInt(flags, 10),\n iterations: parseInt(iterations, 10),\n salt,\n 'next hashed owner name': rdataStr.trim().split(/\\s+/)[0],\n 'type bit maps': rdataStr.trim().split(/\\s+/).slice(1).join('\\t'),\n })\n }\n\n fromTinydns({ tinyline }) {\n const [fqdn, n, rdata, ttl, ts, loc] = tinyline.slice(1).split(':');\n if (n != 50) this.throwHelp('NSEC3 fromTinydns, invalid n');\n\n const bytes = Uint8Array.from(octalToChar(rdata), (c) => c.charCodeAt(0));\n const dv = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);\n\n const hashAlgorithm = bytes[0];\n const flags = bytes[1];\n const iterations = dv.getUint16(2);\n\n // The remaining bytes in the buffer contain:\n // Salt Length (1 octet)\n // Salt (variable length based on Salt Length)\n // Next Hashed Owner Name (variable length)\n // Type Bit Maps (variable length)\n const { salt, nextHashedOwnerName, typeBitMaps } = parseNSEC3Buffer(bytes);\n\n return new NSEC3({\n owner: this.fullyQualify(fqdn),\n ttl: parseInt(ttl, 10),\n type: 'NSEC3',\n 'hash algorithm': hashAlgorithm,\n flags: flags,\n iterations: iterations,\n salt: salt,\n 'next hashed owner name': nextHashedOwnerName,\n 'type bit maps': typeBitMaps,\n timestamp: ts,\n location: loc?.trim() ?? '',\n })\n }\n\n fromWire({ owner, cls, ttl, rdata }) {\n const dv = new DataView(rdata.buffer, rdata.byteOffset);\n const { salt, nextHashedOwnerName, typeBitMaps } = parseNSEC3Buffer(rdata);\n return new NSEC3({\n owner,\n ttl,\n class: cls,\n type: 'NSEC3',\n 'hash algorithm': rdata[0],\n flags: rdata[1],\n iterations: dv.getUint16(2),\n salt,\n 'next hashed owner name': nextHashedOwnerName,\n 'type bit maps': typeBitMaps,\n })\n }\n\n /****** EXPORTERS *******/\n\n toBind(zone_opts) {\n return `${this.getFQDN('owner', zone_opts)}\t${this.get('ttl')}\t${this.get('class')}\tNSEC3${this.getRdataFields()\n .slice(0, 4)\n .map((f) => '\t' + this.get(f))\n .join('')}\t(${this.getRdataFields()\n .slice(4)\n .map((f) => this.get(f))\n .join('\t')})\n`\n }\n\n toTinydns() {\n const dataRe = new RegExp(/[\\r\\n\\t:\\\\/]/, 'g');\n\n return this.getTinydnsGeneric(\n UInt8toOctal(this.get('hash algorithm')) +\n UInt8toOctal(this.get('flags')) +\n UInt16toOctal(this.get('iterations')) +\n escapeOctal(dataRe, this.get('salt')) +\n escapeOctal(dataRe, this.get('next hashed owner name')) +\n escapeOctal(dataRe, this.get('type bit maps')),\n )\n }\n\n getWireRdata() {\n const tail = `${this.get('salt')}${this.get('next hashed owner name')}${this.get('type bit maps')}`;\n const tailBytes = new TextEncoder().encode(tail);\n\n const totalLen = 4 + tailBytes.length;\n const bytes = new Uint8Array(totalLen);\n const dv = new DataView(bytes.buffer, bytes.byteOffset);\n\n let pos = 0;\n bytes[pos++] = this.get('hash algorithm');\n bytes[pos++] = this.get('flags');\n dv.setUint16(pos, this.get('iterations'));\n pos += 2;\n bytes.set(tailBytes, pos);\n\n return bytes\n }\n}\n\nfunction parseNSEC3Buffer(bytes) {\n // bytes is a Uint8Array containing the full RDATA binary (hash alg, flags, iterations, then ASCII salt + next-hashed + type bit maps)\n // Start after the first 4 bytes (hash alg, flags, iterations)\n const rest = new TextDecoder().decode(bytes.subarray(4));\n\n // determine expected next hashed owner name length from hash algorithm\n const hashAlgorithm = bytes[0];\n // common mapping: algorithm 1 => SHA-1 => 20 bytes => base32 length 32\n const expectedLen = hashAlgorithm === 1 ? 32 : hashAlgorithm === 2 ? 52 : 32;\n\n // salt length is ambiguous in this representation; try to find a split where\n // the following segment matches expected base32 length\n let salt = '';\n let nextHashedOwnerName = '';\n let typeBitMaps = '';\n\n const maxSl = Math.min(64, rest.length);\n for (let sl = maxSl; sl >= 1; sl--) {\n const candNext = rest.slice(sl, sl + expectedLen);\n if (candNext.length !== expectedLen) continue\n if (!/^[0-9a-z]+$/.test(candNext)) continue\n // candidate looks like a base32 name; accept and treat remainder as type bit maps\n const saltCandidate = rest.slice(0, sl);\n if (!/^[0-9A-Fa-f]+$/.test(saltCandidate)) continue\n salt = saltCandidate;\n nextHashedOwnerName = candNext;\n typeBitMaps = rest.slice(sl + expectedLen);\n break\n }\n\n // fallback: if we couldn't find a split, treat everything up to first non-hex as salt\n if (!nextHashedOwnerName) {\n const saltMatch = rest.match(/^([0-9A-Fa-f]*)/);\n salt = saltMatch ? saltMatch[1] : '';\n nextHashedOwnerName = rest.slice(salt.length);\n typeBitMaps = '';\n }\n\n return {\n salt,\n nextHashedOwnerName,\n typeBitMaps,\n }\n}\n\nclass NSEC3PARAM extends RR {\n static typeName = 'NSEC3PARAM'\n static typeId = 51\n static RFCs = [5155]\n static rdataFields = ['hash algorithm', 'flags', 'iterations', 'salt']\n static tags = ['dnssec']\n\n constructor(opts) {\n super(opts);\n if (opts === null) return\n }\n\n /****** Resource record specific setters *******/\n setHashAlgorithm(val) {\n // Hash Algorithm is a single octet.\n // The Hash Algorithm field is represented as an unsigned decimal integer.\n if (val === undefined || val === null) this.throwHelp(`NSEC3PARAM: 'hash algorithm' is required`);\n\n this.is8bitInt('NSEC3PARAM', 'hash algorithm', val);\n\n this.set('hash algorithm', val);\n }\n\n setFlags(val) {\n // The Flags field is represented as an unsigned decimal integer.\n if (val === undefined || val === null) this.throwHelp(`NSEC3PARAM: 'flags' is required`);\n\n this.is8bitInt('NSEC3PARAM', 'flags', val);\n\n this.set('flags', val);\n }\n\n setIterations(val) {\n // The Iterations field is represented as an unsigned decimal integer. 0-65535\n if (val === undefined || val === null) this.throwHelp(`NSEC3PARAM: 'iterations' is required`);\n\n this.is16bitInt('NSEC3PARAM', 'iterations', val);\n\n this.set('iterations', val);\n }\n\n setSalt(val) {\n // The Salt field is represented as a sequence of case-insensitive\n // hexadecimal digits. Whitespace is not allowed within the\n // sequence. The Salt field is represented as \"-\" (without the\n // quotes) when the Salt Length field has a value of 0\n if (val === '-') {\n this.set('salt', val);\n return\n }\n\n if (val !== undefined && val !== null && !/^[0-9A-Fa-f]*$/.test(val)) {\n this.throwHelp(`NSEC3PARAM: 'salt' must be hex or '-'`);\n }\n\n this.set('salt', val);\n }\n\n getDescription() {\n return 'Next Secure Parameters'\n }\n\n getCanonical() {\n return {\n owner: 'example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'NSEC3PARAM',\n 'hash algorithm': 1,\n flags: 1,\n iterations: 12,\n salt: 'aabbccdd',\n }\n }\n\n /****** IMPORTERS *******/\n\n fromTinydns({ tinyline }) {\n // RDATA format: Hash Algorithm (3 octal chars) + Flags (3 octal chars) + Iterations (6 octal chars) + Salt (escaped hex string)\n const { owner, typeId, rdata, ttl, timestamp, location } = this.parseTinydnsLine(tinyline);\n if (typeId != this.getTypeId()) this.throwHelp('NSEC3PARAM fromTinydns, invalid n');\n if (rdata.length < 4) {\n this.throwHelp(`NSEC3PARAM: RDATA too short: ${rdata}`);\n }\n\n // rd may contain actual binary characters (from JS string '\\\\001' -> char 0x01),\n // so convert via octalToChar and read bytes from a Uint8Array for robust parsing.\n const bytes = octalRdataToBytes(rdata);\n\n return new NSEC3PARAM({\n owner,\n ttl,\n type: 'NSEC3PARAM',\n 'hash algorithm': bytes[0],\n flags: bytes[1],\n iterations: (bytes[2] << 8) | bytes[3],\n salt: bytes[4] === 0 ? '-' : bytesToHex(bytes.subarray(5, 5 + bytes[4])),\n timestamp,\n location,\n })\n }\n\n fromWire({ owner, cls, ttl, rdata }) {\n const dv = new DataView(rdata.buffer, rdata.byteOffset);\n const saltLen = rdata[4];\n const salt = saltLen === 0 ? '-' : bytesToHex(rdata.subarray(5, 5 + saltLen));\n return new NSEC3PARAM({\n owner,\n ttl,\n class: cls,\n type: 'NSEC3PARAM',\n 'hash algorithm': rdata[0],\n flags: rdata[1],\n iterations: dv.getUint16(2),\n salt,\n })\n }\n\n /****** EXPORTERS *******/\n\n toTinydns() {\n const salt = this.get('salt');\n const saltOctal =\n salt === '-' ? UInt8toOctal(0) : UInt8toOctal(salt.length / 2) + packHex(salt);\n\n return this.getTinydnsGeneric(\n UInt8toOctal(this.get('hash algorithm')) +\n UInt8toOctal(this.get('flags')) +\n UInt16toOctal(this.get('iterations')) +\n saltOctal,\n )\n }\n\n getWireRdata() {\n const salt = this.get('salt');\n const saltBytes = salt === '-' ? new Uint8Array(0) : hexToBytes(salt);\n const bytes = new Uint8Array(4 + 1 + saltBytes.length);\n const dv = new DataView(bytes.buffer, bytes.byteOffset);\n\n bytes[0] = this.get('hash algorithm');\n bytes[1] = this.get('flags');\n dv.setUint16(2, this.get('iterations'));\n bytes[4] = saltBytes.length;\n bytes.set(saltBytes, 5);\n\n return bytes\n }\n}\n\nclass NXT extends RR {\n static typeName = 'NXT'\n static typeId = 30\n static RFCs = [2065]\n static rdataFields = ['next domain', 'type bit map']\n static tags = ['obsolete']\n\n constructor(opts) {\n super(opts);\n if (opts === null) return\n }\n\n /****** Resource record specific setters *******/\n setNextDomain(val) {\n if (!val) this.throwHelp(`NXT: 'next domain' is required`);\n\n this.isFullyQualified('NXT', 'next domain', val);\n this.isValidHostname('NXT', 'next domain', val);\n\n // RFC 4034: letters in the DNS names are lower cased\n this.set('next domain', val.toLowerCase());\n }\n\n setTypeBitMap(val) {\n if (!val) this.throwHelp(`NXT: 'type bit map' is required`);\n\n this.set('type bit map', val);\n }\n\n getDescription() {\n return 'Next Secure'\n }\n\n getCanonical() {\n return {\n owner: 'big.example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'NXT',\n 'next domain': 'host.example.com.',\n 'type bit map': 'A MX NXT',\n }\n }\n\n /****** IMPORTERS *******/\n\n fromTinydns({ tinyline }) {\n const [owner, n, rdata, ttl, ts, loc] = tinyline.slice(1).split(':');\n if (parseInt(n, 10) !== this.getTypeId()) this.throwHelp('NXT fromTinydns, invalid n');\n\n const binaryRdata = Uint8Array.from(octalToChar(rdata), (c) => c.charCodeAt(0));\n const [nextDomain, _escapedLen, binaryLen] = unpackDomainName(rdata);\n\n return new NXT({\n owner: this.fullyQualify(owner),\n ttl: parseInt(ttl, 10),\n type: 'NXT',\n 'next domain': nextDomain,\n 'type bit map': new TextDecoder().decode(binaryRdata.subarray(binaryLen)),\n timestamp: ts,\n location: loc?.trim() ?? '',\n })\n }\n\n fromBind({ bindline }) {\n // test.example.com 3600 IN NXT NextDomain TypeBitMap\n const [owner, ttl, c, type, next] = bindline.split(/\\s+/);\n return new NXT({\n owner,\n ttl: parseInt(ttl, 10),\n class: c,\n type: type,\n 'next domain': next,\n 'type bit map': bindline.split(/\\s+/).slice(5).filter(removeParens).join(' ').trim(),\n })\n }\n\n fromWire({ owner, cls, ttl, rdata }) {\n const { fqdn: nextDomain, end } = this.wireUnpackDomain(rdata, 0);\n const typeBitMap = nxtBitmapToTypes(rdata.subarray(end));\n return new NXT({\n owner,\n ttl,\n class: cls,\n type: 'NXT',\n 'next domain': nextDomain,\n 'type bit map': typeBitMap,\n })\n }\n\n /****** EXPORTERS *******/\n\n toTinydns() {\n const dataRe = new RegExp(/[\\r\\n\\t:\\\\/]/, 'g');\n\n return this.getTinydnsGeneric(\n packDomainName(this.get('next domain')) + escapeOctal(dataRe, this.get('type bit map')),\n )\n }\n\n getWireRdata() {\n const nameBytes = this.wirePackDomain(this.get('next domain'));\n const bitmapBytes = typesToNxtBitmap(this.get('type bit map'));\n const result = new Uint8Array(nameBytes.length + bitmapBytes.length);\n result.set(nameBytes);\n result.set(bitmapBytes, nameBytes.length);\n return result\n }\n}\n\nconst removeParens = (a) => !['(', ')'].includes(a);\n\nfunction nxtBitmapToTypes(bitmap) {\n const DNS_TYPE_NAMES = Object.fromEntries(Object.entries(DNS_TYPE_IDS).map(([k, v]) => [v, k]));\n const types = [];\n for (let i = 0; i < bitmap.length; i++) {\n const byte = bitmap[i];\n for (let bit = 0; bit < 8; bit++) {\n if (byte & (0x80 >> bit)) {\n const typeId = i * 8 + bit;\n types.push(DNS_TYPE_NAMES[typeId] ?? `TYPE${typeId}`);\n }\n }\n }\n return types.join(' ')\n}\n\nfunction typesToNxtBitmap(typeNamesStr) {\n const bitmap = new Uint8Array(16);\n for (const name of typeNamesStr.trim().split(/\\s+/)) {\n const id = /^TYPE\\d+$/i.test(name) ? parseInt(name.slice(4), 10) : DNS_TYPE_IDS[name.toUpperCase()];\n if (id !== undefined && id < 128) bitmap[Math.floor(id / 8)] |= 0x80 >> (id % 8);\n }\n let len = bitmap.length;\n while (len > 0 && bitmap[len - 1] === 0) len--;\n return bitmap.slice(0, len)\n}\n\nclass OPENPGPKEY extends RR {\n static typeName = 'OPENPGPKEY'\n static typeId = 61\n static RFCs = [4880, 7929]\n static rdataFields = [['public key', 'base64']]\n static tags = ['security']\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setPublicKey(val) {\n this.isBase64('OPENPGPKEY', 'public key', val);\n this.set('public key', val);\n }\n\n getDescription() {\n return 'OpenPGP Public Key'\n }\n\n getCanonical() {\n return {\n owner: 'matt.example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'OPENPGPKEY',\n 'public key':\n 'AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwIXAqcOTiW7iHnQt5hwVAAAAA==',\n }\n }\n\n /****** IMPORTERS *******/\n fromBind({ bindline: bindline }) {\n // test.example.com 3600 IN OPENPGPKEY \n const regex =\n /^(?\\S+)\\s+(?\\d{1,10})\\s+(?IN)\\s+(?OPENPGPKEY)\\s+(?\\S[\\s\\S]*)$/i;\n const match = bindline.trim().match(regex);\n if (!match) this.throwHelp(`unable to parse OPENPGPKEY: ${bindline}`);\n\n const { owner, ttl, class: c, type, publickey } = match.groups;\n const keyStr = publickey.trim().replace(/\\s+/g, '');\n\n return new OPENPGPKEY({\n owner,\n ttl: parseInt(ttl, 10),\n class: c,\n type: type,\n 'public key': keyStr,\n })\n }\n\n fromTinydns({ tinyline }) {\n const { owner, typeId, rdata, ttl, timestamp, location } = this.parseTinydnsLine(tinyline);\n if (typeId != this.getTypeId()) this.throwHelp('OPENPGPKEY fromTinydns, invalid n');\n return new OPENPGPKEY({\n owner,\n ttl,\n type: 'OPENPGPKEY',\n 'public key': octalToBase64(rdata),\n timestamp,\n location,\n })\n }\n\n /****** EXPORTERS *******/\n toTinydns() {\n return this.getTinydnsGeneric(base64toOctal(this.get('public key')))\n }\n\n getWireRdata() {\n return base64ToBytes(this.get('public key'))\n }\n}\n\nclass PTR extends RR {\n static typeName = 'PTR'\n static typeId = 12\n static RFCs = [1035]\n static tinydnsType = '^'\n static rdataFields = [['dname', 'fqdn']]\n static tags = ['common']\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setDname(val) {\n this.isFullyQualified('PTR', 'dname', val);\n this.isValidHostname('PTR', 'dname', val);\n\n // RFC 4034: letters in the DNS names are lower cased\n this.set('dname', val.toLowerCase());\n }\n\n getDescription() {\n return 'Pointer'\n }\n\n getCanonical() {\n return {\n owner: '2.2.0.192.in-addr.arpa.',\n ttl: 3600,\n class: 'IN',\n type: 'PTR',\n dname: 'host.example.com.',\n }\n }\n\n /****** EXPORTERS *******/\n getWireRdata() {\n return this.wirePackDomain(this.get('dname'))\n }\n}\n\nclass RP extends RR {\n static typeName = 'RP'\n static rdataFields = [\n ['mbox', 'fqdn'],\n ['txt', 'fqdn'],\n ]\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setMbox(val) {\n if (!val) this.throwHelp('RP: mbox is required');\n\n this.isFullyQualified('RP', 'mbox', val);\n\n this.set('mbox', val.toLowerCase());\n }\n\n setTxt(val) {\n if (!val) this.throwHelp('RP: txt is required');\n\n this.isFullyQualified('RP', 'txt', val);\n\n this.set('txt', val.toLowerCase());\n }\n\n getDescription() {\n return 'Responsible Person'\n }\n static tags = ['obsolete']\n static RFCs = [1183]\n static typeId = 17\n getCanonical() {\n return {\n owner: 'example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'RP',\n mbox: 'admin.example.com.',\n txt: 'info.example.com.',\n }\n }\n\n /****** IMPORTERS *******/\n fromTinydns({ tinyline }) {\n const [owner, _typeId, rdata, ttl, ts, loc] = tinyline.slice(1).split(':');\n\n const [mbox, consumed] = unpackDomainName(rdata);\n const txt = unpackDomainName(rdata.slice(consumed))[0];\n\n return new RP({\n owner: this.fullyQualify(owner),\n ttl: parseInt(ttl, 10),\n type: 'RP',\n mbox,\n txt,\n timestamp: ts,\n location: loc?.trim() ?? '',\n })\n }\n\n /****** EXPORTERS *******/\n\n getWireRdata() {\n const mbox = this.wirePackDomain(this.get('mbox'));\n const txt = this.wirePackDomain(this.get('txt'));\n const result = new Uint8Array(mbox.length + txt.length);\n result.set(mbox, 0);\n result.set(txt, mbox.length);\n return result\n }\n\n toTinydns() {\n return this.getTinydnsGeneric(\n packDomainName(this.get('mbox')) + packDomainName(this.get('txt')),\n )\n }\n}\n\nclass RRSIG extends RR {\n static typeName = 'RRSIG'\n static typeId = 46\n static RFCs = [4034]\n static rdataFields = [\n ['type covered', 'u16'],\n ['algorithm', 'u8'],\n ['labels', 'u8'],\n ['original ttl', 'u32'],\n ['signature expiration', 'u32'],\n ['signature inception', 'u32'],\n ['key tag', 'u16'],\n ['signers name', 'fqdn'],\n ['signature', 'str'],\n ]\n static tags = ['dnssec']\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setTypeCovered(val) {\n // a 16-bit Type Covered field (RFC 4034 \u00A73.1.1)\n if (!val && val !== 0) this.throwHelp(`RRSIG: 'type covered' is required`);\n if (typeof val === 'string') {\n const typeNN = val.match(/^TYPE(\\d+)$/i);\n if (typeNN) {\n val = parseInt(typeNN[1], 10);\n } else {\n const id = DNS_TYPE_IDS[val.toUpperCase()];\n if (id === undefined) this.throwHelp(`RRSIG: 'type covered' is not a recognized type name`);\n val = id;\n }\n }\n this.is16bitInt('RRSIG', 'type covered', val);\n this.set('type covered', val);\n }\n\n setAlgorithm(val) {\n // a 1 octet Algorithm field\n if (!this.getAlgorithmOptions().has(val)) this.throwHelp(`RRSIG: algorithm invalid`);\n\n this.set('algorithm', val);\n }\n\n setLabels(val) {\n this.setTypedValue('u8', 'labels', val);\n }\n\n setOriginalTtl(val) {\n this.setTypedValue('u32', 'original ttl', val);\n }\n\n setSignatureExpiration(val) {\n this.setTypedValue('u32', 'signature expiration', val);\n }\n\n setSignatureInception(val) {\n this.setTypedValue('u32', 'signature inception', val);\n }\n\n setKeyTag(val) {\n this.setTypedValue('u16', 'key tag', val);\n }\n\n setSignersName(val) {\n this.setTypedValue('fqdn', 'signers name', val);\n }\n\n setSignature(val) {\n this.setTypedValue('str', 'signature', val);\n }\n\n getAlgorithmOptions() {\n // IANA DNSSEC Algorithm Numbers\n // https://www.iana.org/assignments/dns-sec-alg-numbers/\n return new Map([\n [1, 'RSA/MD5'],\n [2, 'DH'],\n [3, 'DSA/SHA-1'],\n [4, 'EC'],\n [5, 'RSA/SHA-1'],\n [6, 'DSA-NSEC3-SHA1'],\n [7, 'RSASHA1-NSEC3-SHA1'],\n [8, 'RSA/SHA-256'],\n [10, 'RSA/SHA-512'],\n [13, 'ECDSA P-256/SHA-256'],\n [14, 'ECDSA P-384/SHA-384'],\n [15, 'Ed25519'],\n [16, 'Ed448'],\n [253],\n [254],\n ])\n }\n\n getDescription() {\n return 'Resource Record Signature'\n }\n\n getCanonical() {\n return {\n owner: 'example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'RRSIG',\n 'type covered': 1,\n algorithm: 5,\n labels: 3,\n 'original ttl': 3600,\n 'signature expiration': 1045053120,\n 'signature inception': 1042461120,\n 'key tag': 12345,\n 'signers name': 'example.com.',\n signature: 'ABCDEF...',\n }\n }\n\n /****** IMPORTERS *******/\n\n fromBind({ bindline }) {\n // example.com. 3600 IN RRSIG typecovered algorithm labels origttl sigexp siginc keytag signersname ( signature )\n const parts = bindline.trim().split(/\\s+/);\n const typeCoveredStr = parts[4];\n // type covered may be a type name ('A', 'MX'), TYPEnn (RFC 3597), or a numeric ID\n const typeNN = typeCoveredStr.match(/^TYPE(\\d+)$/i);\n const typeCovered = /^\\d+$/.test(typeCoveredStr)\n ? parseInt(typeCoveredStr, 10)\n : typeNN\n ? parseInt(typeNN[1], 10)\n : (DNS_TYPE_IDS[typeCoveredStr.toUpperCase()] ?? parseInt(typeCoveredStr, 10));\n return new RRSIG({\n owner: parts[0],\n ttl: parseInt(parts[1], 10),\n class: parts[2],\n type: 'RRSIG',\n 'type covered': typeCovered,\n algorithm: parseInt(parts[5], 10),\n labels: parseInt(parts[6], 10),\n 'original ttl': parseInt(parts[7], 10),\n 'signature expiration': parseInt(parts[8], 10),\n 'signature inception': parseInt(parts[9], 10),\n 'key tag': parseInt(parts[10], 10),\n 'signers name': parts[11],\n signature: parts\n .slice(12)\n .filter((a) => a !== '(' && a !== ')')\n .join(' ')\n .trim(),\n })\n }\n\n fromTinydns({ tinyline }) {\n const [fqdn, n, rdata, ttl, ts, loc] = tinyline.slice(1).split(':');\n if (parseInt(n, 10) !== this.getTypeId()) this.throwHelp('RRSIG fromTinydns, invalid n');\n\n const bytes = Uint8Array.from(octalToChar(rdata), (c) => c.charCodeAt(0));\n const dv = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);\n const typeCovered = dv.getUint16(0);\n const algorithm = bytes[2];\n const labels = bytes[3];\n const originalTtl = dv.getUint32(4);\n const signatureExpiration = dv.getUint32(8);\n const signatureInception = dv.getUint32(12);\n const keyTag = dv.getUint16(16);\n\n let pos = 18;\n const labelArr = [];\n while (pos < bytes.length) {\n const len = bytes[pos++];\n if (len === 0) break\n labelArr.push(new TextDecoder().decode(bytes.subarray(pos, pos + len)));\n pos += len;\n }\n const signersName = `${labelArr.join('.')}.`;\n const signature = new TextDecoder().decode(bytes.subarray(pos));\n\n return new RRSIG({\n owner: this.fullyQualify(fqdn),\n ttl: parseInt(ttl, 10),\n type: 'RRSIG',\n 'type covered': typeCovered,\n algorithm,\n labels,\n 'original ttl': originalTtl,\n 'signature expiration': signatureExpiration,\n 'signature inception': signatureInception,\n 'key tag': keyTag,\n 'signers name': signersName,\n signature,\n timestamp: ts,\n location: loc?.trim() ?? '',\n })\n }\n\n /****** EXPORTERS *******/\n\n toTinydns() {\n const dataRe = new RegExp(/[\\r\\n\\t:]/, 'g');\n return this.getTinydnsGeneric(\n UInt16toOctal(this.get('type covered')) +\n UInt8toOctal(this.get('algorithm')) +\n UInt8toOctal(this.get('labels')) +\n UInt32toOctal(this.get('original ttl')) +\n UInt32toOctal(this.get('signature expiration')) +\n UInt32toOctal(this.get('signature inception')) +\n UInt16toOctal(this.get('key tag')) +\n packDomainName(this.get('signers name')) +\n escapeOctal(dataRe, this.get('signature')),\n )\n }\n\n getWireRdata() {\n const signerBytes = wirePackDomain(this.get('signers name'));\n const sigBytes = new TextEncoder().encode(this.get('signature'));\n\n const totalLen = 2 + 1 + 1 + 4 + 4 + 4 + 2 + signerBytes.length + sigBytes.length;\n const bytes = new Uint8Array(totalLen);\n const dv = new DataView(bytes.buffer, bytes.byteOffset);\n\n let pos = 0;\n dv.setUint16(pos, this.get('type covered'));\n pos += 2;\n bytes[pos++] = this.get('algorithm');\n bytes[pos++] = this.get('labels');\n dv.setUint32(pos, this.get('original ttl'));\n pos += 4;\n dv.setUint32(pos, this.get('signature expiration'));\n pos += 4;\n dv.setUint32(pos, this.get('signature inception'));\n pos += 4;\n dv.setUint16(pos, this.get('key tag'));\n pos += 2;\n bytes.set(signerBytes, pos);\n pos += signerBytes.length;\n bytes.set(sigBytes, pos);\n\n return bytes\n }\n}\n\nclass SIG extends RR {\n static typeName = 'SIG'\n static typeId = 24\n static RFCs = [2535, 3755]\n static rdataFields = [\n ['type covered', 'u16'],\n ['algorithm', 'u8'],\n ['labels', 'u8'],\n ['original ttl', 'u32'],\n ['signature expiration', 'u32'],\n ['signature inception', 'u32'],\n ['key tag', 'u16'],\n ['signers name', 'fqdn'],\n ['signature', 'str'],\n ]\n static tags = ['obsolete']\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setTypeCovered(val) {\n // a 2 octet Type Covered field\n if (!val) this.throwHelp(`SIG: 'type covered' is required`);\n\n this.set('type covered', val);\n }\n\n setAlgorithm(val) {\n // a 1 octet Algorithm field\n this.is8bitInt('SIG', 'algorithm', val);\n\n this.set('algorithm', val);\n }\n\n setLabels(val) {\n // a 1 octet Labels field\n this.is8bitInt('SIG', 'labels', val);\n\n this.set('labels', val);\n }\n\n setOriginalTtl(val) {\n // a 4 octet Original TTL field\n this.is32bitInt('SIG', 'original ttl', val);\n\n this.set('original ttl', val);\n }\n\n setSignatureExpiration(val) {\n // a 4 octet Signature Expiration field\n this.set('signature expiration', val);\n }\n\n setSignatureInception(val) {\n // a 4 octet Signature Inception field\n this.set('signature inception', val);\n }\n\n setKeyTag(val) {\n // a 2 octet Key tag\n this.set('key tag', val);\n }\n\n setSignersName(val) {\n // the domain name of the signer generating the SIG RR\n\n // RFC 4034: letters in the DNS names are lower cased\n this.set('signers name', val.toLowerCase());\n }\n\n setSignature(val) {\n // the Signature field.\n\n this.set('signature', val);\n }\n\n getDescription() {\n return 'Signature'\n }\n\n getCanonical() {\n return {\n owner: 'example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'SIG',\n 'type covered': 1,\n algorithm: 5,\n labels: 3,\n 'original ttl': 3600,\n 'signature expiration': 1045053120,\n 'signature inception': 1042461120,\n 'key tag': 12345,\n 'signers name': 'example.com.',\n signature: 'ABCDEF...',\n }\n }\n\n /****** IMPORTERS *******/\n\n fromBind({ bindline }) {\n // example.com. 3600 IN SIG TypeCovered Algorithm Labels OrigTTL SigExpiration SigInception KeyTag SignersName ( Signature )\n const parts = bindline.trim().split(/\\s+/);\n const typeCoveredStr = parts[4];\n const typeCovered = /^\\d+$/.test(typeCoveredStr)\n ? parseInt(typeCoveredStr, 10)\n : (DNS_TYPE_IDS[typeCoveredStr.toUpperCase()] ?? parseInt(typeCoveredStr, 10));\n\n return new SIG({\n owner: parts[0],\n ttl: parseInt(parts[1], 10),\n class: parts[2],\n type: 'SIG',\n 'type covered': typeCovered,\n algorithm: parseInt(parts[5], 10),\n labels: parseInt(parts[6], 10),\n 'original ttl': parseInt(parts[7], 10),\n 'signature expiration': parseInt(parts[8], 10),\n 'signature inception': parseInt(parts[9], 10),\n 'key tag': parseInt(parts[10], 10),\n 'signers name': parts[11],\n signature: parts\n .slice(12)\n .filter((a) => a !== '(' && a !== ')')\n .join(' ')\n .trim(),\n })\n }\n\n /****** EXPORTERS *******/\n toTinydns() {\n const dataRe = new RegExp(/[\\r\\n\\t:]/, 'g');\n\n return this.getTinydnsGeneric(\n UInt16toOctal(this.get('type covered')) +\n UInt8toOctal(this.get('algorithm')) +\n UInt8toOctal(this.get('labels')) +\n UInt32toOctal(this.get('original ttl')) +\n UInt32toOctal(this.get('signature expiration')) +\n UInt32toOctal(this.get('signature inception')) +\n UInt16toOctal(this.get('key tag')) +\n packDomainName(this.get('signers name')) +\n escapeOctal(dataRe, this.get('signature')),\n )\n }\n\n getWireRdata() {\n const signerBytes = wirePackDomain(this.get('signers name'));\n const sigBytes = new TextEncoder().encode(this.get('signature'));\n\n const totalLen = 2 + 1 + 1 + 4 + 4 + 4 + 2 + signerBytes.length + sigBytes.length;\n const bytes = new Uint8Array(totalLen);\n const dv = new DataView(bytes.buffer, bytes.byteOffset);\n\n let pos = 0;\n dv.setUint16(pos, this.get('type covered'));\n pos += 2;\n bytes[pos++] = this.get('algorithm');\n bytes[pos++] = this.get('labels');\n dv.setUint32(pos, this.get('original ttl'));\n pos += 4;\n dv.setUint32(pos, this.get('signature expiration'));\n pos += 4;\n dv.setUint32(pos, this.get('signature inception'));\n pos += 4;\n dv.setUint16(pos, this.get('key tag'));\n pos += 2;\n bytes.set(signerBytes, pos);\n pos += signerBytes.length;\n bytes.set(sigBytes, pos);\n\n return bytes\n }\n\n fromTinydns({ tinyline }) {\n const { owner, typeId, rdata, ttl, timestamp, location } = this.parseTinydnsLine(tinyline);\n if (parseInt(typeId, 10) !== this.getTypeId()) this.throwHelp('SIG fromTinydns, invalid n');\n\n const bytes = octalRdataToBytes(rdata);\n const dv = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);\n\n const typeCovered = dv.getUint16(0);\n const algorithm = bytes[2];\n const labels = bytes[3];\n const originalTtl = dv.getUint32(4);\n const signatureExpiration = dv.getUint32(8);\n const signatureInception = dv.getUint32(12);\n const keyTag = dv.getUint16(16);\n\n // parse signers name from binary starting at offset 18\n let pos = 18;\n const labelsArr = [];\n while (pos < bytes.length) {\n const len = bytes[pos++];\n if (len === 0) break\n labelsArr.push(new TextDecoder().decode(bytes.subarray(pos, pos + len)));\n pos += len;\n }\n const signersName = `${labelsArr.join('.')}.`;\n\n const signature = new TextDecoder().decode(bytes.subarray(pos));\n\n return new SIG({\n owner,\n ttl,\n type: 'SIG',\n 'type covered': typeCovered,\n algorithm,\n labels,\n 'original ttl': originalTtl,\n 'signature expiration': signatureExpiration,\n 'signature inception': signatureInception,\n 'key tag': keyTag,\n 'signers name': signersName,\n signature,\n timestamp,\n location,\n })\n }\n\n toBind(zone_opts) {\n return `${this.getFQDN('owner', zone_opts)}\t${this.get('ttl')}\t${this.get('class')}\tSIG${this.getRdataFields()\n .slice(0, 4)\n .map((f) => '\t' + this.get(f))\n .join('')}\t${this.getRdataFields()\n .slice(4, 8)\n .map((f) => this.get(f))\n .join('\t')}\t( ${this.get('signature')} )`\n }\n}\n\nclass SMIMEA extends RR {\n static typeName = 'SMIMEA'\n static typeId = 53\n static RFCs = [8162]\n static rdataFields = [\n ['certificate usage', 'u8'],\n ['selector', 'u8'],\n ['matching type', 'u8'],\n ['certificate association data', 'hex'],\n ]\n static tags = ['security']\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setCertificateUsage(val) {\n if (!this.getCertificateUsageOptions().has(val)) this.throwHelp(`SMIMEA: certificate usage invalid`);\n\n this.set('certificate usage', val);\n }\n\n getCertificateUsageOptions() {\n return new Map([\n [0, 'CA certificate'],\n [1, 'an end entity certificate'],\n [2, 'the trust anchor'],\n [3, 'domain-issued certificate'],\n ])\n }\n\n setSelector(val) {\n if (!this.getSelectorOptions().has(val)) this.throwHelp(`SMIMEA: selector invalid`);\n\n this.set('selector', val);\n }\n\n getSelectorOptions() {\n return new Map([\n [0, 'Full certificate'],\n [1, 'SubjectPublicKeyInfo'],\n ])\n }\n\n setMatchingType(val) {\n if (!this.getMatchingTypeOptions().has(val)) this.throwHelp(`SMIMEA: matching type`);\n\n this.set('matching type', val);\n }\n\n getMatchingTypeOptions() {\n return new Map([\n [0, 'Exact match'],\n [1, 'SHA-256 hash'],\n [2, 'SHA-512 hash'],\n ])\n }\n\n setCertificateAssociationData(val) {\n this.set('certificate association data', val);\n }\n\n getDescription() {\n return 'S/MIME cert association'\n }\n\n getCanonical() {\n return {\n owner: '_443._tcp.www.example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'SMIMEA',\n 'certificate usage': 0,\n selector: 0,\n 'matching type': 1,\n 'certificate association data': 'ABCDEF...',\n }\n }\n\n /****** IMPORTERS *******/\n\n fromBind({ bindline }) {\n // test.example.com 3600 IN SMIMEA, usage, selector, match, data\n const [owner, ttl, c, type, usage, selector, match] = bindline.split(/\\s+/);\n return new SMIMEA({\n owner,\n ttl: parseInt(ttl, 10),\n class: c,\n type: type,\n 'certificate usage': parseInt(usage, 10),\n selector: parseInt(selector, 10),\n 'matching type': parseInt(match, 10),\n 'certificate association data': bindline.split(/\\s+/).slice(7).join(' ').trim(),\n })\n }\n\n fromTinydns({ tinyline }) {\n const { owner, rdata, ttl, timestamp, location } = this.parseTinydnsLine(tinyline);\n const binaryRdata = octalRdataToBytes(rdata);\n\n return new SMIMEA({\n owner,\n ttl,\n type: 'SMIMEA',\n 'certificate usage': binaryRdata[0],\n selector: binaryRdata[1],\n 'matching type': binaryRdata[2],\n 'certificate association data': bytesToHex(binaryRdata.subarray(3)),\n timestamp,\n location,\n })\n }\n\n /****** EXPORTERS *******/\n toTinydns() {\n return this.getTinydnsGeneric(\n UInt8toOctal(this.get('certificate usage')) +\n UInt8toOctal(this.get('selector')) +\n UInt8toOctal(this.get('matching type')) +\n packHex(this.get('certificate association data').replace(/[\\s()]/g, '')),\n )\n }\n\n getWireRdata() {\n const cadBytes = hexToBytes(this.get('certificate association data').replace(/[\\s()]/g, ''));\n const bytes = new Uint8Array(3 + cadBytes.length);\n bytes[0] = this.get('certificate usage');\n bytes[1] = this.get('selector');\n bytes[2] = this.get('matching type');\n bytes.set(cadBytes, 3);\n return bytes\n }\n}\n\nclass SOA extends RR {\n static typeName = 'SOA'\n static typeId = 6\n static RFCs = [1035, 2308]\n static tinydnsType = 'Z'\n static rdataFields = [\n ['mname', 'fqdn'],\n ['rname', 'fqdn'],\n ['serial', 'u32'],\n ['refresh', 'u32'],\n ['retry', 'u32'],\n ['expire', 'u32'],\n ['minimum', 'u32'],\n ]\n static tags = ['common']\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setMinimum(val) {\n // minimum (used for negative caching, since RFC 2308)\n // RFC 1912 sugggests 1-5 days\n // RIPE recommends 3600 (1 hour)\n this.is32bitInt('SOA', 'minimum', val);\n\n this.set('minimum', val);\n }\n\n setMname(val) {\n // MNAME (primary NS)\n this.isValidHostname('SOA', 'MNAME', val);\n this.isFullyQualified('SOA', 'MNAME', val);\n\n // RFC 4034: letters in the DNS names are lower cased\n this.set('mname', val.toLowerCase());\n }\n\n setRname(val) {\n // RNAME (email of admin) (escape . with \\)\n this.isValidHostname('SOA', 'RNAME', val);\n this.isFullyQualified('SOA', 'RNAME', val);\n if (/@/.test(val)) this.throwHelp(`SOA rname replaces @ with a . (dot)`);\n\n // RFC 4034: letters in the DNS names are lower cased\n this.set('rname', val.toLowerCase());\n }\n\n setSerial(val) {\n this.is32bitInt('SOA', 'serial', val);\n\n this.set('serial', val);\n }\n\n setRefresh(val) {\n // refresh (seconds after which to check with master for update)\n // RFC 1912 suggests 20 min to 12 hours\n // RIPE recommends 86400 (24 hours)\n this.is32bitInt('SOA', 'refresh', val);\n\n this.set('refresh', val);\n }\n\n setRetry(val) {\n // seconds after which to retry serial # update\n // RIPE recommends 7200 seconds (2 hours)\n\n this.is32bitInt('SOA', 'retry', val);\n\n this.set('retry', val);\n }\n\n setExpire(val) {\n // seconds after which secondary should drop zone if no master response\n // RFC 1912 suggests 2-4 weeks\n // RIPE suggests 3600000 (1,000 hours, 6 weeks)\n this.is32bitInt('SOA', 'expire', val);\n\n this.set('expire', val);\n }\n\n getDescription() {\n return 'Start Of Authority'\n }\n\n getCanonical() {\n return {\n owner: 'example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'SOA',\n mname: 'ns1.example.com.',\n rname: 'admin.example.com.',\n serial: 2023051001,\n refresh: 7200,\n retry: 3600,\n expire: 1209600,\n minimum: 3600,\n }\n }\n\n /****** IMPORTERS *******/\n fromTinydns({ tinyline }) {\n // Zfqdn:mname:rname:ser:ref:ret:exp:min:ttl:time:lo\n const [fqdn, mname, rname, ser, ref, ret, exp, min, ttl, ts, loc] = tinyline.slice(1).split(':');\n\n return new SOA({\n owner: this.fullyQualify(fqdn),\n ttl: parseInt(ttl, 10),\n type: 'SOA',\n mname: this.fullyQualify(mname),\n rname: this.fullyQualify(rname),\n serial: parseInt(ser ?? this.default?.serial, 10),\n refresh: parseInt(ref, 10) || 16384,\n retry: parseInt(ret, 10) || 2048,\n expire: parseInt(exp, 10) || 1048576,\n minimum: parseInt(min, 10) || 2560,\n timestamp: parseInt(ts) || '',\n location: loc?.trim() ?? '',\n })\n }\n\n /****** EXPORTERS *******/\n toMaraDNS() {\n return `${this.get('owner')}\\t SOA\\t${this.getFields('rdata')\n .map((f) => this.getQuoted(f))\n .join('\\t')} ~\\n`\n }\n\n getWireRdata() {\n const mname = this.wirePackDomain(this.get('mname'));\n const rname = this.wirePackDomain(this.get('rname'));\n const result = new Uint8Array(mname.length + rname.length + 20);\n let offset = 0;\n result.set(mname, offset);\n offset += mname.length;\n result.set(rname, offset);\n offset += rname.length;\n const view = new DataView(result.buffer, offset);\n view.setUint32(0, this.get('serial'));\n view.setUint32(4, this.get('refresh'));\n view.setUint32(8, this.get('retry'));\n view.setUint32(12, this.get('expire'));\n view.setUint32(16, this.get('minimum'));\n return result\n }\n\n toTinydns() {\n return `Z${this.getTinyFQDN('owner')}:${this.getTinyFQDN('mname')}:${this.getTinyFQDN('rname')}:${this.getEmpty('serial')}:${this.getEmpty('refresh')}:${this.getEmpty('retry')}:${this.getEmpty('expire')}:${this.getEmpty('minimum')}:${this.getTinydnsPostamble()}\\n`\n }\n}\n\nclass TXT extends RR {\n static typeName = 'TXT'\n static typeId = 16\n static RFCs = [1035, 4408, 7208, 6376]\n static tinydnsType = \"'\"\n static rdataFields = [['data', 'charstrs']]\n static tags = ['common']\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setData(val) {\n this.set('data', val);\n }\n\n getDescription() {\n return 'Text'\n }\n\n getCanonical() {\n return {\n owner: 'example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'TXT',\n data: 'v=spf1 mx -all',\n }\n }\n\n /****** IMPORTERS *******/\n fromTinydns({ tinyline }) {\n const str = tinyline;\n let fqdn, rdata, s, ttl, ts, loc;\n // 'fqdn:s:ttl:timestamp:lo\n if (str[0] === \"'\") {\n[fqdn, s, ttl, ts, loc] = str.slice(1).split(':');\n rdata = octalToChar(s);\n } else {\n[fqdn, rdata, ttl, ts, loc] = this.fromTinydnsGeneric(str);\n }\n\n return new this.constructor({\n owner: this.fullyQualify(fqdn),\n ttl: parseInt(ttl, 10),\n type: 'TXT',\n data: rdata,\n timestamp: ts,\n location: loc?.trim() || '',\n })\n }\n\n fromTinydnsGeneric(str) {\n // generic: :fqdn:n:rdata:ttl:timestamp:location\n // eslint-disable-next-line prefer-const\n let [fqdn, n, rdata, ttl, ts, loc] = str.slice(1).split(':');\n if (n != 16) this.throwHelp('TXT fromTinydns, invalid n');\n\n rdata = octalToChar(rdata);\n // Walk RFC 1035 \u00A73.3.14 len-prefixed segments.\n const parts = [];\n let pos = 0;\n while (pos < rdata.length) {\n const len = rdata.charCodeAt(pos);\n pos += 1;\n if (pos + len > rdata.length) {\n this.throwHelp('TXT fromTinydnsGeneric: truncated character-string in rdata');\n }\n parts.push(rdata.slice(pos, pos + len));\n pos += len;\n }\n const data = parts.length > 1 ? parts : (parts[0] ?? '');\n return [fqdn, data, ttl, ts, loc]\n }\n\n /****** EXPORTERS *******/\n toBind(zone_opts) {\n return `${this.getPrefix(zone_opts)}\\t\"${asQuotedStrings(this.get('data'))}\"\\n`\n }\n\n toMaraDNS() {\n const data = asQuotedStrings(this.get('data')).replace(/\"/g, \"'\");\n return `${this.get('owner')}\\t+${this.get('ttl')}\\t${this.get('type')}\\t'${data}' ~\\n`\n }\n\n getWireRdata() {\n // RFC 1035 \u00A73.3.14: TXT rdata is one or more s, each up\n // to 255 bytes. An array preserves explicit boundaries between strings;\n // each element MUST be <= 255 UTF-8 bytes, otherwise we would silently\n // split it and the boundary the caller asked us to preserve would be lost.\n // A single string is auto-chunked at 255-byte UTF-8 boundaries.\n const data = this.get('data');\n if (Array.isArray(data)) {\n const enc = new TextEncoder();\n const buffers = data.map((s, i) => {\n if (enc.encode(s).length > 255) {\n this.throwHelp(\n `TXT: array element ${i} exceeds 255 bytes; split it yourself or pass a single string to auto-chunk`,\n );\n }\n return packStringWire(s)\n });\n const total = buffers.reduce((n, b) => n + b.length, 0);\n const out = new Uint8Array(total);\n let off = 0;\n for (const b of buffers) {\n out.set(b, off);\n off += b.length;\n }\n return out\n }\n return packStringWire(data)\n }\n\n toTinydns() {\n let data = this.get('data');\n if (Array.isArray(data)) data = data.join('');\n const rdata = escapeOctal(new RegExp(/[\\r\\n\\t:\\\\/]/, 'g'), data);\n return `'${this.getTinyFQDN('owner')}:${rdata}:${this.getTinydnsPostamble()}\\n`\n }\n}\n\nfunction asQuotedStrings(data) {\n // RFC 1035 character-strings are 255 bytes max; chunk by UTF-8 bytes,\n // not JS chars, so non-ASCII TXT data doesn't overflow the 255-byte limit.\n const enc = new TextEncoder();\n\n if (Array.isArray(data)) {\n const anyTooLong = data.some((s) => enc.encode(s).length > 255);\n if (!anyTooLong) return data.join('\" \"')\n return chunkByBytes(data.join(''), 255).join('\" \"')\n }\n\n if (enc.encode(data).length <= 255) return data\n return chunkByBytes(data, 255).join('\" \"')\n}\n\nfunction chunkByBytes(str, maxBytes) {\n const bytes = new TextEncoder().encode(str);\n const dec = new TextDecoder();\n const chunks = [];\n let start = 0;\n while (start < bytes.length) {\n let end = Math.min(start + maxBytes, bytes.length);\n // back up to a UTF-8 codepoint boundary so decode() returns whole chars\n while (end < bytes.length && (bytes[end] & 0xc0) === 0x80) end--;\n chunks.push(dec.decode(bytes.subarray(start, end)));\n start = end;\n }\n return chunks\n}\n\nfunction packStringWire(str) {\n const encoded = new TextEncoder().encode(str);\n if (encoded.length === 0) return new Uint8Array([0])\n\n const chunks = [];\n for (let i = 0; i < encoded.length; i += 255) chunks.push(encoded.subarray(i, i + 255));\n\n const buf = new Uint8Array(encoded.length + chunks.length);\n let offset = 0;\n for (const chunk of chunks) {\n buf[offset++] = chunk.length;\n buf.set(chunk, offset);\n offset += chunk.length;\n }\n return buf\n}\n\n// obsoleted by RFC 7208\n\n\nclass SPF extends TXT {\n static typeName = 'SPF'\n static typeId = 99\n static RFCs = [4408, 7208]\n static rdataFields = [['data', 'charstrs']]\n static tags = ['obsolete']\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setData(val) {\n this.set('data', val);\n }\n\n getDescription() {\n return 'Sender Policy Framework'\n }\n getCanonical() {\n return {\n owner: 'example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'SPF',\n data: 'v=spf1 mx -all',\n }\n }\n\n /****** IMPORTERS *******/\n fromTinydns({ tinyline }) {\n // SPF via generic, :fqdn:n:rdata:ttl:timestamp:lo\n const [fqdn, n, rdata, ttl, ts, loc] = tinyline.slice(1).split(':');\n if (n != 99) this.throwHelp('SPF fromTinydns, invalid n');\n\n return new SPF({\n type: 'SPF',\n owner: this.fullyQualify(fqdn),\n data: octalToChar(rdata),\n ttl: parseInt(ttl, 10),\n timestamp: ts,\n location: loc?.trim() ?? '',\n })\n }\n\n /****** EXPORTERS *******/\n getWireRdata() {\n return super.getWireRdata()\n }\n\n toTinydns() {\n // `data` may be a string or an array of s (RFC 1035 \u00A73.3.14).\n // tinydns generic format stores rdata as a flat byte stream, so join here.\n let data = this.get('data');\n if (Array.isArray(data)) data = data.join('');\n const rdata = escapeOctal(new RegExp(/[\\r\\n\\t:\\\\/]/, 'g'), data);\n return this.getTinydnsGeneric(rdata)\n }\n}\n\nclass SRV extends RR {\n static typeName = 'SRV'\n static typeId = 33\n static RFCs = [2782]\n static rdataFields = [\n ['priority', 'u16'],\n ['weight', 'u16'],\n ['port', 'u16'],\n ['target', 'fqdn'],\n ]\n static tags = ['common']\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setPriority(val) {\n this.setTypedValue('u16', 'priority', val);\n }\n\n setWeight(val) {\n this.setTypedValue('u16', 'weight', val);\n }\n\n setPort(val) {\n this.setTypedValue('u16', 'port', val);\n }\n\n setTarget(val) {\n this.setTypedValue('fqdn', 'target', val);\n }\n\n getDescription() {\n return 'Service'\n }\n\n getCanonical() {\n return {\n owner: '_imaps._tcp.example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'SRV',\n priority: 10,\n weight: 10,\n port: 993,\n target: 'mail.example.com.',\n }\n }\n\n /****** IMPORTERS *******/\n fromTinydns({ tinyline }) {\n const str = tinyline;\n let fqdn, addr, port, pri, weight, ttl, ts, loc, n, rdata;\n\n if (str[0] === 'S') {\n[fqdn, addr, port, pri, weight, ttl, ts, loc] = str.slice(1).split(':');\n } else {\n[fqdn, n, rdata, ttl, ts, loc] = str.slice(1).split(':');\n if (n != 33) this.throwHelp('SRV fromTinydns: invalid n');\n\n pri = octalToUInt16(rdata.slice(0, 8));\n weight = octalToUInt16(rdata.slice(8, 16));\n port = octalToUInt16(rdata.slice(16, 24));\n addr = unpackDomainName(rdata.slice(24))[0];\n }\n\n return new SRV({\n owner: this.fullyQualify(fqdn),\n ttl: parseInt(ttl, 10),\n type: 'SRV',\n priority: parseInt(pri, 10),\n weight: parseInt(weight, 10),\n port: parseInt(port, 10),\n target: this.fullyQualify(addr),\n timestamp: ts,\n location: loc?.trim() ?? '',\n })\n }\n\n /****** EXPORTERS *******/\n\n getWireRdata() {\n const target = this.wirePackDomain(this.get('target'));\n const result = new Uint8Array(6 + target.length);\n const dv = new DataView(result.buffer);\n dv.setUint16(0, this.get('priority'));\n dv.setUint16(2, this.get('weight'));\n dv.setUint16(4, this.get('port'));\n result.set(target, 6);\n return result\n }\n\n toTinydns() {\n let rdata = '';\n\n for (const e of ['priority', 'weight', 'port']) {\n rdata += UInt16toOctal(this.get(e));\n }\n\n rdata += packDomainName(this.get('target'));\n\n return this.getTinydnsGeneric(rdata)\n }\n}\n\nclass SSHFP extends RR {\n static typeName = 'SSHFP'\n static typeId = 44\n static RFCs = [4255, 7479, 8709]\n static rdataFields = [\n ['algorithm', 'u8'],\n ['fptype', 'u8'],\n ['fingerprint', 'hex'],\n ]\n static tags = ['security']\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setAlgorithm(val) {\n if (!this.getAlgorithmOptions().has(val)) this.throwHelp(`SSHFP: algorithm invalid`);\n this.setTypedValue('u8', 'algorithm', val);\n }\n\n setFptype(val) {\n if (!this.getFptypeOptions().has(val)) this.throwHelp(`SSHFP: fptype invalid`);\n this.setTypedValue('u8', 'fptype', val);\n }\n\n setFingerprint(val) {\n this.setTypedValue('hex', 'fingerprint', val);\n }\n\n getAlgorithmOptions() {\n return new Map([\n [0, 'reserved'],\n [1, 'RSA'],\n [2, 'DSA'],\n [3, 'ECDSA'],\n [4, 'Ed25519'],\n [6, 'Ed448'],\n ])\n }\n\n getFptypeOptions() {\n return new Map([\n [0, 'reserved'],\n [1, 'SHA-1'],\n [2, 'SHA-256'],\n ])\n }\n\n getDescription() {\n return 'Secure Shell Key Fingerprints'\n }\n\n getCanonical() {\n return {\n owner: 'mail.example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'SSHFP',\n algorithm: 2,\n fptype: 1,\n fingerprint: '123456789abcdef6789abcdf6789abdf6789abcd',\n }\n }\n\n /****** IMPORTERS *******/\n fromTinydns({ tinyline }) {\n // SSHFP via generic, :fqdn:n:rdata:ttl:timestamp:lo\n const { owner, typeId, rdata, ttl, timestamp, location } = this.parseTinydnsLine(tinyline);\n if (typeId != this.getTypeId()) this.throwHelp('SSHFP fromTinydns, invalid n');\n\n return new SSHFP({\n owner,\n ttl,\n type: 'SSHFP',\n algorithm: octalToUInt8(rdata.slice(0, 4)),\n fptype: octalToUInt8(rdata.slice(4, 8)),\n fingerprint: octalToHex(rdata.slice(8)),\n timestamp,\n location,\n })\n }\n\n /****** EXPORTERS *******/\n\n toTinydns() {\n return this.getTinydnsGeneric(\n UInt8toOctal(this.get('algorithm')) +\n UInt8toOctal(this.get('fptype')) +\n packHex(this.get('fingerprint')),\n )\n }\n\n getWireRdata() {\n const bytes = new Uint8Array(2 + hexToBytes(this.get('fingerprint')).length);\n bytes[0] = this.get('algorithm');\n bytes[1] = this.get('fptype');\n bytes.set(hexToBytes(this.get('fingerprint')), 2);\n return bytes\n }\n}\n\nclass SVCB extends RR {\n static typeName = 'SVCB'\n static typeId = 64\n static RFCs = [9460]\n static rdataFields = [\n ['priority', 'u16'],\n ['target name', 'fqdn'],\n ['params', 'svcparams'],\n ]\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setPriority(val) {\n this.is16bitInt('SVCB', 'priority', val);\n\n this.set('priority', val);\n }\n\n setTargetName(val) {\n // this.isFullyQualified('SVCB', 'target name', val)\n // this.isValidHostname('SVCB', 'target name', val)\n\n // RFC 4034: letters in the DNS names are lower cased\n this.set('target name', val.toLowerCase());\n }\n\n setParams(val) {\n // if (!val) throw new Error(`SVCB: params is required`)\n\n this.set('params', val);\n }\n\n getDescription() {\n return 'Service Binding'\n }\n\n getCanonical() {\n return {\n owner: '_8443._foo.api.example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'SVCB',\n priority: 1,\n 'target name': 'svc4.example.net.',\n params: 'alpn=\"h2,h3\"',\n }\n }\n\n /****** IMPORTERS *******/\n\n fromBind({ bindline }) {\n // test.example.com 3600 IN SVCB Priority TargetName Params\n // _8443._foo.api.example.com. 7200 IN SVCB 0 svc4.example.net.\n // svc4.example.net. 7200 IN SVCB 3 svc4.example.net. ( alpn=\"bar\" port=\"8004\" )\n const [owner, ttl, c, type, pri, fqdn] = bindline.split(/\\s+/);\n return new SVCB({\n owner,\n ttl: parseInt(ttl, 10),\n class: c,\n type,\n priority: parseInt(pri, 10),\n 'target name': fqdn,\n params: bindline.split(/\\s+/).slice(6).join(' ').trim(),\n })\n }\n\n fromTinydns({ tinyline }) {\n const { owner, typeId, rdata, ttl, timestamp, location } = this.parseTinydnsLine(tinyline);\n if (typeId != this.getTypeId()) this.throwHelp('SVCB fromTinydns, invalid n');\n const { priority, targetName, params } = parseSvcbLikeRdata(rdata, 'SVCB');\n\n return new SVCB({\n owner,\n ttl,\n type: 'SVCB',\n priority: priority,\n 'target name': targetName,\n params: params,\n timestamp,\n location,\n })\n }\n\n /****** EXPORTERS *******/\n\n toTinydns() {\n const dataRe = new RegExp(/[\\r\\n\\t:\\\\/]/, 'g');\n\n return this.getTinydnsGeneric(\n UInt16toOctal(this.get('priority')) +\n packDomainName(this.get('target name')) +\n escapeOctal(dataRe, this.get('params')),\n )\n }\n\n getWireRdata() {\n const targetBytes = this.wirePackDomain(this.get('target name'));\n const paramsBytes = svcParamsToWire(this.get('params'));\n const result = new Uint8Array(2 + targetBytes.length + paramsBytes.length);\n new DataView(result.buffer).setUint16(0, this.get('priority'));\n result.set(targetBytes, 2);\n result.set(paramsBytes, 2 + targetBytes.length);\n return result\n }\n}\n\nclass TLSA extends RR {\n static typeName = 'TLSA'\n static typeId = 52\n static RFCs = [6698, 7671]\n static rdataFields = [\n ['certificate usage', 'u8'],\n ['selector', 'u8'],\n ['matching type', 'u8'],\n ['certificate association data', 'hex'],\n ]\n static tags = ['security']\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setCertificateUsage(val) {\n if (!this.getCertificateUsageOptions().has(val)) this.throwHelp(`TLSA: certificate usage invalid`);\n\n this.set('certificate usage', val);\n }\n\n getCertificateUsageOptions() {\n return new Map([\n [0, 'CA certificate'],\n [1, 'an end entity certificate'],\n [2, 'the trust anchor'],\n [3, 'domain-issued certificate'],\n ])\n }\n\n setSelector(val) {\n if (!this.getSelectorOptions().has(val)) this.throwHelp(`TLSA: selector invalid`);\n\n this.set('selector', val);\n }\n\n getSelectorOptions() {\n return new Map([\n [0, 'Full certificate'],\n [1, 'SubjectPublicKeyInfo'],\n ])\n }\n\n setMatchingType(val) {\n if (!this.getMatchingTypeOptions().has(val)) this.throwHelp(`TLSA: matching type`);\n\n this.set('matching type', val);\n }\n\n getMatchingTypeOptions() {\n return new Map([\n [0, 'Exact match'],\n [1, 'SHA-256 hash'],\n [2, 'SHA-512 hash'],\n ])\n }\n\n setCertificateAssociationData(val) {\n this.set('certificate association data', val);\n }\n\n getDescription() {\n return 'TLSA certificate association'\n }\n\n getCanonical() {\n return {\n owner: '_443._tcp.www.example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'TLSA',\n 'certificate usage': 3,\n selector: 1,\n 'matching type': 1,\n 'certificate association data': 'ABCDEF...',\n }\n }\n\n /****** IMPORTERS *******/\n\n fromBind({ bindline }) {\n // test.example.com 3600 IN TLSA, usage, selector, match, data\n const regex =\n /^(?\\S+)\\s+(?\\d{1,10})\\s+(?IN)\\s+(?TLSA)\\s+(?\\d+)\\s+(?\\d+)\\s+(?\\d+)\\s+(?\\S.*)$/i;\n const match = bindline.trim().match(regex);\n if (!match) this.throwHelp(`unable to parse TLSA: ${bindline}`);\n const { owner, ttl, cls, type, usage, selector, matchtype, cad } = match.groups;\n\n return new TLSA({\n owner: this.fullyQualify(owner),\n ttl: parseInt(ttl, 10),\n class: cls.toUpperCase(),\n type: type.toUpperCase(),\n 'certificate usage': parseInt(usage, 10),\n selector: parseInt(selector, 10),\n 'matching type': parseInt(matchtype, 10),\n 'certificate association data': cad.trim(),\n })\n }\n\n fromTinydns({ tinyline }) {\n const { owner, typeId, rdata, ttl, timestamp, location } = this.parseTinydnsLine(tinyline);\n if (typeId != this.getTypeId()) this.throwHelp('TLSA fromTinydns, invalid n');\n\n const bytes = octalRdataToBytes(rdata);\n\n return new TLSA({\n owner,\n ttl,\n type: 'TLSA',\n 'certificate usage': bytes[0],\n selector: bytes[1],\n 'matching type': bytes[2],\n 'certificate association data': bytesToHex(bytes.subarray(3)),\n timestamp,\n location,\n })\n }\n\n /****** EXPORTERS *******/\n toTinydns() {\n return this.getTinydnsGeneric(\n UInt8toOctal(this.get('certificate usage')) +\n UInt8toOctal(this.get('selector')) +\n UInt8toOctal(this.get('matching type')) +\n packHex(this.get('certificate association data').replace(/[\\s()]/g, '')),\n )\n }\n\n getWireRdata() {\n const cadBytes = hexToBytes(this.get('certificate association data').replace(/[\\s()]/g, ''));\n const bytes = new Uint8Array(3 + cadBytes.length);\n bytes[0] = this.get('certificate usage');\n bytes[1] = this.get('selector');\n bytes[2] = this.get('matching type');\n bytes.set(cadBytes, 3);\n return bytes\n }\n}\n\nclass TSIG extends RR {\n static typeName = 'TSIG'\n static typeId = 250\n static RFCs = [2845, 8945]\n static rdataFields = ['algorithm name', 'time signed', 'fudge', 'mac', 'original id', 'error', 'other']\n\n constructor(opts) {\n super(opts);\n if (opts === null) return\n }\n\n /****** Resource record specific setters *******/\n\n getDescription() {\n return 'Transaction Signature'\n }\n\n getCanonical() {\n return {\n owner: 'test.example.',\n ttl: 0,\n class: 'ANY',\n type: 'TSIG',\n 'algorithm name': 'hmac-sha256.',\n 'time signed': 1620650000,\n fudge: 300,\n mac: 'ABCDEF...',\n 'original id': 12345,\n error: 0,\n other: '',\n }\n }\n\n setClass(t) {\n if (t !== 'ANY') this.throwHelp('TSIG: Class is required to be ANY');\n this.set('class', t);\n }\n\n setTtl(t) {\n if (t !== 0) this.throwHelp('TSIG: TTL is required to be 0');\n this.set('ttl', t);\n }\n\n setAlgorithmName(val) {\n if (!val) this.throwHelp(`TSIG: 'algorithm name' is required`);\n this.set('algorithm name', val);\n }\n\n setTimeSigned(val) {\n // a 48-bit unsigned integer, as seconds since the UNIX epoch\n if (val === undefined) this.throwHelp(`TSIG: 'time signed' is required`);\n this.set('time signed', val);\n }\n\n setFudge(val) {\n // 16-bit unsigned\n this.is16bitInt('TSIG', 'fudge', val);\n this.set('fudge', val);\n }\n\n setMac(val) {\n this.set('mac', val ?? '');\n }\n\n setOriginalId(val) {\n this.is16bitInt('TSIG', 'original id', val);\n this.set('original id', val);\n }\n\n setError(val) {\n this.is16bitInt('TSIG', 'error', val);\n this.set('error', val);\n }\n\n setOther(val) {\n this.set('other', val ?? '');\n }\n\n /****** IMPORTERS *******/\n\n fromBind({ bindline }) {\n // owner ttl ANY TSIG alg time fudge mac_size mac original_id error other_len\n const parts = bindline.trimEnd().split('\\t');\n const [owner, ttl, cls, type, alg, time, fudge, , mac, origId, error] = parts;\n\n return new TSIG({\n owner,\n ttl: parseInt(ttl, 10),\n class: cls,\n type: type.toUpperCase(),\n 'algorithm name': alg,\n 'time signed': parseInt(time, 10),\n fudge: parseInt(fudge, 10),\n mac: mac || '',\n 'original id': parseInt(origId, 10),\n error: parseInt(error, 10),\n other: '',\n })\n }\n\n fromTinydns({ tinyline }) {\n const [owner, _typeId, rdata, ttl, ts, loc] = tinyline.slice(1).split(':');\n\n const algUnpacked = unpackDomainName(rdata);\n const algBinaryLen = algUnpacked[2];\n\n const bytes = Uint8Array.from(octalToChar(rdata), (c) => c.charCodeAt(0));\n const dv = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);\n let bpos = algBinaryLen;\n\n const timeSigned = dv.getUint32(bpos);\n bpos += 4;\n const fudge = dv.getUint16(bpos);\n bpos += 2;\n const macSize = dv.getUint16(bpos);\n bpos += 2;\n const mac = macSize > 0 ? bytesToHex(bytes.subarray(bpos, bpos + macSize)) : '';\n bpos += macSize;\n const originalId = dv.getUint16(bpos);\n bpos += 2;\n const error = dv.getUint16(bpos);\n bpos += 2;\n const other = bpos < bytes.length ? new TextDecoder().decode(bytes.subarray(bpos)) : '';\n\n return new TSIG({\n owner: this.fullyQualify(owner),\n ttl: parseInt(ttl, 10),\n class: 'ANY',\n type: 'TSIG',\n 'algorithm name': algUnpacked[0],\n 'time signed': timeSigned,\n fudge,\n mac,\n 'original id': originalId,\n error,\n other,\n timestamp: ts,\n location: loc?.trim() ?? '',\n })\n }\n\n fromWire({ owner, cls, ttl, rdata }) {\n const { fqdn: algorithmName, end } = this.wireUnpackDomain(rdata, 0);\n const dv = new DataView(rdata.buffer, rdata.byteOffset);\n let pos = end;\n const timeSigned = dv.getUint32(pos);\n pos += 4;\n const fudge = dv.getUint16(pos);\n pos += 2;\n const macSize = dv.getUint16(pos);\n pos += 2;\n const mac = macSize > 0 ? bytesToHex(rdata.subarray(pos, pos + macSize)) : '';\n pos += macSize;\n const originalId = dv.getUint16(pos);\n pos += 2;\n const error = dv.getUint16(pos);\n pos += 2;\n const other = pos < rdata.length ? new TextDecoder().decode(rdata.subarray(pos)) : '';\n return new TSIG({\n owner,\n ttl: 0,\n class: 'ANY',\n type: 'TSIG',\n 'algorithm name': algorithmName,\n 'time signed': timeSigned,\n fudge,\n mac,\n 'original id': originalId,\n error,\n other,\n })\n }\n\n /****** EXPORTERS *******/\n toBind(zone_opts) {\n const mac = this.get('mac') ?? '';\n const macSize = mac.length > 0 ? mac.length : '';\n const other = this.get('other') ?? '';\n const otherLen = other.length > 0 ? other.length : 0;\n return (\n [\n this.getFQDN('owner', zone_opts),\n this.get('ttl'),\n this.get('class'),\n this.get('type'),\n this.get('algorithm name'),\n this.get('time signed'),\n this.get('fudge'),\n macSize,\n mac,\n this.get('original id'),\n this.get('error'),\n otherLen,\n ].join('\\t') + '\\n'\n )\n }\n\n getWireRdata() {\n const algWire = wirePackDomain(this.get('algorithm name') || '');\n const mac = this.get('mac') ?? '';\n const macBytes = mac.length > 0 ? hexToBytes(mac) : new Uint8Array();\n const other = this.get('other') ?? '';\n const otherBytes = other.length > 0 ? new TextEncoder().encode(other) : new Uint8Array();\n\n const bytes = new Uint8Array(algWire.length + 4 + 2 + 2 + macBytes.length + 2 + 2 + otherBytes.length);\n const dv = new DataView(bytes.buffer, bytes.byteOffset);\n let pos = 0;\n\n bytes.set(algWire, pos);\n pos += algWire.length;\n dv.setUint32(pos, this.get('time signed') ?? 0);\n pos += 4;\n dv.setUint16(pos, this.get('fudge') ?? 0);\n pos += 2;\n dv.setUint16(pos, macBytes.length);\n pos += 2;\n if (macBytes.length > 0) {\n bytes.set(macBytes, pos);\n pos += macBytes.length;\n }\n dv.setUint16(pos, this.get('original id') ?? 0);\n pos += 2;\n dv.setUint16(pos, this.get('error') ?? 0);\n pos += 2;\n if (otherBytes.length > 0) bytes.set(otherBytes, pos);\n\n return bytes\n }\n\n toTinydns() {\n const alg = this.get('algorithm name') || '';\n const mac = this.get('mac') ?? '';\n const macByteLen = mac.length > 0 ? mac.length / 2 : 0;\n\n return this.getTinydnsGeneric(\n packDomainName(alg) +\n UInt32toOctal(this.get('time signed') ?? 0) +\n UInt16toOctal(this.get('fudge')) +\n UInt16toOctal(macByteLen) +\n (macByteLen > 0 ? packHex(mac) : '') +\n UInt16toOctal(this.get('original id') ?? 0) +\n UInt16toOctal(this.get('error') ?? 0) +\n (this.get('other').length > 0\n ? escapeOctal(new RegExp(/[\\r\\n\\t:\\\\/]/, 'g'), this.get('other'))\n : ''),\n )\n }\n}\n\nclass URI extends RR {\n static typeName = 'URI'\n static typeId = 256\n static RFCs = [7553]\n static rdataFields = [\n ['priority', 'u16'],\n ['weight', 'u16'],\n ['target', 'qstr'],\n ]\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setPriority(val) {\n this.is16bitInt('URI', 'priority', val);\n\n this.set('priority', val);\n }\n\n setWeight(val) {\n this.is16bitInt('URI', 'weight', val);\n\n this.set('weight', val);\n }\n\n setTarget(val) {\n if (!val) this.throwHelp(`URI: target is required`);\n\n this.set('target', val);\n }\n\n /****** IMPORTERS *******/\n fromTinydns({ tinyline }) {\n // URI via generic, :fqdn:n:rdata:ttl:timestamp:lo\n const [fqdn, n, rdata, ttl, ts, loc] = tinyline.slice(1).split(':');\n if (n != 256) this.throwHelp('URI fromTinydns, invalid n');\n\n return new URI({\n type: 'URI',\n owner: this.fullyQualify(fqdn),\n priority: octalToUInt16(rdata.slice(0, 8)),\n weight: octalToUInt16(rdata.slice(8, 16)),\n target: octalToChar(rdata.slice(16)),\n ttl: parseInt(ttl, 10),\n timestamp: ts,\n location: loc?.trim() ?? '',\n })\n }\n\n /****** MISC *******/\n getDescription() {\n return 'URI'\n }\n\n getCanonical() {\n return {\n owner: 'www.example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'URI',\n priority: 10,\n weight: 10,\n target: 'http://www.example.com/',\n }\n }\n\n /****** EXPORTERS *******/\n\n getWireRdata() {\n const target = new TextEncoder().encode(this.get('target'));\n const result = new Uint8Array(4 + target.length);\n const dv = new DataView(result.buffer);\n dv.setUint16(0, this.get('priority'));\n dv.setUint16(2, this.get('weight'));\n result.set(target, 4);\n return result\n }\n\n toTinydns() {\n const dataRe = new RegExp(/[\\r\\n\\t:\\\\/]/, 'g');\n let rdata = '';\n\n for (const e of ['priority', 'weight']) {\n rdata += UInt16toOctal(this.get(e));\n }\n\n rdata += escapeOctal(dataRe, this.get('target'));\n return this.getTinydnsGeneric(rdata)\n }\n}\n\nconst WELL_KNOWN_PORTS = {\n echo: 7,\n discard: 9,\n systat: 11,\n daytime: 13,\n netstat: 15,\n ftp_data: 20,\n ftp: 21,\n ssh: 22,\n telnet: 23,\n smtp: 25,\n time: 37,\n rlp: 39,\n nameserver: 42,\n nicname: 43,\n domain: 53,\n mtp: 57,\n bootps: 67,\n bootpc: 68,\n tftp: 69,\n gopher: 70,\n rje: 77,\n finger: 79,\n http: 80,\n link: 87,\n supdup: 95,\n hostnames: 101,\n iso_tsap: 102,\n csnet_ns: 105,\n pop_2: 109,\n pop3: 110,\n sunrpc: 111,\n auth: 113,\n sftp: 115,\n uucp_path: 117,\n nntp: 119,\n ntp: 123,\n netbios_ns: 137,\n netbios_dgm: 138,\n netbios_ssn: 139,\n imap: 143,\n sql_net: 150,\n snmp: 161,\n snmp_trap: 162,\n cmip_man: 163,\n cmip_agent: 164,\n xdmcp: 177,\n nextstep: 178,\n bgp: 179,\n prospero: 191,\n irc: 194,\n smux: 199,\n at_rtmp: 201,\n at_nbp: 202,\n at_echo: 204,\n at_zis: 206,\n qmtp: 209,\n z3950: 210,\n ipx: 213,\n imap3: 220,\n ulistproc: 372,\n https: 443,\n snpp: 444,\n microsoft_ds: 445,\n kpasswd: 464,\n urd: 465,\n saft: 487,\n isakmp: 500,\n exec: 512,\n biff: 512,\n login: 513,\n who: 513,\n cmd: 514,\n syslog: 514,\n printer: 515,\n talk: 517,\n ntalk: 518,\n route: 520,\n timed: 525,\n tempo: 526,\n courier: 530,\n netnews: 532,\n netwall: 533,\n uucp: 540,\n remotefs: 556,\n nntps: 563,\n ldap: 389,\n};\n\nclass WKS extends RR {\n static typeName = 'WKS'\n static typeId = 11\n static RFCs = [883, 1035]\n static rdataFields = ['address', 'protocol', 'bit map']\n static tags = ['obsolete']\n\n constructor(opts) {\n super(opts);\n }\n\n /****** Resource record specific setters *******/\n setAddress(val) {\n if (!val) this.throwHelp('WKS: address is required');\n if (!this.isIPv4(val)) this.throwHelp('WKS address must be IPv4');\n this.set('address', val);\n }\n\n setProtocol(val) {\n if (!val) this.throwHelp('WKS: protocol is required');\n const upper = typeof val === 'string' ? val.toUpperCase() : val;\n if (!['TCP', 'UDP', 6, 17].includes(upper)) this.throwHelp('WKS protocol must be TCP or UDP');\n this.set('protocol', upper);\n }\n\n setBitMap(val) {\n this.set('bit map', val ?? '');\n }\n\n getDescription() {\n return 'Well Known Service'\n }\n\n getCanonical() {\n return {\n owner: 'host.example.com.',\n ttl: 3600,\n class: 'IN',\n type: 'WKS',\n address: '192.0.2.1',\n protocol: 'TCP',\n 'bit map': 'ftp smtp',\n }\n }\n\n /****** IMPORTERS *******/\n\n fromBind({ bindline }) {\n // test.example.com 3600 IN WKS 192.168.1.1 TCP ftp smtp\n const parts = bindline.split(/\\s+/);\n const [owner, ttl, c, type, address, protocol] = parts;\n return new WKS({\n owner,\n ttl: parseInt(ttl, 10),\n class: c,\n type,\n address,\n protocol,\n 'bit map': parts.slice(6).join(' ').trim(),\n })\n }\n\n fromTinydns({ tinyline }) {\n const [owner, _typeId, rdata, ttl, ts, loc] = tinyline.slice(1).split(':');\n\n const binary = Uint8Array.from(octalToChar(rdata), (c) => c.charCodeAt(0));\n const address = [binary[0], binary[1], binary[2], binary[3]].join('.');\n const protoNum = binary[4];\n const protoMap = { 6: 'TCP', 17: 'UDP' };\n const protocol = protoMap[protoNum] ?? protoNum;\n const bitmap = new TextDecoder().decode(binary.subarray(5));\n\n return new WKS({\n owner: this.fullyQualify(owner),\n ttl: parseInt(ttl, 10),\n type: 'WKS',\n address,\n protocol,\n 'bit map': bitmap,\n timestamp: ts,\n location: loc?.trim() ?? '',\n })\n }\n\n fromWire({ owner, cls, ttl, rdata }) {\n const address = [...rdata.subarray(0, 4)].join('.');\n const protoNum = rdata[4];\n const protoMap = { 6: 'TCP', 17: 'UDP' };\n const protocol = protoMap[protoNum] ?? String(protoNum);\n const PORT_NAMES = Object.fromEntries(Object.entries(WELL_KNOWN_PORTS).map(([k, v]) => [v, k]));\n const bitmap = rdata.subarray(5);\n const ports = [];\n for (let i = 0; i < bitmap.length; i++) {\n for (let bit = 0; bit < 8; bit++) {\n if (bitmap[i] & (0x80 >> bit)) {\n const port = i * 8 + bit;\n ports.push(PORT_NAMES[port] ?? String(port));\n }\n }\n }\n return new WKS({\n owner,\n ttl,\n class: cls,\n type: 'WKS',\n address,\n protocol,\n 'bit map': ports.join(' '),\n })\n }\n\n /****** EXPORTERS *******/\n\n toTinydns() {\n const dataRe = new RegExp(/[\\r\\n\\t:\\\\/]/, 'g');\n const protoMap = { TCP: 6, UDP: 17, 6: 6, 17: 17 };\n const protoNum = protoMap[this.get('protocol')];\n\n return this.getTinydnsGeneric(\n ipv4toOctal(this.get('address')) +\n UInt8toOctal(protoNum) +\n escapeOctal(dataRe, this.get('bit map')),\n )\n }\n\n getWireRdata() {\n const protoMap = { TCP: 6, UDP: 17, 6: 6, 17: 17 };\n const addrBytes = this.get('address').split('.').map(Number);\n const protoNum = protoMap[this.get('protocol')];\n\n const portNums = this.get('bit map')\n .trim()\n .split(/\\s+/)\n .map((s) => {\n if (/^\\d+$/.test(s)) return parseInt(s, 10)\n return WELL_KNOWN_PORTS[s.toLowerCase()]\n })\n .filter((p) => p !== undefined);\n\n if (portNums.length === 0) return new Uint8Array([...addrBytes, protoNum])\n\n const maxPort = Math.max(...portNums);\n const bitmapLen = Math.floor(maxPort / 8) + 1;\n const bitmap = new Uint8Array(bitmapLen);\n for (const port of portNums) bitmap[Math.floor(port / 8)] |= 0x80 >> (port % 8);\n\n const result = new Uint8Array(5 + bitmapLen);\n result.set(addrBytes);\n result[4] = protoNum;\n result.set(bitmap, 5);\n return result\n }\n}\n\nconst typeMap = {};\nconst classes = [\n A,\n AAAA,\n APL,\n CAA,\n CERT,\n CNAME,\n DHCID,\n DNAME,\n DNSKEY,\n DS,\n HINFO,\n HIP,\n HTTPS,\n IPSECKEY,\n KEY,\n KX,\n LOC,\n MX,\n NAPTR,\n NS,\n NSEC,\n NSEC3,\n NSEC3PARAM,\n NXT,\n OPENPGPKEY,\n PTR,\n RP,\n RRSIG,\n SIG,\n SMIMEA,\n SSHFP,\n SOA,\n SPF,\n SRV,\n SVCB,\n TLSA,\n TSIG,\n TXT,\n URI,\n WKS,\n];\n\nfor (const c of classes) {\n const id = c.getTypeId();\n typeMap[id] = c.typeName;\n typeMap[c.typeName] = id;\n}\n\nexport { A, AAAA, APL, CAA, CERT, CNAME, DHCID, DNAME, DNSKEY, DS, HINFO, HIP, HTTPS, IPSECKEY, KEY, KX, LOC, MX, NAPTR, NS, NSEC, NSEC3, NSEC3PARAM, NXT, OPENPGPKEY, PTR, RP, RRSIG, SIG, SMIMEA, SOA, SPF, SRV, SSHFP, SVCB, TLSA, TSIG, TXT, URI, WKS, RR as default, typeMap };\n"], + "mappings": "AAAA,MAAMA,GAAU,IAAI,OAAO,mCAAoC,GAAG,EAC5DC,GAAc,IAAI,YAExB,SAASC,GAAYC,EAAUC,EAAY,CACzC,MAAMC,EAAQF,EAAS,MAAM,CAAC,EAAE,MAAM,GAAG,EACnCG,EAAQD,EAAM,CAAC,EACfE,EAAQF,EAAM,MAAM,EAAG,EAAID,CAAU,EACrC,CAACI,EAAKC,EAAWC,CAAQ,EAAIL,EAAM,MAAM,EAAID,CAAU,EAC7D,MAAO,CAAE,MAAAE,EAAO,MAAAC,EAAO,IAAAC,EAAK,UAAAC,EAAW,SAAUC,GAAU,KAAK,GAAK,EAAG,CAC1E,CAEA,SAASC,GAAiBR,EAAU,CAElC,KAAM,CAACG,EAAOM,EAAQL,EAAOC,EAAKC,EAAWC,CAAQ,EAAIP,EAAS,MAAM,CAAC,EAAE,MAAM,GAAG,EACpF,MAAO,CAAE,MAAAG,EAAO,OAAAM,EAAQ,MAAAL,EAAO,IAAK,SAASC,EAAK,EAAE,EAAG,UAAAC,EAAW,SAAUC,GAAU,KAAK,GAAK,EAAG,CACrG,CAEA,SAASG,EAAkBN,EAAO,CAChC,OAAO,WAAW,KAAKO,EAAYP,CAAK,EAAIQ,GAAMA,EAAE,WAAW,CAAC,CAAC,CACnE,CAEA,SAASC,GAAmBT,EAAOU,EAAY,CAC7C,GAAIV,EAAM,OAAS,EACjB,MAAM,IAAI,MAAM,GAAGU,CAAU,sBAAsBV,CAAK,EAAE,EAG5D,MAAMW,EAASL,EAAkBN,CAAK,EAChCY,EAAYD,EAAO,CAAC,GAAK,EAAKA,EAAO,CAAC,EAE5C,IAAIE,EAAM,EACV,MAAMC,EAAS,CAAC,EAChB,OAAa,CACX,MAAMC,EAAMJ,EAAOE,CAAG,EAEtB,GADAA,GAAO,EACHE,IAAQ,EAAG,MACfD,EAAO,KAAKpB,GAAY,OAAOiB,EAAO,SAASE,EAAKA,EAAME,CAAG,CAAC,CAAC,EAC/DF,GAAOE,CACT,CAEA,MAAO,CACL,SAAAH,EACA,WAAY,GAAGE,EAAO,KAAK,GAAG,CAAC,IAC/B,OAAQpB,GAAY,OAAOiB,EAAO,SAASE,CAAG,CAAC,CACjD,CACF,CAEA,SAASG,GAAGC,EAAY,CACtB,GAAIA,EAAW,YAAY,YAAa,CAEtC,MAAMjB,EADSiB,EAAW,UAAU,OAAO,EAExC,IAAKC,GACAD,EAAW,YAAYC,CAAC,EAAUD,EAAW,YAAYC,CAAC,EACvDD,EAAW,IAAIC,CAAC,CACxB,EACA,KAAK,GAAG,EACX,MAAO,GAAGD,EAAW,YAAY,WAAW,GAAGA,EAAW,YAAY,OAAO,CAAC,IAAIjB,CAAK,IAAIiB,EAAW,oBAAoB,CAAC;AAAA,CAC7H,CACA,OAAOA,EAAW,kBAAkBE,GAAmBF,EAAW,aAAa,CAAC,CAAC,CACnF,CAEA,SAASG,GAAYH,EAAY,CAAE,SAAArB,CAAS,EAAG,CAC7C,MAAMyB,EAASJ,EAAW,UAAU,OAAO,EACrC,CAAE,MAAAlB,EAAO,MAAAC,EAAO,IAAAC,EAAK,UAAAC,EAAW,SAAAC,CAAS,EAAIR,GAAYC,EAAUyB,EAAO,MAAM,EAEhFC,EAAS,CACb,MAAOL,EAAW,aAAalB,CAAK,EACpC,KAAMkB,EAAW,YAAY,SAC7B,IAAK,SAAShB,EAAK,EAAE,EACrB,UAAWC,EACX,SAAUC,CACZ,EAEA,QAASoB,EAAI,EAAGA,EAAIF,EAAO,OAAQE,IAAK,CACtC,MAAMC,EAAMxB,EAAMuB,CAAC,EACnBD,EAAOD,EAAOE,CAAC,CAAC,EAAIN,EAAW,YAAYI,EAAOE,CAAC,CAAC,EAAIN,EAAW,aAAaO,CAAG,EAAIA,CACzF,CAEA,OAAO,IAAIP,EAAW,YAAYK,CAAM,CAC1C,CAEA,SAASG,EAAYC,EAAIC,EAAK,CAC5B,IAAIC,EAAU,GACd,OAAAD,EAAI,MAAM,SAAS,EAAE,IAAKnB,GAAM,CAC9BoB,GAAWF,EAAG,KAAKlB,CAAC,EAAIqB,GAAYrB,CAAC,EAAIA,CAC3C,CAAC,EACMoB,CACT,CAEA,SAASrB,EAAYoB,EAAK,CAExB,OAAOA,EAAI,QAAQlC,GAAUqC,GAAM,OAAO,aAAa,SAASA,EAAE,MAAM,CAAC,EAAG,CAAC,CAAC,CAAC,CACjF,CAEA,SAASC,GAAWJ,EAAK,CAEvB,OAAOA,EAAI,QAAQlC,GAAUqC,GAGpB,SAASA,EAAE,MAAM,CAAC,EAAG,CAAC,EAAE,SAAS,EAAE,EAAE,SAAS,EAAG,CAAC,CAC1D,CACH,CAEA,SAASE,EAAaL,EAAK,CACzB,OAAO,SAASA,EAAI,MAAM,EAAG,CAAC,EAAG,CAAC,EAAI,GACxC,CAEA,SAASM,EAAcN,EAAK,CAC1B,OAAQ,SAASA,EAAI,MAAM,EAAG,CAAC,EAAG,CAAC,GAAK,EAAK,SAASA,EAAI,MAAM,EAAG,CAAC,EAAG,CAAC,CAC1E,CAEA,SAASO,GAAcP,EAAK,CAC1B,MAAMQ,EAAK,SAASR,EAAI,MAAM,EAAG,CAAC,EAAG,CAAC,EAChCS,EAAK,SAAST,EAAI,MAAM,EAAG,CAAC,EAAG,CAAC,EAChCU,EAAK,SAASV,EAAI,MAAM,EAAG,EAAE,EAAG,CAAC,EACjCW,EAAK,SAASX,EAAI,MAAM,GAAI,EAAE,EAAG,CAAC,EACxC,OAASQ,GAAM,GAAOC,GAAM,GAAOC,GAAM,EAAKC,KAAQ,CACxD,CAEA,SAASC,GAAWZ,EAAK,CACvB,OAAOA,EACJ,MAAM,aAAa,EACnB,IAAKa,GAAM,GAAGC,EAAaD,EAAE,MAAM,CAAC,GAAGA,CAAC,EAAE,EAC1C,KAAK,EAAE,CACZ,CAEA,SAASE,GAAaf,EAAK,CACzB,MAAMgB,EAAQ,WAAW,KAAKpC,EAAYoB,EAAI,SAAS,CAAC,EAAInB,GAAMA,EAAE,WAAW,CAAC,CAAC,EAC3EoC,EAAM,IAAI,YACVC,EAAM,CAAC,EACb,IAAIhC,EAAM,EACNE,EACJ,MAAQA,EAAM4B,EAAM9B,CAAG,KAErBA,IACAgC,EAAI,KAAKD,EAAI,OAAOD,EAAM,SAAS9B,EAAKA,EAAME,CAAG,CAAC,CAAC,EACnDF,EAAM,EAAEA,EAAME,GACV,EAAAF,GAAO8B,EAAM,UAAjB,CAEF,OAAOE,CACT,CAEA,SAASC,EAAeC,EAAM,CAC5B,MAAMC,EAAa,IAAI,OAAO,iBAAkB,GAAG,EAInD,IAAIC,EAAS,GACb,OAAAF,EAAK,MAAM,GAAG,EAAE,QAASG,GAAU,CAC7BA,IAAU,QAAa,CAACA,EAAM,SAElCD,GAAUR,EAAaS,EAAM,MAAM,EAEnCD,GAAUxB,EAAYuB,EAAYE,CAAK,EACzC,CAAC,EACDD,GAAU,QACHA,CACT,CAEA,SAASE,EAAiBvB,EAAS,CACjC,IAAIf,EAAM,EACNuC,EAAY,EAChB,MAAMtC,EAAS,CAAC,EAGVuC,EAAc,IAAM,CACxB,GAAIxC,GAAOe,EAAQ,OAAQ,OAAO,KAElC,IAAI0B,EACJ,OAAI1B,EAAQf,CAAG,IAAM,MACnByC,EAAQ,SAAS1B,EAAQ,MAAMf,EAAM,EAAGA,EAAM,CAAC,EAAG,CAAC,EACnDA,GAAO,GAEPyC,EAAQ1B,EAAQ,WAAWf,GAAK,EAGlCuC,IACOE,CACT,EAEA,IAAIC,EACJ,MAAQA,EAAaF,EAAY,IAAME,IAAe,GAAG,CACvD,IAAIL,EAAQ,GACZ,QAAS3B,EAAI,EAAGA,EAAIgC,EAAYhC,IAAK,CACnC,MAAMiC,EAAOH,EAAY,EACzB,GAAIG,IAAS,KAAM,MACnBN,GAAS,OAAO,aAAaM,CAAI,CACnC,CACA1C,EAAO,KAAKoC,CAAK,CACnB,CAEA,MAAO,CAAC,GAAGpC,EAAO,KAAK,GAAG,CAAC,IAAKD,EAAKuC,CAAS,CAChD,CAEA,SAASK,EAAQ9B,EAAK,CACpB,IAAI+B,EAAI,GACR,QAASnC,EAAI,EAAGA,EAAII,EAAI,OAAQJ,EAAIA,EAAI,EAEtCmC,GAAKjB,EAAa,SAASd,EAAI,MAAMJ,EAAGA,EAAI,CAAC,EAAG,EAAE,CAAC,EAErD,OAAOmC,CACT,CAEA,SAAS7B,GAAYrB,EAAG,CACtB,OAAkCiC,EAA9B,OAAOjC,GAAM,SAA8BA,EAE3BA,EAAE,WAAW,CAAC,CAFc,CAGlD,CAEA,SAASiC,EAAakB,EAAG,CACvB,GAAIA,EAAI,IACN,MAAM,IAAI,MACR,uBAAuBA,CAAC,uFAC1B,EAGF,MAAO,KAAK,SAASA,EAAG,EAAE,EAAE,SAAS,CAAC,EAAE,SAAS,EAAG,CAAC,CAAC,EACxD,CAEA,SAASC,EAAcD,EAAG,CACxB,OAAOlB,EAAckB,IAAM,EAAK,GAAI,EAAIlB,EAAakB,EAAI,GAAI,CAC/D,CAEA,SAASE,EAAcF,EAAG,CACxB,OACElB,EAAckB,IAAM,GAAM,GAAI,EAC9BlB,EAAckB,IAAM,GAAM,GAAI,EAC9BlB,EAAckB,IAAM,EAAK,GAAI,EAC7BlB,EAAakB,EAAI,GAAI,CAEzB,CAEA,SAASG,GAAYC,EAAI,CACvB,OAAOF,EAAcE,EAAG,SAAS,OAAO,CAACC,EAAKV,IAAUU,EAAM,KAAM,CAACV,CAAK,CAAC,CAC7E,CAEA,SAASW,GAAYtC,EAAK,CACxB,MAAMuC,EAAQhC,GAAcP,CAAG,EAC/B,MAAO,CAAC,GAAI,GAAI,EAAG,CAAC,EAAE,IAAKgC,GAAOO,GAASP,EAAK,GAAI,EAAE,KAAK,GAAG,CAChE,CAEA,SAASQ,GAAW3C,EAAK4C,EAAY,IAAK,CACxC,MAAMC,EAAS7C,EAAI,MAAM,IAAI,EAC7B,OAAI6C,GAAQ,OAAS,IACnB7C,EAAMA,EAAI,QAAQ,KAAM,IAAI,OAAO,EAAI6C,EAAO,MAAM,CAAC,GAEhD7C,EACJ,MAAM,GAAG,EACT,IAAK,GAAM,EAAE,SAAS,EAAG,GAAG,CAAC,EAC7B,KAAK4C,CAAS,EACd,YAAY,CACjB,CAEA,SAASE,GAAYP,EAAI,CACvB,OAAON,EAAQU,GAAWJ,EAAI,EAAE,CAAC,CACnC,CAEA,SAASQ,GAAY5C,EAAK,CACxB,OAAOI,GAAWJ,CAAG,EAClB,MAAM,SAAS,EACf,KAAK,GAAG,CACb,CAEA,SAAS6C,EAAc7C,EAAK,CAC1B,MAAMhB,EAAS,KAAKgB,CAAG,EACvB,IAAIC,EAAU,GACd,QAASL,EAAI,EAAGA,EAAIZ,EAAO,OAAQY,IAAK,CACtC,MAAMkD,EAAI9D,EAAO,WAAWY,CAAC,EAC7BK,GAAW,iBAAiB,KAAKjB,EAAOY,CAAC,CAAC,EAAIZ,EAAOY,CAAC,EAAIkB,EAAagC,CAAC,CAC1E,CACA,OAAO7C,CACT,CAEA,SAAS8C,GAAc/C,EAAK,CAC1B,OAAO,KAAKpB,EAAYoB,CAAG,CAAC,CAC9B,CAEA,SAASR,GAAmBwD,EAAO,CACjC,IAAIrD,EAAS,GACb,UAAWmD,KAAKE,EAAOrD,GAAUmB,EAAagC,CAAC,EAC/C,OAAOnD,CACT,CAEA,SAASsD,EAAWC,EAAK,CACvB,OAAO,WAAW,KAAK,CAAE,OAAQA,EAAI,OAAS,CAAE,EAAG,CAACC,EAAGvD,IAAM,SAASsD,EAAI,MAAMtD,EAAI,EAAGA,EAAI,EAAI,CAAC,EAAG,EAAE,CAAC,CACxG,CAEA,SAASwD,EAAWJ,EAAO,CACzB,MAAO,CAAC,GAAGA,CAAK,EAAE,IAAKF,GAAMA,EAAE,SAAS,EAAE,EAAE,SAAS,EAAG,GAAG,CAAC,EAAE,KAAK,EAAE,CACvE,CAEA,SAASO,EAAcL,EAAO,CAC5B,OAAO,KAAK,CAAC,GAAGA,CAAK,EAAE,IAAKF,GAAM,OAAO,aAAaA,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CACpE,CAEA,SAASQ,EAAcC,EAAK,CAC1B,OAAO,WAAW,KAAK,KAAKA,CAAG,EAAI1E,GAAMA,EAAE,WAAW,CAAC,CAAC,CAC1D,CAGA,MAAM2E,EAAe,CACnB,EAAG,EACH,GAAI,EACJ,GAAI,EACJ,GAAI,EACJ,MAAO,EACP,IAAK,EACL,GAAI,EACJ,GAAI,EACJ,GAAI,EACJ,KAAM,GACN,IAAK,GACL,IAAK,GACL,MAAO,GACP,MAAO,GACP,GAAI,GACJ,IAAK,GACL,GAAI,GACJ,MAAO,GACP,IAAK,GACL,KAAM,GACN,GAAI,GACJ,KAAM,GACN,SAAU,GACV,IAAK,GACL,IAAK,GACL,GAAI,GACJ,KAAM,GACN,KAAM,GACN,IAAK,GACL,IAAK,GACL,IAAK,GACL,OAAQ,GACR,IAAK,GACL,KAAM,GACN,MAAO,GACP,GAAI,GACJ,KAAM,GACN,GAAI,GACJ,MAAO,GACP,KAAM,GACN,IAAK,GACL,IAAK,GACL,GAAI,GACJ,MAAO,GACP,SAAU,GACV,MAAO,GACP,KAAM,GACN,OAAQ,GACR,MAAO,GACP,MAAO,GACP,WAAY,GACZ,KAAM,GACN,OAAQ,GACR,IAAK,GACL,MAAO,GACP,KAAM,GACN,OAAQ,GACR,IAAK,GACL,QAAS,GACT,WAAY,GACZ,MAAO,GACP,OAAQ,GACR,KAAM,GACN,MAAO,GACP,IAAK,GACL,MAAO,IACP,IAAK,IACL,IAAK,IACL,OAAQ,IACR,IAAK,IACL,IAAK,IACL,IAAK,IACL,GAAI,IACJ,MAAO,IACP,MAAO,IACP,KAAM,IACN,KAAM,IACN,KAAM,IACN,KAAM,IACN,MAAO,IACP,MAAO,IACP,IAAK,IACL,IAAK,IACL,IAAK,IACL,IAAK,IACL,IAAK,IACL,SAAU,IACV,GAAI,MACJ,IAAK,KACP,EAQA,SAASC,GAAiBT,EAAOU,EAAS,EAAG,CAC3C,MAAMvE,EAAS,CAAC,EAChB,IAAID,EAAMwE,EACV,KAAOxE,EAAM8D,EAAM,QAAQ,CACzB,MAAM5D,EAAM4D,EAAM9D,CAAG,EACrB,GAAIE,IAAQ,EAAG,CACbF,IACA,KACF,CACAC,EAAO,KAAK,IAAI,YAAY,EAAE,OAAO6D,EAAM,SAAS9D,EAAM,EAAGA,EAAM,EAAIE,CAAG,CAAC,CAAC,EAC5EF,GAAO,EAAIE,CACb,CACA,MAAO,CAAE,KAAMD,EAAO,OAASA,EAAO,KAAK,GAAG,EAAI,IAAM,IAAK,IAAKD,CAAI,CACxE,CAMA,SAASyE,EAAevC,EAAM,CAC5B,GAAIA,IAAS,IAAK,OAAO,IAAI,WAAW,CAAC,CAAC,CAAC,EAC3C,MAAMwC,EAAM,IAAI,YACVzE,EAASiC,EACZ,MAAM,GAAG,EACT,OAAQyC,GAAMA,EAAE,OAAS,CAAC,EAC1B,IAAKA,GAAM,CACV,MAAMf,EAAIc,EAAI,OAAOC,CAAC,EACtB,GAAIf,EAAE,OAAS,GAAI,MAAM,IAAI,MAAM,+BAA+Be,CAAC,EAAE,EACrE,OAAOf,CACT,CAAC,EAEGgB,EAAM,IAAI,WAAW3E,EAAO,OAAO,CAAC,EAAG2D,IAAM,EAAIA,EAAE,OAAS,EAAG,CAAC,CAAC,EACvE,IAAIY,EAAS,EACb,UAAWZ,KAAK3D,EACd2E,EAAIJ,GAAQ,EAAIZ,EAAE,OAClBgB,EAAI,IAAIhB,EAAGY,CAAM,EACjBA,GAAUZ,EAAE,OAEd,OAAAgB,EAAIJ,CAAM,EAAI,EACPI,CACT,CAOA,SAASC,GAAazE,EAAY,CAChC,MAAM0E,EAAO1E,EAAW,UAAU,EAClC,GAAI,CAAC0E,EAAK,WAAW,GAAG,EACtB,MAAM,IAAI,MACR,GAAG1E,EAAW,IAAI,MAAM,CAAC,oDAAoDA,EAAW,IAAI,MAAM,EAAE,YAAY,CAAC,KACnH,EAIF,MAAMjB,EAAQ2F,EAAK,MAAM,GAAG,EAAE,CAAC,EAC/B,OAAO1E,EAAW,kBAAkBjB,GAAS,EAAE,CACjD,CAMA,SAAS4F,GAAO3E,EAAY4E,EAAW,CACrC,MAAM7F,EAAQiB,EAAW,aAAa,EAChClB,EAAQuF,EAAerE,EAAW,IAAI,OAAO,CAAC,EAC9CK,EAAS,IAAI,WAAWvB,EAAM,OAAS,GAAKC,EAAM,MAAM,EAC9DsB,EAAO,IAAIvB,EAAO,CAAC,EACnB,MAAM+F,EAAO,IAAI,SAASxE,EAAO,OAAQvB,EAAM,OAAQ,EAAE,EACzD,OAAA+F,EAAK,UAAU,EAAG7E,EAAW,UAAU,CAAC,EACxC6E,EAAK,UAAU,EAAGD,EAAU5E,EAAW,IAAI,OAAO,CAAC,GAAK,CAAC,EACzD6E,EAAK,UAAU,EAAG7E,EAAW,IAAI,KAAK,CAAC,EACvC6E,EAAK,UAAU,EAAG9F,EAAM,MAAM,EAC9BsB,EAAO,IAAItB,EAAOD,EAAM,OAAS,EAAE,EAC5BuB,CACT,CAMA,SAASyE,GAAcC,EAAeC,EAAWC,EAAc,CAC7D,MAAMC,EAAW,IAAIH,EAAc,IAAI,EACjCrB,EAAQsB,aAAqB,WAAaA,EAAY,IAAI,WAAWA,CAAS,EAC9E,CAAE,KAAMlG,EAAO,IAAAqG,CAAI,EAAIF,EAAavB,EAAO,CAAC,EAC5C0B,EAAO,IAAI,SAAS1B,EAAM,OAAQA,EAAM,UAAU,EAClD2B,EAAWD,EAAK,UAAUD,EAAM,CAAC,EACjCP,EAAY,CAAE,GAAI,EAAG,GAAI,EAAG,GAAI,EAAG,GAAI,EAAG,KAAM,IAAK,IAAK,GAAI,EAC9DU,EAAM,OAAO,KAAKV,CAAS,EAAE,KAAMW,GAAMX,EAAUW,CAAC,IAAMF,CAAQ,GAAK,KACvErG,EAAMoG,EAAK,UAAUD,EAAM,CAAC,EAC5BK,EAAQJ,EAAK,UAAUD,EAAM,CAAC,EAC9BpG,EAAQ2E,EAAM,MAAMyB,EAAM,GAAIA,EAAM,GAAKK,CAAK,EACpD,OAAON,EAAS,SAAS,CAAE,MAAApG,EAAO,IAAAwG,EAAK,IAAAtG,EAAK,MAAAD,CAAM,CAAC,CACrD,CAQA,SAAS0G,GAAgBzF,EAAY,CAAE,MAAAlB,EAAO,IAAAwG,EAAK,IAAAtG,EAAK,MAAAD,CAAM,EAAG,CAC/D,MAAMsB,EAAS,CAAE,MAAAvB,EAAO,IAAAE,EAAK,MAAOsG,EAAK,KAAMtF,EAAW,YAAY,QAAS,EACzE0F,EAAc1F,EAAW,YAAY,aAAe,CAAC,EACrD2F,EAAK,IAAI,SAAS5G,EAAM,OAAQA,EAAM,UAAU,EACtD,IAAIa,EAAM,EAEV,QAASU,EAAI,EAAGA,EAAIoF,EAAY,OAAQpF,IAAK,CAC3C,MAAMsF,EAAQF,EAAYpF,CAAC,EACrBuF,EAAY,MAAM,QAAQD,CAAK,EAAIA,EAAM,CAAC,EAAIA,EAGpD,OAFkB,MAAM,QAAQA,CAAK,EAAIA,EAAM,CAAC,EAAI,KAEjC,CACjB,IAAK,KACHvF,EAAOwF,CAAS,EAAI9G,EAAMa,GAAK,EAC/B,MACF,IAAK,MACHS,EAAOwF,CAAS,EAAIF,EAAG,UAAU/F,CAAG,EACpCA,GAAO,EACP,MACF,IAAK,WAAY,CACf,MAAMkG,EAAcH,EAAG,UAAU/F,CAAG,EAC9BmG,EAAU/F,EAAW,YAAY,mBACvCK,EAAOwF,CAAS,EAAIE,IAAUD,CAAW,GAAKA,EAC9ClG,GAAO,EACP,KACF,CACA,IAAK,MACHS,EAAOwF,CAAS,EAAIF,EAAG,UAAU/F,CAAG,EACpCA,GAAO,EACP,MACF,IAAK,OAAQ,CACX,KAAM,CAAE,KAAAkC,EAAM,IAAAqD,CAAI,EAAIhB,GAAiBpF,EAAOa,CAAG,EACjDS,EAAOwF,CAAS,EAAI/D,EACpBlC,EAAMuF,EACN,KACF,CACA,IAAK,MACH9E,EAAOwF,CAAS,EAAI/B,EAAW/E,EAAM,SAASa,CAAG,CAAC,EAAE,YAAY,EAChEA,EAAMb,EAAM,OACZ,MACF,IAAK,SACHsB,EAAOwF,CAAS,EAAI9B,EAAchF,EAAM,SAASa,CAAG,CAAC,EACrDA,EAAMb,EAAM,OACZ,MACF,IAAK,MACHsB,EAAOwF,CAAS,EAAI,IAAI,YAAY,EAAE,OAAO9G,EAAM,SAASa,CAAG,CAAC,EAChEA,EAAMb,EAAM,OACZ,MACF,IAAK,OACHsB,EAAOwF,CAAS,EAAI,IAAI,YAAY,EAAE,OAAO9G,EAAM,SAASa,CAAG,CAAC,EAChEA,EAAMb,EAAM,OACZ,MACF,IAAK,UAAW,CACd,MAAMiH,EAASjH,EAAMa,GAAK,EAC1BS,EAAOwF,CAAS,EAAI,IAAI,YAAY,EAAE,OAAO9G,EAAM,SAASa,EAAKA,EAAMoG,CAAM,CAAC,EAC9EpG,GAAOoG,EACP,KACF,CACA,IAAK,WAAY,CACf,MAAMA,EAASjH,EAAMa,GAAK,EAC1BS,EAAOwF,CAAS,EAAI,IAAI,YAAY,EAAE,OAAO9G,EAAM,SAASa,EAAKA,EAAMoG,CAAM,CAAC,EAC9EpG,GAAOoG,EACP,KACF,CACA,IAAK,WAAY,CAGf,MAAMnH,EAAQ,CAAC,EACf,KAAOe,EAAMb,EAAM,QAAQ,CACzB,MAAMiH,EAASjH,EAAMa,GAAK,EAC1B,GAAIA,EAAMoG,EAASjH,EAAM,OACvB,MAAM,IAAI,MAAM,sDAAsD,EAExEF,EAAM,KAAK,IAAI,YAAY,EAAE,OAAOE,EAAM,SAASa,EAAKA,EAAMoG,CAAM,CAAC,CAAC,EACtEpG,GAAOoG,CACT,CACA3F,EAAOwF,CAAS,EAAIhH,EAAM,OAAS,EAAIA,EAASA,EAAM,CAAC,GAAK,GAC5D,KACF,CACA,IAAK,YACHwB,EAAOwF,CAAS,EAAII,GAAkBlH,EAAM,SAASa,CAAG,CAAC,EACzDA,EAAMb,EAAM,OACZ,MACF,IAAK,OACHsB,EAAOwF,CAAS,EAAI,CAAC,GAAG9G,EAAM,SAASa,EAAKA,EAAM,CAAC,CAAC,EAAE,KAAK,GAAG,EAC9DA,GAAO,EACP,MACF,IAAK,OAAQ,CACX,MAAMf,EAAQ,CAAC,EACf,QAASqH,EAAI,EAAGA,EAAI,GAAIA,GAAK,EAC3BrH,EAAM,KACJ8G,EACG,UAAU/F,EAAMsG,CAAC,EACjB,SAAS,EAAE,EACX,SAAS,EAAG,GAAG,CACpB,EAEF7F,EAAOwF,CAAS,EAAIhH,EAAM,KAAK,GAAG,EAClCe,GAAO,GACP,KACF,CACA,QACES,EAAOwF,CAAS,EAAI9G,EAAMa,GAAK,EAC/B,KACJ,CACF,CAEA,OAAO,IAAII,EAAW,YAAYK,CAAM,CAC1C,CAIA,MAAM8F,GAAgB,CACpB,UAAW,EACX,KAAM,EACN,kBAAmB,EACnB,KAAM,EACN,SAAU,EACV,IAAK,EACL,SAAU,CACZ,EAKA,SAASC,GAAgBC,EAAW,CAClC,GAAI,CAACA,GAAa,CAACA,EAAU,KAAK,EAAG,OAAO,IAAI,WAAW,CAAC,EAE5D,MAAMxH,EAAQ,CAAC,EAET4B,EAAK,8CACX,IAAI6F,EACJ,MAAQA,EAAI7F,EAAG,KAAK4F,EAAU,KAAK,CAAC,KAAO,MAAM,CAC/C,MAAME,EAAMD,EAAE,CAAC,EAAE,YAAY,EACvB/F,EAAM+F,EAAE,CAAC,GAAKA,EAAE,CAAC,GAAK,GACtBE,EAAQL,GAAcI,CAAG,EAC/B,GAAIC,IAAU,OAAW,SAEzB,IAAIC,EACJ,GAAID,IAAU,EAAG,CAEf,MAAMlC,EAAM,IAAI,YACVoC,EAAUnG,EAAI,MAAM,GAAG,EAAE,IAAKoG,GAAMrC,EAAI,OAAOqC,EAAE,KAAK,CAAC,CAAC,EACxDC,EAAQF,EAAQ,OAAO,CAACnF,EAAGoF,IAAMpF,EAAI,EAAIoF,EAAE,OAAQ,CAAC,EAC1DF,EAAW,IAAI,WAAWG,CAAK,EAC/B,IAAIrC,EAAI,EACR,UAAWoC,KAAKD,EACdD,EAASlC,GAAG,EAAIoC,EAAE,OAClBF,EAAS,IAAIE,EAAGpC,CAAC,EACjBA,GAAKoC,EAAE,MAEX,SAAWH,IAAU,EAEnBC,EAAW,IAAI,WAAW,CAAC,UAClBD,IAAU,EAEnBC,EAAW,IAAI,WAAW,CAAC,EAC3B,IAAI,SAASA,EAAS,MAAM,EAAE,UAAU,EAAG,SAASlG,EAAK,EAAE,CAAC,UACnDiG,IAAU,EAAG,CAEtB,MAAMK,EAAQtG,EAAI,MAAM,GAAG,EAAE,IAAKuG,GAAMA,EAAE,KAAK,EAAE,MAAM,GAAG,EAAE,IAAI,MAAM,CAAC,EACvEL,EAAW,IAAI,WAAWI,EAAM,OAAS,CAAC,EAC1CA,EAAM,QAAQ,CAACE,EAAMzG,IAAMyG,EAAK,QAAQ,CAACvD,EAAG0C,IAAOO,EAASnG,EAAI,EAAI4F,CAAC,EAAI1C,CAAE,CAAC,CAC9E,SAAWgD,IAAU,EAEnBC,EAAWzC,EAAczD,CAAG,UACnBiG,IAAU,EAAG,CAEtB,MAAMK,EAAQtG,EAAI,MAAM,GAAG,EAAE,IAAKuG,GAAMnD,EAAWT,GAAW4D,EAAE,KAAK,EAAG,EAAE,CAAC,CAAC,EAC5EL,EAAW,IAAI,WAAWI,EAAM,OAAS,EAAE,EAC3CA,EAAM,QAAQ,CAACE,EAAMzG,IAAMmG,EAAS,IAAIM,EAAMzG,EAAI,EAAE,CAAC,CACvD,MACEmG,EAAW,IAAI,YAAY,EAAE,OAAOlG,CAAG,EAGzC,MAAMyG,EAAQ,IAAI,WAAW,EAAIP,EAAS,MAAM,EAChD,IAAI,SAASO,EAAM,MAAM,EAAE,UAAU,EAAGR,CAAK,EAC7C,IAAI,SAASQ,EAAM,MAAM,EAAE,UAAU,EAAGP,EAAS,MAAM,EACvDO,EAAM,IAAIP,EAAU,CAAC,EACrB5H,EAAM,KAAKmI,CAAK,CAClB,CAGAnI,EAAM,KAAK,CAACiI,EAAGtD,IAAM,IAAI,SAASsD,EAAE,MAAM,EAAE,UAAU,CAAC,EAAI,IAAI,SAAStD,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC,EAE9F,MAAMoD,EAAQ/H,EAAM,OAAO,CAAC0C,EAAGgD,IAAMhD,EAAIgD,EAAE,OAAQ,CAAC,EAC9ClE,EAAS,IAAI,WAAWuG,CAAK,EACnC,IAAIhH,EAAM,EACV,UAAW2E,KAAK1F,EACdwB,EAAO,IAAIkE,EAAG3E,CAAG,EACjBA,GAAO2E,EAAE,OAEX,OAAOlE,CACT,CAEA,MAAM4G,GAAqB,CACzB,EAAG,YACH,EAAG,OACH,EAAG,kBACH,EAAG,OACH,EAAG,WACH,EAAG,MACH,EAAG,UACL,EAKA,SAAShB,GAAkBvC,EAAO,CAChC,GAAI,CAACA,GAASA,EAAM,SAAW,EAAG,MAAO,GACzC,MAAM7E,EAAQ,CAAC,EACf,IAAIe,EAAM,EACV,KAAOA,EAAM,GAAK8D,EAAM,QAAQ,CAC9B,MAAMiC,EAAK,IAAI,SAASjC,EAAM,OAAQA,EAAM,WAAa9D,CAAG,EACtD4G,EAAQb,EAAG,UAAU,CAAC,EACtBuB,EAASvB,EAAG,UAAU,CAAC,EACvBpF,EAAMmD,EAAM,SAAS9D,EAAM,EAAGA,EAAM,EAAIsH,CAAM,EACpDtH,GAAO,EAAIsH,EAEX,MAAMC,EAAUF,GAAmBT,CAAK,GAAK,MAAMA,CAAK,GACxD,GAAIA,IAAU,EAAG,CAEf,MAAME,EAAU,CAAC,EACjB,IAAInC,EAAI,EACR,KAAOA,EAAIhE,EAAI,QAAQ,CACrB,MAAMT,EAAMS,EAAIgE,GAAG,EACnBmC,EAAQ,KAAK,IAAI,YAAY,EAAE,OAAOnG,EAAI,SAASgE,EAAGA,EAAIzE,CAAG,CAAC,CAAC,EAC/DyE,GAAKzE,CACP,CACAjB,EAAM,KAAK,SAAS6H,EAAQ,KAAK,GAAG,CAAC,GAAG,CAC1C,SAAWF,IAAU,EACnB3H,EAAM,KAAK,iBAAiB,UACnB2H,IAAU,EACnB3H,EAAM,KAAK,QAAQ,IAAI,SAAS0B,EAAI,OAAQA,EAAI,UAAU,EAAE,UAAU,CAAC,CAAC,EAAE,UACjEiG,IAAU,EAAG,CACtB,MAAMK,EAAQ,CAAC,EACf,QAASvG,EAAI,EAAGA,EAAIC,EAAI,OAAQD,GAAK,EAAGuG,EAAM,KAAK,CAAC,GAAGtG,EAAI,SAASD,EAAGA,EAAI,CAAC,CAAC,EAAE,KAAK,GAAG,CAAC,EACxFzB,EAAM,KAAK,YAAYgI,EAAM,KAAK,GAAG,CAAC,EAAE,CAC1C,SAAWL,IAAU,EACnB3H,EAAM,KAAK,OAAO,KAAK,CAAC,GAAG0B,CAAG,EAAE,IAAKiD,GAAM,OAAO,aAAaA,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,UACrEgD,IAAU,EAAG,CACtB,MAAMK,EAAQ,CAAC,EACf,QAASvG,EAAI,EAAGA,EAAIC,EAAI,OAAQD,GAAK,GAAI,CACvC,MAAM8G,EAAO,IAAI,SAAS7G,EAAI,OAAQA,EAAI,WAAaD,CAAC,EAClD+G,EAAS,CAAC,EAChB,QAASnB,EAAI,EAAGA,EAAI,GAAIA,GAAK,EAAGmB,EAAO,KAAKD,EAAK,UAAUlB,CAAC,EAAE,SAAS,EAAE,EAAE,SAAS,EAAG,GAAG,CAAC,EAC3FW,EAAM,KAAKQ,EAAO,KAAK,GAAG,CAAC,CAC7B,CACAxI,EAAM,KAAK,YAAYgI,EAAM,KAAK,GAAG,CAAC,EAAE,CAC1C,MACEhI,EAAM,KAAK,GAAGsI,CAAO,IAAI,CAAC,GAAG5G,CAAG,EAAE,IAAKiD,GAAMA,EAAE,SAAS,EAAE,EAAE,SAAS,EAAG,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAE5F,CACA,OAAO3E,EAAM,KAAK,GAAG,CACvB,CAEA,SAASyI,GAAc5C,EAAME,EAAW,CACtC,MAAMhD,EAAM,CACV,MAAO,KACP,KAAM,GACN,MAAO,CAAC,CACV,EAGA,IAAI2F,EAAY,GACZC,EAAU,GACd,QAASlH,EAAI,EAAGA,EAAIoE,EAAK,OAAQpE,IAAK,CACpC,MAAMf,EAAImF,EAAKpE,CAAC,EAEhB,GADIf,IAAM,MAAKiI,EAAU,CAACA,GACtBjI,IAAM,KAAO,CAACiI,EAAS,MAC3BD,GAAahI,CACf,CAEA,GADAgI,EAAYA,EAAU,KAAK,EACvB,CAACA,EAAW,OAAO,KAGvB,MAAME,EAASF,EAAU,MAAM,cAAc,GAAK,CAAC,EACnD,GAAIE,EAAO,OAAS,EAAG,OAAO,KAQ9B,IALK,MAAM,KAAK/C,CAAI,IAClB9C,EAAI,MAAQ6F,EAAO,MAAM,GAIpBA,EAAO,OAAS,GAAG,CACxB,MAAMC,EAAQD,EAAO,CAAC,EAAE,YAAY,EAEpC,GAAI7C,EAAU8C,CAAK,EAAG,CACpB9F,EAAI,MAAQ6F,EAAO,MAAM,EAAE,YAAY,EACvC,QACF,CAEA,GAAI,QAAQ,KAAKC,CAAK,EAAG,CACvB9F,EAAI,IAAM,SAAS6F,EAAO,MAAM,EAAG,EAAE,EACrC,QACF,CAGA7F,EAAI,KAAO6F,EAAO,MAAM,EAAE,YAAY,EACtC,KACF,CAGA,OAAA7F,EAAI,MAAQ6F,EAEL7F,CACT,CAEA,SAAS+F,GAAS3H,EAAY4H,EAAM,CAClC,KAAM,CAAE,MAAA9I,EAAO,IAAAE,EAAK,IAAAsG,EAAK,MAAAvG,CAAM,EAAI6I,EAC7BvH,EAAS,CACb,MAAAvB,EACA,IAAAE,EACA,MAAOsG,EACP,KAAMtF,EAAW,YAAY,QAC/B,EAEMI,EAASJ,EAAW,UAAU,OAAO,EACrC6H,EAAY7H,EAAW,YAAY,aAAe,CAAC,EACzD,QAASM,EAAI,EAAGA,EAAIF,EAAO,OAAQE,IAAK,CAEtC,GADoBA,IAAMF,EAAO,OAAS,GACvBJ,EAAW,cAAcI,EAAOE,CAAC,CAAC,EAAG,CAEtD,MAAMmH,EAAS1I,EAAM,MAAMuB,CAAC,EAAE,IAAKiB,GAAMA,EAAE,QAAQ,SAAU,EAAE,CAAC,EAG1DuG,EAAMD,EAAUvH,CAAC,EACjByH,EAAY,MAAM,QAAQD,CAAG,EAAIA,EAAI,CAAC,EAAI,KAChDzH,EAAOD,EAAOE,CAAC,CAAC,EAAIyH,IAAc,YAAcN,EAAO,OAAS,EAAIA,EAASA,EAAO,KAAK,EAAE,EAC3F,KACF,CAEA,IAAIlH,EAAMxB,EAAMuB,CAAC,EACbN,EAAW,cAAcI,EAAOE,CAAC,CAAC,EACpCC,EAAMA,GAAK,QAAQ,SAAU,EAAE,EACtB,QAAQ,KAAKA,CAAG,IACzBA,EAAM,SAASA,EAAK,EAAE,GAExBF,EAAOD,EAAOE,CAAC,CAAC,EAAIC,CACtB,CAEA,OAAO,IAAIP,EAAW,YAAYK,CAAM,CAC1C,CAEA,SAAS2H,GAAOhI,EAAYiI,EAAW,CAErC,MAAMlJ,EADSiB,EAAW,UAAU,OAAO,EAExC,IAAKC,GAAOD,EAAW,YAAYC,CAAC,EAAID,EAAW,QAAQC,EAAGgI,CAAS,EAAIjI,EAAW,UAAUC,CAAC,CAAE,EACnG,KAAK,GAAI,EACZ,MAAO,GAAGD,EAAW,UAAUiI,CAAS,CAAC,IAAKlJ,CAAK;AAAA,CACrD,CAEA,MAAMmJ,GAAgB,OAAO,IAAI,4BAA4B,EAE7D,MAAMC,CAAG,CACP,OAAO,QAAU,CAAE,GAAI,EAAG,GAAI,EAAG,GAAI,EAAG,GAAI,EAAG,KAAM,IAAK,IAAK,GAAI,EACnE,OAAO,OACP,OAAO,KAAO,CAAC,EACf,OAAO,KAAO,CAAC,EAEf,YAAYP,EAAM,CAChB,GAAIA,IAAS,KAEb,CAAIA,GAAM,UAAS,KAAK,QAAUA,EAAK,SAGvC,KAAK,YAAYA,GAAM,QAAQ,EAC/B,KAAK,aAAaA,GAAM,SAAS,EAEjC,KAAK,SAASA,GAAM,KAAK,EACzB,KAAK,QAAQA,GAAM,IAAI,EACvB,KAAK,OAAOA,GAAM,GAAG,EACrB,KAAK,SAASA,GAAM,KAAK,EAEzB,UAAWhC,KAAS,KAAK,YAAY,aAAe,CAAC,EAAG,CACtD,MAAM3F,EAAIkI,EAAG,UAAUvC,CAAK,EACtBmC,EAAY,MAAM,QAAQnC,CAAK,EAAIA,EAAM,CAAC,EAAI,KAC9CwC,EAAS,MAAM,KAAK,QAAQnI,CAAC,CAAC,GAChC,OAAO,KAAKmI,CAAM,GAAM,WAC1B,KAAKA,CAAM,EAAER,IAAO3H,CAAC,CAAC,EACb8H,EACT,KAAK,cAAcA,EAAW9H,EAAG2H,IAAO3H,CAAC,CAAC,EAE1C,KAAK,IAAIA,EAAG2H,IAAO3H,CAAC,CAAC,CAEzB,CAEI2H,GAAM,SAAS,KAAK,IAAI,UAAWA,EAAK,OAAO,EACrD,CAEA,OAAO,SAASlD,EAAMkD,EAAO,CAAC,EAAG,CAC/B,MAAM1C,EAAW,IAAI,KAAK,IAAI,EAC1B0C,EAAK,UAAY,SAAW1C,EAAS,QAAU0C,EAAK,SACxD,MAAMS,EAAS,KAAK,cAAc3D,CAAI,EACtC,OAAK2D,EACEnD,EAAS,SAAS,CAAE,GAAG0C,EAAM,GAAGS,EAAQ,SAAU3D,CAAK,CAAC,EAD3C,IAEtB,CAEA,SAASkD,EAAM,CACb,OAAOD,GAAS,KAAMC,CAAI,CAC5B,CAEA,OAAO,cAAclD,EAAM,CACzB,OAAO4C,GAAc5C,EAAMyD,EAAG,OAAO,CACvC,CAEA,OAAO,YAAYzD,EAAMkD,EAAO,CAAC,EAAG,CAClC,MAAM1C,EAAW,IAAI,KAAK,IAAI,EAC9B,OAAI0C,EAAK,UAAY,SAAW1C,EAAS,QAAU0C,EAAK,SACjD1C,EAAS,YAAY,CAAE,GAAG0C,EAAM,SAAUlD,CAAK,CAAC,CACzD,CAEA,YAAYkD,EAAM,CAChB,OAAOzH,GAAY,KAAMyH,CAAI,CAC/B,CAEA,OAAO,SAAS5C,EAAW,CACzB,OAAOF,GAAc,KAAME,EAAWb,EAAgB,CACxD,CAEA,SAASyD,EAAM,CACb,OAAOnC,GAAgB,KAAMmC,CAAI,CACnC,CAEA,MAAOU,GAAY,CAAC,YAAa,cAAe,WAAW,EAE3D,IAAI/B,EAAK,CACP,GAAI4B,EAAGG,GAAU,SAAS/B,CAAG,EAAG,MAAM,IAAI,MAAM,uBAAuBA,CAAG,EAAE,EAC5E,OAAO,KAAKA,CAAG,CACjB,CAEA,IAAIA,EAAKlE,EAAO,CACd,GAAI8F,EAAGG,GAAU,SAAS/B,CAAG,EAAG,MAAM,IAAI,MAAM,uBAAuBA,CAAG,EAAE,EAC5E,YAAKA,CAAG,EAAIlE,EACL,IACT,CAEA,QAAS,CACP,MAAMjC,EAAS,CAAC,GAAG,KAAK,UAAU,EAAG,WAAY,YAAa,SAAS,EACjEmI,EAAM,CAAC,EACb,UAAWtI,KAAKG,EAAQ,CACtB,MAAMoI,EAAI,KAAK,IAAIvI,CAAC,EAChBuI,IAAM,SAAWD,EAAItI,CAAC,EAAIuI,EAChC,CACA,OAAOD,CACT,CAEA,CAACL,EAAa,EAAEO,EAAOC,EAASC,EAAa,CAE3C,MAAO,GAAG,KAAK,IAAI,IAAIA,EAAY,KAAK,OAAO,EAAGD,CAAO,CAAC,EAC5D,CAEA,QAAQhI,EAAK,CACX,OAAKA,GACEA,EACJ,MAAM,IAAI,EACV,IAAKkI,GAAMA,EAAE,OAAO,CAAC,EAAE,YAAY,EAAIA,EAAE,MAAM,CAAC,CAAC,EACjD,KAAK,EAAE,CACZ,CAEA,SAASrJ,EAAG,CACV,GAAI,CAAC,OAAW,KAAM,EAAE,EAAE,SAASA,CAAC,EAAG,CACrC,KAAK,IAAI,QAAS,IAAI,EACtB,MACF,CACA,GAAI4I,EAAG,QAAQ5I,EAAE,YAAY,CAAC,EAAG,CAC/B,KAAK,IAAI,QAASA,EAAE,YAAY,CAAC,EACjC,MACF,CACA,KAAK,UAAU,iBAAiBA,CAAC,EAAE,CACrC,CAEA,YAAYsJ,EAAG,CACLA,IACD,QAGH,KAAK,IAAI,WAAYA,CAAC,CAE5B,CAEA,aAAaA,EAAG,CACNA,IACD,QAGH,KAAK,IAAI,YAAaA,CAAC,CAE7B,CAEA,SAASnG,EAAG,CACNA,IAAM,QAAW,KAAK,UAAU,mBAAmB,GAEnDA,EAAE,OAAS,GAAKA,EAAE,OAAS,MAC7B,KAAK,UAAU,4DAA4D,EAE7E,KAAK,iBAAiB,KAAK,YAAY,UAAY,KAAK,YAAY,KAAM,QAASA,CAAC,EACpF,KAAK,eAAeA,CAAC,EAGjB,KAAK,KAAKA,CAAC,GACT,CAAC,QAAQ,KAAKA,CAAC,GAAK,CAAC,SAAS,KAAKA,CAAC,GACtC,KAAK,UAAU,uDAAuD,EAG1E,KAAK,IAAI,QAASA,EAAE,YAAY,CAAC,CACnC,CAEA,OAAO,EAAG,CAER,GADA,EAAI,GAAK,KAAK,SAAS,IACnB,IAAM,OAAW,CACnB,GAAI,CAAC,MAAO,QAAS,OAAO,EAAE,SAAS,KAAK,IAAI,MAAM,CAAC,EAAG,OAC1D,KAAK,UAAU,uCAAuC,CACxD,CAEI,OAAO,GAAM,UAAU,KAAK,UAAU,wBAAwB,OAAO,CAAC,GAAG,EAG7E,KAAK,WAAW,KAAK,IAAI,MAAM,EAAG,MAAO,CAAC,EAE1C,KAAK,IAAI,MAAO,CAAC,CACnB,CAEA,QAAQ,EAAG,CACL,CAAC,OAAW,EAAE,EAAE,SAAS,CAAC,IAAG,EAAI,KAAK,YAAY,UAElD,IAAM,QAAW,KAAK,UAAU,kBAAkB,EAElD,EAAE,YAAY,IAAM,KAAK,YAAY,UACvC,KAAK,UAAU,QAAQ,CAAC,kBAAkB,KAAK,YAAY,QAAQ,EAAE,EAEvE,KAAK,IAAI,OAAQ,EAAE,YAAY,CAAC,CAClC,CAEA,UAAUiE,EAAG,CACX,GAAI,CAAC,KAAK,YAAY,SAAU,MAAM,IAAI,MAAMA,CAAC,EAEjD,MAAMmC,EAAW,KAAK,YAAY,SAC5BC,EAAU,KAAK,aACjB,WAAWD,CAAQ;AAAA,EAAM,KAAK,UAAU,KAAK,aAAa,EAAG,KAAM,GAAI,CAAC;AAAA;AAAA,EACxE,GAAGA,CAAQ,6BAA6B,KAAK,UAAU,EAAE,KAAK,IAAI,CAAC;AAAA;AAAA,EAEvE,MAAM,IAAI,MAAM,GAAGnC,CAAC;AAAA;AAAA,EAAOoC,CAAO,GAAG,KAAK,QAAQ,CAAC;AAAA,CAAI,CACzD,CAEA,SAAU,CACR,MAAO,UAAU,KAAK,QAAQ,EAAE,OAAS,EAAI,IAAM,EAAE,IAAI,KAAK,QAAQ,CAAC,EACzE,CAEA,aAAaC,EAAUC,EAAQ,CAC7B,OAAKD,IACDA,IAAa,KAAOC,IAAQD,EAAWC,GACvCD,EAAS,SAAS,GAAG,EAAUA,EAAS,YAAY,EACpDC,EAAe,GAAGD,CAAQ,IAAIC,CAAM,GAAG,YAAY,EAChD,GAAGD,CAAQ,IACpB,CAEA,UAAUf,EAAY,CAAC,EAAG,CACxB,MAAMiB,EAAWjB,EAAU,MAAM,MAAQ,GAAK,KAAK,IAAI,OAAO,EAE9D,IAAIkB,EAAQ,KAAK,IAAI,KAAK,EACtBlB,EAAU,MAAM,KAAOkB,IAAUlB,EAAU,MAAKkB,EAAQ,IAE5D,IAAIrK,EAAQ,KAAK,IAAI,OAAO,EAC5B,OAAImJ,EAAU,MAAM,WAAaA,EAAU,gBAAkBnJ,EAC3DA,EAAQ,GAERA,EAAQ,KAAK,QAAQ,QAASmJ,CAAS,EAGlC,GAAGnJ,CAAK,IAAKqK,CAAK,IAAKD,CAAQ,IAAK,KAAK,IAAI,MAAM,CAAC,EAC7D,CAEA,SAASE,EAAM,CACb,OAAO,KAAK,IAAIA,CAAI,GAAK,EAC3B,CAEA,WAAWA,EAAM,CACf,MAAM7J,EAAI,KAAK,IAAI,SAAS,EAC5B,MAAI,CAACA,GAAK,CAACA,EAAE6J,CAAI,EAAU,GACpB7J,EAAE6J,CAAI,CACf,CAEA,UAAUA,EAAM,CAEd,OAAK,KAAK,cAAcA,CAAI,EAGxB,OAAO,KAAK,KAAK,IAAIA,CAAI,EAAE,CAAC,CAAC,EAAU,KAAK,IAAIA,CAAI,EAEjD,IAAI,KAAK,IAAIA,CAAI,CAAC,IALa,KAAK,IAAIA,CAAI,CAMrD,CAEA,OAAO,UAAUxD,EAAO,CACtB,OAAO,MAAM,QAAQA,CAAK,EAAIA,EAAM,CAAC,EAAIA,CAC3C,CAEA,OAAO,UAAUA,EAAO,CACtB,OAAO,MAAM,QAAQA,CAAK,EAAIA,EAAM,CAAC,EAAI,IAC3C,CAEA,gBAAiB,CACf,OAAQ,KAAK,YAAY,aAAe,CAAC,GAAG,IAAKe,GAAMwB,EAAG,UAAUxB,CAAC,CAAC,CACxE,CAEA,SAAU,CACR,OAAO,KAAK,YAAY,MAAQ,CAAC,CACnC,CAEA,SAAU,CACR,OAAO,KAAK,YAAY,MAAQ,CAAC,CACnC,CAEA,WAAY,CACV,MAAMvH,EAAS,KAAK,YAAY,OAChC,OAAIA,IAAW,QAAW,KAAK,UAAU,GAAG,KAAK,YAAY,QAAQ,yBAAyB,EACvFA,CACT,CAEA,OAAO,WAAY,CACjB,OAAO,KAAK,MACd,CAEA,UAAUiK,EAAK,CACb,MAAMC,EAAe,CAAC,QAAS,MAAO,QAAS,MAAM,EACrD,OAAO,OAAOA,CAAY,EAE1B,MAAM5D,EAAc,KAAK,eAAe,EAExC,OAAQ2D,EAAK,CACX,IAAK,SACH,OAAOC,EACT,IAAK,QACH,OAAO5D,EACT,QACE,OAAO4D,EAAa,OAAO5D,CAAW,CAC1C,CACF,CAEA,QAAQ6D,EAAOtB,EAAY,CAAC,EAAG,CAC7B,IAAInG,EAAO,KAAK,IAAIyH,CAAK,EAIzB,GAHKzH,GAAM,KAAK,UAAU,yBAAyByH,CAAK,EAAE,EACrDzH,EAAK,SAAS,GAAG,IAAGA,GAAQ,KAE7BmG,EAAU,MAAM,QAAUA,EAAU,OAAQ,CAC9C,GAAInG,IAASmG,EAAU,OAAQ,MAAO,IACtC,GAAInG,EAAK,SAASmG,EAAU,MAAM,EAAG,OAAOnG,EAAK,MAAM,EAAGA,EAAK,OAASmG,EAAU,OAAO,OAAS,CAAC,CACrG,CAEA,OAAOnG,CACT,CAEA,YAAYyH,EAAO,CACjB,MAAMhJ,EAAM,KAAK,IAAIgJ,CAAK,EAE1B,OADIhJ,IAAQ,IACRA,IAAQ,IAAYA,EAGpBA,EAAI,SAAS,GAAG,EAAUA,EAAI,MAAM,EAAG,EAAE,EAEtCA,CACT,CAEA,kBAAkBxB,EAAO,CACvB,MAAO,IAAI,KAAK,YAAY,OAAO,CAAC,IAAI,KAAK,UAAU,CAAC,IAAIA,CAAK,IAAI,KAAK,oBAAoB,CAAC;AAAA,CACjG,CAEA,qBAAsB,CACpB,MAAO,CAAC,MAAO,YAAa,UAAU,EAAE,IAAKkB,GAAM,KAAK,SAASA,CAAC,CAAC,EAAE,KAAK,GAAG,CAC/E,CAEA,eAAe+I,EAAU,CAKvB,MAAMQ,EAAKR,EAAS,SAAS,GAAG,EAAIA,EAAS,MAAM,EAAG,EAAE,EAAIA,EAC5D,UAAW/G,KAASuH,EAAG,MAAM,GAAG,GAC1BvH,EAAM,OAAS,GAAKA,EAAM,OAAS,KACrC,KAAK,UAAU,qDAAqD,CAE1E,CAEA,UAAUwH,EAAMF,EAAOlH,EAAO,CAC5B,GAAI,OAAO,UAAUA,CAAK,GAAKA,GAAS,GAAKA,GAAS,IAAK,MAAO,GAElE,KAAK,UAAU,GAAGoH,CAAI,IAAIF,CAAK,+CAA+C,CAChF,CAEA,WAAWE,EAAMF,EAAOlH,EAAO,CAC7B,GAAI,OAAO,UAAUA,CAAK,GAAKA,GAAS,GAAKA,GAAS,MAAO,MAAO,GAEpE,KAAK,UAAU,GAAGoH,CAAI,IAAIF,CAAK,kDAAkD,CACnF,CAEA,WAAWE,EAAMF,EAAOlH,EAAO,CAC7B,GAAI,OAAO,UAAUA,CAAK,GAAKA,GAAS,GAAKA,GAAS,WAAY,MAAO,GAEzE,KAAK,UAAU,GAAGoH,CAAI,IAAIF,CAAK,uDAAuD,CACxF,CAEA,SAASE,EAAMF,EAAOlH,EAAO,CAC3B,GACE,OAAOA,GAAU,UACjBA,EAAM,OAAS,GACfA,EAAM,OAAS,IAAM,GACrB,yBAAyB,KAAKA,CAAK,EAEnC,MAAO,GAET,KAAK,UAAU,GAAGoH,CAAI,IAAIF,CAAK,gCAAgC,CACjE,CAEA,SAAShJ,EAAK,CACZ,MAAO,QAAQ,KAAKA,CAAG,GAAK,QAAQ,KAAKA,CAAG,CAC9C,CAEA,aAAauI,EAAUjD,EAAWtF,EAAK,CAChCA,GAAK,KAAK,UAAU,GAAGuI,CAAQ,KAAKjD,CAAS,cAAc,GAC5D,KAAK,OAAOtF,CAAG,GAAK,KAAK,OAAOA,CAAG,IACrC,KAAK,UAAU,GAAGuI,CAAQ,KAAKjD,CAAS,wBAAwB,EAClE,KAAK,iBAAiBiD,EAAUjD,EAAWtF,CAAG,EAC9C,KAAK,gBAAgBuI,EAAUjD,EAAWtF,CAAG,EAC7C,KAAK,IAAIsF,EAAWtF,EAAI,YAAY,CAAC,CACvC,CAEA,cAAckJ,EAAM5D,EAAWtF,EAAK,CAClC,MAAMuI,EAAW,KAAK,YAAY,SAClC,OAAQW,EAAM,CACZ,IAAK,KACH,KAAK,UAAUX,EAAUjD,EAAWtF,CAAG,EACvC,KAAK,IAAIsF,EAAW,SAAStF,EAAK,EAAE,CAAC,EACrC,MACF,IAAK,MACH,KAAK,WAAWuI,EAAUjD,EAAWtF,CAAG,EACxC,KAAK,IAAIsF,EAAW,SAAStF,EAAK,EAAE,CAAC,EACrC,MACF,IAAK,WAAY,CAGf,IAFyBA,GAAQ,MAAQA,IAAQ,KAC/C,KAAK,UAAU,GAAGuI,CAAQ,KAAKjD,CAAS,cAAc,EACpD,OAAOtF,GAAQ,UAAY,CAAC,WAAW,KAAKA,CAAG,EAAG,CACpD,MAAMmJ,EAAY,KAAK,YAAY,YAC/B,CAACA,GAAa,CAAC,OAAO,OAAOA,EAAWnJ,CAAG,IAC7C,KAAK,UAAU,GAAGuI,CAAQ,iCAAiCvI,CAAG,EAAE,EAElE,KAAK,IAAIsF,EAAWtF,CAAG,EACvB,KACF,CACA,KAAK,WAAWuI,EAAUjD,EAAWtF,CAAG,EACxC,KAAK,IAAIsF,EAAW,SAAStF,EAAK,EAAE,CAAC,EACrC,KACF,CACA,IAAK,MACH,KAAK,WAAWuI,EAAUjD,EAAWtF,CAAG,EACxC,KAAK,IAAIsF,EAAW,SAAStF,EAAK,EAAE,CAAC,EACrC,MACF,IAAK,OACH,KAAK,aAAauI,EAAUjD,EAAWtF,CAAG,EAC1C,MACF,IAAK,SACH,KAAK,SAASuI,EAAUjD,EAAWtF,CAAG,EACtC,KAAK,IAAIsF,EAAWtF,CAAG,EACvB,MACF,IAAK,MACE,iBAAiB,KAAKA,CAAG,GAAG,KAAK,UAAU,GAAGuI,CAAQ,KAAKjD,CAAS,sBAAsB,EAC/F,KAAK,IAAIA,EAAWtF,CAAG,EACvB,MACF,IAAK,MACEA,GAAK,KAAK,UAAU,GAAGuI,CAAQ,KAAKjD,CAAS,cAAc,EAChE,KAAK,IAAIA,EAAWtF,CAAG,EACvB,MACF,IAAK,OACsBA,GAAQ,MAAM,KAAK,UAAU,GAAGuI,CAAQ,KAAKjD,CAAS,cAAc,EAC7F,KAAK,IAAIA,EAAWtF,CAAG,EACvB,MACF,IAAK,UAAW,CACWA,GAAQ,MAAM,KAAK,UAAU,GAAGuI,CAAQ,KAAKjD,CAAS,cAAc,EAC7F,MAAMxD,EAAQ,OAAO9B,CAAG,EACR,IAAI,YAAY,EAAE,OAAO8B,CAAK,EAAE,OAClC,KAAK,KAAK,UAAU,GAAGyG,CAAQ,KAAKjD,CAAS,sBAAsB,EACjF,KAAK,IAAIA,EAAWxD,CAAK,EACzB,KACF,CACA,IAAK,WAAY,CACU9B,GAAQ,MAAM,KAAK,UAAU,GAAGuI,CAAQ,KAAKjD,CAAS,cAAc,EAC7F,MAAMxD,EAAQ,OAAO9B,CAAG,EACR,IAAI,YAAY,EAAE,OAAO8B,CAAK,EAAE,OAClC,KAAK,KAAK,UAAU,GAAGyG,CAAQ,KAAKjD,CAAS,sBAAsB,EACjF,KAAK,IAAIA,EAAWxD,CAAK,EACzB,KACF,CACA,IAAK,WACsB9B,GAAQ,MAAM,KAAK,UAAU,GAAGuI,CAAQ,KAAKjD,CAAS,cAAc,EAC7F,KAAK,IAAIA,EAAWtF,CAAG,EACvB,MACF,IAAK,YACsBA,GAAQ,MAAM,KAAK,UAAU,GAAGuI,CAAQ,KAAKjD,CAAS,cAAc,EAC7F,KAAK,IAAIA,EAAWtF,CAAG,EACvB,MACF,IAAK,OACE,KAAK,OAAOA,CAAG,GAAG,KAAK,UAAU,GAAGuI,CAAQ,KAAKjD,CAAS,+BAA+B,EAC9F,KAAK,IAAIA,EAAWtF,CAAG,EACvB,MACF,IAAK,OACE,KAAK,OAAOA,CAAG,GAAG,KAAK,UAAU,GAAGuI,CAAQ,KAAKjD,CAAS,+BAA+B,EAC9F,KAAK,IAAIA,EAAW,KAAK,WAAWtF,EAAI,YAAY,CAAC,CAAC,EACtD,KACJ,CACF,CAEA,iBAAiBkJ,EAAMF,EAAOP,EAAU,CACtC,GAAIA,EAAS,SAAS,GAAG,EAAG,MAAO,GAEnC,KAAK,UAAU,GAAGS,CAAI,KAAKF,CAAK,0BAA0B,CAC5D,CAEA,gBAAgBE,EAAMF,EAAOP,EAAU,CACrC,MAAMW,EAAU,IAAI,OAAO,qBAAqB,EAChD,GAAI,CAACA,EAAQ,KAAKX,CAAQ,EAAG,MAAO,GAEpC,MAAMY,EAAUD,EAAQ,KAAKX,CAAQ,EACrC,KAAK,UAAU,GAAGS,CAAI,KAAKF,CAAK,oCAAoCK,EAAQ,CAAC,CAAC,GAAG,CACnF,CAEA,OAAOC,EAAQ,CAEb,MAAO,8CAA8C,KAAKA,CAAM,CAClE,CAEA,OAAOA,EAAQ,CACb,MAAO,woCAAwoC,KAC7oCA,CACF,CACF,CAEA,WAAWtJ,EAAK4C,EAAW,CACzB,OAAOD,GAAW3C,EAAK4C,CAAS,CAClC,CAEA,aAAa5C,EAAK,CAShB,MAAMuJ,EAAWvJ,EACd,YAAY,EACZ,MAAM,GAAG,EACT,IAAKgB,GAAMA,EAAE,QAAQ,MAAO,EAAE,GAAK,GAAG,EAEzC,IAAIwI,EAAY,GACZC,EAAU,EACVC,EAAW,GACXC,EAAS,EAGb,QAAS5J,EAAI,EAAGA,EAAIwJ,EAAS,OAAQxJ,IAC/BwJ,EAASxJ,CAAC,IAAM,KACd2J,IAAa,KAAIA,EAAW3J,GAChC4J,IACIA,EAASF,IACXA,EAAUE,EACVH,EAAYE,KAGdA,EAAW,GACXC,EAAS,GAKb,GAAIF,EAAU,EACZ,OAAOF,EAAS,KAAK,GAAG,EAG1B,MAAMK,EAAOL,EAAS,MAAM,EAAGC,CAAS,EAAE,KAAK,GAAG,EAC5CK,EAAON,EAAS,MAAMC,EAAYC,CAAO,EAAE,KAAK,GAAG,EAEzD,MAAO,GAAGG,CAAI,KAAKC,CAAI,EACzB,CAEA,kBAAkBC,EAAU,CAC1B,MAAM3J,EAAMpB,EAAY+K,CAAQ,EAChC,OAAO,WAAW,KAAK3J,EAAMnB,GAAMA,EAAE,WAAW,CAAC,CAAC,CACpD,CAEA,iBAAiBmE,EAAOU,EAAS,EAAG,CAClC,OAAOD,GAAiBT,EAAOU,CAAM,CACvC,CAEA,eAAetC,EAAM,CACnB,OAAOuC,EAAevC,CAAI,CAC5B,CAEA,cAAe,CACb,OAAO2C,GAAa,IAAI,CAC1B,CAEA,QAAS,CACP,OAAOE,GAAO,KAAMwD,EAAG,OAAO,CAChC,CAEA,OAAOF,EAAW,CAChB,OAAOD,GAAO,KAAMC,CAAS,CAC/B,CAEA,iBAAiBtJ,EAAU,CACzB,MAAM0J,EAASlJ,GAAiBR,CAAQ,EACxC,MAAO,CAAE,GAAG0J,EAAQ,MAAO,KAAK,aAAaA,EAAO,KAAK,CAAE,CAC7D,CAEA,WAAY,CACV,OAAOtI,GAAG,IAAI,CAChB,CAEA,YAAYwJ,EAAO,CACjB,OACG,KAAK,YAAY,aAAe,CAAC,GAAG,KAClC3D,GAAUuC,EAAG,UAAUvC,CAAK,IAAM2D,GAASpB,EAAG,UAAUvC,CAAK,IAAM,MACtE,GAAK,EAET,CAEA,cAAc2D,EAAO,CACnB,MAAMe,EAAc,IAAI,IAAI,CAAC,OAAQ,WAAY,UAAU,CAAC,EAC5D,OACG,KAAK,YAAY,aAAe,CAAC,GAAG,KAClC1E,GAAUuC,EAAG,UAAUvC,CAAK,IAAM2D,GAASe,EAAY,IAAInC,EAAG,UAAUvC,CAAK,CAAC,CACjF,GAAK,EAET,CAEA,WAAY,CACV,MAAM6D,EAAO,KAAK,IAAI,MAAM,EAI5B,MAHuB,6EAA6E,MAClG,MACF,EACoB,SAASA,CAAI,EAC1B,GAAG,KAAK,IAAI,OAAO,CAAC,KAAM,KAAK,IAAI,KAAK,CAAC,IAAKA,CAAI,IAAK,KAAK,UAAU,OAAO,EACjF,IAAKxJ,GAAM,KAAK,UAAUA,CAAC,CAAC,EAC5B,KAAK,GAAI,CAAC;AAAA,EAH8B,KAAK,cAAc,CAIhE,CAEA,eAAgB,CAEd,MAAO,GAAG,KAAK,IAAI,OAAO,CAAC,KAAM,KAAK,IAAI,KAAK,CAAC,QAAS,KAAK,UAAU,CAAC,KAAM,KAAK,UAAU,OAAO,EAClG,IAAKA,GAAM,KAAK,UAAUA,CAAC,CAAC,EAC5B,KAAK,GAAG,CAAC;AAAA,CACd,CACF,CAEA,MAAMsK,WAAUpC,CAAG,CACjB,OAAO,SAAW,IAClB,OAAO,OAAS,EAChB,OAAO,KAAO,CAAC,IAAI,EACnB,OAAO,YAAc,IACrB,OAAO,YAAc,CAAC,CAAC,UAAW,MAAM,CAAC,EACzC,OAAO,KAAO,CAAC,QAAQ,EAEvB,YAAYP,EAAM,CAChB,MAAMA,CAAI,CACZ,CAGA,WAAWrH,EAAK,CACTA,GAAK,KAAK,UAAU,wBAAwB,EAC5C,KAAK,OAAOA,CAAG,GAAG,KAAK,UAAU,wBAAwB,EAC9D,KAAK,IAAI,UAAWA,CAAG,CACzB,CAEA,gBAAiB,CACf,MAAO,SACT,CAEA,cAAe,CACb,MAAO,CACL,MAAO,oBACP,MAAO,KACP,IAAK,KACL,KAAM,IACN,QAAS,aACX,CACF,CAGA,cAAe,CACb,OAAO,IAAI,WAAW,KAAK,IAAI,SAAS,EAAE,MAAM,GAAG,EAAE,IAAI,MAAM,CAAC,CAClE,CACF,CAEA,MAAMiK,WAAarC,CAAG,CACpB,OAAO,SAAW,OAClB,OAAO,OAAS,GAChB,OAAO,KAAO,CAAC,KAAM,IAAI,EACzB,OAAO,YAAc,CAAC,CAAC,UAAW,MAAM,CAAC,EACzC,OAAO,KAAO,CAAC,QAAQ,EAEvB,YAAYP,EAAM,CAChB,MAAMA,CAAI,CACZ,CAGA,WAAWrH,EAAK,CACTA,GAAK,KAAK,UAAU,2BAA2B,EAC/C,KAAK,OAAOA,CAAG,GAAG,KAAK,UAAU,+BAA+BA,CAAG,GAAG,EAE3E,KAAK,IAAI,UAAW,KAAK,WAAWA,EAAI,YAAY,CAAC,CAAC,CACxD,CAEA,cAAcA,EAAK,CACjB,OAAO,KAAK,aAAaA,GAAO,KAAK,IAAI,SAAS,CAAC,CACrD,CAEA,gBAAiB,CACf,MAAO,cACT,CAEA,cAAe,CACb,MAAO,CACL,MAAO,oBACP,QAAS,0CACT,MAAO,KACP,IAAK,KACL,KAAM,MACR,CACF,CAGA,YAAY,CAAE,SAAA5B,CAAS,EAAG,CACxB,MAAM+B,EAAM/B,EACZ,IAAImD,EAAMgB,EAAI,EAAG/D,EAAOC,EAAKyL,EAAIC,EAEjC,OAAQhK,EAAI,CAAC,EAAG,CACd,IAAK,IACX,CAACoB,EAAM,EAAG/C,EAAOC,EAAKyL,EAAIC,CAAG,EAAIhK,EAAI,MAAM,CAAC,EAAE,MAAM,GAAG,EAC3C,GAAK,IAAI,KAAK,UAAU,6BAA6B,EACzDoC,EAAKhC,GAAW/B,CAAK,EAClB,MAAM,mBAAmB,EACzB,KAAK,GAAG,EACX,MACF,IAAK,IACL,IAAK,IACX,CAAC+C,EAAM/C,EAAOC,EAAKyL,EAAIC,CAAG,EAAIhK,EAAI,MAAM,CAAC,EAAE,MAAM,GAAG,EAC5CoC,EAAK/D,EAAM,MAAM,SAAS,EAAE,KAAK,GAAG,EACpC,KACJ,CAEA,OAAO,IAAIyL,GAAK,CACd,MAAO,KAAK,aAAa1I,CAAI,EAC7B,IAAK,SAAS9C,EAAK,EAAE,EACrB,KAAM,OACN,QAAS8D,EACT,UAAW2H,EACX,SAAUC,GAAK,KAAK,GAAK,EAC3B,CAAC,CACH,CAGA,cAAe,CACb,MAAM9G,EAAM,KAAK,WAAW,KAAK,IAAI,SAAS,EAAG,EAAE,EAC7C+G,EAAM,IAAI,WAAW/G,EAAI,OAAS,CAAC,EACzC,QAAStD,EAAI,EAAGA,EAAIqK,EAAI,OAAQrK,IAAKqK,EAAIrK,CAAC,EAAI,SAASsD,EAAI,MAAMtD,EAAI,EAAGA,EAAI,EAAI,CAAC,EAAG,EAAE,EACtF,OAAOqK,CACT,CAEA,OAAO1C,EAAW,CAChB,MAAO,GAAG,KAAK,UAAUA,CAAS,CAAC,IAAK,KAAK,cAAc,CAAC;AAAA,CAC9D,CAEA,WAAY,CAEV,MAAMlJ,EAAQyD,EAAQ,KAAK,WAAW,KAAK,IAAI,SAAS,EAAG,EAAE,CAAC,EAC9D,OAAO,KAAK,kBAAkBzD,CAAK,CACrC,CACF,CAEA,MAAM6L,UAAYzC,CAAG,CACnB,OAAO,SAAW,MAClB,OAAO,OAAS,GAChB,OAAO,KAAO,CAAC,IAAI,EACnB,OAAO,YAAc,CAAC,WAAW,EAEjC,YAAYP,EAAM,CAChB,MAAMA,CAAI,CACZ,CAGA,YAAYrH,EAAK,CACVA,GAAK,KAAK,UAAU,4BAA4B,EACrD,KAAK,IAAI,YAAaA,CAAG,CAC3B,CAEA,gBAAiB,CACf,MAAO,qBACT,CAEA,cAAe,CACb,MAAO,CACL,MAAO,eACP,IAAK,KACL,MAAO,KACP,KAAM,MACN,YAAa,mDACf,CACF,CAGA,YAAY,CAAE,SAAA5B,CAAS,EAAG,CAExB,KAAM,CAACmD,EAAMY,EAAG3D,EAAOC,EAAKyL,EAAIC,CAAG,EAAI/L,EAAS,MAAM,CAAC,EAAE,MAAM,GAAG,EAC9D+D,GAAK,IAAI,KAAK,UAAU,4BAA4B,EAExD,MAAMgB,EAAQ,WAAW,KAAKpE,EAAYP,CAAK,EAAIQ,GAAMA,EAAE,WAAW,CAAC,CAAC,EAClEsL,EAAQ,CAAC,EACf,IAAIjL,EAAM,EAEV,KAAOA,EAAM8D,EAAM,QAAQ,CACzB,MAAMoH,EAAOpH,EAAM9D,CAAG,GAAK,EAAK8D,EAAM9D,EAAM,CAAC,EAC7CA,GAAO,EACP,MAAMmL,EAASrH,EAAM9D,CAAG,EACxBA,IACA,MAAMoL,EAAatH,EAAM9D,CAAG,EAC5BA,IACA,MAAMqL,GAAOD,EAAa,OAAU,EAC9BE,EAAUF,EAAa,IACvBG,EAAYzH,EAAM,SAAS9D,EAAKA,EAAMsL,CAAO,EACnDtL,GAAOsL,EAEP,IAAInE,EACJ,GAAI+D,IAAQ,EAAG,CACb,MAAMM,EAAS,IAAI,WAAW,CAAC,EAC/BA,EAAO,IAAID,CAAS,EACpBpE,EAAO,CAAC,GAAGqE,CAAM,EAAE,KAAK,GAAG,CAC7B,KAAO,CACL,MAAMA,EAAS,IAAI,WAAW,EAAE,EAChCA,EAAO,IAAID,CAAS,EACpB,MAAME,EAAW,IAAI,SAASD,EAAO,MAAM,EACrC/D,EAAS,CAAC,EAChB,QAAS/G,EAAI,EAAGA,EAAI,GAAIA,GAAK,EAAG+G,EAAO,KAAKgE,EAAS,UAAU/K,CAAC,EAAE,SAAS,EAAE,EAAE,SAAS,EAAG,GAAG,CAAC,EAC/FyG,EAAO,KAAK,aAAaM,EAAO,KAAK,GAAG,CAAC,CAC3C,CAEAwD,EAAM,KAAK,GAAGI,EAAM,IAAM,EAAE,GAAGH,CAAG,IAAI/D,CAAI,IAAIgE,CAAM,EAAE,CACxD,CAEA,OAAO,IAAIH,EAAI,CACb,MAAO,KAAK,aAAa9I,CAAI,EAC7B,IAAK,SAAS9C,EAAK,EAAE,EACrB,KAAM,MACN,YAAa6L,EAAM,KAAK,GAAG,EAC3B,UAAWJ,EACX,SAAUC,GAAK,KAAK,GAAK,EAC3B,CAAC,CACH,CAEA,SAAS,CAAE,SAAAY,CAAS,EAAG,CAErB,MAAMzM,EAAQyM,EAAS,MAAM,KAAK,EAC5B,CAACxM,EAAOE,EAAKO,EAAGkK,CAAI,EAAI5K,EAC9B,OAAO,IAAI+L,EAAI,CACb,MAAA9L,EACA,IAAK,SAASE,EAAK,EAAE,EACrB,MAAOO,EACP,KAAAkK,EACA,YAAa5K,EAAM,MAAM,CAAC,EAAE,KAAK,GAAG,EAAE,KAAK,CAC7C,CAAC,CACH,CAEA,SAAS,CAAE,MAAAC,EAAO,IAAAwG,EAAK,IAAAtG,EAAK,MAAAD,CAAM,EAAG,CACnC,MAAM8L,EAAQ,CAAC,EACf,IAAIjL,EAAM,EACV,KAAOA,EAAMb,EAAM,QAAQ,CACzB,MAAM+L,EAAO/L,EAAMa,CAAG,GAAK,EAAKb,EAAMa,EAAM,CAAC,EAC7CA,GAAO,EACP,MAAMmL,EAAShM,EAAMa,GAAK,EACpBoL,EAAajM,EAAMa,GAAK,EACxBqL,GAAOD,EAAa,OAAU,EAC9BE,EAAUF,EAAa,IACvBG,EAAYpM,EAAM,SAASa,EAAKA,EAAMsL,CAAO,EACnDtL,GAAOsL,EAEP,IAAInE,EACJ,GAAI+D,IAAQ,EAAG,CACb,MAAMM,EAAS,IAAI,WAAW,CAAC,EAC/BA,EAAO,IAAID,CAAS,EACpBpE,EAAO,CAAC,GAAGqE,CAAM,EAAE,KAAK,GAAG,CAC7B,KAAO,CACL,MAAMA,EAAS,IAAI,WAAW,EAAE,EAChCA,EAAO,IAAID,CAAS,EACpB,MAAMxF,EAAK,IAAI,SAASyF,EAAO,MAAM,EAC/B/D,EAAS,CAAC,EAChB,QAAS/G,EAAI,EAAGA,EAAI,GAAIA,GAAK,EAAG+G,EAAO,KAAK1B,EAAG,UAAUrF,CAAC,EAAE,SAAS,EAAE,EAAE,SAAS,EAAG,GAAG,CAAC,EACzFyG,EAAO,KAAK,aAAaM,EAAO,KAAK,GAAG,CAAC,CAC3C,CACAwD,EAAM,KAAK,GAAGI,EAAM,IAAM,EAAE,GAAGH,CAAG,IAAI/D,CAAI,IAAIgE,CAAM,EAAE,CACxD,CACA,OAAO,IAAIH,EAAI,CACb,MAAA9L,EACA,IAAAE,EACA,MAAOsG,EACP,KAAM,MACN,YAAauF,EAAM,KAAK,GAAG,CAC7B,CAAC,CACH,CAGA,WAAY,CACV,OAAO,KAAK,kBACV,KAAK,IAAI,WAAW,EACjB,MAAM,KAAK,EACX,IAAKU,GAAS,CACb,MAAMN,EAAMM,EAAK,WAAW,GAAG,EACzBC,EAAOP,EAAMM,EAAK,MAAM,CAAC,EAAIA,EAC7BE,EAAWD,EAAK,QAAQ,GAAG,EAC3BV,EAAM,SAASU,EAAK,MAAM,EAAGC,CAAQ,EAAG,EAAE,EAC1CC,EAAOF,EAAK,MAAMC,EAAW,CAAC,EAC9BE,EAAWD,EAAK,YAAY,GAAG,EAC/B3E,EAAO2E,EAAK,MAAM,EAAGC,CAAQ,EAC7BZ,EAAS,SAASW,EAAK,MAAMC,EAAW,CAAC,EAAG,EAAE,EAEpD,IAAIR,EACJ,GAAIL,IAAQ,EACVK,EAAY,IAAI,WAAWpE,EAAK,MAAM,GAAG,EAAE,IAAKrE,GAAM,SAASA,EAAG,EAAE,CAAC,CAAC,MACjE,CACL,MAAMkJ,EAAS7E,EAAK,QAAQ,IAAI,EAChC,IAAIM,EACJ,GAAIuE,IAAW,GAAI,CACjB,MAAMC,EAAO9E,EACV,MAAM,EAAG6E,CAAM,EACf,MAAM,GAAG,EACT,OAAQrK,GAAMA,IAAM,EAAE,EACnBuK,EAAQ/E,EACX,MAAM6E,EAAS,CAAC,EAChB,MAAM,GAAG,EACT,OAAQrK,GAAMA,IAAM,EAAE,EACzB8F,EAAS,CAAC,GAAGwE,EAAM,GAAG,MAAM,EAAIA,EAAK,OAASC,EAAM,MAAM,EAAE,KAAK,MAAM,EAAG,GAAGA,CAAK,CACpF,MACEzE,EAASN,EAAK,MAAM,GAAG,EAEzB,MAAMgF,EAAS1E,EAAO,IAAK2E,GAAMA,EAAE,SAAS,EAAG,GAAG,CAAC,EAAE,KAAK,EAAE,EAC5Db,EAAY,WAAW,KAAK,CAAE,OAAQY,EAAO,OAAS,CAAE,EAAG,CAAClI,EAAGvD,IAC7D,SAASyL,EAAO,MAAMzL,EAAI,EAAGA,EAAI,EAAI,CAAC,EAAG,EAAE,CAC7C,CACF,CAEA,IAAIR,EAAMqL,EAAU,OACpB,KAAOrL,EAAM,GAAKqL,EAAUrL,EAAM,CAAC,IAAM,GAAGA,IAC5C,MAAMmM,EAAUd,EAAU,MAAM,EAAGrL,CAAG,EAEtC,IAAI2C,EAAIE,EAAcmI,CAAG,EACzBrI,GAAKjB,EAAauJ,CAAM,EACxBtI,GAAKjB,GAAcyJ,EAAM,IAAO,GAAKgB,EAAQ,MAAM,EACnD,UAAWzI,KAAKyI,EAASxJ,GAAKjB,EAAagC,CAAC,EAC5C,OAAOf,CACT,CAAC,EACA,KAAK,EAAE,CACZ,CACF,CAEA,cAAe,CACb,MAAMoI,EAAQ,KAAK,IAAI,WAAW,EAAE,MAAM,KAAK,EACzC9L,EAAQ,CAAC,EAEf,UAAWwM,KAAQV,EAAO,CACxB,MAAMI,EAAMM,EAAK,WAAW,GAAG,EACzBC,EAAOP,EAAMM,EAAK,MAAM,CAAC,EAAIA,EAC7BE,EAAWD,EAAK,QAAQ,GAAG,EAC3BV,EAAM,SAASU,EAAK,MAAM,EAAGC,CAAQ,EAAG,EAAE,EAC1CC,EAAOF,EAAK,MAAMC,EAAW,CAAC,EAC9BE,EAAWD,EAAK,YAAY,GAAG,EAC/B3E,EAAO2E,EAAK,MAAM,EAAGC,CAAQ,EAC7BZ,EAAS,SAASW,EAAK,MAAMC,EAAW,CAAC,EAAG,EAAE,EAEpD,IAAIR,EACJ,GAAIL,IAAQ,EACVK,EAAY,IAAI,WAAWpE,EAAK,MAAM,GAAG,EAAE,IAAKrE,GAAM,SAASA,EAAG,EAAE,CAAC,CAAC,MACjE,CACL,MAAMkJ,EAAS7E,EAAK,QAAQ,IAAI,EAChC,IAAIM,EACJ,GAAIuE,IAAW,GAAI,CACjB,MAAMC,EAAO9E,EACV,MAAM,EAAG6E,CAAM,EACf,MAAM,GAAG,EACT,OAAQrK,IAAMA,KAAM,EAAE,EACnBuK,GAAQ/E,EACX,MAAM6E,EAAS,CAAC,EAChB,MAAM,GAAG,EACT,OAAQrK,IAAMA,KAAM,EAAE,EACzB8F,EAAS,CAAC,GAAGwE,EAAM,GAAG,MAAM,EAAIA,EAAK,OAASC,GAAM,MAAM,EAAE,KAAK,MAAM,EAAG,GAAGA,EAAK,CACpF,MACEzE,EAASN,EAAK,MAAM,GAAG,EAEzB,MAAMgF,GAAS1E,EAAO,IAAK2E,GAAMA,EAAE,SAAS,EAAG,GAAG,CAAC,EAAE,KAAK,EAAE,EAC5Db,EAAY,WAAW,KAAK,CAAE,OAAQY,GAAO,OAAS,CAAE,EAAG,CAAC,EAAGzL,KAC7D,SAASyL,GAAO,MAAMzL,GAAI,EAAGA,GAAI,EAAI,CAAC,EAAG,EAAE,CAC7C,CACF,CAEA,IAAIR,EAAMqL,EAAU,OACpB,KAAOrL,EAAM,GAAKqL,EAAUrL,EAAM,CAAC,IAAM,GAAGA,IAC5C,MAAMmM,EAAUd,EAAU,MAAM,EAAGrL,CAAG,EAEhCoM,EAAY,IAAI,WAAW,EAAID,EAAQ,MAAM,EACxC,IAAI,SAASC,EAAU,OAAQA,EAAU,UAAU,EAC3D,UAAU,EAAGpB,CAAG,EACnBoB,EAAU,CAAC,EAAInB,EACfmB,EAAU,CAAC,GAAKjB,EAAM,IAAO,GAAKgB,EAAQ,OAC1CC,EAAU,IAAID,EAAS,CAAC,EAExBlN,EAAM,KAAKmN,CAAS,CACtB,CAEA,MAAMC,EAAWpN,EAAM,OAAO,CAACqN,EAAK3J,IAAM2J,EAAM3J,EAAE,OAAQ,CAAC,EACrDiB,EAAQ,IAAI,WAAWyI,CAAQ,EACrC,IAAIvM,EAAM,EACV,UAAW6C,KAAK1D,EACd2E,EAAM,IAAIjB,EAAG7C,CAAG,EAChBA,GAAO6C,EAAE,OAGX,OAAOiB,CACT,CACF,CAEA,MAAM2I,WAAYlE,CAAG,CACnB,OAAO,SAAW,MAClB,OAAO,OAAS,IAChB,OAAO,KAAO,CAAC,KAAM,KAAM,IAAI,EAC/B,OAAO,YAAc,CACnB,CAAC,QAAS,IAAI,EACd,CAAC,MAAO,SAAS,EACjB,CAAC,QAAS,MAAM,CAClB,EACA,OAAO,KAAO,CAAC,UAAU,EAEzB,YAAYP,EAAM,CAChB,MAAMA,CAAI,CACZ,CAGA,SAASrH,EAAK,CACZ,KAAK,UAAU,MAAO,QAASA,CAAG,EAE7B,KAAK,gBAAgB,EAAE,IAAIA,CAAG,GACjC,KAAK,UAAU,aAAaA,CAAG,iBAAiB,EAGlD,KAAK,IAAI,QAASA,CAAG,CACvB,CAEA,iBAAkB,CAChB,OAAO,IAAI,IAAI,CACb,CAAC,EAAG,cAAc,EAClB,CAAC,IAAK,UAAU,CAClB,CAAC,CACH,CAEA,OAAOA,EAAK,EACN,OAAOA,GAAQ,UAAYA,EAAI,OAAS,GAAK,YAAY,KAAKA,CAAG,IACnE,KAAK,UAAU,sEAAsE,EAElF,KAAK,cAAc,EAAE,IAAIA,CAAG,GAC/B,KAAK,UAAU,WAAWA,CAAG,iBAAiB,EAEhD,KAAK,IAAI,MAAOA,CAAG,CACrB,CAEA,eAAgB,CACd,OAAO,IAAI,IAAI,CAAC,CAAC,OAAO,EAAG,CAAC,WAAW,EAAG,CAAC,OAAO,CAAC,CAAC,CACtD,CAEA,SAASA,EAAK,CAGR,KAAK,SAASA,CAAG,IACnBA,EAAMA,EAAI,QAAQ,eAAgB,EAAE,GAIlC,KAAK,IAAI,KAAK,IAAM,UACD,CAAC,UAAW,QAAS,QAAQ,EAChC,OAAQ,GAAMA,EAAI,WAAW,CAAC,CAAC,EAAE,QACjD,KAAK,UAAU,8CAA8C,GAIjE,KAAK,IAAI,QAASA,CAAG,CACvB,CAEA,gBAAiB,CACf,MAAO,uCACT,CAEA,cAAe,CACb,MAAO,CACL,MAAO,eACP,IAAK,KACL,MAAO,KACP,KAAM,MACN,MAAO,EACP,IAAK,QACL,MAAO,wBACT,CACF,CAGA,YAAY,CAAE,SAAA5B,CAAS,EAAG,CAExB,KAAM,CAAE,MAAAG,EAAO,OAAAM,EAAQ,MAAAL,EAAO,IAAAC,EAAK,UAAAC,EAAW,SAAAC,CAAS,EAAI,KAAK,iBAAiBP,CAAQ,EACrFS,GAAU,KAAK,UAAU,GAAG,KAAK,UAAU,iCAAiC,EAEhF,MAAMkN,EAAQvL,EAAahC,EAAM,MAAM,EAAG,CAAC,CAAC,EACtCwN,EAASxL,EAAahC,EAAM,MAAM,EAAG,CAAC,CAAC,EAEvCyN,EAAYlN,EAAYP,EAAM,MAAM,CAAC,CAAC,EACtC0N,EAAMD,EAAU,MAAM,EAAGD,CAAM,EAC/BG,EAAcF,EAAU,MAAMD,CAAM,EAE1C,OAAO,IAAIF,GAAI,CACb,MAAAvN,EACA,IAAAE,EACA,KAAM,MACN,MAAAsN,EACA,IAAAG,EACA,MAAOC,EACP,UAAAzN,EACA,SAAAC,CACF,CAAC,CACH,CAIA,cAAe,CACb,MAAMuN,EAAM,IAAI,YAAY,EAAE,OAAO,KAAK,IAAI,KAAK,CAAC,EAC9CpK,EAAQ,IAAI,YAAY,EAAE,OAAO,KAAK,IAAI,OAAO,CAAC,EAClDhC,EAAS,IAAI,WAAW,EAAIoM,EAAI,OAASpK,EAAM,MAAM,EAC3D,OAAAhC,EAAO,CAAC,EAAI,KAAK,IAAI,OAAO,EAC5BA,EAAO,CAAC,EAAIoM,EAAI,OAChBpM,EAAO,IAAIoM,EAAK,CAAC,EACjBpM,EAAO,IAAIgC,EAAO,EAAIoK,EAAI,MAAM,EACzBpM,CACT,CAEA,WAAY,CACV,OAAO,KAAK,kBACVmB,EAAa,KAAK,IAAI,OAAO,CAAC,EAC5BA,EAAa,KAAK,IAAI,KAAK,EAAE,MAAM,EACnChB,EAAY,eAAgB,KAAK,IAAI,KAAK,CAAC,EAC3CA,EAAY,eAAgB,KAAK,IAAI,OAAO,CAAC,CACjD,CACF,CACF,CAEA,MAAMmM,UAAaxE,CAAG,CACpB,OAAO,SAAW,OAClB,OAAO,OAAS,GAChB,OAAO,KAAO,CAAC,KAAM,IAAI,EACzB,OAAO,YAAc,CACnB,CAAC,YAAa,UAAU,EACxB,CAAC,UAAW,KAAK,EACjB,CAAC,YAAa,IAAI,EAClB,CAAC,cAAe,QAAQ,CAC1B,EAEA,OAAO,WAAa,CAClB,KAAM,EACN,KAAM,EACN,IAAK,EACL,MAAO,EACP,MAAO,EACP,KAAM,EACN,OAAQ,EACR,QAAS,EACT,IAAK,IACL,IAAK,GACP,EAEA,OAAO,mBAAqB,OAAO,YAAY,OAAO,QAAQwE,EAAK,UAAU,EAAE,IAAI,CAAC,CAACpH,EAAGiD,CAAC,IAAM,CAACA,EAAGjD,CAAC,CAAC,CAAC,EAEtG,YAAYqC,EAAM,CAChB,MAAMA,CAAI,CACZ,CAGA,YAAYrH,EAAK,EAGUA,GAAQ,MAAQA,IAAQ,KAC/C,KAAK,UAAU,uBAAuB,EAGpC,OAAOA,GAAQ,UAAY,CAAC,WAAW,KAAKA,CAAG,EAC5C,OAAO,OAAOoM,EAAK,WAAYpM,CAAG,GACrC,KAAK,UAAU,qCAAqCA,CAAG,EAAE,EAG3D,KAAK,WAAW,OAAQ,YAAaA,CAAG,EAE1C,KAAK,IAAI,YAAaA,CAAG,CAC3B,CAEA,iBAAiBA,EAAK,CACpB,GAAI,OAAOA,GAAQ,SAAU,OAAOA,EACpC,GAAI,WAAW,KAAKA,CAAG,EAAG,OAAO,SAASA,EAAK,EAAE,EACjD,GAAI,OAAO,OAAOoM,EAAK,WAAYpM,CAAG,EAAG,OAAOoM,EAAK,WAAWpM,CAAG,EACnE,KAAK,UAAU,qCAAqCA,CAAG,EAAE,CAC3D,CAEA,UAAUA,EAAK,CACb,KAAK,cAAc,MAAO,UAAWA,CAAG,CAC1C,CAEA,aAAaA,EAAK,CAChB,KAAK,cAAc,KAAM,YAAaA,CAAG,CAC3C,CAEA,eAAeA,EAAK,EAGOA,GAAQ,MAAQA,IAAQ,KAC/C,KAAK,UAAU,6CAA6C,EAE9D,KAAK,SAAS,OAAQ,cAAeA,EAAI,QAAQ,UAAW,EAAE,CAAC,EAC/D,KAAK,IAAI,cAAeA,CAAG,CAC7B,CAEA,gBAAiB,CACf,MAAO,aACT,CAEA,cAAe,CACb,MAAO,CACL,MAAO,oBACP,IAAK,KACL,MAAO,KACP,KAAM,OACN,YAAa,MACb,UAAW,EACX,UAAW,EACX,YAAa,UACf,CACF,CAIA,YAAY,CAAE,SAAA5B,CAAS,EAAG,CACxB,KAAM,CAAE,MAAAG,EAAO,OAAAM,EAAQ,MAAAL,EAAO,IAAAC,EAAK,UAAAC,EAAW,SAAAC,CAAS,EAAI,KAAK,iBAAiBP,CAAQ,EACrFS,GAAU,KAAK,UAAU,GAAG,KAAK,UAAU,6BAA6B,EAE5E,MAAMsE,EAAQrE,EAAkBN,CAAK,EAC/B6N,EAAWlJ,EAAM,CAAC,GAAK,EAAKA,EAAM,CAAC,EAEnCmJ,EAAWF,EAAK,mBAAmBC,CAAO,GAAKA,EAErD,OAAO,IAAID,EAAK,CACd,MAAA7N,EACA,IAAAE,EACA,KAAM,OACN,YAAa6N,EACb,UAAYnJ,EAAM,CAAC,GAAK,EAAKA,EAAM,CAAC,EACpC,UAAWA,EAAM,CAAC,EAClB,YAAaK,EAAcL,EAAM,SAAS,CAAC,CAAC,EAC5C,UAAAzE,EACA,SAAAC,CACF,CAAC,CACH,CAEA,SAAS,CAAE,SAAAoM,CAAS,EAAG,CAErB,KAAM,CAACxM,EAAOE,EAAKO,EAAGkK,EAAMqD,EAAUC,EAAQC,EAAMC,CAAW,EAAI3B,EAAS,MAAM,KAAK,EACvF,OAAO,IAAIqB,EAAK,CACd,MAAA7N,EACA,IAAK,SAASE,EAAK,EAAE,EACrB,MAAOO,EACP,KAAAkK,EACA,YAAa,WAAW,KAAKqD,CAAQ,EAAI,SAASA,EAAU,EAAE,EAAIA,EAClE,UAAW,SAASC,EAAQ,EAAE,EAC9B,UAAW,SAASC,EAAM,EAAE,EAC5B,YAAAC,CACF,CAAC,CACH,CAIA,WAAY,CACV,OAAO,KAAK,kBACVtK,EAAc,KAAK,iBAAiB,KAAK,IAAI,WAAW,CAAC,CAAC,EACxDA,EAAc,KAAK,IAAI,SAAS,CAAC,EACjCnB,EAAa,KAAK,IAAI,WAAW,CAAC,EAClC+B,EAAc,KAAK,IAAI,aAAa,EAAE,QAAQ,UAAW,EAAE,CAAC,CAChE,CACF,CAEA,cAAe,CACb,MAAM2J,EAAYlJ,EAAc,KAAK,IAAI,aAAa,EAAE,QAAQ,UAAW,EAAE,CAAC,EACxEN,EAAQ,IAAI,WAAW,EAAIwJ,EAAU,MAAM,EAC3CvH,EAAK,IAAI,SAASjC,EAAM,OAAQA,EAAM,UAAU,EACtD,OAAAiC,EAAG,UAAU,EAAG,KAAK,iBAAiB,KAAK,IAAI,WAAW,CAAC,CAAC,EAC5DA,EAAG,UAAU,EAAG,KAAK,IAAI,SAAS,CAAC,EACnCjC,EAAM,CAAC,EAAI,KAAK,IAAI,WAAW,EAC/BA,EAAM,IAAIwJ,EAAW,CAAC,EACfxJ,CACT,CACF,CAEA,MAAMyJ,WAAchF,CAAG,CACrB,OAAO,SAAW,QAClB,OAAO,OAAS,EAChB,OAAO,KAAO,CAAC,KAAM,IAAI,EACzB,OAAO,YAAc,IACrB,OAAO,YAAc,CAAC,CAAC,QAAS,MAAM,CAAC,EACvC,OAAO,KAAO,CAAC,QAAQ,EAEvB,YAAYP,EAAM,CAChB,MAAMA,CAAI,CACZ,CAGA,SAASrH,EAAK,CACZ,KAAK,cAAc,OAAQ,QAASA,CAAG,CACzC,CAEA,gBAAiB,CACf,MAAO,gBACT,CAEA,cAAe,CACb,MAAO,CACL,MAAO,mBACP,IAAK,KACL,MAAO,KACP,KAAM,QACN,MAAO,kBACT,CACF,CAGA,cAAe,CACb,OAAO,KAAK,eAAe,KAAK,IAAI,OAAO,CAAC,CAC9C,CACF,CAEA,MAAM6M,WAAcjF,CAAG,CACrB,OAAO,SAAW,QAClB,OAAO,OAAS,GAChB,OAAO,KAAO,CAAC,IAAI,EACnB,OAAO,YAAc,CAAC,CAAC,OAAQ,QAAQ,CAAC,EAExC,YAAYP,EAAM,CAChB,MAAMA,CAAI,CACZ,CAGA,QAAQrH,EAAK,CACNA,GAAK,KAAK,UAAU,yBAAyB,EAClD,KAAK,SAAS,QAAS,OAAQA,CAAG,EAClC,KAAK,IAAI,OAAQA,CAAG,CACtB,CAEA,gBAAiB,CACf,MAAO,iBACT,CAEA,cAAe,CACb,MAAO,CACL,MAAO,oBACP,IAAK,KACL,MAAO,KACP,KAAM,QACN,KAAM,kDACR,CACF,CAGA,YAAY,CAAE,SAAA5B,CAAS,EAAG,CAExB,KAAM,CAAE,MAAAG,EAAO,OAAAM,EAAQ,MAAAL,EAAO,IAAAC,EAAK,UAAAC,EAAW,SAAAC,CAAS,EAAI,KAAK,iBAAiBP,CAAQ,EACzF,OAAIS,GAAU,KAAK,UAAU,GAAG,KAAK,UAAU,8BAA8B,EAEtE,IAAIgO,GAAM,CACf,MAAAtO,EACA,IAAAE,EACA,KAAM,QACN,KAAMyE,GAAc1E,CAAK,EACzB,UAAAE,EACA,SAAAC,CACF,CAAC,CACH,CAIA,cAAe,CACb,OAAO,IAAI,WACT,KAAK,KAAK,IAAI,MAAM,CAAC,EAClB,MAAM,EAAE,EACR,IAAKK,GAAMA,EAAE,WAAW,CAAC,CAAC,CAC/B,CACF,CAEA,WAAY,CACV,OAAO,KAAK,kBAAkBgE,EAAc,KAAK,IAAI,MAAM,CAAC,CAAC,CAC/D,CACF,CAEA,MAAM8J,WAAclF,CAAG,CACrB,OAAO,SAAW,QAClB,OAAO,OAAS,GAChB,OAAO,KAAO,CAAC,KAAM,IAAI,EACzB,OAAO,YAAc,CAAC,CAAC,SAAU,MAAM,CAAC,EAExC,YAAYP,EAAM,CAChB,MAAMA,CAAI,CACZ,CAGA,UAAUrH,EAAK,CACb,KAAK,cAAc,OAAQ,SAAUA,CAAG,CAC1C,CAEA,gBAAiB,CACf,MAAO,iBACT,CAEA,cAAe,CACb,MAAO,CACL,MAAO,eACP,IAAK,KACL,MAAO,KACP,KAAM,QACN,OAAQ,cACV,CACF,CAGA,YAAY,CAAE,SAAA5B,CAAS,EAAG,CAExB,KAAM,CAACmD,EAAMY,EAAG3D,EAAOC,EAAKyL,EAAIC,CAAG,EAAI/L,EAAS,MAAM,CAAC,EAAE,MAAM,GAAG,EAClE,OAAI+D,GAAK,IAAI,KAAK,UAAU,8BAA8B,EAEnD,IAAI2K,GAAM,CACf,KAAM,QACN,MAAO,KAAK,aAAavL,CAAI,EAC7B,OAAQI,EAAiBnD,CAAK,EAAE,CAAC,EACjC,IAAK,SAASC,EAAK,EAAE,EACrB,UAAWyL,EACX,SAAUC,GAAK,KAAK,GAAK,EAC3B,CAAC,CACH,CAIA,cAAe,CACb,OAAO,KAAK,eAAe,KAAK,IAAI,QAAQ,CAAC,CAC/C,CAEA,WAAY,CACV,MAAM3L,EAAQ8C,EAAe,KAAK,IAAI,QAAQ,CAAC,EAC/C,OAAO,KAAK,kBAAkB9C,CAAK,CACrC,CACF,CAEA,MAAMuO,WAAenF,CAAG,CACtB,OAAO,SAAW,SAClB,OAAO,OAAS,GAChB,OAAO,KAAO,CAAC,KAAM,KAAM,KAAM,KAAM,IAAI,EAC3C,OAAO,YAAc,CACnB,CAAC,QAAS,KAAK,EACf,CAAC,WAAY,IAAI,EACjB,CAAC,YAAa,IAAI,EAClB,CAAC,YAAa,QAAQ,CACxB,EACA,OAAO,KAAO,CAAC,QAAQ,EAEvB,YAAYP,EAAM,CAChB,MAAMA,CAAI,CACZ,CAGA,SAASrH,EAAK,CAEZ,KAAK,WAAW,SAAU,QAASA,CAAG,EAEjC,KAAK,gBAAgB,EAAE,IAAIA,CAAG,GACjC,KAAK,UAAU,qCAAqC,KAAK,gBAAgB,CAAC,EAAE,EAG9E,KAAK,IAAI,QAASA,CAAG,CACvB,CAGA,iBAAkB,CAChB,OAAO,IAAI,IAAI,CAAC,CAAC,CAAC,EAAG,CAAC,GAAG,EAAG,CAAC,GAAG,CAAC,CAAC,CACpC,CAEA,YAAYA,EAAK,CAEf,KAAK,UAAU,SAAU,WAAYA,CAAG,EAGnC,KAAK,mBAAmB,EAAE,IAAIA,CAAG,GAAG,KAAK,UAAU,0BAA0B,EAElF,KAAK,IAAI,WAAYA,CAAG,CAC1B,CAEA,oBAAqB,CACnB,OAAO,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CACtB,CAEA,aAAaA,EAAK,CAEhB,KAAK,UAAU,SAAU,YAAaA,CAAG,EAGpC,KAAK,oBAAoB,EAAE,IAAIA,CAAG,GAAG,QAAQ,MAAM,sBAAsBA,CAAG,kBAAkB,EAEnG,KAAK,IAAI,YAAaA,CAAG,CAC3B,CAEA,qBAAsB,CACpB,OAAO,IAAI,IAAI,CACb,CAAC,EAAG,sBAAsB,EAC1B,CAAC,EAAG,IAAI,EACR,CAAC,EAAG,WAAW,EACf,CAAC,EAAG,IAAI,EACR,CAAC,EAAG,WAAW,EACf,CAAC,EAAG,gBAAgB,EACpB,CAAC,EAAG,oBAAoB,EACxB,CAAC,EAAG,aAAa,EACjB,CAAC,EAAG,EAAE,EACN,CAAC,GAAI,aAAa,EAClB,CAAC,GAAI,gCAAgC,EACrC,CAAC,GAAI,gCAAgC,EACrC,CAAC,GAAI,SAAS,EACd,CAAC,GAAI,OAAO,EACZ,CAAC,GAAG,EACJ,CAAC,GAAG,CACN,CAAC,CACH,CAEA,aAAaA,EAAK,CACXA,GAAK,KAAK,UAAU,+BAA+B,EACxD,KAAK,SAAS,SAAU,YAAaA,EAAI,QAAQ,UAAW,EAAE,CAAC,EAC/D,KAAK,IAAI,YAAaA,CAAG,CAC3B,CAEA,gBAAiB,CACf,MAAO,gBACT,CAEA,cAAe,CACb,MAAO,CACL,MAAO,eACP,IAAK,KACL,MAAO,KACP,KAAM,SACN,MAAO,IACP,SAAU,EACV,UAAW,EACX,UACE,8GACJ,CACF,CAIA,SAAS,CAAE,SAAA+K,CAAS,EAAG,CAErB,MAAMiC,EACJ,6IAEIC,EAAQlC,EAAS,KAAK,EAAE,MAAMiC,CAAK,EAEpCC,GACH,KAAK,UAAU,2BAA2BlC,CAAQ,EAAE,EAGtD,KAAM,CAAE,MAAAxM,EAAO,IAAAE,EAAK,EAAAO,EAAG,KAAAkK,EAAM,MAAA6C,EAAO,SAAAmB,EAAU,UAAAC,EAAW,UAAAC,CAAU,EAAIH,EAAM,OAE7E,OAAO,IAAIF,GAAO,CAChB,MAAAxO,EACA,IAAK,SAASE,EAAK,EAAE,EACrB,MAAOO,EACP,KAAMkK,EACN,MAAO,SAAS6C,EAAO,EAAE,EACzB,SAAU,SAASmB,EAAU,EAAE,EAC/B,UAAW,SAASC,EAAW,EAAE,EACjC,UAAWC,CACb,CAAC,CACH,CAEA,YAAY,CAAE,SAAAhP,CAAS,EAAG,CACxB,KAAM,CAAE,MAAAG,EAAO,OAAAM,EAAQ,MAAAL,EAAO,IAAAC,EAAK,UAAAC,EAAW,SAAAC,CAAS,EAAI,KAAK,iBAAiBP,CAAQ,EACrFS,GAAU,KAAK,UAAU,GAAG,KAAK,UAAU,+BAA+B,EAE9E,MAAMsE,EAAQrE,EAAkBN,CAAK,EAErC,OAAO,IAAIuO,GAAO,CAChB,MAAAxO,EACA,IAAAE,EACA,KAAM,SACN,MAAQ0E,EAAM,CAAC,GAAK,EAAKA,EAAM,CAAC,EAChC,SAAUA,EAAM,CAAC,EACjB,UAAWA,EAAM,CAAC,EAClB,UAAWK,EAAcL,EAAM,SAAS,CAAC,CAAC,EAC1C,UAAAzE,EACA,SAAAC,CACF,CAAC,CACH,CAIA,WAAY,CACV,OAAO,KAAK,kBACVyD,EAAc,KAAK,IAAI,OAAO,CAAC,EAC7BnB,EAAa,KAAK,IAAI,UAAU,CAAC,EACjCA,EAAa,KAAK,IAAI,WAAW,CAAC,EAClC+B,EAAc,KAAK,IAAI,WAAW,EAAE,QAAQ,UAAW,EAAE,CAAC,CAC9D,CACF,CAEA,cAAe,CACb,MAAMqK,EAAW5J,EAAc,KAAK,IAAI,WAAW,EAAE,QAAQ,UAAW,EAAE,CAAC,EACrEN,EAAQ,IAAI,WAAW,EAAIkK,EAAS,MAAM,EAEhD,OADW,IAAI,SAASlK,EAAM,OAAQA,EAAM,UAAU,EACnD,UAAU,EAAG,KAAK,IAAI,OAAO,CAAC,EACjCA,EAAM,CAAC,EAAI,KAAK,IAAI,UAAU,EAC9BA,EAAM,CAAC,EAAI,KAAK,IAAI,WAAW,EAC/BA,EAAM,IAAIkK,EAAU,CAAC,EACdlK,CACT,CACF,CAEA,MAAMmK,WAAW1F,CAAG,CAClB,OAAO,SAAW,KAClB,OAAO,OAAS,GAChB,OAAO,KAAO,CAAC,KAAM,KAAM,IAAI,EAC/B,OAAO,YAAc,CAAC,CAAC,UAAW,KAAK,EAAG,YAAa,cAAe,CAAC,SAAU,KAAK,CAAC,EACvF,OAAO,KAAO,CAAC,QAAQ,EAEvB,YAAYP,EAAM,CAChB,MAAMA,CAAI,CACZ,CAGA,UAAUrH,EAAK,CACb,KAAK,cAAc,MAAO,UAAWA,CAAG,CAC1C,CAEA,UAAUA,EAAK,CACb,KAAK,cAAc,MAAO,SAAUA,CAAG,CACzC,CAEA,aAAaA,EAAK,CACX,KAAK,oBAAoB,EAAE,IAAIA,CAAG,GAAG,KAAK,UAAU,uBAAuB,EAEhF,KAAK,IAAI,YAAaA,CAAG,CAC3B,CAEA,qBAAsB,CAGpB,OAAO,IAAI,IAAI,CACb,CAAC,EAAG,SAAS,EACb,CAAC,EAAG,IAAI,EACR,CAAC,EAAG,WAAW,EACf,CAAC,EAAG,IAAI,EACR,CAAC,EAAG,WAAW,EACf,CAAC,EAAG,gBAAgB,EACpB,CAAC,EAAG,oBAAoB,EACxB,CAAC,EAAG,aAAa,EACjB,CAAC,GAAI,aAAa,EAClB,CAAC,GAAI,qBAAqB,EAC1B,CAAC,GAAI,qBAAqB,EAC1B,CAAC,GAAI,SAAS,EACd,CAAC,GAAI,OAAO,EACZ,CAAC,IAAK,EAAE,EACR,CAAC,IAAK,EAAE,CACV,CAAC,CACH,CAEA,cAAcA,EAAK,CAEZ,CAAC,EAAG,EAAG,CAAC,EAAE,SAASA,CAAG,GAAG,KAAK,UAAU,yBAAyB,EAEtE,KAAK,IAAI,cAAeA,CAAG,CAC7B,CAEA,gBAAiB,CACf,MAAO,mBACT,CAEA,cAAe,CACb,MAAO,CACL,MAAO,eACP,IAAK,KACL,MAAO,KACP,KAAM,KACN,UAAW,MACX,UAAW,EACX,cAAe,EACf,OAAQ,cACV,CACF,CAIA,YAAYqH,EAAM,CAChB,KAAM,CAAE,SAAAjJ,CAAS,EAAIiJ,EACf,CAAE,MAAA9I,EAAO,OAAAM,EAAQ,MAAAL,EAAO,IAAAC,EAAK,UAAAC,EAAW,SAAAC,CAAS,EAAI,KAAK,iBAAiBP,CAAQ,EACrFS,GAAU,KAAK,UAAU,GAAG,KAAK,UAAU,2BAA2B,EAE1E,MAAM0O,EAAWzO,EAAkBN,CAAK,EAExC,OAAO,IAAI8O,GAAG,CACZ,MAAA/O,EACA,IAAAE,EACA,KAAM,KACN,UAAY8O,EAAS,CAAC,GAAK,EAAKA,EAAS,CAAC,EAC1C,UAAWA,EAAS,CAAC,EACrB,cAAeA,EAAS,CAAC,EACzB,OAAQhK,EAAWgK,EAAS,SAAS,CAAC,CAAC,EAAE,YAAY,EACrD,UAAA7O,EACA,SAAAC,CACF,CAAC,CACH,CAEA,SAAS,CAAE,MAAAJ,EAAO,IAAAwG,EAAK,IAAAtG,EAAK,MAAAD,CAAM,EAAG,CACnC,MAAM4G,EAAK,IAAI,SAAS5G,EAAM,OAAQA,EAAM,UAAU,EACtD,OAAO,IAAI8O,GAAG,CACZ,MAAA/O,EACA,IAAAE,EACA,MAAOsG,EACP,KAAM,KACN,UAAWK,EAAG,UAAU,CAAC,EACzB,UAAW5G,EAAM,CAAC,EAClB,cAAeA,EAAM,CAAC,EACtB,OAAQ+E,EAAW/E,EAAM,SAAS,CAAC,CAAC,EAAE,YAAY,CACpD,CAAC,CACH,CAIA,WAAY,CACV,OAAO,KAAK,kBACV4D,EAAc,KAAK,IAAI,SAAS,CAAC,EAC/BnB,EAAa,KAAK,IAAI,WAAW,CAAC,EAClCA,EAAa,KAAK,IAAI,aAAa,CAAC,EACpCgB,EAAQ,KAAK,IAAI,QAAQ,EAAE,QAAQ,OAAQ,EAAE,CAAC,CAClD,CACF,CAEA,cAAe,CACb,MAAMuL,EAAcpK,EAAW,KAAK,IAAI,QAAQ,EAAE,QAAQ,OAAQ,EAAE,CAAC,EAC/DD,EAAQ,IAAI,WAAW,EAAIqK,EAAY,MAAM,EAEnD,OADW,IAAI,SAASrK,EAAM,OAAQA,EAAM,UAAU,EACnD,UAAU,EAAG,KAAK,IAAI,SAAS,CAAC,EACnCA,EAAM,CAAC,EAAI,KAAK,IAAI,WAAW,EAC/BA,EAAM,CAAC,EAAI,KAAK,IAAI,aAAa,EACjCA,EAAM,IAAIqK,EAAa,CAAC,EACjBrK,CACT,CACF,CAEA,MAAMsK,WAAc7F,CAAG,CACrB,OAAO,SAAW,QAClB,OAAO,OAAS,GAChB,OAAO,KAAO,CAAC,KAAM,KAAM,IAAI,EAC/B,OAAO,YAAc,CACnB,CAAC,MAAO,UAAU,EAClB,CAAC,KAAM,UAAU,CACnB,EACA,OAAO,KAAO,CAAC,UAAU,EAEzB,YAAYP,EAAM,CAChB,MAAMA,CAAI,CACZ,CAGA,OAAOrH,EAAK,CACNA,EAAI,OAAS,KAAK,KAAK,UAAU,mCAAmC,EACxE,KAAK,IAAI,MAAOA,EAAI,QAAQ,eAAgB,EAAE,CAAC,CACjD,CAEA,MAAMA,EAAK,CACLA,EAAI,OAAS,KAAK,KAAK,UAAU,kCAAkC,EACvE,KAAK,IAAI,KAAMA,EAAI,QAAQ,eAAgB,EAAE,CAAC,CAChD,CAEA,gBAAiB,CACf,MAAO,WACT,CAEA,cAAe,CACb,MAAO,CACL,MAAO,oBACP,IAAK,KACL,MAAO,KACP,KAAM,QACN,IAAK,WACL,GAAI,QACN,CACF,CAGA,YAAY,CAAE,SAAA5B,CAAS,EAAG,CAExB,KAAM,CAACmD,EAAM,CAAE/C,EAAOC,EAAKyL,EAAIC,CAAG,EAAI/L,EAAS,MAAM,CAAC,EAAE,MAAM,GAAG,EAC3D,CAACsP,EAAKC,CAAE,EAAI,CAAC,GAAGzM,GAAa1C,CAAK,CAAC,EAEzC,OAAO,IAAI,KAAK,YAAY,CAC1B,MAAO,KAAK,aAAa+C,CAAI,EAC7B,IAAK,SAAS9C,EAAK,EAAE,EACrB,KAAM,QACN,IAAAiP,EACA,GAAAC,EACA,UAAWzD,EACX,SAAUC,GAAK,KAAK,GAAK,EAC3B,CAAC,CACH,CAIA,cAAe,CACb,MAAMuD,EAAM,IAAI,YAAY,EAAE,OAAO,KAAK,IAAI,KAAK,CAAC,EAC9CC,EAAK,IAAI,YAAY,EAAE,OAAO,KAAK,IAAI,IAAI,CAAC,EAC5C7N,EAAS,IAAI,WAAW,EAAI4N,EAAI,OAASC,EAAG,MAAM,EACxD,OAAA7N,EAAO,CAAC,EAAI4N,EAAI,OAChB5N,EAAO,IAAI4N,EAAK,CAAC,EACjB5N,EAAO,EAAI4N,EAAI,MAAM,EAAIC,EAAG,OAC5B7N,EAAO,IAAI6N,EAAI,EAAID,EAAI,MAAM,EACtB5N,CACT,CAEA,WAAY,CACV,OAAO,KAAK,kBACV,CAACiB,GAAW,KAAK,IAAI,KAAK,CAAC,EAAGA,GAAW,KAAK,IAAI,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,CACnE,CACF,CACF,CAEA,MAAM6M,UAAYhG,CAAG,CACnB,OAAO,SAAW,MAClB,OAAO,OAAS,GAChB,OAAO,KAAO,CAAC,IAAI,EACnB,OAAO,YAAc,CAAC,eAAgB,MAAO,aAAc,oBAAoB,EAE/E,YAAYP,EAAM,CAChB,MAAMA,CAAI,CACZ,CAGA,eAAerH,EAAK,CACdA,IAAQ,QAAW,KAAK,UAAU,+BAA+B,EACrE,KAAK,UAAU,MAAO,eAAgBA,CAAG,EACzC,KAAK,IAAI,eAAgBA,CAAG,CAC9B,CAEA,OAAOA,EAAK,CACLA,GAAK,KAAK,UAAU,sBAAsB,EAC/C,KAAK,IAAI,MAAOA,CAAG,CACrB,CAEA,aAAaA,EAAK,CACXA,GAAK,KAAK,UAAU,6BAA6B,EACtD,KAAK,IAAI,aAAcA,CAAG,CAC5B,CAEA,qBAAqBA,EAAK,CACxB,KAAK,IAAI,qBAAsBA,GAAO,EAAE,CAC1C,CAEA,gBAAiB,CACf,MAAO,wBACT,CAEA,cAAe,CACb,MAAO,CACL,MAAO,eACP,IAAK,KACL,MAAO,KACP,KAAM,MACN,eAAgB,EAChB,IAAK,mCACL,aACE,+GACF,qBAAsB,EACxB,CACF,CAGA,YAAY,CAAE,SAAA5B,CAAS,EAAG,CAExB,KAAM,CAACmD,EAAMY,EAAG3D,EAAOC,EAAKyL,EAAIC,CAAG,EAAI/L,EAAS,MAAM,CAAC,EAAE,MAAM,GAAG,EAC9D+D,GAAK,IAAI,KAAK,UAAU,4BAA4B,EAExD,MAAMgB,EAAQ,WAAW,KAAKpE,EAAYP,CAAK,EAAIQ,GAAMA,EAAE,WAAW,CAAC,CAAC,EAClE6O,EAAS1K,EAAM,CAAC,EAChB2K,EAAc3K,EAAM,CAAC,EACrB4K,EAAS5K,EAAM,CAAC,GAAK,EAAKA,EAAM,CAAC,EAEjC6K,EAAMzK,EAAWJ,EAAM,SAAS,EAAG,EAAI0K,CAAM,CAAC,EAAE,YAAY,EAC5DI,EAAYzK,EAAcL,EAAM,SAAS,EAAI0K,EAAQ,EAAIA,EAASE,CAAK,CAAC,EAExEG,EAAW,CAAC,EAClB,IAAI7O,EAAM,EAAIwO,EAASE,EACvB,KAAO1O,EAAM8D,EAAM,QAAQ,CACzB,KAAM,CAACgL,EAAMC,CAAM,EAAIzM,EACrB,CAAC,GAAGwB,EAAM,SAAS9D,CAAG,CAAC,EACpB,IAAK4D,GAAOA,EAAI,IAAMA,EAAI,IAAMhC,EAAagC,CAAC,EAAI,OAAO,aAAaA,CAAC,CAAE,EACzE,KAAK,EAAE,CACZ,EACA5D,GAAO+O,EACHD,IAAS,KAAKD,EAAS,KAAKC,CAAI,CACtC,CAEA,OAAO,IAAIP,EAAI,CACb,MAAO,KAAK,aAAarM,CAAI,EAC7B,IAAK,SAAS9C,EAAK,EAAE,EACrB,KAAM,MACN,eAAgBqP,EAChB,IAAAE,EACA,aAAcC,EACd,qBAAsBC,EAAS,KAAK,GAAG,EACvC,UAAWhE,EACX,SAAUC,GAAK,KAAK,GAAK,EAC3B,CAAC,CACH,CAEA,SAAS,CAAE,SAAAY,CAAS,EAAG,CAIrB,MAAMzM,EAAQyM,EAAS,MAAM,KAAK,EAC5B,CAACxM,EAAOE,EAAKO,EAAGkK,EAAM4E,EAAaE,CAAG,EAAI1P,EAC1C6M,EAAO7M,EAAM,MAAM,CAAC,EACpB+P,EAAW,CAAC,EACZC,EAAW,CAAC,EAClB,UAAWnH,KAASgE,EACd,oBAAoB,KAAKhE,CAAK,EAChCkH,EAAS,KAAKlH,CAAK,EAEnBmH,EAAS,KAAKnH,CAAK,EAGvB,OAAO,IAAIyG,EAAI,CACb,MAAArP,EACA,IAAK,SAASE,EAAK,EAAE,EACrB,MAAOO,EACP,KAAAkK,EACA,eAAgB,SAAS4E,EAAa,EAAE,EACxC,IAAAE,EACA,aAAcK,EAAS,KAAK,EAAE,EAC9B,qBAAsBC,EAAS,KAAK,GAAG,EAAE,KAAK,CAChD,CAAC,CACH,CAEA,SAAS,CAAE,MAAA/P,EAAO,IAAAwG,EAAK,IAAAtG,EAAK,MAAAD,CAAM,EAAG,CACnC,MAAM4G,EAAK,IAAI,SAAS5G,EAAM,OAAQA,EAAM,UAAU,EAChDqP,EAASrP,EAAM,CAAC,EAChBsP,EAActP,EAAM,CAAC,EACrBuP,EAAQ3I,EAAG,UAAU,CAAC,EACtB4I,EAAMzK,EAAW/E,EAAM,SAAS,EAAG,EAAIqP,CAAM,CAAC,EAAE,YAAY,EAC5DI,EAAYzK,EAAchF,EAAM,SAAS,EAAIqP,EAAQ,EAAIA,EAASE,CAAK,CAAC,EACxEG,EAAW,CAAC,EAClB,IAAI7O,EAAM,EAAIwO,EAASE,EACvB,KAAO1O,EAAMb,EAAM,QAAQ,CACzB,KAAM,CAAE,KAAA+C,EAAM,IAAAqD,CAAI,EAAI,KAAK,iBAAiBpG,EAAOa,CAAG,EACtD6O,EAAS,KAAK3M,CAAI,EAClBlC,EAAMuF,CACR,CACA,OAAO,IAAIgJ,EAAI,CACb,MAAArP,EACA,IAAAE,EACA,MAAOsG,EACP,KAAM,MACN,eAAgB+I,EAChB,IAAAE,EACA,aAAcC,EACd,qBAAsBC,EAAS,KAAK,GAAG,CACzC,CAAC,CACH,CAGA,OAAOxG,EAAW,CAChB,MAAM6G,EAAK,KAAK,IAAI,oBAAoB,EAClCC,EAASD,EAAK,IAAKA,CAAE,GAAK,GAChC,MAAO,GAAG,KAAK,UAAU7G,CAAS,CAAC,IAAK,KAAK,IAAI,cAAc,CAAC,IAAK,KAAK,IAAI,KAAK,CAAC,IAAK,KAAK,IAAI,YAAY,CAAC,GAAG8G,CAAM;AAAA,CAC1H,CAEA,WAAY,CACV,MAAMC,EAAS,KAAK,IAAI,KAAK,EACvBC,EAAWtL,EAAWqL,CAAM,EAC5BE,EAAUlL,EAAc,KAAK,IAAI,YAAY,CAAC,EAC9C8K,EAAK,KAAK,IAAI,oBAAoB,EAExC,IAAI/P,EAAQ,GACZA,GAASyC,EAAayN,EAAS,MAAM,EACrClQ,GAASyC,EAAa,KAAK,IAAI,cAAc,CAAC,EAC9CzC,GAAS4D,EAAcuM,EAAQ,MAAM,EACrC,UAAW1L,KAAKyL,EAAUlQ,GAASyC,EAAagC,CAAC,EACjD,UAAWA,KAAK0L,EAASnQ,GAASyC,EAAagC,CAAC,EAChD,GAAIsL,EACF,UAAWJ,KAAQI,EAAG,MAAM,KAAK,EAAG/P,GAAS8C,EAAe6M,CAAI,EAGlE,OAAO,KAAK,kBAAkB3P,CAAK,CACrC,CAEA,cAAe,CACb,MAAMiQ,EAAS,KAAK,IAAI,KAAK,EACvBC,EAAWtL,EAAWqL,CAAM,EAC5BE,EAAUlL,EAAc,KAAK,IAAI,YAAY,CAAC,EAC9C8K,EAAK,KAAK,IAAI,oBAAoB,EAGlCK,GADUL,EAAKA,EAAG,MAAM,KAAK,EAAI,CAAC,GACd,IAAKJ,GAASrK,EAAeqK,CAAI,CAAC,EACtDU,EAAaD,EAAU,OAAO,CAAC/C,EAAK5I,IAAM4I,EAAM5I,EAAE,OAAQ,CAAC,EAE3D2I,EAAW,EAAY8C,EAAS,OAASC,EAAQ,OAASE,EAC1D1L,EAAQ,IAAI,WAAWyI,CAAQ,EAC/BxG,EAAK,IAAI,SAASjC,EAAM,OAAQA,EAAM,UAAU,EAEtD,IAAI9D,EAAM,EACV8D,EAAM9D,GAAK,EAAIqP,EAAS,OACxBvL,EAAM9D,GAAK,EAAI,KAAK,IAAI,cAAc,EACtC+F,EAAG,UAAU/F,EAAKsP,EAAQ,MAAM,EAChCtP,GAAO,EACP8D,EAAM,IAAIuL,EAAUrP,CAAG,EACvBA,GAAOqP,EAAS,OAChBvL,EAAM,IAAIwL,EAAStP,CAAG,EACtBA,GAAOsP,EAAQ,OACf,UAAWG,KAAWF,EACpBzL,EAAM,IAAI2L,EAASzP,CAAG,EACtBA,GAAOyP,EAAQ,OAGjB,OAAO3L,CACT,CACF,CAEA,MAAM4L,WAAcnH,CAAG,CACrB,OAAO,SAAW,QAClB,OAAO,OAAS,GAChB,OAAO,KAAO,CAAC,IAAI,EACnB,OAAO,KAAO,CAAC,QAAQ,EACvB,OAAO,YAAc,CACnB,CAAC,WAAY,KAAK,EAClB,CAAC,cAAe,MAAM,EACtB,CAAC,SAAU,WAAW,CACxB,EAEA,YAAYP,EAAM,CAChB,MAAMA,CAAI,CACZ,CAGA,YAAYrH,EAAK,CACf,KAAK,WAAW,QAAS,WAAYA,CAAG,EAExC,KAAK,IAAI,WAAYA,CAAG,CAC1B,CAEA,cAAcA,EAAK,CAKjB,KAAK,IAAI,cAAeA,EAAI,YAAY,CAAC,CAC3C,CAEA,UAAUA,EAAK,CAGb,KAAK,IAAI,SAAUA,CAAG,CACxB,CAEA,gBAAiB,CACf,MAAO,gBACT,CAEA,cAAe,CACb,MAAO,CACL,MAAO,eACP,IAAK,KACL,MAAO,KACP,KAAM,QACN,SAAU,EACV,cAAe,eACf,OAAQ,cACV,CACF,CAIA,SAAS,CAAE,SAAA+K,CAAS,EAAG,CAErB,KAAM,CAACxM,EAAOE,EAAKO,EAAGkK,EAAM8F,EAAKzN,CAAI,EAAIwJ,EAAS,MAAM,KAAK,EAC7D,OAAO,IAAIgE,GAAM,CACf,MAAAxQ,EACA,IAAK,SAASE,EAAK,EAAE,EACrB,MAAOO,EACP,KAAAkK,EACA,SAAU,SAAS8F,EAAK,EAAE,EAC1B,cAAezN,EACf,OAAQwJ,EAAS,MAAM,KAAK,EAAE,MAAM,CAAC,EAAE,KAAK,GAAG,EAAE,KAAK,CACxD,CAAC,CACH,CAEA,YAAY,CAAE,SAAA3M,CAAS,EAAG,CACxB,KAAM,CAAE,MAAAG,EAAO,OAAAM,EAAQ,MAAAL,EAAO,IAAAC,EAAK,UAAAC,EAAW,SAAAC,CAAS,EAAI,KAAK,iBAAiBP,CAAQ,EACrFS,GAAU,KAAK,UAAU,GAAG,KAAK,UAAU,8BAA8B,EAC7E,KAAM,CAAE,SAAAO,EAAU,WAAA6P,EAAY,OAAAC,CAAO,EAAIjQ,GAAmBT,EAAO,OAAO,EAE1E,OAAO,IAAIuQ,GAAM,CACf,MAAAxQ,EACA,IAAAE,EACA,KAAM,QACN,SAAAW,EACA,cAAe6P,EACf,OAAAC,EACA,UAAAxQ,EACA,SAAAC,CACF,CAAC,CACH,CAIA,WAAY,CACV,MAAMwQ,EAAS,IAAI,OAAO,eAAgB,GAAG,EAE7C,OAAO,KAAK,kBACV/M,EAAc,KAAK,IAAI,UAAU,CAAC,EAChCd,EAAe,KAAK,IAAI,aAAa,CAAC,EACtCrB,EAAYkP,EAAQ,KAAK,IAAI,QAAQ,CAAC,CAC1C,CACF,CAEA,cAAe,CACb,MAAMC,EAAc,KAAK,eAAe,KAAK,IAAI,aAAa,CAAC,EACzDC,EAAcxJ,GAAgB,KAAK,IAAI,QAAQ,CAAC,EAChD/F,EAAS,IAAI,WAAW,EAAIsP,EAAY,OAASC,EAAY,MAAM,EACzE,WAAI,SAASvP,EAAO,MAAM,EAAE,UAAU,EAAG,KAAK,IAAI,UAAU,CAAC,EAC7DA,EAAO,IAAIsP,EAAa,CAAC,EACzBtP,EAAO,IAAIuP,EAAa,EAAID,EAAY,MAAM,EACvCtP,CACT,CACF,CAEA,MAAMwP,UAAiB1H,CAAG,CACxB,OAAO,SAAW,WAClB,OAAO,OAAS,GAChB,OAAO,KAAO,CAAC,IAAI,EACnB,OAAO,YAAc,CAAC,aAAc,eAAgB,YAAa,UAAW,WAAW,EACvF,OAAO,KAAO,CAAC,UAAU,EAEzB,YAAYP,EAAM,CAChB,MAAMA,CAAI,CACZ,CAGA,cAAcrH,EAAK,CAEjB,KAAK,UAAU,WAAY,aAAcA,CAAG,EAE5C,KAAK,IAAI,aAAcA,CAAG,CAC5B,CAEA,eAAeA,EAAK,CACb,KAAK,sBAAsB,EAAE,IAAIA,CAAG,GAAG,KAAK,UAAU,mCAAmC,EAE9F,KAAK,IAAI,eAAgBA,CAAG,CAC9B,CAEA,uBAAwB,CACtB,OAAO,IAAI,IAAI,CACb,CAAC,EAAG,MAAM,EACV,CAAC,EAAG,aAAa,EACjB,CAAC,EAAG,cAAc,EAClB,CAAC,EAAG,0BAA0B,CAChC,CAAC,CACH,CAEA,aAAaA,EAAK,CACX,KAAK,oBAAoB,EAAE,IAAIA,CAAG,GAAG,KAAK,UAAU,6BAA6B,EAEtF,KAAK,IAAI,YAAaA,CAAG,CAC3B,CAEA,qBAAsB,CACpB,OAAO,IAAI,IAAI,CACb,CAAC,EAAG,KAAK,EACT,CAAC,EAAG,KAAK,CACX,CAAC,CACH,CAEA,WAAWA,EAAK,CACd,MAAMkJ,EAAO,KAAK,IAAI,cAAc,EAC9BqG,EAAQ,IAAI,MAAM,8BAA8BvP,CAAG,cAAckJ,CAAI,EAAE,EAC7E,OAAQA,EAAM,CACZ,IAAK,GACH,GAAIlJ,IAAQ,IAAK,MAAMuP,EACvB,MACF,IAAK,GACH,GAAI,CAAC,KAAK,OAAOvP,CAAG,EAAG,MAAMuP,EAC7B,MACF,IAAK,GACH,GAAI,CAAC,KAAK,OAAOvP,CAAG,EAAG,MAAMuP,EAC7B,KACJ,CAEA,KAAK,IAAI,UAAWvP,CAAG,CACzB,CAEA,aAAaA,EAAK,CACZA,GAAK,KAAK,SAAS,WAAY,YAAaA,CAAG,EACnD,KAAK,IAAI,YAAaA,CAAG,CAC3B,CAEA,gBAAiB,CACf,MAAO,cACT,CAEA,cAAe,CACb,MAAO,CACL,MAAO,2BACP,IAAK,KACL,MAAO,KACP,KAAM,WACN,WAAY,GACZ,eAAgB,EAChB,UAAW,EACX,QAAS,aACT,UAAW,kDACb,CACF,CAGA,SAAS,CAAE,SAAA+K,CAAS,EAAG,CAErB,KAAM,CAACxM,EAAOE,EAAKO,EAAGkK,EAAMsG,EAAMC,EAAKhD,EAAMiD,EAAStC,CAAS,EAAIrC,EAAS,MAAM,KAAK,EACvF,OAAO,IAAIuE,EAAS,CAClB,MAAA/Q,EACA,IAAK,SAASE,EAAK,EAAE,EACrB,MAAOO,EACP,KAAAkK,EACA,WAAY,SAASsG,EAAM,EAAE,EAC7B,eAAgB,SAASC,EAAK,EAAE,EAChC,UAAW,SAAShD,EAAM,EAAE,EAC5B,QAAAiD,EACA,UAAAtC,CACF,CAAC,CACH,CAEA,YAAY,CAAE,SAAAhP,CAAS,EAAG,CACxB,KAAM,CAACmD,EAAMY,EAAG3D,EAAOC,EAAKyL,EAAIC,CAAG,EAAI/L,EAAS,MAAM,CAAC,EAAE,MAAM,GAAG,EAC9D+D,GAAK,IAAI,KAAK,UAAU,iCAAiC,EAE7D,MAAMwN,EAAanP,EAAahC,EAAM,MAAM,EAAG,CAAC,CAAC,EAC3CoR,EAASpP,EAAahC,EAAM,MAAM,EAAG,CAAC,CAAC,EACvC2O,EAAY3M,EAAahC,EAAM,MAAM,EAAG,EAAE,CAAC,EAEjD,IAAIe,EAAKmQ,EAASG,EAElB,OAAQD,EAAQ,CACd,IAAK,GACHF,EAAUlR,EAAM,MAAM,GAAI,EAAE,EAC5BqR,EAAWrR,EAAM,MAAM,EAAE,EACzB,MACF,IAAK,GACHkR,EAAUjN,GAAYjE,EAAM,MAAM,GAAI,EAAE,CAAC,EACzCqR,EAAWrR,EAAM,MAAM,EAAE,EACzB,MACF,IAAK,GACHkR,EAAU3M,GAAYvE,EAAM,MAAM,GAAI,EAAE,CAAC,EACzCqR,EAAWrR,EAAM,MAAM,EAAE,EACzB,MACF,IAAK,GACX,CAACkR,EAASnQ,CAAG,EAAIoC,EAAiBnD,EAAM,MAAM,EAAE,CAAC,EACzCqR,EAAWrR,EAAM,MAAM,GAAKe,CAAG,EAC/B,KACJ,CAEA,OAAO,IAAI+P,EAAS,CAClB,MAAO,KAAK,aAAa/N,CAAI,EAC7B,IAAK,SAAS9C,EAAK,EAAE,EACrB,KAAM,WACN,WAAAkR,EACA,eAAgBC,EAChB,UAAAzC,EACA,QAAAuC,EACA,UAAWxM,GAAc2M,CAAQ,EACjC,UAAW3F,EACX,SAAUC,GAAK,KAAK,GAAK,EAC3B,CAAC,CACH,CAEA,SAAS,CAAE,MAAA5L,EAAO,IAAAwG,EAAK,IAAAtG,EAAK,MAAAD,CAAM,EAAG,CACnC,MAAMmR,EAAanR,EAAM,CAAC,EACpBoR,EAASpR,EAAM,CAAC,EAChB2O,EAAY3O,EAAM,CAAC,EACzB,IAAIkR,EAASI,EACb,OAAQF,EAAQ,CACd,IAAK,GACHF,EAAU,IACVI,EAAW,EACX,MACF,IAAK,GACHJ,EAAU,CAAC,GAAGlR,EAAM,SAAS,EAAG,CAAC,CAAC,EAAE,KAAK,GAAG,EAC5CsR,EAAW,EACX,MACF,IAAK,GAAG,CACN,MAAM1K,EAAK,IAAI,SAAS5G,EAAM,OAAQA,EAAM,WAAa,CAAC,EACpDsI,EAAS,CAAC,EAChB,QAAS/G,EAAI,EAAGA,EAAI,GAAIA,GAAK,EAAG+G,EAAO,KAAK1B,EAAG,UAAUrF,CAAC,EAAE,SAAS,EAAE,EAAE,SAAS,EAAG,GAAG,CAAC,EACzF2P,EAAU5I,EAAO,KAAK,GAAG,EACzBgJ,EAAW,GACX,KACF,CACA,IAAK,GAAG,CACN,KAAM,CAAE,KAAAvO,EAAM,IAAAqD,CAAI,EAAI,KAAK,iBAAiBpG,EAAO,CAAC,EACpDkR,EAAUnO,EACVuO,EAAWlL,EACX,KACF,CACF,CACA,MAAMwI,EAAY5J,EAAchF,EAAM,SAASsR,CAAQ,CAAC,EACxD,OAAO,IAAIR,EAAS,CAClB,MAAA/Q,EACA,IAAAE,EACA,MAAOsG,EACP,KAAM,WACN,WAAA4K,EACA,eAAgBC,EAChB,UAAAzC,EACA,QAAAuC,EACA,UAAAtC,CACF,CAAC,CACH,CAIA,WAAY,CACV,MAAM2C,EAAU,IAAI,OAAO,eAAgB,GAAG,EAE9C,IAAIvR,EAAQ,GAKZ,OAJAA,GAASyC,EAAa,KAAK,IAAI,YAAY,CAAC,EAC5CzC,GAASyC,EAAa,KAAK,IAAI,cAAc,CAAC,EAC9CzC,GAASyC,EAAa,KAAK,IAAI,WAAW,CAAC,EAEnC,KAAK,IAAI,cAAc,EAAG,CAChC,IAAK,GACHzC,GAASyB,EAAY8P,EAAS,GAAG,EACjC,MACF,IAAK,GACHvR,GAAS8D,GAAY,KAAK,IAAI,SAAS,CAAC,EACxC,MACF,IAAK,GACH9D,GAASsE,GAAY,KAAK,IAAI,SAAS,CAAC,EACxC,MACF,IAAK,GACHtE,GAAS8C,EAAe,KAAK,IAAI,SAAS,CAAC,EAC3C,KACJ,CAEA,OAAA9C,GAASwE,EAAc,KAAK,IAAI,WAAW,CAAC,EAErC,KAAK,kBAAkBxE,CAAK,CACrC,CAEA,cAAe,CACb,MAAMwR,EAAcvM,EAAc,KAAK,IAAI,WAAW,CAAC,EACjDmM,EAAS,KAAK,IAAI,cAAc,EAEtC,IAAIK,EACJ,OAAQL,EAAQ,CACd,IAAK,GACHK,EAAU,IAAI,WAAW,CAAC,EAC1B,MACF,IAAK,GACHA,EAAU,IAAI,WAAW,CAAC,EAC1B,KAAK,IAAI,SAAS,EACf,MAAM,GAAG,EACT,QAAQ,CAACC,EAAMnQ,IAAM,CACpBkQ,EAAQlQ,CAAC,EAAI,SAASmQ,EAAM,EAAE,CAChC,CAAC,EACH,MACF,IAAK,GACHD,EAAU,IAAI,WAAW,EAAE,EAC3B,CACE,MAAM3R,EAAQ,KAAK,IAAI,SAAS,EAAE,MAAM,GAAG,EAC3C,IAAIe,EAAM,EACV,UAAW6Q,KAAQ5R,EAAO,CACxB,GAAI4R,IAAS,GAAI,SACjB,MAAMlQ,EAAM,SAASkQ,EAAM,EAAE,EAC7BD,EAAQ5Q,GAAK,EAAKW,IAAQ,EAAK,IAC/BiQ,EAAQ5Q,GAAK,EAAIW,EAAM,GACzB,CACF,CACA,MACF,IAAK,GACHiQ,EAAUnM,EAAe,KAAK,IAAI,SAAS,CAAC,EAC5C,KACJ,CAEA,MAAMX,EAAQ,IAAI,WAAW,EAAI8M,EAAQ,OAASD,EAAY,MAAM,EACpE,OAAA7M,EAAM,CAAC,EAAI,KAAK,IAAI,YAAY,EAChCA,EAAM,CAAC,EAAIyM,EACXzM,EAAM,CAAC,EAAI,KAAK,IAAI,WAAW,EAC/BA,EAAM,IAAI8M,EAAS,CAAC,EACpB9M,EAAM,IAAI6M,EAAa,EAAIC,EAAQ,MAAM,EAElC9M,CACT,CACF,CAEA,MAAMgN,WAAYvI,CAAG,CACnB,OAAO,SAAW,MAClB,OAAO,OAAS,GAChB,OAAO,KAAO,CAAC,KAAM,KAAM,KAAM,IAAI,EACrC,OAAO,YAAc,CACnB,CAAC,QAAS,KAAK,EACf,CAAC,WAAY,IAAI,EACjB,CAAC,YAAa,IAAI,EAClB,CAAC,YAAa,QAAQ,CACxB,EACA,OAAO,KAAO,CAAC,UAAU,EAEzB,YAAYP,EAAM,CAChB,MAAMA,CAAI,CACZ,CAGA,SAASrH,EAAK,CAEZ,KAAK,WAAW,MAAO,QAASA,CAAG,EAEnC,KAAK,IAAI,QAASA,CAAG,CACvB,CAEA,YAAYA,EAAK,CAEf,KAAK,UAAU,MAAO,WAAYA,CAAG,EAErC,KAAK,IAAI,WAAYA,CAAG,CAC1B,CAEA,aAAaA,EAAK,CAGX,KAAK,oBAAoB,EAAE,IAAIA,CAAG,GAAG,KAAK,UAAU,wBAAwB,EAEjF,KAAK,IAAI,YAAaA,CAAG,CAC3B,CAEA,qBAAsB,CACpB,OAAO,IAAI,IAAI,CACb,CAAC,EAAG,SAAS,EACb,CAAC,EAAG,IAAI,EACR,CAAC,EAAG,WAAW,EACf,CAAC,EAAG,IAAI,EACR,CAAC,EAAG,WAAW,EACf,CAAC,IAAK,EAAE,EACR,CAAC,IAAK,EAAE,CACV,CAAC,CACH,CAEA,aAAaA,EAAK,CACXA,GAAK,KAAK,UAAU,4BAA4B,EACrD,KAAK,SAAS,MAAO,YAAaA,EAAI,QAAQ,UAAW,EAAE,CAAC,EAC5D,KAAK,IAAI,YAAaA,CAAG,CAC3B,CAEA,gBAAiB,CACf,MAAO,gBACT,CAEA,cAAe,CACb,MAAO,CACL,MAAO,eACP,IAAK,KACL,MAAO,KACP,KAAM,MACN,MAAO,IACP,SAAU,EACV,UAAW,EACX,UACE,8GACJ,CACF,CAIA,SAAS,CAAE,SAAA+K,CAAS,EAAG,CAErB,KAAM,CAACxM,EAAOE,EAAKO,EAAGkK,EAAM6C,EAAOmB,EAAUC,CAAS,EAAIpC,EAAS,MAAM,KAAK,EAC9E,OAAO,IAAIoF,GAAI,CACb,MAAA5R,EACA,IAAK,SAASE,EAAK,EAAE,EACrB,MAAOO,EACP,KAAMkK,EACN,MAAO,SAAS6C,EAAO,EAAE,EACzB,SAAU,SAASmB,EAAU,EAAE,EAC/B,UAAW,SAASC,EAAW,EAAE,EACjC,UAAWpC,EAAS,MAAM,KAAK,EAAE,MAAM,CAAC,EAAE,KAAK,GAAG,EAAE,KAAK,CAC3D,CAAC,CACH,CAEA,YAAY,CAAE,SAAA3M,CAAS,EAAG,CAExB,KAAM,CAAE,MAAAG,EAAO,MAAAC,EAAO,IAAAC,EAAK,UAAAC,EAAW,SAAAC,CAAS,EAAI,KAAK,iBAAiBP,CAAQ,EACjF,OAAII,EAAM,OAAS,IACjB,KAAK,UAAU,yBAAyBA,CAAK,EAAE,EAG1C,IAAI2R,GAAI,CACb,MAAA5R,EACA,IAAAE,EACA,KAAM,MACN,MAAOgC,EAAcjC,EAAM,MAAM,EAAG,CAAC,CAAC,EACtC,SAAUgC,EAAahC,EAAM,MAAM,EAAG,EAAE,CAAC,EACzC,UAAWgC,EAAahC,EAAM,MAAM,GAAI,EAAE,CAAC,EAC3C,UAAW0E,GAAc1E,EAAM,MAAM,EAAE,CAAC,EACxC,UAAAE,EACA,SAAAC,CACF,CAAC,CACH,CAGA,WAAY,CACV,OAAO,KAAK,kBACVyD,EAAc,KAAK,IAAI,OAAO,CAAC,EAC7BnB,EAAa,KAAK,IAAI,UAAU,CAAC,EACjCA,EAAa,KAAK,IAAI,WAAW,CAAC,EAClC+B,EAAc,KAAK,IAAI,WAAW,EAAE,QAAQ,UAAW,EAAE,CAAC,CAC9D,CACF,CAEA,cAAe,CACb,MAAMqK,EAAW5J,EAAc,KAAK,IAAI,WAAW,EAAE,QAAQ,UAAW,EAAE,CAAC,EACrEN,EAAQ,IAAI,WAAW,EAAIkK,EAAS,MAAM,EAEhD,OADW,IAAI,SAASlK,EAAM,OAAQA,EAAM,UAAU,EACnD,UAAU,EAAG,KAAK,IAAI,OAAO,CAAC,EACjCA,EAAM,CAAC,EAAI,KAAK,IAAI,UAAU,EAC9BA,EAAM,CAAC,EAAI,KAAK,IAAI,WAAW,EAC/BA,EAAM,IAAIkK,EAAU,CAAC,EACdlK,CACT,CACF,CAEA,MAAMiN,WAAWxI,CAAG,CAClB,OAAO,SAAW,KAClB,OAAO,OAAS,GAChB,OAAO,KAAO,CAAC,IAAI,EACnB,OAAO,YAAc,CACnB,CAAC,aAAc,KAAK,EACpB,CAAC,YAAa,MAAM,CACtB,EAEA,YAAYP,EAAM,CAChB,MAAMA,CAAI,CACZ,CAGA,cAAcrH,EAAK,CACbA,IAAQ,QAAW,KAAK,UAAU,4BAA4B,EAClE,KAAK,WAAW,KAAM,aAAcA,CAAG,EACvC,KAAK,IAAI,aAAcA,CAAG,CAC5B,CAEA,aAAaA,EAAK,CACXA,GAAK,KAAK,UAAU,2BAA2B,EAEpD,KAAK,iBAAiB,KAAM,YAAaA,CAAG,EAC5C,KAAK,gBAAgB,KAAM,YAAaA,CAAG,EAE3C,KAAK,IAAI,YAAaA,EAAI,YAAY,CAAC,CACzC,CAEA,gBAAiB,CACf,MAAO,eACT,CAEA,cAAe,CACb,MAAO,CACL,MAAO,eACP,IAAK,KACL,MAAO,KACP,KAAM,KACN,WAAY,GACZ,UAAW,iBACb,CACF,CAGA,YAAY,CAAE,SAAA5B,CAAS,EAAG,CAExB,KAAM,CAACmD,EAAMY,EAAG3D,EAAOC,EAAKyL,EAAIC,CAAG,EAAI/L,EAAS,MAAM,CAAC,EAAE,MAAM,GAAG,EAClE,OAAI+D,GAAK,IAAI,KAAK,UAAU,2BAA2B,EAEhD,IAAIiO,GAAG,CACZ,MAAO,KAAK,aAAa7O,CAAI,EAC7B,IAAK,SAAS9C,EAAK,EAAE,EACrB,KAAM,KACN,WAAYgC,EAAcjC,EAAM,MAAM,EAAG,CAAC,CAAC,EAC3C,UAAWmD,EAAiBnD,EAAM,MAAM,CAAC,CAAC,EAAE,CAAC,EAC7C,UAAW0L,EACX,SAAUC,GAAK,KAAK,GAAK,EAC3B,CAAC,CACH,CAIA,cAAe,CACb,MAAMkG,EAAY,KAAK,eAAe,KAAK,IAAI,WAAW,CAAC,EACrDvQ,EAAS,IAAI,WAAW,EAAIuQ,EAAU,MAAM,EAElD,OADW,IAAI,SAASvQ,EAAO,MAAM,EAClC,UAAU,EAAG,KAAK,IAAI,YAAY,CAAC,EACtCA,EAAO,IAAIuQ,EAAW,CAAC,EAChBvQ,CACT,CAEA,WAAY,CACV,OAAO,KAAK,kBACVsC,EAAc,KAAK,IAAI,YAAY,CAAC,EAAId,EAAe,KAAK,IAAI,WAAW,CAAC,CAC9E,CACF,CACF,CAEA,MAAMgP,EAAM,CAEV,OAAQ,GAAK,GACb,SAAU,IAAS,GACrB,EAEMC,EAAO,CACX,IAAK,IACL,IAAK,GAAK,IACV,IAAK,KAAU,GACjB,EAEA,MAAMC,UAAY5I,CAAG,CACnB,OAAO,SAAW,MAClB,OAAO,OAAS,GAChB,OAAO,KAAO,CAAC,IAAI,EACnB,OAAO,YAAc,CAAC,SAAS,EAE/B,YAAYP,EAAM,CAChB,MAAMA,CAAI,CACZ,CAGA,WAAWrH,EAAK,CACTA,GAAK,KAAK,UAAU,0BAA0B,EAOnD,KAAK,SAASA,CAAG,EAEjB,KAAK,IAAI,UAAWA,CAAG,CACzB,CAEA,gBAAiB,CACf,MAAO,UACT,CAEA,cAAe,CACb,MAAO,CACL,MAAO,eACP,IAAK,KACL,MAAO,KACP,KAAM,MACN,QAAS,8CACX,CACF,CAEA,SAASsJ,EAAQ,CAEf,MAAMmH,EAAM,8CAGNC,EAAM,4EAGNC,EAAQ,IAAI,OAAO,IAAIF,CAAG,YAAYA,CAAG,YAAYC,CAAG,GAAI,GAAG,EAC/DxO,EAAIoH,EAAO,MAAMqH,CAAK,EAC5B,OAAKzO,GAAG,KAAK,UAAU,2CAA2C,EAEtD,CACV,SAAU,CACR,QAASA,EAAE,CAAC,EACZ,QAASA,EAAE,CAAC,EACZ,QAASA,EAAE,CAAC,EACZ,WAAYA,EAAE,CAAC,EAAE,YAAY,CAC/B,EACA,UAAW,CACT,QAASA,EAAE,CAAC,EACZ,QAASA,EAAE,CAAC,EACZ,QAASA,EAAE,CAAC,EACZ,WAAYA,EAAE,CAAC,EAAE,YAAY,CAC/B,EACA,SAAUA,EAAE,CAAC,EAAI,IACjB,KAAMA,EAAE,EAAE,EAAI,IACd,UAAW,CACT,WAAYA,EAAE,EAAE,EAAI,IACpB,SAAUA,EAAE,EAAE,EAAI,GACpB,CACF,CAGF,CAGA,YAAY,CAAE,SAAA9D,CAAS,EAAG,CAExB,KAAM,CAACmD,EAAMY,EAAG3D,EAAOC,EAAKyL,EAAIC,CAAG,EAAI/L,EAAS,MAAM,CAAC,EAAE,MAAM,GAAG,EAC9D+D,GAAK,IAAI,KAAK,UAAU,4BAA4B,EAGxD,MAAMmG,EAAI,CACR,QAAS9H,EAAahC,EAAM,MAAM,EAAG,CAAC,CAAC,EACvC,KAAM,KAAK,aAAagC,EAAahC,EAAM,MAAM,EAAG,CAAC,CAAC,CAAC,EACvD,UAAW,CACT,WAAY,KAAK,aAAagC,EAAahC,EAAM,MAAM,EAAG,EAAE,CAAC,CAAC,EAC9D,SAAU,KAAK,aAAagC,EAAahC,EAAM,MAAM,GAAI,EAAE,CAAC,CAAC,CAC/D,EACA,SAAU,KAAK,YAAYkC,GAAclC,EAAM,MAAM,GAAI,EAAE,CAAC,EAAG,KAAK,EACpE,UAAW,KAAK,YAAYkC,GAAclC,EAAM,MAAM,GAAI,EAAE,CAAC,EAAG,KAAK,EACrE,SAAUkC,GAAclC,EAAM,MAAM,GAAI,EAAE,CAAC,EAAI8R,EAAI,QACrD,EAEA,OAAO,IAAIE,EAAI,CACb,KAAM,MACN,MAAO,KAAK,aAAajP,CAAI,EAC7B,QAAS,KAAK,QAAQ+G,CAAC,EACvB,IAAK,SAAS7J,EAAK,EAAE,EACrB,UAAWyL,EACX,SAAUC,GAAK,KAAK,GAAK,EAC3B,CAAC,CACH,CAEA,SAAS,CAAE,SAAAY,CAAS,EAAG,CACrB,KAAM,CAACxM,EAAOE,EAAKO,EAAGkK,CAAI,EAAI6B,EAAS,MAAM,KAAK,EAElD,OAAO,IAAIyF,EAAI,CACb,MAAAjS,EACA,IAAK,SAASE,EAAK,EAAE,EACrB,MAAOO,EACP,KAAMkK,EACN,QAAS6B,EAAS,MAAM,KAAK,EAAE,MAAM,CAAC,EAAE,KAAK,GAAG,EAAE,KAAK,CACzD,CAAC,CACH,CAEA,YAAY/C,EAAK,CACf,IAAI4I,EAAS5I,EAAI,QAAUuI,EAAK,KAAOvI,EAAI,SAAW,GAAKuI,EAAK,KAAOvI,EAAI,SAAW,GAAKuI,EAAK,IAChG,OAAQvI,EAAI,WAAW,YAAY,EAAG,CACpC,IAAK,IACL,IAAK,IACH4I,EAAS,CAACA,EACV,KACJ,CACA,OAAAA,GAAUN,EAAI,OACPM,CACT,CAEA,YAAYC,EAASC,EAAQ,CAC3B,IAAIC,EAAO,KAAK,IAAIF,EAAUP,EAAI,MAAM,EAGxC,MAAMU,EAAM,KAAK,MAAMD,EAAOR,EAAK,GAAG,EACtCQ,GAAQC,EAAMT,EAAK,IAEnB,MAAMU,EAAM,KAAK,MAAMF,EAAOR,EAAK,GAAG,EACtCQ,GAAQE,EAAMV,EAAK,IAEnB,MAAMW,EAAM,KAAK,MAAMH,EAAOR,EAAK,GAAG,EACtCQ,GAAQG,EAAMX,EAAK,IAEnB,IAAIY,EACJ,OAAQL,EAAQ,CACd,IAAK,MACHK,EAAMN,GAAWP,EAAI,OAAS,IAAM,IACpC,MACF,IAAK,MACHa,EAAMN,GAAWP,EAAI,OAAS,IAAM,IACpC,MACF,QACE,KAAK,UAAU,+BAA+B,CAClD,CAEA,MAAO,GAAGU,CAAG,IAAIC,CAAG,IAAIC,CAAG,GAAGH,EAAO,IAAMA,EAAO,EAAE,IAAII,CAAG,EAC7D,CAEA,aAAa3B,EAAM,CACjB,MAAM4B,GAAa5B,GAAQ,EAAK,IAAQ,GAClC6B,GAAa7B,GAAQ,EAAK,IAAQ,GACxC,OAAO4B,EAAW,KAAK,IAAI,GAAIC,CAAQ,CACzC,CAEA,WAAWrR,EAAK,CAQd,IAAIqR,EAAW,EACf,KAAOrR,GAAO,IACZA,GAAO,GACP,EAAEqR,EAEJ,OAAQ,SAASrR,CAAG,GAAK,EAAMqR,EAAW,EAC5C,CAEA,QAAQrJ,EAAK,CACX,IAAI9F,EAAI,GAAG8F,EAAI,QAAQ,IAAIA,EAAI,SAAS,IAAIA,EAAI,SAAW,GAAG,IAC9D,OAAIA,EAAI,OAAM9F,GAAK,IAAI8F,EAAI,KAAO,GAAG,KACjCA,EAAI,UAAU,aAAY9F,GAAK,IAAI8F,EAAI,UAAU,WAAa,GAAG,KACjEA,EAAI,UAAU,WAAU9F,GAAK,IAAI8F,EAAI,UAAU,SAAW,GAAG,KAC1D9F,CACT,CAEA,SAAS,CAAE,MAAA3D,EAAO,IAAAwG,EAAK,IAAAtG,EAAK,MAAAD,CAAM,EAAG,CACnC,MAAM4G,EAAK,IAAI,SAAS5G,EAAM,OAAQA,EAAM,UAAU,EAChD8J,EAAI,CACR,KAAM,KAAK,aAAa9J,EAAM,CAAC,CAAC,EAChC,UAAW,CACT,WAAY,KAAK,aAAaA,EAAM,CAAC,CAAC,EACtC,SAAU,KAAK,aAAaA,EAAM,CAAC,CAAC,CACtC,EACA,SAAU,KAAK,YAAY4G,EAAG,UAAU,CAAC,EAAG,KAAK,EACjD,UAAW,KAAK,YAAYA,EAAG,UAAU,CAAC,EAAG,KAAK,EAClD,SAAUA,EAAG,UAAU,EAAE,EAAIkL,EAAI,QACnC,EACA,OAAO,IAAIE,EAAI,CACb,MAAAjS,EACA,IAAAE,EACA,MAAOsG,EACP,KAAM,MACN,QAAS,KAAK,QAAQuD,CAAC,CACzB,CAAC,CACH,CAIA,WAAY,CACV,MAAM6B,EAAM,KAAK,SAAS,KAAK,IAAI,SAAS,CAAC,EAG7C,IAAI3L,EAAQ,GACZ,OAAAA,GAASyC,EAAa,CAAC,EACvBzC,GAASyC,EAAa,KAAK,WAAWkJ,EAAI,IAAI,CAAC,EAC/C3L,GAASyC,EAAa,KAAK,WAAWkJ,EAAI,UAAU,UAAU,CAAC,EAC/D3L,GAASyC,EAAa,KAAK,WAAWkJ,EAAI,UAAU,QAAQ,CAAC,EAC7D3L,GAAS6D,EAAc,KAAK,YAAY8H,EAAI,QAAQ,CAAC,EACrD3L,GAAS6D,EAAc,KAAK,YAAY8H,EAAI,SAAS,CAAC,EACtD3L,GAAS6D,EAAc8H,EAAI,SAAWmG,EAAI,QAAQ,EAE3C,KAAK,kBAAkB9R,CAAK,CACrC,CAEA,cAAe,CACb,MAAM2L,EAAM,KAAK,SAAS,KAAK,IAAI,SAAS,CAAC,EACvChH,EAAQ,IAAI,WAAW,EAAE,EACzBiC,EAAK,IAAI,SAASjC,EAAM,OAAQA,EAAM,UAAU,EAEtD,OAAAA,EAAM,CAAC,EAAI,EACXA,EAAM,CAAC,EAAI,KAAK,WAAWgH,EAAI,IAAI,EACnChH,EAAM,CAAC,EAAI,KAAK,WAAWgH,EAAI,UAAU,UAAU,EACnDhH,EAAM,CAAC,EAAI,KAAK,WAAWgH,EAAI,UAAU,QAAQ,EACjD/E,EAAG,UAAU,EAAG,KAAK,YAAY+E,EAAI,QAAQ,CAAC,EAC9C/E,EAAG,UAAU,EAAG,KAAK,YAAY+E,EAAI,SAAS,CAAC,EAC/C/E,EAAG,UAAU,GAAI+E,EAAI,SAAWmG,EAAI,QAAQ,EAErCnN,CACT,CACF,CAEA,MAAMmO,WAAW1J,CAAG,CAClB,OAAO,SAAW,KAClB,OAAO,OAAS,GAChB,OAAO,KAAO,CAAC,KAAM,KAAM,IAAI,EAC/B,OAAO,YAAc,IACrB,OAAO,YAAc,CACnB,CAAC,aAAc,KAAK,EACpB,CAAC,WAAY,MAAM,CACrB,EACA,OAAO,KAAO,CAAC,QAAQ,EAEvB,YAAYP,EAAM,CAChB,MAAMA,CAAI,CACZ,CAGA,cAAcrH,EAAK,CACbA,IAAQ,SAAWA,EAAM,MAAM,SAAS,YACxCA,IAAQ,QAAW,KAAK,UAAU,4BAA4B,EAClE,KAAK,WAAW,KAAM,aAAcA,CAAG,EACvC,KAAK,IAAI,aAAcA,CAAG,CAC5B,CAEA,YAAYA,EAAK,CACf,KAAK,cAAc,OAAQ,WAAYA,CAAG,CAC5C,CAEA,gBAAiB,CACf,MAAO,gBACT,CAEA,cAAe,CACb,MAAO,CACL,MAAO,eACP,IAAK,MACL,MAAO,KACP,KAAM,KACN,WAAY,GACZ,SAAU,mBACZ,CACF,CAGA,YAAY,CAAE,SAAA5B,CAAS,EAAG,CAExB,KAAM,CAACG,EAAOgT,EAAKC,EAAGC,EAAYhT,EAAKyL,EAAIC,CAAG,EAAI/L,EAAS,MAAM,CAAC,EAAE,MAAM,GAAG,EAE7E,OAAO,IAAIkT,GAAG,CACZ,KAAM,KACN,MAAO,KAAK,aAAa/S,CAAK,EAC9B,SAAU,KAAK,aAAa,KAAK,KAAKiT,CAAC,EAAIA,EAAI,GAAGA,CAAC,OAAOjT,CAAK,EAAE,EACjE,WAAY,SAASkT,EAAY,EAAE,GAAK,EACxC,IAAK,SAAShT,EAAK,EAAE,EACrB,UAAWyL,EACX,SAAUC,GAAK,KAAK,GAAK,EAC3B,CAAC,CACH,CAGA,cAAe,CACb,MAAMuH,EAAS,KAAK,eAAe,KAAK,IAAI,UAAU,CAAC,EACjD5R,EAAS,IAAI,WAAW,EAAI4R,EAAO,MAAM,EAC/C,WAAI,SAAS5R,EAAO,MAAM,EAAE,UAAU,EAAG,KAAK,IAAI,YAAY,CAAC,EAC/DA,EAAO,IAAI4R,EAAQ,CAAC,EACb5R,CACT,CAEA,WAAY,CACV,MAAO,IAAI,KAAK,YAAY,OAAO,CAAC,KAAK,KAAK,YAAY,UAAU,CAAC,IAAI,KAAK,IAAI,YAAY,CAAC,IAAI,KAAK,oBAAoB,CAAC;AAAA,CAC/H,CACF,CAEA,MAAMiQ,GAAU,eAEhB,MAAM4B,WAAc/J,CAAG,CACrB,OAAO,SAAW,QAClB,OAAO,OAAS,GAChB,OAAO,KAAO,CAAC,KAAM,KAAM,IAAI,EAC/B,OAAO,YAAc,CACnB,CAAC,QAAS,KAAK,EACf,CAAC,aAAc,KAAK,EACpB,CAAC,QAAS,UAAU,EACpB,CAAC,UAAW,UAAU,EACtB,CAAC,SAAU,UAAU,EACrB,CAAC,cAAe,MAAM,CACxB,EAEA,YAAYP,EAAM,CAChB,MAAMA,CAAI,CACZ,CAEA,gBAAiB,CACf,MAAO,0BACT,CAEA,cAAe,CACb,MAAO,CACL,MAAO,gBACP,IAAK,KACL,MAAO,KACP,KAAM,QACN,MAAO,IACP,WAAY,GACZ,MAAO,IACP,QAAS,gBACT,OAAQ,GACR,YAAa,yBACf,CACF,CAGA,SAASrH,EAAK,CACZ,KAAK,WAAW,QAAS,QAASA,CAAG,EACrC,KAAK,IAAI,QAASA,CAAG,CACvB,CAEA,cAAcA,EAAK,CACjB,KAAK,WAAW,QAAS,aAAcA,CAAG,EAC1C,KAAK,IAAI,aAAcA,CAAG,CAC5B,CAEA,SAASA,EAAK,CACP,KAAK,gBAAgB,EAAE,IAAIA,EAAI,YAAY,CAAC,GAAG,KAAK,UAAU,yBAAyB,EAE5F,KAAK,IAAI,QAASA,EAAI,YAAY,CAAC,CACrC,CAEA,iBAAkB,CAChB,OAAO,IAAI,IAAI,CAAC,CAAC,EAAE,EAAG,CAAC,GAAG,EAAG,CAAC,GAAG,EAAG,CAAC,GAAG,EAAG,CAAC,GAAG,CAAC,CAAC,CACnD,CAEA,WAAWA,EAAK,CACd,KAAK,IAAI,UAAWA,CAAG,CACzB,CAEA,UAAUA,EAAK,CACb,KAAK,IAAI,SAAUA,CAAG,CACxB,CAEA,eAAeA,EAAK,CAClB,KAAK,IAAI,cAAeA,CAAG,CAC7B,CAGA,YAAY,CAAE,SAAA5B,CAAS,EAAG,CAExB,KAAM,CAAE,MAAAG,EAAO,OAAAM,EAAQ,MAAAL,EAAO,IAAAC,EAAK,UAAAC,EAAW,SAAAC,CAAS,EAAI,KAAK,iBAAiBP,CAAQ,EACrFS,GAAU,KAAK,UAAU,GAAG,KAAK,UAAU,8BAA8B,EAE7E,MAAM0O,EAAWzO,EAAkBN,CAAK,EAClC4G,EAAK,IAAI,SAASmI,EAAS,OAAQA,EAAS,WAAYA,EAAS,UAAU,EAE3EqE,EAAM,CACV,KAAM,QACN,MAAArT,EACA,IAAAE,EACA,UAAAC,EACA,SAAAC,EACA,MAAOyG,EAAG,UAAU,CAAC,EACrB,WAAYA,EAAG,UAAU,CAAC,CAC5B,EAEA,IAAIyM,EAAM,EACV,MAAMC,EAAcvE,EAASsE,CAAG,EAChCA,IACAD,EAAI,MAAQ,IAAI,YAAY,EAAE,OAAOrE,EAAS,SAASsE,EAAKA,EAAMC,CAAW,CAAC,EAC9ED,GAAOC,EAEP,MAAMC,EAAaxE,EAASsE,CAAG,EAC/BA,IACAD,EAAI,QAAU,IAAI,YAAY,EAAE,OAAOrE,EAAS,SAASsE,EAAKA,EAAME,CAAU,CAAC,EAC/EF,GAAOE,EAEP,MAAMC,EAAYzE,EAASsE,CAAG,EAC9BA,IACAD,EAAI,OAAS,IAAI,YAAY,EAAE,OAAOrE,EAAS,SAASsE,EAAKA,EAAMG,CAAS,CAAC,EAC7EH,GAAOG,EAEP,MAAMC,EAAa1E,EAASsE,CAAG,EAC/B,OAAAA,IACAD,EAAI,YAAc,IAAI,YAAY,EAAE,OAAOrE,EAAS,SAASsE,EAAKA,EAAMI,CAAU,CAAC,EAE5E,IAAIN,GAAMC,CAAG,CACtB,CAEA,SAAS,CAAE,SAAA7G,CAAS,EAAG,CACrB,MAAMiC,EACJ,gNAEIC,EAAQlC,EAAS,KAAK,EAAE,MAAMiC,CAAK,EAEzC,GAAI,CAACC,EACH,MAAM,IAAI,MAAM,4BAA4BlC,CAAQ,EAAE,EAGxD,KAAM,CAAE,MAAAxM,EAAO,IAAAE,EAAK,KAAAyK,EAAM,MAAAgJ,EAAO,WAAAT,EAAY,MAAA1F,EAAO,QAAAoG,EAAS,OAAAC,EAAQ,YAAAC,CAAY,EAAIpF,EAAM,OAE3F,OAAO,IAAI0E,GAAM,CACf,MAAO,KAAK,aAAapT,CAAK,EAC9B,IAAK,SAASE,EAAK,EAAE,EACrB,MAAOwO,EAAM,OAAO,MACpB,KAAA/D,EACA,MAAO,SAASgJ,EAAO,EAAE,EACzB,WAAY,SAAST,EAAY,EAAE,EACnC,MAAA1F,EACA,QAAAoG,EACA,OAAAC,EACA,YAAAC,CACF,CAAC,CACH,CAGA,WAAY,CACV,IAAI7T,EACF4D,EAAc,KAAK,IAAI,OAAO,CAAC,EAC/BA,EAAc,KAAK,IAAI,YAAY,CAAC,EACpCnB,EAAa,KAAK,IAAI,OAAO,EAAE,MAAM,EACrC,KAAK,IAAI,OAAO,EAChBA,EAAa,KAAK,IAAI,SAAS,EAAE,MAAM,EACvChB,EAAY8P,GAAS,KAAK,IAAI,SAAS,CAAC,EACxC9O,EAAa,KAAK,IAAI,QAAQ,EAAE,MAAM,EACtChB,EAAY8P,GAAS,KAAK,IAAI,QAAQ,CAAC,EAEzC,MAAMsC,EAAc,KAAK,IAAI,aAAa,EAC1C,OAAIA,IAAgB,KAClB7T,GAASyC,EAAaoR,EAAY,MAAM,EACxC7T,GAASyB,EAAY8P,GAASsC,CAAW,GAE3C7T,GAAS,QAEF,KAAK,kBAAkBA,CAAK,CACrC,CAEA,cAAe,CACb,MAAMuF,EAAM,IAAI,YACVgI,EAAQhI,EAAI,OAAO,KAAK,IAAI,OAAO,CAAC,EACpCoO,EAAUpO,EAAI,OAAO,KAAK,IAAI,SAAS,CAAC,EACxCqO,EAASrO,EAAI,OAAO,KAAK,IAAI,QAAQ,CAAC,EACtCuO,EAAmB,KAAK,eAAe,KAAK,IAAI,aAAa,CAAC,EAE9D/S,EAAM,EAAQwM,EAAM,OAAS,EAAIoG,EAAQ,OAAS,EAAIC,EAAO,OAASE,EAAiB,OACvFrO,EAAM,IAAI,WAAW1E,CAAG,EACxBsF,EAAO,IAAI,SAASZ,EAAI,MAAM,EACpC,IAAI5E,EAAM,EACV,OAAAwF,EAAK,UAAUxF,EAAK,KAAK,IAAI,OAAO,CAAC,EACrCA,GAAO,EACPwF,EAAK,UAAUxF,EAAK,KAAK,IAAI,YAAY,CAAC,EAC1CA,GAAO,EACP4E,EAAI5E,GAAK,EAAI0M,EAAM,OACnB9H,EAAI,IAAI8H,EAAO1M,CAAG,EAClBA,GAAO0M,EAAM,OACb9H,EAAI5E,GAAK,EAAI8S,EAAQ,OACrBlO,EAAI,IAAIkO,EAAS9S,CAAG,EACpBA,GAAO8S,EAAQ,OACflO,EAAI5E,GAAK,EAAI+S,EAAO,OACpBnO,EAAI,IAAImO,EAAQ/S,CAAG,EACnBA,GAAO+S,EAAO,OACdnO,EAAI,IAAIqO,EAAkBjT,CAAG,EACtB4E,CACT,CACF,CAEA,MAAMsO,WAAW3K,CAAG,CAClB,OAAO,SAAW,KAClB,OAAO,OAAS,EAChB,OAAO,KAAO,CAAC,IAAI,EACnB,OAAO,YAAc,IACrB,OAAO,YAAc,CAAC,CAAC,QAAS,MAAM,CAAC,EACvC,OAAO,KAAO,CAAC,QAAQ,EAEvB,YAAYP,EAAM,CAChB,MAAMA,CAAI,CACZ,CAGA,SAASrH,EAAK,CACPA,GAAK,KAAK,UAAU,uBAAuB,EAEhD,KAAK,iBAAiB,KAAM,QAASA,CAAG,EACxC,KAAK,gBAAgB,KAAM,QAASA,CAAG,EAGvC,KAAK,IAAI,QAASA,EAAI,YAAY,CAAC,CACrC,CAEA,gBAAiB,CACf,MAAO,aACT,CAEA,cAAe,CACb,MAAO,CACL,MAAO,eACP,IAAK,KACL,MAAO,KACP,KAAM,KACN,MAAO,kBACT,CACF,CAGA,YAAY,CAAE,SAAA5B,CAAS,EAAG,CAExB,KAAM,CAACmD,EAAMgQ,EAAKiB,EAAO/T,EAAKyL,EAAIC,CAAG,EAAI/L,EAAS,MAAM,CAAC,EAAE,MAAM,GAAG,EAEpE,OAAO,IAAImU,GAAG,CACZ,KAAM,KACN,MAAO,KAAK,aAAahR,CAAI,EAC7B,MAAO,KAAK,aAAa,KAAK,KAAKiR,CAAK,EAAIA,EAAQ,GAAGA,CAAK,OAAOjR,CAAI,EAAE,EACzE,IAAK,SAAS9C,EAAK,EAAE,EACrB,UAAWyL,EACX,SAAUC,GAAK,KAAK,GAAK,EAC3B,CAAC,CACH,CAGA,cAAe,CACb,OAAO,KAAK,eAAe,KAAK,IAAI,OAAO,CAAC,CAC9C,CAEA,WAAY,CACV,MAAO,IAAI,KAAK,YAAY,OAAO,CAAC,KAAK,KAAK,YAAY,OAAO,CAAC,IAAI,KAAK,oBAAoB,CAAC;AAAA,CAClG,CACF,CAEA,MAAMsI,UAAa7K,CAAG,CACpB,OAAO,SAAW,OAClB,OAAO,OAAS,GAChB,OAAO,KAAO,CAAC,IAAI,EACnB,OAAO,YAAc,CAAC,cAAe,eAAe,EACpD,OAAO,KAAO,CAAC,QAAQ,EAEvB,YAAYP,EAAM,CAChB,MAAMA,CAAI,CAEZ,CAGA,cAAcrH,EAAK,CACZA,GAAK,KAAK,UAAU,kCAAkC,EAE3D,KAAK,iBAAiB,OAAQ,cAAeA,CAAG,EAChD,KAAK,gBAAgB,OAAQ,cAAeA,CAAG,EAG/C,KAAK,IAAI,cAAeA,EAAI,YAAY,CAAC,CAC3C,CAEA,eAAeA,EAAK,CACbA,GAAK,KAAK,UAAU,mCAAmC,EAE5D,KAAK,IAAI,gBAAiBA,CAAG,CAC/B,CAEA,gBAAiB,CACf,MAAO,aACT,CAEA,cAAe,CACb,MAAO,CACL,MAAO,oBACP,IAAK,KACL,MAAO,KACP,KAAM,OACN,cAAe,oBACf,gBAAiB,0BACnB,CACF,CAIA,YAAY,CAAE,SAAA5B,CAAS,EAAG,CACxB,KAAM,CAACG,EAAOmU,EAASlU,EAAOC,EAAKyL,EAAIC,CAAG,EAAI/L,EAAS,MAAM,CAAC,EAAE,MAAM,GAAG,EACnEuU,EAAc,WAAW,KAAK5T,EAAYP,CAAK,EAAIQ,GAAMA,EAAE,WAAW,CAAC,CAAC,EACxE,CAAC4T,EAAYC,EAAajR,CAAS,EAAID,EAAiBnD,CAAK,EAEnE,OAAO,IAAIiU,EAAK,CACd,MAAO,KAAK,aAAalU,CAAK,EAC9B,IAAK,SAASE,EAAK,EAAE,EACrB,KAAM,OACN,cAAemU,EACf,gBAAiB,IAAI,YAAY,EAAE,OAAOD,EAAY,SAAS/Q,CAAS,CAAC,EACzE,UAAWsI,EACX,SAAUC,GAAK,KAAK,GAAK,EAC3B,CAAC,CACH,CAEA,SAAS,CAAE,SAAAY,CAAS,EAAG,CAErB,KAAM,CAACxM,EAAOE,EAAKO,EAAGkK,EAAM4J,CAAI,EAAI/H,EAAS,MAAM,KAAK,EACxD,OAAO,IAAI0H,EAAK,CACd,MAAAlU,EACA,IAAK,SAASE,EAAK,EAAE,EACrB,MAAOO,EACP,KAAMkK,EACN,cAAe4J,EACf,gBAAiB/H,EAAS,MAAM,KAAK,EAAE,MAAM,CAAC,EAAE,OAAOgI,EAAc,EAAE,KAAK,GAAG,EAAE,KAAK,CACxF,CAAC,CACH,CAEA,SAAS,CAAE,MAAAxU,EAAO,IAAAwG,EAAK,IAAAtG,EAAK,MAAAD,CAAM,EAAG,CACnC,KAAM,CAAE,KAAMoU,EAAY,IAAAhO,CAAI,EAAI,KAAK,iBAAiBpG,EAAO,CAAC,EAC1DwU,EAAcC,GAAkBzU,EAAM,SAASoG,CAAG,CAAC,EACzD,OAAO,IAAI6N,EAAK,CACd,MAAAlU,EACA,IAAAE,EACA,MAAOsG,EACP,KAAM,OACN,cAAe6N,EACf,gBAAiBI,CACnB,CAAC,CACH,CAIA,WAAY,CACV,MAAM7D,EAAS,IAAI,OAAO,eAAgB,GAAG,EAE7C,OAAO,KAAK,kBACV7N,EAAe,KAAK,IAAI,aAAa,CAAC,EACpCrB,EAAYkP,EAAQ,KAAK,IAAI,eAAe,CAAC,CACjD,CACF,CAEA,cAAe,CACb,MAAM+D,EAAY,KAAK,eAAe,KAAK,IAAI,aAAa,CAAC,EACvDC,EAAcC,GAAkB,KAAK,IAAI,eAAe,CAAC,EACzDtT,EAAS,IAAI,WAAWoT,EAAU,OAASC,EAAY,MAAM,EACnE,OAAArT,EAAO,IAAIoT,CAAS,EACpBpT,EAAO,IAAIqT,EAAaD,EAAU,MAAM,EACjCpT,CACT,CACF,CAEA,MAAMiT,GAAkBxM,GAAM,CAAC,CAAC,IAAK,GAAG,EAAE,SAASA,CAAC,EAEpD,SAAS0M,GAAkBI,EAAQ,CACjC,MAAMC,EAAiB,OAAO,YAAY,OAAO,QAAQ3P,CAAY,EAAE,IAAI,CAAC,CAACqB,EAAGiD,CAAC,IAAM,CAACA,EAAGjD,CAAC,CAAC,CAAC,EACxFuO,EAAQ,CAAC,EACf,IAAIlU,EAAM,EACV,KAAOA,EAAM,GAAKgU,EAAO,QAAQ,CAC/B,MAAMG,EAAYH,EAAOhU,CAAG,EACtBoU,EAAYJ,EAAOhU,EAAM,CAAC,EAChCA,GAAO,EACP,QAASU,EAAI,EAAGA,EAAI0T,EAAW1T,IAAK,CAClC,MAAM2T,EAAOL,EAAOhU,EAAMU,CAAC,EAC3B,QAAS4T,EAAM,EAAGA,EAAM,EAAGA,IACzB,GAAID,EAAQ,KAAQC,EAAM,CACxB,MAAM9U,EAAS2U,EAAY,IAAMzT,EAAI,EAAI4T,EACzCJ,EAAM,KAAKD,EAAezU,CAAM,GAAK,OAAOA,CAAM,EAAE,CACtD,CAEJ,CACAQ,GAAOoU,CACT,CACA,OAAOF,EAAM,KAAK,GAAG,CACvB,CAEA,SAASH,GAAkBQ,EAAc,CACvC,MAAMC,EAAUD,EACb,KAAK,EACL,MAAM,KAAK,EACX,IAAKE,GACA,aAAa,KAAKA,CAAC,EAAU,SAASA,EAAE,MAAM,CAAC,EAAG,EAAE,EACjDnQ,EAAamQ,EAAE,YAAY,CAAC,CACpC,EACA,OAAQC,GAAOA,IAAO,QAAaA,GAAM,CAAC,EAEvCC,EAAU,IAAI,IACpB,UAAWD,KAAMF,EAAS,CACxB,MAAMxL,EAAI,KAAK,MAAM0L,EAAK,GAAG,EACxBC,EAAQ,IAAI3L,CAAC,GAAG2L,EAAQ,IAAI3L,EAAG,CAAC,CAAC,EACtC2L,EAAQ,IAAI3L,CAAC,EAAE,KAAK0L,EAAK,GAAG,CAC9B,CAEA,MAAME,EAAS,CAAC,EAChB,SAAW,CAACC,EAAMC,CAAI,GAAK,CAAC,GAAGH,EAAQ,QAAQ,CAAC,EAAE,KAAK,CAACzN,EAAGtD,IAAMsD,EAAE,CAAC,EAAItD,EAAE,CAAC,CAAC,EAAG,CAC7E,MAAMmR,EAAS,KAAK,IAAI,GAAGD,CAAI,EACzBV,EAAY,KAAK,MAAMW,EAAS,CAAC,EAAI,EACrCf,EAAS,IAAI,WAAWI,CAAS,EACvC,UAAWxQ,KAAKkR,EAAMd,EAAO,KAAK,MAAMpQ,EAAI,CAAC,CAAC,GAAK,KAASA,EAAI,EAChEgR,EAAO,KAAK,IAAI,WAAW,CAACC,EAAMT,EAAW,GAAGJ,CAAM,CAAC,CAAC,CAC1D,CAEA,MAAMhN,EAAQ4N,EAAO,OAAO,CAACjT,EAAGiC,IAAMjC,EAAIiC,EAAE,OAAQ,CAAC,EAC/CnD,EAAS,IAAI,WAAWuG,CAAK,EACnC,IAAIhH,EAAM,EACV,UAAW4D,KAAKgR,EACdnU,EAAO,IAAImD,EAAG5D,CAAG,EACjBA,GAAO4D,EAAE,OAEX,OAAOnD,CACT,CAEA,MAAMuU,UAAczM,CAAG,CACrB,OAAO,SAAW,QAClB,OAAO,OAAS,GAChB,OAAO,KAAO,CAAC,KAAM,IAAI,EACzB,OAAO,YAAc,CACnB,iBACA,QACA,aACA,OACA,yBACA,eACF,EACA,OAAO,KAAO,CAAC,QAAQ,EAEvB,YAAYP,EAAM,CAChB,MAAMA,CAAI,CAEZ,CAGA,iBAAiBrH,EAAK,CAGfA,GAAK,KAAK,UAAU,qCAAqC,EAE9D,KAAK,UAAU,QAAS,iBAAkBA,CAAG,EAE7C,KAAK,IAAI,iBAAkBA,CAAG,CAChC,CAEA,SAASA,EAAK,CAEPA,GAAK,KAAK,UAAU,4BAA4B,EAErD,KAAK,UAAU,QAAS,QAASA,CAAG,EAEpC,KAAK,IAAI,QAASA,CAAG,CACvB,CAEA,cAAcA,EAAK,CAEZA,GAAK,KAAK,UAAU,iCAAiC,EAE1D,KAAK,WAAW,QAAS,QAASA,CAAG,EAErC,KAAK,IAAI,aAAcA,CAAG,CAC5B,CAEA,QAAQA,EAAK,CAKX,KAAK,IAAI,OAAQA,CAAG,CACtB,CAEA,uBAAuBA,EAAK,CAGrBA,GAAK,KAAK,UAAU,6CAA6C,EAEtE,KAAK,IAAI,yBAA0BA,CAAG,CACxC,CAEA,eAAeA,EAAK,CAEbA,GAAK,KAAK,UAAU,oCAAoC,EAE7D,KAAK,IAAI,gBAAiBA,CAAG,CAC/B,CAEA,gBAAiB,CACf,MAAO,aACT,CAEA,cAAe,CACb,MAAO,CACL,MAAO,oBACP,IAAK,KACL,MAAO,KACP,KAAM,QACN,iBAAkB,EAClB,MAAO,EACP,WAAY,GACZ,KAAM,WACN,yBAA0B,mCAC1B,gBAAiB,SACnB,CACF,CAIA,SAAS,CAAE,SAAA+K,CAAS,EAAG,CAErB,KAAM,CAACxM,EAAOE,EAAKO,EAAGkK,EAAMoL,EAAIvI,EAAOwI,EAAYC,CAAI,EAAIzJ,EAAS,MAAM,KAAK,EAEzE0J,EAAW1J,EAAS,SAAS,GAAG,EAClCA,EAAS,MAAM,OAAO,EAAE,CAAC,EACzBA,EAAS,MAAM,KAAK,EAAE,MAAM,CAAC,EAAE,KAAK,GAAG,EAE3C,OAAO,IAAIsJ,EAAM,CACf,MAAA9V,EACA,IAAK,SAASE,EAAK,EAAE,EACrB,MAAOO,EACP,KAAMkK,EACN,iBAAkB,SAASoL,EAAI,EAAE,EACjC,MAAO,SAASvI,EAAO,EAAE,EACzB,WAAY,SAASwI,EAAY,EAAE,EACnC,KAAAC,EACA,yBAA0BC,EAAS,KAAK,EAAE,MAAM,KAAK,EAAE,CAAC,EACxD,gBAAiBA,EAAS,KAAK,EAAE,MAAM,KAAK,EAAE,MAAM,CAAC,EAAE,KAAK,GAAI,CAClE,CAAC,CACH,CAEA,YAAY,CAAE,SAAArW,CAAS,EAAG,CACxB,KAAM,CAACmD,EAAMY,EAAG3D,EAAOC,EAAKyL,EAAIC,CAAG,EAAI/L,EAAS,MAAM,CAAC,EAAE,MAAM,GAAG,EAC9D+D,GAAK,IAAI,KAAK,UAAU,8BAA8B,EAE1D,MAAMgB,EAAQ,WAAW,KAAKpE,EAAYP,CAAK,EAAIQ,GAAMA,EAAE,WAAW,CAAC,CAAC,EAClEoG,EAAK,IAAI,SAASjC,EAAM,OAAQA,EAAM,WAAYA,EAAM,UAAU,EAElEuR,EAAgBvR,EAAM,CAAC,EACvB4I,EAAQ5I,EAAM,CAAC,EACfoR,EAAanP,EAAG,UAAU,CAAC,EAO3B,CAAE,KAAAoP,EAAM,oBAAAG,EAAqB,YAAA3B,CAAY,EAAI4B,GAAiBzR,CAAK,EAEzE,OAAO,IAAIkR,EAAM,CACf,MAAO,KAAK,aAAa9S,CAAI,EAC7B,IAAK,SAAS9C,EAAK,EAAE,EACrB,KAAM,QACN,iBAAkBiW,EAClB,MAAO3I,EACP,WAAYwI,EACZ,KAAMC,EACN,yBAA0BG,EAC1B,gBAAiB3B,EACjB,UAAW9I,EACX,SAAUC,GAAK,KAAK,GAAK,EAC3B,CAAC,CACH,CAEA,SAAS,CAAE,MAAA5L,EAAO,IAAAwG,EAAK,IAAAtG,EAAK,MAAAD,CAAM,EAAG,CACnC,MAAM4G,EAAK,IAAI,SAAS5G,EAAM,OAAQA,EAAM,UAAU,EAChD,CAAE,KAAAgW,EAAM,oBAAAG,EAAqB,YAAA3B,CAAY,EAAI4B,GAAiBpW,CAAK,EACzE,OAAO,IAAI6V,EAAM,CACf,MAAA9V,EACA,IAAAE,EACA,MAAOsG,EACP,KAAM,QACN,iBAAkBvG,EAAM,CAAC,EACzB,MAAOA,EAAM,CAAC,EACd,WAAY4G,EAAG,UAAU,CAAC,EAC1B,KAAAoP,EACA,yBAA0BG,EAC1B,gBAAiB3B,CACnB,CAAC,CACH,CAIA,OAAOtL,EAAW,CAChB,MAAO,GAAG,KAAK,QAAQ,QAASA,CAAS,CAAC,IAAI,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,IAAI,OAAO,CAAC,SAAS,KAAK,eAAe,EAC5G,MAAM,EAAG,CAAC,EACV,IAAKhI,GAAM,IAAM,KAAK,IAAIA,CAAC,CAAC,EAC5B,KAAK,EAAE,CAAC,KAAK,KAAK,eAAe,EACjC,MAAM,CAAC,EACP,IAAKA,GAAM,KAAK,IAAIA,CAAC,CAAC,EACtB,KAAK,GAAG,CAAC;AAAA,CAEd,CAEA,WAAY,CACV,MAAMyP,EAAS,IAAI,OAAO,eAAgB,GAAG,EAE7C,OAAO,KAAK,kBACVlO,EAAa,KAAK,IAAI,gBAAgB,CAAC,EACrCA,EAAa,KAAK,IAAI,OAAO,CAAC,EAC9BmB,EAAc,KAAK,IAAI,YAAY,CAAC,EACpCnC,EAAYkP,EAAQ,KAAK,IAAI,MAAM,CAAC,EACpClP,EAAYkP,EAAQ,KAAK,IAAI,wBAAwB,CAAC,EACtDlP,EAAYkP,EAAQ,KAAK,IAAI,eAAe,CAAC,CACjD,CACF,CAEA,cAAe,CACb,MAAMtF,EAAO,GAAG,KAAK,IAAI,MAAM,CAAC,GAAG,KAAK,IAAI,wBAAwB,CAAC,GAAG,KAAK,IAAI,eAAe,CAAC,GAC3FgL,EAAY,IAAI,YAAY,EAAE,OAAOhL,CAAI,EAEzC+B,EAAW,EAAIiJ,EAAU,OACzB1R,EAAQ,IAAI,WAAWyI,CAAQ,EAC/BxG,EAAK,IAAI,SAASjC,EAAM,OAAQA,EAAM,UAAU,EAEtD,IAAI9D,EAAM,EACV,OAAA8D,EAAM9D,GAAK,EAAI,KAAK,IAAI,gBAAgB,EACxC8D,EAAM9D,GAAK,EAAI,KAAK,IAAI,OAAO,EAC/B+F,EAAG,UAAU/F,EAAK,KAAK,IAAI,YAAY,CAAC,EACxCA,GAAO,EACP8D,EAAM,IAAI0R,EAAWxV,CAAG,EAEjB8D,CACT,CACF,CAEA,SAASyR,GAAiBzR,EAAO,CAG/B,MAAMgI,EAAO,IAAI,YAAY,EAAE,OAAOhI,EAAM,SAAS,CAAC,CAAC,EAGjDuR,EAAgBvR,EAAM,CAAC,EAEvB2R,EAAcJ,IAAkB,EAAI,GAAKA,IAAkB,EAAI,GAAK,GAI1E,IAAIF,EAAO,GACPG,EAAsB,GACtB3B,EAAc,GAElB,MAAM+B,EAAQ,KAAK,IAAI,GAAI5J,EAAK,MAAM,EACtC,QAAS6J,EAAKD,EAAOC,GAAM,EAAGA,IAAM,CAClC,MAAMC,EAAW9J,EAAK,MAAM6J,EAAIA,EAAKF,CAAW,EAEhD,GADIG,EAAS,SAAWH,GACpB,CAAC,cAAc,KAAKG,CAAQ,EAAG,SAEnC,MAAMC,EAAgB/J,EAAK,MAAM,EAAG6J,CAAE,EACtC,GAAK,iBAAiB,KAAKE,CAAa,EACxC,CAAAV,EAAOU,EACPP,EAAsBM,EACtBjC,EAAc7H,EAAK,MAAM6J,EAAKF,CAAW,EACzC,MACF,CAGA,GAAI,CAACH,EAAqB,CACxB,MAAMQ,EAAYhK,EAAK,MAAM,iBAAiB,EAC9CqJ,EAAOW,EAAYA,EAAU,CAAC,EAAI,GAClCR,EAAsBxJ,EAAK,MAAMqJ,EAAK,MAAM,EAC5CxB,EAAc,EAChB,CAEA,MAAO,CACL,KAAAwB,EACA,oBAAAG,EACA,YAAA3B,CACF,CACF,CAEA,MAAMoC,WAAmBxN,CAAG,CAC1B,OAAO,SAAW,aAClB,OAAO,OAAS,GAChB,OAAO,KAAO,CAAC,IAAI,EACnB,OAAO,YAAc,CAAC,iBAAkB,QAAS,aAAc,MAAM,EACrE,OAAO,KAAO,CAAC,QAAQ,EAEvB,YAAYP,EAAM,CAChB,MAAMA,CAAI,CAEZ,CAGA,iBAAiBrH,EAAK,CAGKA,GAAQ,MAAM,KAAK,UAAU,0CAA0C,EAEhG,KAAK,UAAU,aAAc,iBAAkBA,CAAG,EAElD,KAAK,IAAI,iBAAkBA,CAAG,CAChC,CAEA,SAASA,EAAK,CAEaA,GAAQ,MAAM,KAAK,UAAU,iCAAiC,EAEvF,KAAK,UAAU,aAAc,QAASA,CAAG,EAEzC,KAAK,IAAI,QAASA,CAAG,CACvB,CAEA,cAAcA,EAAK,CAEQA,GAAQ,MAAM,KAAK,UAAU,sCAAsC,EAE5F,KAAK,WAAW,aAAc,aAAcA,CAAG,EAE/C,KAAK,IAAI,aAAcA,CAAG,CAC5B,CAEA,QAAQA,EAAK,CAKX,GAAIA,IAAQ,IAAK,CACf,KAAK,IAAI,OAAQA,CAAG,EACpB,MACF,CAEyBA,GAAQ,MAAQ,CAAC,iBAAiB,KAAKA,CAAG,GACjE,KAAK,UAAU,uCAAuC,EAGxD,KAAK,IAAI,OAAQA,CAAG,CACtB,CAEA,gBAAiB,CACf,MAAO,wBACT,CAEA,cAAe,CACb,MAAO,CACL,MAAO,eACP,IAAK,KACL,MAAO,KACP,KAAM,aACN,iBAAkB,EAClB,MAAO,EACP,WAAY,GACZ,KAAM,UACR,CACF,CAIA,YAAY,CAAE,SAAA5B,CAAS,EAAG,CAExB,KAAM,CAAE,MAAAG,EAAO,OAAAM,EAAQ,MAAAL,EAAO,IAAAC,EAAK,UAAAC,EAAW,SAAAC,CAAS,EAAI,KAAK,iBAAiBP,CAAQ,EACrFS,GAAU,KAAK,UAAU,GAAG,KAAK,UAAU,mCAAmC,EAC9EL,EAAM,OAAS,GACjB,KAAK,UAAU,gCAAgCA,CAAK,EAAE,EAKxD,MAAM2E,EAAQrE,EAAkBN,CAAK,EAErC,OAAO,IAAI4W,GAAW,CACpB,MAAA7W,EACA,IAAAE,EACA,KAAM,aACN,iBAAkB0E,EAAM,CAAC,EACzB,MAAOA,EAAM,CAAC,EACd,WAAaA,EAAM,CAAC,GAAK,EAAKA,EAAM,CAAC,EACrC,KAAMA,EAAM,CAAC,IAAM,EAAI,IAAMI,EAAWJ,EAAM,SAAS,EAAG,EAAIA,EAAM,CAAC,CAAC,CAAC,EACvE,UAAAzE,EACA,SAAAC,CACF,CAAC,CACH,CAEA,SAAS,CAAE,MAAAJ,EAAO,IAAAwG,EAAK,IAAAtG,EAAK,MAAAD,CAAM,EAAG,CACnC,MAAM4G,EAAK,IAAI,SAAS5G,EAAM,OAAQA,EAAM,UAAU,EAChD6W,EAAU7W,EAAM,CAAC,EACjBgW,EAAOa,IAAY,EAAI,IAAM9R,EAAW/E,EAAM,SAAS,EAAG,EAAI6W,CAAO,CAAC,EAC5E,OAAO,IAAID,GAAW,CACpB,MAAA7W,EACA,IAAAE,EACA,MAAOsG,EACP,KAAM,aACN,iBAAkBvG,EAAM,CAAC,EACzB,MAAOA,EAAM,CAAC,EACd,WAAY4G,EAAG,UAAU,CAAC,EAC1B,KAAAoP,CACF,CAAC,CACH,CAIA,WAAY,CACV,MAAMA,EAAO,KAAK,IAAI,MAAM,EACtBc,EACJd,IAAS,IAAMvT,EAAa,CAAC,EAAIA,EAAauT,EAAK,OAAS,CAAC,EAAIvS,EAAQuS,CAAI,EAE/E,OAAO,KAAK,kBACVvT,EAAa,KAAK,IAAI,gBAAgB,CAAC,EACrCA,EAAa,KAAK,IAAI,OAAO,CAAC,EAC9BmB,EAAc,KAAK,IAAI,YAAY,CAAC,EACpCkT,CACJ,CACF,CAEA,cAAe,CACb,MAAMd,EAAO,KAAK,IAAI,MAAM,EACtBe,EAAYf,IAAS,IAAM,IAAI,WAAW,CAAC,EAAIpR,EAAWoR,CAAI,EAC9DrR,EAAQ,IAAI,WAAW,EAAQoS,EAAU,MAAM,EAC/CnQ,EAAK,IAAI,SAASjC,EAAM,OAAQA,EAAM,UAAU,EAEtD,OAAAA,EAAM,CAAC,EAAI,KAAK,IAAI,gBAAgB,EACpCA,EAAM,CAAC,EAAI,KAAK,IAAI,OAAO,EAC3BiC,EAAG,UAAU,EAAG,KAAK,IAAI,YAAY,CAAC,EACtCjC,EAAM,CAAC,EAAIoS,EAAU,OACrBpS,EAAM,IAAIoS,EAAW,CAAC,EAEfpS,CACT,CACF,CAEA,MAAMqS,UAAY5N,CAAG,CACnB,OAAO,SAAW,MAClB,OAAO,OAAS,GAChB,OAAO,KAAO,CAAC,IAAI,EACnB,OAAO,YAAc,CAAC,cAAe,cAAc,EACnD,OAAO,KAAO,CAAC,UAAU,EAEzB,YAAYP,EAAM,CAChB,MAAMA,CAAI,CAEZ,CAGA,cAAcrH,EAAK,CACZA,GAAK,KAAK,UAAU,gCAAgC,EAEzD,KAAK,iBAAiB,MAAO,cAAeA,CAAG,EAC/C,KAAK,gBAAgB,MAAO,cAAeA,CAAG,EAG9C,KAAK,IAAI,cAAeA,EAAI,YAAY,CAAC,CAC3C,CAEA,cAAcA,EAAK,CACZA,GAAK,KAAK,UAAU,iCAAiC,EAE1D,KAAK,IAAI,eAAgBA,CAAG,CAC9B,CAEA,gBAAiB,CACf,MAAO,aACT,CAEA,cAAe,CACb,MAAO,CACL,MAAO,mBACP,IAAK,KACL,MAAO,KACP,KAAM,MACN,cAAe,oBACf,eAAgB,UAClB,CACF,CAIA,YAAY,CAAE,SAAA5B,CAAS,EAAG,CACxB,KAAM,CAACG,EAAO4D,EAAG3D,EAAOC,EAAKyL,EAAIC,CAAG,EAAI/L,EAAS,MAAM,CAAC,EAAE,MAAM,GAAG,EAC/D,SAAS+D,EAAG,EAAE,IAAM,KAAK,UAAU,GAAG,KAAK,UAAU,4BAA4B,EAErF,MAAMwQ,EAAc,WAAW,KAAK5T,EAAYP,CAAK,EAAIQ,GAAMA,EAAE,WAAW,CAAC,CAAC,EACxE,CAAC4T,EAAYC,EAAajR,CAAS,EAAID,EAAiBnD,CAAK,EAEnE,OAAO,IAAIgX,EAAI,CACb,MAAO,KAAK,aAAajX,CAAK,EAC9B,IAAK,SAASE,EAAK,EAAE,EACrB,KAAM,MACN,cAAemU,EACf,eAAgB,IAAI,YAAY,EAAE,OAAOD,EAAY,SAAS/Q,CAAS,CAAC,EACxE,UAAWsI,EACX,SAAUC,GAAK,KAAK,GAAK,EAC3B,CAAC,CACH,CAEA,SAAS,CAAE,SAAAY,CAAS,EAAG,CAErB,KAAM,CAACxM,EAAOE,EAAKO,EAAGkK,EAAM4J,CAAI,EAAI/H,EAAS,MAAM,KAAK,EACxD,OAAO,IAAIyK,EAAI,CACb,MAAAjX,EACA,IAAK,SAASE,EAAK,EAAE,EACrB,MAAOO,EACP,KAAMkK,EACN,cAAe4J,EACf,eAAgB/H,EAAS,MAAM,KAAK,EAAE,MAAM,CAAC,EAAE,OAAO0K,EAAY,EAAE,KAAK,GAAG,EAAE,KAAK,CACrF,CAAC,CACH,CAEA,SAAS,CAAE,MAAAlX,EAAO,IAAAwG,EAAK,IAAAtG,EAAK,MAAAD,CAAM,EAAG,CACnC,KAAM,CAAE,KAAMoU,EAAY,IAAAhO,CAAI,EAAI,KAAK,iBAAiBpG,EAAO,CAAC,EAC1DkX,EAAaC,GAAiBnX,EAAM,SAASoG,CAAG,CAAC,EACvD,OAAO,IAAI4Q,EAAI,CACb,MAAAjX,EACA,IAAAE,EACA,MAAOsG,EACP,KAAM,MACN,cAAe6N,EACf,eAAgB8C,CAClB,CAAC,CACH,CAIA,WAAY,CACV,MAAMvG,EAAS,IAAI,OAAO,eAAgB,GAAG,EAE7C,OAAO,KAAK,kBACV7N,EAAe,KAAK,IAAI,aAAa,CAAC,EAAIrB,EAAYkP,EAAQ,KAAK,IAAI,cAAc,CAAC,CACxF,CACF,CAEA,cAAe,CACb,MAAM+D,EAAY,KAAK,eAAe,KAAK,IAAI,aAAa,CAAC,EACvDC,EAAcyC,GAAiB,KAAK,IAAI,cAAc,CAAC,EACvD9V,EAAS,IAAI,WAAWoT,EAAU,OAASC,EAAY,MAAM,EACnE,OAAArT,EAAO,IAAIoT,CAAS,EACpBpT,EAAO,IAAIqT,EAAaD,EAAU,MAAM,EACjCpT,CACT,CACF,CAEA,MAAM2V,GAAgBlP,GAAM,CAAC,CAAC,IAAK,GAAG,EAAE,SAASA,CAAC,EAElD,SAASoP,GAAiBtC,EAAQ,CAChC,MAAMC,EAAiB,OAAO,YAAY,OAAO,QAAQ3P,CAAY,EAAE,IAAI,CAAC,CAACqB,EAAGiD,CAAC,IAAM,CAACA,EAAGjD,CAAC,CAAC,CAAC,EACxFuO,EAAQ,CAAC,EACf,QAASxT,EAAI,EAAGA,EAAIsT,EAAO,OAAQtT,IAAK,CACtC,MAAM2T,EAAOL,EAAOtT,CAAC,EACrB,QAAS4T,EAAM,EAAGA,EAAM,EAAGA,IACzB,GAAID,EAAQ,KAAQC,EAAM,CACxB,MAAM9U,EAASkB,EAAI,EAAI4T,EACvBJ,EAAM,KAAKD,EAAezU,CAAM,GAAK,OAAOA,CAAM,EAAE,CACtD,CAEJ,CACA,OAAO0U,EAAM,KAAK,GAAG,CACvB,CAEA,SAASqC,GAAiBhC,EAAc,CACtC,MAAMP,EAAS,IAAI,WAAW,EAAE,EAChC,UAAWlF,KAAQyF,EAAa,KAAK,EAAE,MAAM,KAAK,EAAG,CACnD,MAAMG,EAAK,aAAa,KAAK5F,CAAI,EAAI,SAASA,EAAK,MAAM,CAAC,EAAG,EAAE,EAAIxK,EAAawK,EAAK,YAAY,CAAC,EAC9F4F,IAAO,QAAaA,EAAK,MAAKV,EAAO,KAAK,MAAMU,EAAK,CAAC,CAAC,GAAK,KAASA,EAAK,EAChF,CACA,IAAIxU,EAAM8T,EAAO,OACjB,KAAO9T,EAAM,GAAK8T,EAAO9T,EAAM,CAAC,IAAM,GAAGA,IACzC,OAAO8T,EAAO,MAAM,EAAG9T,CAAG,CAC5B,CAEA,MAAMsW,WAAmBjO,CAAG,CAC1B,OAAO,SAAW,aAClB,OAAO,OAAS,GAChB,OAAO,KAAO,CAAC,KAAM,IAAI,EACzB,OAAO,YAAc,CAAC,CAAC,aAAc,QAAQ,CAAC,EAC9C,OAAO,KAAO,CAAC,UAAU,EAEzB,YAAYP,EAAM,CAChB,MAAMA,CAAI,CACZ,CAGA,aAAarH,EAAK,CAChB,KAAK,SAAS,aAAc,aAAcA,CAAG,EAC7C,KAAK,IAAI,aAAcA,CAAG,CAC5B,CAEA,gBAAiB,CACf,MAAO,oBACT,CAEA,cAAe,CACb,MAAO,CACL,MAAO,oBACP,IAAK,KACL,MAAO,KACP,KAAM,aACN,aACE,8GACJ,CACF,CAGA,SAAS,CAAE,SAAU+K,CAAS,EAAG,CAE/B,MAAMiC,EACJ,qGACIC,EAAQlC,EAAS,KAAK,EAAE,MAAMiC,CAAK,EACpCC,GAAO,KAAK,UAAU,+BAA+BlC,CAAQ,EAAE,EAEpE,KAAM,CAAE,MAAAxM,EAAO,IAAAE,EAAK,MAAOO,EAAG,KAAAkK,EAAM,UAAAkE,CAAU,EAAIH,EAAM,OAClD6I,EAAS1I,EAAU,KAAK,EAAE,QAAQ,OAAQ,EAAE,EAElD,OAAO,IAAIyI,GAAW,CACpB,MAAAtX,EACA,IAAK,SAASE,EAAK,EAAE,EACrB,MAAOO,EACP,KAAMkK,EACN,aAAc4M,CAChB,CAAC,CACH,CAEA,YAAY,CAAE,SAAA1X,CAAS,EAAG,CACxB,KAAM,CAAE,MAAAG,EAAO,OAAAM,EAAQ,MAAAL,EAAO,IAAAC,EAAK,UAAAC,EAAW,SAAAC,CAAS,EAAI,KAAK,iBAAiBP,CAAQ,EACzF,OAAIS,GAAU,KAAK,UAAU,GAAG,KAAK,UAAU,mCAAmC,EAC3E,IAAIgX,GAAW,CACpB,MAAAtX,EACA,IAAAE,EACA,KAAM,aACN,aAAcyE,GAAc1E,CAAK,EACjC,UAAAE,EACA,SAAAC,CACF,CAAC,CACH,CAGA,WAAY,CACV,OAAO,KAAK,kBAAkBqE,EAAc,KAAK,IAAI,YAAY,CAAC,CAAC,CACrE,CAEA,cAAe,CACb,OAAOS,EAAc,KAAK,IAAI,YAAY,CAAC,CAC7C,CACF,CAEA,MAAMsS,WAAYnO,CAAG,CACnB,OAAO,SAAW,MAClB,OAAO,OAAS,GAChB,OAAO,KAAO,CAAC,IAAI,EACnB,OAAO,YAAc,IACrB,OAAO,YAAc,CAAC,CAAC,QAAS,MAAM,CAAC,EACvC,OAAO,KAAO,CAAC,QAAQ,EAEvB,YAAYP,EAAM,CAChB,MAAMA,CAAI,CACZ,CAGA,SAASrH,EAAK,CACZ,KAAK,iBAAiB,MAAO,QAASA,CAAG,EACzC,KAAK,gBAAgB,MAAO,QAASA,CAAG,EAGxC,KAAK,IAAI,QAASA,EAAI,YAAY,CAAC,CACrC,CAEA,gBAAiB,CACf,MAAO,SACT,CAEA,cAAe,CACb,MAAO,CACL,MAAO,0BACP,IAAK,KACL,MAAO,KACP,KAAM,MACN,MAAO,mBACT,CACF,CAGA,cAAe,CACb,OAAO,KAAK,eAAe,KAAK,IAAI,OAAO,CAAC,CAC9C,CACF,CAEA,MAAMgW,WAAWpO,CAAG,CAClB,OAAO,SAAW,KAClB,OAAO,YAAc,CACnB,CAAC,OAAQ,MAAM,EACf,CAAC,MAAO,MAAM,CAChB,EAEA,YAAYP,EAAM,CAChB,MAAMA,CAAI,CACZ,CAGA,QAAQrH,EAAK,CACNA,GAAK,KAAK,UAAU,sBAAsB,EAE/C,KAAK,iBAAiB,KAAM,OAAQA,CAAG,EAEvC,KAAK,IAAI,OAAQA,EAAI,YAAY,CAAC,CACpC,CAEA,OAAOA,EAAK,CACLA,GAAK,KAAK,UAAU,qBAAqB,EAE9C,KAAK,iBAAiB,KAAM,MAAOA,CAAG,EAEtC,KAAK,IAAI,MAAOA,EAAI,YAAY,CAAC,CACnC,CAEA,gBAAiB,CACf,MAAO,oBACT,CACA,OAAO,KAAO,CAAC,UAAU,EACzB,OAAO,KAAO,CAAC,IAAI,EACnB,OAAO,OAAS,GAChB,cAAe,CACb,MAAO,CACL,MAAO,eACP,IAAK,KACL,MAAO,KACP,KAAM,KACN,KAAM,qBACN,IAAK,mBACP,CACF,CAGA,YAAY,CAAE,SAAA5B,CAAS,EAAG,CACxB,KAAM,CAACG,EAAOmU,EAASlU,EAAOC,EAAKyL,EAAIC,CAAG,EAAI/L,EAAS,MAAM,CAAC,EAAE,MAAM,GAAG,EAEnE,CAAC6X,EAAMC,CAAQ,EAAIvU,EAAiBnD,CAAK,EACzC2X,EAAMxU,EAAiBnD,EAAM,MAAM0X,CAAQ,CAAC,EAAE,CAAC,EAErD,OAAO,IAAIF,GAAG,CACZ,MAAO,KAAK,aAAazX,CAAK,EAC9B,IAAK,SAASE,EAAK,EAAE,EACrB,KAAM,KACN,KAAAwX,EACA,IAAAE,EACA,UAAWjM,EACX,SAAUC,GAAK,KAAK,GAAK,EAC3B,CAAC,CACH,CAIA,cAAe,CACb,MAAM8L,EAAO,KAAK,eAAe,KAAK,IAAI,MAAM,CAAC,EAC3CE,EAAM,KAAK,eAAe,KAAK,IAAI,KAAK,CAAC,EACzCrW,EAAS,IAAI,WAAWmW,EAAK,OAASE,EAAI,MAAM,EACtD,OAAArW,EAAO,IAAImW,EAAM,CAAC,EAClBnW,EAAO,IAAIqW,EAAKF,EAAK,MAAM,EACpBnW,CACT,CAEA,WAAY,CACV,OAAO,KAAK,kBACVwB,EAAe,KAAK,IAAI,MAAM,CAAC,EAAIA,EAAe,KAAK,IAAI,KAAK,CAAC,CACnE,CACF,CACF,CAEA,MAAM8U,WAAcxO,CAAG,CACrB,OAAO,SAAW,QAClB,OAAO,OAAS,GAChB,OAAO,KAAO,CAAC,IAAI,EACnB,OAAO,YAAc,CACnB,CAAC,eAAgB,KAAK,EACtB,CAAC,YAAa,IAAI,EAClB,CAAC,SAAU,IAAI,EACf,CAAC,eAAgB,KAAK,EACtB,CAAC,uBAAwB,KAAK,EAC9B,CAAC,sBAAuB,KAAK,EAC7B,CAAC,UAAW,KAAK,EACjB,CAAC,eAAgB,MAAM,EACvB,CAAC,YAAa,KAAK,CACrB,EACA,OAAO,KAAO,CAAC,QAAQ,EAEvB,YAAYP,EAAM,CAChB,MAAMA,CAAI,CACZ,CAGA,eAAerH,EAAK,CAGlB,GADI,CAACA,GAAOA,IAAQ,GAAG,KAAK,UAAU,mCAAmC,EACrE,OAAOA,GAAQ,SAAU,CAC3B,MAAMqW,EAASrW,EAAI,MAAM,cAAc,EACvC,GAAIqW,EACFrW,EAAM,SAASqW,EAAO,CAAC,EAAG,EAAE,MACvB,CACL,MAAMtC,EAAKpQ,EAAa3D,EAAI,YAAY,CAAC,EACrC+T,IAAO,QAAW,KAAK,UAAU,qDAAqD,EAC1F/T,EAAM+T,CACR,CACF,CACA,KAAK,WAAW,QAAS,eAAgB/T,CAAG,EAC5C,KAAK,IAAI,eAAgBA,CAAG,CAC9B,CAEA,aAAaA,EAAK,CAEX,KAAK,oBAAoB,EAAE,IAAIA,CAAG,GAAG,KAAK,UAAU,0BAA0B,EAEnF,KAAK,IAAI,YAAaA,CAAG,CAC3B,CAEA,UAAUA,EAAK,CACb,KAAK,cAAc,KAAM,SAAUA,CAAG,CACxC,CAEA,eAAeA,EAAK,CAClB,KAAK,cAAc,MAAO,eAAgBA,CAAG,CAC/C,CAEA,uBAAuBA,EAAK,CAC1B,KAAK,cAAc,MAAO,uBAAwBA,CAAG,CACvD,CAEA,sBAAsBA,EAAK,CACzB,KAAK,cAAc,MAAO,sBAAuBA,CAAG,CACtD,CAEA,UAAUA,EAAK,CACb,KAAK,cAAc,MAAO,UAAWA,CAAG,CAC1C,CAEA,eAAeA,EAAK,CAClB,KAAK,cAAc,OAAQ,eAAgBA,CAAG,CAChD,CAEA,aAAaA,EAAK,CAChB,KAAK,cAAc,MAAO,YAAaA,CAAG,CAC5C,CAEA,qBAAsB,CAGpB,OAAO,IAAI,IAAI,CACb,CAAC,EAAG,SAAS,EACb,CAAC,EAAG,IAAI,EACR,CAAC,EAAG,WAAW,EACf,CAAC,EAAG,IAAI,EACR,CAAC,EAAG,WAAW,EACf,CAAC,EAAG,gBAAgB,EACpB,CAAC,EAAG,oBAAoB,EACxB,CAAC,EAAG,aAAa,EACjB,CAAC,GAAI,aAAa,EAClB,CAAC,GAAI,qBAAqB,EAC1B,CAAC,GAAI,qBAAqB,EAC1B,CAAC,GAAI,SAAS,EACd,CAAC,GAAI,OAAO,EACZ,CAAC,GAAG,EACJ,CAAC,GAAG,CACN,CAAC,CACH,CAEA,gBAAiB,CACf,MAAO,2BACT,CAEA,cAAe,CACb,MAAO,CACL,MAAO,eACP,IAAK,KACL,MAAO,KACP,KAAM,QACN,eAAgB,EAChB,UAAW,EACX,OAAQ,EACR,eAAgB,KAChB,uBAAwB,WACxB,sBAAuB,WACvB,UAAW,MACX,eAAgB,eAChB,UAAW,WACb,CACF,CAIA,SAAS,CAAE,SAAA+K,CAAS,EAAG,CAErB,MAAMzM,EAAQyM,EAAS,KAAK,EAAE,MAAM,KAAK,EACnCuL,EAAiBhY,EAAM,CAAC,EAExB+X,EAASC,EAAe,MAAM,cAAc,EAC5CC,EAAc,QAAQ,KAAKD,CAAc,EAC3C,SAASA,EAAgB,EAAE,EAC3BD,EACE,SAASA,EAAO,CAAC,EAAG,EAAE,EACrB1S,EAAa2S,EAAe,YAAY,CAAC,GAAK,SAASA,EAAgB,EAAE,EAChF,OAAO,IAAIF,GAAM,CACf,MAAO9X,EAAM,CAAC,EACd,IAAK,SAASA,EAAM,CAAC,EAAG,EAAE,EAC1B,MAAOA,EAAM,CAAC,EACd,KAAM,QACN,eAAgBiY,EAChB,UAAW,SAASjY,EAAM,CAAC,EAAG,EAAE,EAChC,OAAQ,SAASA,EAAM,CAAC,EAAG,EAAE,EAC7B,eAAgB,SAASA,EAAM,CAAC,EAAG,EAAE,EACrC,uBAAwB,SAASA,EAAM,CAAC,EAAG,EAAE,EAC7C,sBAAuB,SAASA,EAAM,CAAC,EAAG,EAAE,EAC5C,UAAW,SAASA,EAAM,EAAE,EAAG,EAAE,EACjC,eAAgBA,EAAM,EAAE,EACxB,UAAWA,EACR,MAAM,EAAE,EACR,OAAQ,GAAM,IAAM,KAAO,IAAM,GAAG,EACpC,KAAK,GAAG,EACR,KAAK,CACV,CAAC,CACH,CAEA,YAAY,CAAE,SAAAF,CAAS,EAAG,CACxB,KAAM,CAACmD,EAAMY,EAAG3D,EAAOC,EAAKyL,EAAIC,CAAG,EAAI/L,EAAS,MAAM,CAAC,EAAE,MAAM,GAAG,EAC9D,SAAS+D,EAAG,EAAE,IAAM,KAAK,UAAU,GAAG,KAAK,UAAU,8BAA8B,EAEvF,MAAMgB,EAAQ,WAAW,KAAKpE,EAAYP,CAAK,EAAIQ,GAAMA,EAAE,WAAW,CAAC,CAAC,EAClEoG,EAAK,IAAI,SAASjC,EAAM,OAAQA,EAAM,WAAYA,EAAM,UAAU,EAClEoT,EAAcnR,EAAG,UAAU,CAAC,EAC5B+H,EAAYhK,EAAM,CAAC,EACnB7D,EAAS6D,EAAM,CAAC,EAChBqT,EAAcpR,EAAG,UAAU,CAAC,EAC5BqR,EAAsBrR,EAAG,UAAU,CAAC,EACpCsR,EAAqBtR,EAAG,UAAU,EAAE,EACpCuR,EAASvR,EAAG,UAAU,EAAE,EAE9B,IAAI/F,EAAM,GACV,MAAMuX,EAAW,CAAC,EAClB,KAAOvX,EAAM8D,EAAM,QAAQ,CACzB,MAAM5D,EAAM4D,EAAM9D,GAAK,EACvB,GAAIE,IAAQ,EAAG,MACfqX,EAAS,KAAK,IAAI,YAAY,EAAE,OAAOzT,EAAM,SAAS9D,EAAKA,EAAME,CAAG,CAAC,CAAC,EACtEF,GAAOE,CACT,CACA,MAAMsX,EAAc,GAAGD,EAAS,KAAK,GAAG,CAAC,IACnCE,EAAY,IAAI,YAAY,EAAE,OAAO3T,EAAM,SAAS9D,CAAG,CAAC,EAE9D,OAAO,IAAI+W,GAAM,CACf,MAAO,KAAK,aAAa7U,CAAI,EAC7B,IAAK,SAAS9C,EAAK,EAAE,EACrB,KAAM,QACN,eAAgB8X,EAChB,UAAApJ,EACA,OAAA7N,EACA,eAAgBkX,EAChB,uBAAwBC,EACxB,sBAAuBC,EACvB,UAAWC,EACX,eAAgBE,EAChB,UAAAC,EACA,UAAW5M,EACX,SAAUC,GAAK,KAAK,GAAK,EAC3B,CAAC,CACH,CAIA,WAAY,CACV,MAAMgF,EAAS,IAAI,OAAO,YAAa,GAAG,EAC1C,OAAO,KAAK,kBACV/M,EAAc,KAAK,IAAI,cAAc,CAAC,EACpCnB,EAAa,KAAK,IAAI,WAAW,CAAC,EAClCA,EAAa,KAAK,IAAI,QAAQ,CAAC,EAC/BoB,EAAc,KAAK,IAAI,cAAc,CAAC,EACtCA,EAAc,KAAK,IAAI,sBAAsB,CAAC,EAC9CA,EAAc,KAAK,IAAI,qBAAqB,CAAC,EAC7CD,EAAc,KAAK,IAAI,SAAS,CAAC,EACjCd,EAAe,KAAK,IAAI,cAAc,CAAC,EACvCrB,EAAYkP,EAAQ,KAAK,IAAI,WAAW,CAAC,CAC7C,CACF,CAEA,cAAe,CACb,MAAM4H,EAAcjT,EAAe,KAAK,IAAI,cAAc,CAAC,EACrDkT,EAAW,IAAI,YAAY,EAAE,OAAO,KAAK,IAAI,WAAW,CAAC,EAEzDpL,EAAW,GAA4BmL,EAAY,OAASC,EAAS,OACrE7T,EAAQ,IAAI,WAAWyI,CAAQ,EAC/BxG,EAAK,IAAI,SAASjC,EAAM,OAAQA,EAAM,UAAU,EAEtD,IAAI9D,EAAM,EACV,OAAA+F,EAAG,UAAU/F,EAAK,KAAK,IAAI,cAAc,CAAC,EAC1CA,GAAO,EACP8D,EAAM9D,GAAK,EAAI,KAAK,IAAI,WAAW,EACnC8D,EAAM9D,GAAK,EAAI,KAAK,IAAI,QAAQ,EAChC+F,EAAG,UAAU/F,EAAK,KAAK,IAAI,cAAc,CAAC,EAC1CA,GAAO,EACP+F,EAAG,UAAU/F,EAAK,KAAK,IAAI,sBAAsB,CAAC,EAClDA,GAAO,EACP+F,EAAG,UAAU/F,EAAK,KAAK,IAAI,qBAAqB,CAAC,EACjDA,GAAO,EACP+F,EAAG,UAAU/F,EAAK,KAAK,IAAI,SAAS,CAAC,EACrCA,GAAO,EACP8D,EAAM,IAAI4T,EAAa1X,CAAG,EAC1BA,GAAO0X,EAAY,OACnB5T,EAAM,IAAI6T,EAAU3X,CAAG,EAEhB8D,CACT,CACF,CAEA,MAAM8T,WAAYrP,CAAG,CACnB,OAAO,SAAW,MAClB,OAAO,OAAS,GAChB,OAAO,KAAO,CAAC,KAAM,IAAI,EACzB,OAAO,YAAc,CACnB,CAAC,eAAgB,KAAK,EACtB,CAAC,YAAa,IAAI,EAClB,CAAC,SAAU,IAAI,EACf,CAAC,eAAgB,KAAK,EACtB,CAAC,uBAAwB,KAAK,EAC9B,CAAC,sBAAuB,KAAK,EAC7B,CAAC,UAAW,KAAK,EACjB,CAAC,eAAgB,MAAM,EACvB,CAAC,YAAa,KAAK,CACrB,EACA,OAAO,KAAO,CAAC,UAAU,EAEzB,YAAYP,EAAM,CAChB,MAAMA,CAAI,CACZ,CAGA,eAAerH,EAAK,CAEbA,GAAK,KAAK,UAAU,iCAAiC,EAE1D,KAAK,IAAI,eAAgBA,CAAG,CAC9B,CAEA,aAAaA,EAAK,CAEhB,KAAK,UAAU,MAAO,YAAaA,CAAG,EAEtC,KAAK,IAAI,YAAaA,CAAG,CAC3B,CAEA,UAAUA,EAAK,CAEb,KAAK,UAAU,MAAO,SAAUA,CAAG,EAEnC,KAAK,IAAI,SAAUA,CAAG,CACxB,CAEA,eAAeA,EAAK,CAElB,KAAK,WAAW,MAAO,eAAgBA,CAAG,EAE1C,KAAK,IAAI,eAAgBA,CAAG,CAC9B,CAEA,uBAAuBA,EAAK,CAE1B,KAAK,IAAI,uBAAwBA,CAAG,CACtC,CAEA,sBAAsBA,EAAK,CAEzB,KAAK,IAAI,sBAAuBA,CAAG,CACrC,CAEA,UAAUA,EAAK,CAEb,KAAK,IAAI,UAAWA,CAAG,CACzB,CAEA,eAAeA,EAAK,CAIlB,KAAK,IAAI,eAAgBA,EAAI,YAAY,CAAC,CAC5C,CAEA,aAAaA,EAAK,CAGhB,KAAK,IAAI,YAAaA,CAAG,CAC3B,CAEA,gBAAiB,CACf,MAAO,WACT,CAEA,cAAe,CACb,MAAO,CACL,MAAO,eACP,IAAK,KACL,MAAO,KACP,KAAM,MACN,eAAgB,EAChB,UAAW,EACX,OAAQ,EACR,eAAgB,KAChB,uBAAwB,WACxB,sBAAuB,WACvB,UAAW,MACX,eAAgB,eAChB,UAAW,WACb,CACF,CAIA,SAAS,CAAE,SAAA+K,CAAS,EAAG,CAErB,MAAMzM,EAAQyM,EAAS,KAAK,EAAE,MAAM,KAAK,EACnCuL,EAAiBhY,EAAM,CAAC,EACxBiY,EAAc,QAAQ,KAAKD,CAAc,EAC3C,SAASA,EAAgB,EAAE,EAC1B3S,EAAa2S,EAAe,YAAY,CAAC,GAAK,SAASA,EAAgB,EAAE,EAE9E,OAAO,IAAIW,GAAI,CACb,MAAO3Y,EAAM,CAAC,EACd,IAAK,SAASA,EAAM,CAAC,EAAG,EAAE,EAC1B,MAAOA,EAAM,CAAC,EACd,KAAM,MACN,eAAgBiY,EAChB,UAAW,SAASjY,EAAM,CAAC,EAAG,EAAE,EAChC,OAAQ,SAASA,EAAM,CAAC,EAAG,EAAE,EAC7B,eAAgB,SAASA,EAAM,CAAC,EAAG,EAAE,EACrC,uBAAwB,SAASA,EAAM,CAAC,EAAG,EAAE,EAC7C,sBAAuB,SAASA,EAAM,CAAC,EAAG,EAAE,EAC5C,UAAW,SAASA,EAAM,EAAE,EAAG,EAAE,EACjC,eAAgBA,EAAM,EAAE,EACxB,UAAWA,EACR,MAAM,EAAE,EACR,OAAQiI,GAAMA,IAAM,KAAOA,IAAM,GAAG,EACpC,KAAK,GAAG,EACR,KAAK,CACV,CAAC,CACH,CAGA,WAAY,CACV,MAAM4I,EAAS,IAAI,OAAO,YAAa,GAAG,EAE1C,OAAO,KAAK,kBACV/M,EAAc,KAAK,IAAI,cAAc,CAAC,EACpCnB,EAAa,KAAK,IAAI,WAAW,CAAC,EAClCA,EAAa,KAAK,IAAI,QAAQ,CAAC,EAC/BoB,EAAc,KAAK,IAAI,cAAc,CAAC,EACtCA,EAAc,KAAK,IAAI,sBAAsB,CAAC,EAC9CA,EAAc,KAAK,IAAI,qBAAqB,CAAC,EAC7CD,EAAc,KAAK,IAAI,SAAS,CAAC,EACjCd,EAAe,KAAK,IAAI,cAAc,CAAC,EACvCrB,EAAYkP,EAAQ,KAAK,IAAI,WAAW,CAAC,CAC7C,CACF,CAEA,cAAe,CACb,MAAM4H,EAAcjT,EAAe,KAAK,IAAI,cAAc,CAAC,EACrDkT,EAAW,IAAI,YAAY,EAAE,OAAO,KAAK,IAAI,WAAW,CAAC,EAEzDpL,EAAW,GAA4BmL,EAAY,OAASC,EAAS,OACrE7T,EAAQ,IAAI,WAAWyI,CAAQ,EAC/BxG,EAAK,IAAI,SAASjC,EAAM,OAAQA,EAAM,UAAU,EAEtD,IAAI9D,EAAM,EACV,OAAA+F,EAAG,UAAU/F,EAAK,KAAK,IAAI,cAAc,CAAC,EAC1CA,GAAO,EACP8D,EAAM9D,GAAK,EAAI,KAAK,IAAI,WAAW,EACnC8D,EAAM9D,GAAK,EAAI,KAAK,IAAI,QAAQ,EAChC+F,EAAG,UAAU/F,EAAK,KAAK,IAAI,cAAc,CAAC,EAC1CA,GAAO,EACP+F,EAAG,UAAU/F,EAAK,KAAK,IAAI,sBAAsB,CAAC,EAClDA,GAAO,EACP+F,EAAG,UAAU/F,EAAK,KAAK,IAAI,qBAAqB,CAAC,EACjDA,GAAO,EACP+F,EAAG,UAAU/F,EAAK,KAAK,IAAI,SAAS,CAAC,EACrCA,GAAO,EACP8D,EAAM,IAAI4T,EAAa1X,CAAG,EAC1BA,GAAO0X,EAAY,OACnB5T,EAAM,IAAI6T,EAAU3X,CAAG,EAEhB8D,CACT,CAEA,YAAY,CAAE,SAAA/E,CAAS,EAAG,CACxB,KAAM,CAAE,MAAAG,EAAO,OAAAM,EAAQ,MAAAL,EAAO,IAAAC,EAAK,UAAAC,EAAW,SAAAC,CAAS,EAAI,KAAK,iBAAiBP,CAAQ,EACrF,SAASS,EAAQ,EAAE,IAAM,KAAK,UAAU,GAAG,KAAK,UAAU,4BAA4B,EAE1F,MAAMsE,EAAQrE,EAAkBN,CAAK,EAC/B4G,EAAK,IAAI,SAASjC,EAAM,OAAQA,EAAM,WAAYA,EAAM,UAAU,EAElEoT,EAAcnR,EAAG,UAAU,CAAC,EAC5B+H,EAAYhK,EAAM,CAAC,EACnB7D,EAAS6D,EAAM,CAAC,EAChBqT,EAAcpR,EAAG,UAAU,CAAC,EAC5BqR,EAAsBrR,EAAG,UAAU,CAAC,EACpCsR,EAAqBtR,EAAG,UAAU,EAAE,EACpCuR,EAASvR,EAAG,UAAU,EAAE,EAG9B,IAAI/F,EAAM,GACV,MAAM6X,EAAY,CAAC,EACnB,KAAO7X,EAAM8D,EAAM,QAAQ,CACzB,MAAM5D,EAAM4D,EAAM9D,GAAK,EACvB,GAAIE,IAAQ,EAAG,MACf2X,EAAU,KAAK,IAAI,YAAY,EAAE,OAAO/T,EAAM,SAAS9D,EAAKA,EAAME,CAAG,CAAC,CAAC,EACvEF,GAAOE,CACT,CACA,MAAMsX,EAAc,GAAGK,EAAU,KAAK,GAAG,CAAC,IAEpCJ,EAAY,IAAI,YAAY,EAAE,OAAO3T,EAAM,SAAS9D,CAAG,CAAC,EAE9D,OAAO,IAAI4X,GAAI,CACb,MAAA1Y,EACA,IAAAE,EACA,KAAM,MACN,eAAgB8X,EAChB,UAAApJ,EACA,OAAA7N,EACA,eAAgBkX,EAChB,uBAAwBC,EACxB,sBAAuBC,EACvB,UAAWC,EACX,eAAgBE,EAChB,UAAAC,EACA,UAAApY,EACA,SAAAC,CACF,CAAC,CACH,CAEA,OAAO+I,EAAW,CAChB,MAAO,GAAG,KAAK,QAAQ,QAASA,CAAS,CAAC,IAAI,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,IAAI,OAAO,CAAC,OAAO,KAAK,eAAe,EAC1G,MAAM,EAAG,CAAC,EACV,IAAKhI,GAAM,IAAM,KAAK,IAAIA,CAAC,CAAC,EAC5B,KAAK,EAAE,CAAC,IAAI,KAAK,eAAe,EAChC,MAAM,EAAG,CAAC,EACV,IAAKA,GAAM,KAAK,IAAIA,CAAC,CAAC,EACtB,KAAK,GAAG,CAAC,MAAM,KAAK,IAAI,WAAW,CAAC,IACzC,CACF,CAEA,MAAMyX,WAAevP,CAAG,CACtB,OAAO,SAAW,SAClB,OAAO,OAAS,GAChB,OAAO,KAAO,CAAC,IAAI,EACnB,OAAO,YAAc,CACnB,CAAC,oBAAqB,IAAI,EAC1B,CAAC,WAAY,IAAI,EACjB,CAAC,gBAAiB,IAAI,EACtB,CAAC,+BAAgC,KAAK,CACxC,EACA,OAAO,KAAO,CAAC,UAAU,EAEzB,YAAYP,EAAM,CAChB,MAAMA,CAAI,CACZ,CAGA,oBAAoBrH,EAAK,CAClB,KAAK,2BAA2B,EAAE,IAAIA,CAAG,GAAG,KAAK,UAAU,mCAAmC,EAEnG,KAAK,IAAI,oBAAqBA,CAAG,CACnC,CAEA,4BAA6B,CAC3B,OAAO,IAAI,IAAI,CACb,CAAC,EAAG,gBAAgB,EACpB,CAAC,EAAG,2BAA2B,EAC/B,CAAC,EAAG,kBAAkB,EACtB,CAAC,EAAG,2BAA2B,CACjC,CAAC,CACH,CAEA,YAAYA,EAAK,CACV,KAAK,mBAAmB,EAAE,IAAIA,CAAG,GAAG,KAAK,UAAU,0BAA0B,EAElF,KAAK,IAAI,WAAYA,CAAG,CAC1B,CAEA,oBAAqB,CACnB,OAAO,IAAI,IAAI,CACb,CAAC,EAAG,kBAAkB,EACtB,CAAC,EAAG,sBAAsB,CAC5B,CAAC,CACH,CAEA,gBAAgBA,EAAK,CACd,KAAK,uBAAuB,EAAE,IAAIA,CAAG,GAAG,KAAK,UAAU,uBAAuB,EAEnF,KAAK,IAAI,gBAAiBA,CAAG,CAC/B,CAEA,wBAAyB,CACvB,OAAO,IAAI,IAAI,CACb,CAAC,EAAG,aAAa,EACjB,CAAC,EAAG,cAAc,EAClB,CAAC,EAAG,cAAc,CACpB,CAAC,CACH,CAEA,8BAA8BA,EAAK,CACjC,KAAK,IAAI,+BAAgCA,CAAG,CAC9C,CAEA,gBAAiB,CACf,MAAO,yBACT,CAEA,cAAe,CACb,MAAO,CACL,MAAO,6BACP,IAAK,KACL,MAAO,KACP,KAAM,SACN,oBAAqB,EACrB,SAAU,EACV,gBAAiB,EACjB,+BAAgC,WAClC,CACF,CAIA,SAAS,CAAE,SAAA+K,CAAS,EAAG,CAErB,KAAM,CAACxM,EAAOE,EAAKO,EAAGkK,EAAMkO,EAAOC,EAAUpK,CAAK,EAAIlC,EAAS,MAAM,KAAK,EAC1E,OAAO,IAAIoM,GAAO,CAChB,MAAA5Y,EACA,IAAK,SAASE,EAAK,EAAE,EACrB,MAAOO,EACP,KAAMkK,EACN,oBAAqB,SAASkO,EAAO,EAAE,EACvC,SAAU,SAASC,EAAU,EAAE,EAC/B,gBAAiB,SAASpK,EAAO,EAAE,EACnC,+BAAgClC,EAAS,MAAM,KAAK,EAAE,MAAM,CAAC,EAAE,KAAK,GAAG,EAAE,KAAK,CAChF,CAAC,CACH,CAEA,YAAY,CAAE,SAAA3M,CAAS,EAAG,CACxB,KAAM,CAAE,MAAAG,EAAO,MAAAC,EAAO,IAAAC,EAAK,UAAAC,EAAW,SAAAC,CAAS,EAAI,KAAK,iBAAiBP,CAAQ,EAC3EuU,EAAc7T,EAAkBN,CAAK,EAE3C,OAAO,IAAI2Y,GAAO,CAChB,MAAA5Y,EACA,IAAAE,EACA,KAAM,SACN,oBAAqBkU,EAAY,CAAC,EAClC,SAAUA,EAAY,CAAC,EACvB,gBAAiBA,EAAY,CAAC,EAC9B,+BAAgCpP,EAAWoP,EAAY,SAAS,CAAC,CAAC,EAClE,UAAAjU,EACA,SAAAC,CACF,CAAC,CACH,CAGA,WAAY,CACV,OAAO,KAAK,kBACVsC,EAAa,KAAK,IAAI,mBAAmB,CAAC,EACxCA,EAAa,KAAK,IAAI,UAAU,CAAC,EACjCA,EAAa,KAAK,IAAI,eAAe,CAAC,EACtCgB,EAAQ,KAAK,IAAI,8BAA8B,EAAE,QAAQ,UAAW,EAAE,CAAC,CAC3E,CACF,CAEA,cAAe,CACb,MAAMqV,EAAWlU,EAAW,KAAK,IAAI,8BAA8B,EAAE,QAAQ,UAAW,EAAE,CAAC,EACrFD,EAAQ,IAAI,WAAW,EAAImU,EAAS,MAAM,EAChD,OAAAnU,EAAM,CAAC,EAAI,KAAK,IAAI,mBAAmB,EACvCA,EAAM,CAAC,EAAI,KAAK,IAAI,UAAU,EAC9BA,EAAM,CAAC,EAAI,KAAK,IAAI,eAAe,EACnCA,EAAM,IAAImU,EAAU,CAAC,EACdnU,CACT,CACF,CAEA,MAAMoU,WAAY3P,CAAG,CACnB,OAAO,SAAW,MAClB,OAAO,OAAS,EAChB,OAAO,KAAO,CAAC,KAAM,IAAI,EACzB,OAAO,YAAc,IACrB,OAAO,YAAc,CACnB,CAAC,QAAS,MAAM,EAChB,CAAC,QAAS,MAAM,EAChB,CAAC,SAAU,KAAK,EAChB,CAAC,UAAW,KAAK,EACjB,CAAC,QAAS,KAAK,EACf,CAAC,SAAU,KAAK,EAChB,CAAC,UAAW,KAAK,CACnB,EACA,OAAO,KAAO,CAAC,QAAQ,EAEvB,YAAYP,EAAM,CAChB,MAAMA,CAAI,CACZ,CAGA,WAAWrH,EAAK,CAId,KAAK,WAAW,MAAO,UAAWA,CAAG,EAErC,KAAK,IAAI,UAAWA,CAAG,CACzB,CAEA,SAASA,EAAK,CAEZ,KAAK,gBAAgB,MAAO,QAASA,CAAG,EACxC,KAAK,iBAAiB,MAAO,QAASA,CAAG,EAGzC,KAAK,IAAI,QAASA,EAAI,YAAY,CAAC,CACrC,CAEA,SAASA,EAAK,CAEZ,KAAK,gBAAgB,MAAO,QAASA,CAAG,EACxC,KAAK,iBAAiB,MAAO,QAASA,CAAG,EACrC,IAAI,KAAKA,CAAG,GAAG,KAAK,UAAU,qCAAqC,EAGvE,KAAK,IAAI,QAASA,EAAI,YAAY,CAAC,CACrC,CAEA,UAAUA,EAAK,CACb,KAAK,WAAW,MAAO,SAAUA,CAAG,EAEpC,KAAK,IAAI,SAAUA,CAAG,CACxB,CAEA,WAAWA,EAAK,CAId,KAAK,WAAW,MAAO,UAAWA,CAAG,EAErC,KAAK,IAAI,UAAWA,CAAG,CACzB,CAEA,SAASA,EAAK,CAIZ,KAAK,WAAW,MAAO,QAASA,CAAG,EAEnC,KAAK,IAAI,QAASA,CAAG,CACvB,CAEA,UAAUA,EAAK,CAIb,KAAK,WAAW,MAAO,SAAUA,CAAG,EAEpC,KAAK,IAAI,SAAUA,CAAG,CACxB,CAEA,gBAAiB,CACf,MAAO,oBACT,CAEA,cAAe,CACb,MAAO,CACL,MAAO,eACP,IAAK,KACL,MAAO,KACP,KAAM,MACN,MAAO,mBACP,MAAO,qBACP,OAAQ,WACR,QAAS,KACT,MAAO,KACP,OAAQ,QACR,QAAS,IACX,CACF,CAGA,YAAY,CAAE,SAAA5B,CAAS,EAAG,CAExB,KAAM,CAACmD,EAAMiW,EAAOC,EAAOC,EAAKC,EAAKC,EAAKC,EAAK5G,EAAKxS,EAAKyL,EAAIC,CAAG,EAAI/L,EAAS,MAAM,CAAC,EAAE,MAAM,GAAG,EAE/F,OAAO,IAAImZ,GAAI,CACb,MAAO,KAAK,aAAahW,CAAI,EAC7B,IAAK,SAAS9C,EAAK,EAAE,EACrB,KAAM,MACN,MAAO,KAAK,aAAa+Y,CAAK,EAC9B,MAAO,KAAK,aAAaC,CAAK,EAC9B,OAAQ,SAASC,GAAO,KAAK,SAAS,OAAQ,EAAE,EAChD,QAAS,SAASC,EAAK,EAAE,GAAK,MAC9B,MAAO,SAASC,EAAK,EAAE,GAAK,KAC5B,OAAQ,SAASC,EAAK,EAAE,GAAK,QAC7B,QAAS,SAAS5G,EAAK,EAAE,GAAK,KAC9B,UAAW,SAAS/G,CAAE,GAAK,GAC3B,SAAUC,GAAK,KAAK,GAAK,EAC3B,CAAC,CACH,CAGA,WAAY,CACV,MAAO,GAAG,KAAK,IAAI,OAAO,CAAC,SAAW,KAAK,UAAU,OAAO,EACzD,IAAKzK,GAAM,KAAK,UAAUA,CAAC,CAAC,EAC5B,KAAK,GAAI,CAAC;AAAA,CACf,CAEA,cAAe,CACb,MAAM8X,EAAQ,KAAK,eAAe,KAAK,IAAI,OAAO,CAAC,EAC7CC,EAAQ,KAAK,eAAe,KAAK,IAAI,OAAO,CAAC,EAC7C3X,EAAS,IAAI,WAAW0X,EAAM,OAASC,EAAM,OAAS,EAAE,EAC9D,IAAI5T,EAAS,EACb/D,EAAO,IAAI0X,EAAO3T,CAAM,EACxBA,GAAU2T,EAAM,OAChB1X,EAAO,IAAI2X,EAAO5T,CAAM,EACxBA,GAAU4T,EAAM,OAChB,MAAM5S,EAAO,IAAI,SAAS/E,EAAO,OAAQ+D,CAAM,EAC/C,OAAAgB,EAAK,UAAU,EAAG,KAAK,IAAI,QAAQ,CAAC,EACpCA,EAAK,UAAU,EAAG,KAAK,IAAI,SAAS,CAAC,EACrCA,EAAK,UAAU,EAAG,KAAK,IAAI,OAAO,CAAC,EACnCA,EAAK,UAAU,GAAI,KAAK,IAAI,QAAQ,CAAC,EACrCA,EAAK,UAAU,GAAI,KAAK,IAAI,SAAS,CAAC,EAC/B/E,CACT,CAEA,WAAY,CACV,MAAO,IAAI,KAAK,YAAY,OAAO,CAAC,IAAI,KAAK,YAAY,OAAO,CAAC,IAAI,KAAK,YAAY,OAAO,CAAC,IAAI,KAAK,SAAS,QAAQ,CAAC,IAAI,KAAK,SAAS,SAAS,CAAC,IAAI,KAAK,SAAS,OAAO,CAAC,IAAI,KAAK,SAAS,QAAQ,CAAC,IAAI,KAAK,SAAS,SAAS,CAAC,IAAI,KAAK,oBAAoB,CAAC;AAAA,CACtQ,CACF,CAEA,MAAMgY,WAAYlQ,CAAG,CACnB,OAAO,SAAW,MAClB,OAAO,OAAS,GAChB,OAAO,KAAO,CAAC,KAAM,KAAM,KAAM,IAAI,EACrC,OAAO,YAAc,IACrB,OAAO,YAAc,CAAC,CAAC,OAAQ,UAAU,CAAC,EAC1C,OAAO,KAAO,CAAC,QAAQ,EAEvB,YAAYP,EAAM,CAChB,MAAMA,CAAI,CACZ,CAGA,QAAQrH,EAAK,CACX,KAAK,IAAI,OAAQA,CAAG,CACtB,CAEA,gBAAiB,CACf,MAAO,MACT,CAEA,cAAe,CACb,MAAO,CACL,MAAO,eACP,IAAK,KACL,MAAO,KACP,KAAM,MACN,KAAM,gBACR,CACF,CAGA,YAAY,CAAE,SAAA5B,CAAS,EAAG,CACxB,MAAM+B,EAAM/B,EACZ,IAAImD,EAAM/C,EAAOwC,EAAGvC,EAAKyL,EAAIC,EAE7B,OAAIhK,EAAI,CAAC,IAAM,KACnB,CAACoB,EAAMP,EAAGvC,EAAKyL,EAAIC,CAAG,EAAIhK,EAAI,MAAM,CAAC,EAAE,MAAM,GAAG,EAC1C3B,EAAQO,EAAYiC,CAAC,GAE3B,CAACO,EAAM/C,EAAOC,EAAKyL,EAAIC,CAAG,EAAI,KAAK,mBAAmBhK,CAAG,EAG9C,IAAI,KAAK,YAAY,CAC1B,MAAO,KAAK,aAAaoB,CAAI,EAC7B,IAAK,SAAS9C,EAAK,EAAE,EACrB,KAAM,MACN,KAAMD,EACN,UAAW0L,EACX,SAAUC,GAAK,KAAK,GAAK,EAC3B,CAAC,CACH,CAEA,mBAAmBhK,EAAK,CAGtB,GAAI,CAACoB,EAAMY,EAAG3D,EAAOC,EAAKyL,EAAIC,CAAG,EAAIhK,EAAI,MAAM,CAAC,EAAE,MAAM,GAAG,EACvDgC,GAAK,IAAI,KAAK,UAAU,4BAA4B,EAExD3D,EAAQO,EAAYP,CAAK,EAEzB,MAAMF,EAAQ,CAAC,EACf,IAAIe,EAAM,EACV,KAAOA,EAAMb,EAAM,QAAQ,CACzB,MAAMe,EAAMf,EAAM,WAAWa,CAAG,EAChCA,GAAO,EACHA,EAAME,EAAMf,EAAM,QACpB,KAAK,UAAU,6DAA6D,EAE9EF,EAAM,KAAKE,EAAM,MAAMa,EAAKA,EAAME,CAAG,CAAC,EACtCF,GAAOE,CACT,CACA,MAAMwY,EAAOzZ,EAAM,OAAS,EAAIA,EAASA,EAAM,CAAC,GAAK,GACrD,MAAO,CAACiD,EAAMwW,EAAMtZ,EAAKyL,EAAIC,CAAG,CAClC,CAGA,OAAOzC,EAAW,CAChB,MAAO,GAAG,KAAK,UAAUA,CAAS,CAAC,KAAMsQ,GAAgB,KAAK,IAAI,MAAM,CAAC,CAAC;AAAA,CAC5E,CAEA,WAAY,CACV,MAAMD,EAAOC,GAAgB,KAAK,IAAI,MAAM,CAAC,EAAE,QAAQ,KAAM,GAAG,EAChE,MAAO,GAAG,KAAK,IAAI,OAAO,CAAC,KAAM,KAAK,IAAI,KAAK,CAAC,IAAK,KAAK,IAAI,MAAM,CAAC,KAAMD,CAAI;AAAA,CACjF,CAEA,cAAe,CAMb,MAAMA,EAAO,KAAK,IAAI,MAAM,EAC5B,GAAI,MAAM,QAAQA,CAAI,EAAG,CACvB,MAAMhU,EAAM,IAAI,YACVkU,EAAUF,EAAK,IAAI,CAAC/W,EAAGjB,KACvBgE,EAAI,OAAO/C,CAAC,EAAE,OAAS,KACzB,KAAK,UACH,sBAAsBjB,CAAC,6EACzB,EAEKmY,GAAelX,CAAC,EACxB,EACKqF,EAAQ4R,EAAQ,OAAO,CAAC9V,EAAGc,IAAMd,EAAIc,EAAE,OAAQ,CAAC,EAChDkV,EAAM,IAAI,WAAW9R,CAAK,EAChC,IAAI+R,EAAM,EACV,UAAWnV,KAAKgV,EACdE,EAAI,IAAIlV,EAAGmV,CAAG,EACdA,GAAOnV,EAAE,OAEX,OAAOkV,CACT,CACA,OAAOD,GAAeH,CAAI,CAC5B,CAEA,WAAY,CACV,IAAIA,EAAO,KAAK,IAAI,MAAM,EACtB,MAAM,QAAQA,CAAI,IAAGA,EAAOA,EAAK,KAAK,EAAE,GAC5C,MAAMvZ,EAAQyB,EAAY,IAAI,OAAO,eAAgB,GAAG,EAAG8X,CAAI,EAC/D,MAAO,IAAI,KAAK,YAAY,OAAO,CAAC,IAAIvZ,CAAK,IAAI,KAAK,oBAAoB,CAAC;AAAA,CAC7E,CACF,CAEA,SAASwZ,GAAgBD,EAAM,CAG7B,MAAMhU,EAAM,IAAI,YAEhB,OAAI,MAAM,QAAQgU,CAAI,EACDA,EAAK,KAAM,GAAMhU,EAAI,OAAO,CAAC,EAAE,OAAS,GAAG,EAEvDsU,GAAaN,EAAK,KAAK,EAAE,EAAG,GAAG,EAAE,KAAK,KAAK,EAD1BA,EAAK,KAAK,KAAK,EAIrChU,EAAI,OAAOgU,CAAI,EAAE,QAAU,IAAYA,EACpCM,GAAaN,EAAM,GAAG,EAAE,KAAK,KAAK,CAC3C,CAEA,SAASM,GAAalY,EAAKmY,EAAU,CACnC,MAAMnV,EAAQ,IAAI,YAAY,EAAE,OAAOhD,CAAG,EACpCiB,EAAM,IAAI,YACVmX,EAAS,CAAC,EAChB,IAAIC,EAAQ,EACZ,KAAOA,EAAQrV,EAAM,QAAQ,CAC3B,IAAIyB,EAAM,KAAK,IAAI4T,EAAQF,EAAUnV,EAAM,MAAM,EAEjD,KAAOyB,EAAMzB,EAAM,SAAWA,EAAMyB,CAAG,EAAI,OAAU,KAAMA,IAC3D2T,EAAO,KAAKnX,EAAI,OAAO+B,EAAM,SAASqV,EAAO5T,CAAG,CAAC,CAAC,EAClD4T,EAAQ5T,CACV,CACA,OAAO2T,CACT,CAEA,SAASL,GAAe/X,EAAK,CAC3B,MAAMsY,EAAU,IAAI,YAAY,EAAE,OAAOtY,CAAG,EAC5C,GAAIsY,EAAQ,SAAW,EAAG,OAAO,IAAI,WAAW,CAAC,CAAC,CAAC,EAEnD,MAAMF,EAAS,CAAC,EAChB,QAASxY,EAAI,EAAGA,EAAI0Y,EAAQ,OAAQ1Y,GAAK,IAAKwY,EAAO,KAAKE,EAAQ,SAAS1Y,EAAGA,EAAI,GAAG,CAAC,EAEtF,MAAMkE,EAAM,IAAI,WAAWwU,EAAQ,OAASF,EAAO,MAAM,EACzD,IAAI1U,EAAS,EACb,UAAW6U,KAASH,EAClBtU,EAAIJ,GAAQ,EAAI6U,EAAM,OACtBzU,EAAI,IAAIyU,EAAO7U,CAAM,EACrBA,GAAU6U,EAAM,OAElB,OAAOzU,CACT,CAKA,MAAM0U,WAAYb,EAAI,CACpB,OAAO,SAAW,MAClB,OAAO,OAAS,GAChB,OAAO,KAAO,CAAC,KAAM,IAAI,EACzB,OAAO,YAAc,CAAC,CAAC,OAAQ,UAAU,CAAC,EAC1C,OAAO,KAAO,CAAC,UAAU,EAEzB,YAAYzQ,EAAM,CAChB,MAAMA,CAAI,CACZ,CAGA,QAAQrH,EAAK,CACX,KAAK,IAAI,OAAQA,CAAG,CACtB,CAEA,gBAAiB,CACf,MAAO,yBACT,CACA,cAAe,CACb,MAAO,CACL,MAAO,eACP,IAAK,KACL,MAAO,KACP,KAAM,MACN,KAAM,gBACR,CACF,CAGA,YAAY,CAAE,SAAA5B,CAAS,EAAG,CAExB,KAAM,CAACmD,EAAMY,EAAG3D,EAAOC,EAAKyL,EAAIC,CAAG,EAAI/L,EAAS,MAAM,CAAC,EAAE,MAAM,GAAG,EAClE,OAAI+D,GAAK,IAAI,KAAK,UAAU,4BAA4B,EAEjD,IAAIwW,GAAI,CACb,KAAM,MACN,MAAO,KAAK,aAAapX,CAAI,EAC7B,KAAMxC,EAAYP,CAAK,EACvB,IAAK,SAASC,EAAK,EAAE,EACrB,UAAWyL,EACX,SAAUC,GAAK,KAAK,GAAK,EAC3B,CAAC,CACH,CAGA,cAAe,CACb,OAAO,MAAM,aAAa,CAC5B,CAEA,WAAY,CAGV,IAAI4N,EAAO,KAAK,IAAI,MAAM,EACtB,MAAM,QAAQA,CAAI,IAAGA,EAAOA,EAAK,KAAK,EAAE,GAC5C,MAAMvZ,EAAQyB,EAAY,IAAI,OAAO,eAAgB,GAAG,EAAG8X,CAAI,EAC/D,OAAO,KAAK,kBAAkBvZ,CAAK,CACrC,CACF,CAEA,MAAMoa,WAAYhR,CAAG,CACnB,OAAO,SAAW,MAClB,OAAO,OAAS,GAChB,OAAO,KAAO,CAAC,IAAI,EACnB,OAAO,YAAc,CACnB,CAAC,WAAY,KAAK,EAClB,CAAC,SAAU,KAAK,EAChB,CAAC,OAAQ,KAAK,EACd,CAAC,SAAU,MAAM,CACnB,EACA,OAAO,KAAO,CAAC,QAAQ,EAEvB,YAAYP,EAAM,CAChB,MAAMA,CAAI,CACZ,CAGA,YAAYrH,EAAK,CACf,KAAK,cAAc,MAAO,WAAYA,CAAG,CAC3C,CAEA,UAAUA,EAAK,CACb,KAAK,cAAc,MAAO,SAAUA,CAAG,CACzC,CAEA,QAAQA,EAAK,CACX,KAAK,cAAc,MAAO,OAAQA,CAAG,CACvC,CAEA,UAAUA,EAAK,CACb,KAAK,cAAc,OAAQ,SAAUA,CAAG,CAC1C,CAEA,gBAAiB,CACf,MAAO,SACT,CAEA,cAAe,CACb,MAAO,CACL,MAAO,2BACP,IAAK,KACL,MAAO,KACP,KAAM,MACN,SAAU,GACV,OAAQ,GACR,KAAM,IACN,OAAQ,mBACV,CACF,CAGA,YAAY,CAAE,SAAA5B,CAAS,EAAG,CACxB,MAAM+B,EAAM/B,EACZ,IAAImD,EAAMiF,EAAMqS,EAAM7J,EAAK8J,EAAQra,EAAKyL,EAAIC,EAAKhI,EAAG3D,EAEpD,OAAI2B,EAAI,CAAC,IAAM,IACnB,CAACoB,EAAMiF,EAAMqS,EAAM7J,EAAK8J,EAAQra,EAAKyL,EAAIC,CAAG,EAAIhK,EAAI,MAAM,CAAC,EAAE,MAAM,GAAG,GAEtE,CAACoB,EAAMY,EAAG3D,EAAOC,EAAKyL,EAAIC,CAAG,EAAIhK,EAAI,MAAM,CAAC,EAAE,MAAM,GAAG,EAC7CgC,GAAK,IAAI,KAAK,UAAU,4BAA4B,EAExD6M,EAAMvO,EAAcjC,EAAM,MAAM,EAAG,CAAC,CAAC,EACrCsa,EAASrY,EAAcjC,EAAM,MAAM,EAAG,EAAE,CAAC,EACzCqa,EAAOpY,EAAcjC,EAAM,MAAM,GAAI,EAAE,CAAC,EACxCgI,EAAO7E,EAAiBnD,EAAM,MAAM,EAAE,CAAC,EAAE,CAAC,GAGrC,IAAIoa,GAAI,CACb,MAAO,KAAK,aAAarX,CAAI,EAC7B,IAAK,SAAS9C,EAAK,EAAE,EACrB,KAAM,MACN,SAAU,SAASuQ,EAAK,EAAE,EAC1B,OAAQ,SAAS8J,EAAQ,EAAE,EAC3B,KAAM,SAASD,EAAM,EAAE,EACvB,OAAQ,KAAK,aAAarS,CAAI,EAC9B,UAAW0D,EACX,SAAUC,GAAK,KAAK,GAAK,EAC3B,CAAC,CACH,CAIA,cAAe,CACb,MAAM4O,EAAS,KAAK,eAAe,KAAK,IAAI,QAAQ,CAAC,EAC/CjZ,EAAS,IAAI,WAAW,EAAIiZ,EAAO,MAAM,EACzC3T,EAAK,IAAI,SAAStF,EAAO,MAAM,EACrC,OAAAsF,EAAG,UAAU,EAAG,KAAK,IAAI,UAAU,CAAC,EACpCA,EAAG,UAAU,EAAG,KAAK,IAAI,QAAQ,CAAC,EAClCA,EAAG,UAAU,EAAG,KAAK,IAAI,MAAM,CAAC,EAChCtF,EAAO,IAAIiZ,EAAQ,CAAC,EACbjZ,CACT,CAEA,WAAY,CACV,IAAItB,EAAQ,GAEZ,UAAW,IAAK,CAAC,WAAY,SAAU,MAAM,EAC3CA,GAAS4D,EAAc,KAAK,IAAI,CAAC,CAAC,EAGpC,OAAA5D,GAAS8C,EAAe,KAAK,IAAI,QAAQ,CAAC,EAEnC,KAAK,kBAAkB9C,CAAK,CACrC,CACF,CAEA,MAAMwa,WAAcpR,CAAG,CACrB,OAAO,SAAW,QAClB,OAAO,OAAS,GAChB,OAAO,KAAO,CAAC,KAAM,KAAM,IAAI,EAC/B,OAAO,YAAc,CACnB,CAAC,YAAa,IAAI,EAClB,CAAC,SAAU,IAAI,EACf,CAAC,cAAe,KAAK,CACvB,EACA,OAAO,KAAO,CAAC,UAAU,EAEzB,YAAYP,EAAM,CAChB,MAAMA,CAAI,CACZ,CAGA,aAAarH,EAAK,CACX,KAAK,oBAAoB,EAAE,IAAIA,CAAG,GAAG,KAAK,UAAU,0BAA0B,EACnF,KAAK,cAAc,KAAM,YAAaA,CAAG,CAC3C,CAEA,UAAUA,EAAK,CACR,KAAK,iBAAiB,EAAE,IAAIA,CAAG,GAAG,KAAK,UAAU,uBAAuB,EAC7E,KAAK,cAAc,KAAM,SAAUA,CAAG,CACxC,CAEA,eAAeA,EAAK,CAClB,KAAK,cAAc,MAAO,cAAeA,CAAG,CAC9C,CAEA,qBAAsB,CACpB,OAAO,IAAI,IAAI,CACb,CAAC,EAAG,UAAU,EACd,CAAC,EAAG,KAAK,EACT,CAAC,EAAG,KAAK,EACT,CAAC,EAAG,OAAO,EACX,CAAC,EAAG,SAAS,EACb,CAAC,EAAG,OAAO,CACb,CAAC,CACH,CAEA,kBAAmB,CACjB,OAAO,IAAI,IAAI,CACb,CAAC,EAAG,UAAU,EACd,CAAC,EAAG,OAAO,EACX,CAAC,EAAG,SAAS,CACf,CAAC,CACH,CAEA,gBAAiB,CACf,MAAO,+BACT,CAEA,cAAe,CACb,MAAO,CACL,MAAO,oBACP,IAAK,KACL,MAAO,KACP,KAAM,QACN,UAAW,EACX,OAAQ,EACR,YAAa,0CACf,CACF,CAGA,YAAY,CAAE,SAAA5B,CAAS,EAAG,CAExB,KAAM,CAAE,MAAAG,EAAO,OAAAM,EAAQ,MAAAL,EAAO,IAAAC,EAAK,UAAAC,EAAW,SAAAC,CAAS,EAAI,KAAK,iBAAiBP,CAAQ,EACzF,OAAIS,GAAU,KAAK,UAAU,GAAG,KAAK,UAAU,8BAA8B,EAEtE,IAAIma,GAAM,CACf,MAAAza,EACA,IAAAE,EACA,KAAM,QACN,UAAW+B,EAAahC,EAAM,MAAM,EAAG,CAAC,CAAC,EACzC,OAAQgC,EAAahC,EAAM,MAAM,EAAG,CAAC,CAAC,EACtC,YAAa+B,GAAW/B,EAAM,MAAM,CAAC,CAAC,EACtC,UAAAE,EACA,SAAAC,CACF,CAAC,CACH,CAIA,WAAY,CACV,OAAO,KAAK,kBACVsC,EAAa,KAAK,IAAI,WAAW,CAAC,EAChCA,EAAa,KAAK,IAAI,QAAQ,CAAC,EAC/BgB,EAAQ,KAAK,IAAI,aAAa,CAAC,CACnC,CACF,CAEA,cAAe,CACb,MAAMkB,EAAQ,IAAI,WAAW,EAAIC,EAAW,KAAK,IAAI,aAAa,CAAC,EAAE,MAAM,EAC3E,OAAAD,EAAM,CAAC,EAAI,KAAK,IAAI,WAAW,EAC/BA,EAAM,CAAC,EAAI,KAAK,IAAI,QAAQ,EAC5BA,EAAM,IAAIC,EAAW,KAAK,IAAI,aAAa,CAAC,EAAG,CAAC,EACzCD,CACT,CACF,CAEA,MAAM8V,WAAarR,CAAG,CACpB,OAAO,SAAW,OAClB,OAAO,OAAS,GAChB,OAAO,KAAO,CAAC,IAAI,EACnB,OAAO,YAAc,CACnB,CAAC,WAAY,KAAK,EAClB,CAAC,cAAe,MAAM,EACtB,CAAC,SAAU,WAAW,CACxB,EAEA,YAAYP,EAAM,CAChB,MAAMA,CAAI,CACZ,CAGA,YAAYrH,EAAK,CACf,KAAK,WAAW,OAAQ,WAAYA,CAAG,EAEvC,KAAK,IAAI,WAAYA,CAAG,CAC1B,CAEA,cAAcA,EAAK,CAKjB,KAAK,IAAI,cAAeA,EAAI,YAAY,CAAC,CAC3C,CAEA,UAAUA,EAAK,CAGb,KAAK,IAAI,SAAUA,CAAG,CACxB,CAEA,gBAAiB,CACf,MAAO,iBACT,CAEA,cAAe,CACb,MAAO,CACL,MAAO,8BACP,IAAK,KACL,MAAO,KACP,KAAM,OACN,SAAU,EACV,cAAe,oBACf,OAAQ,cACV,CACF,CAIA,SAAS,CAAE,SAAA+K,CAAS,EAAG,CAIrB,KAAM,CAACxM,EAAOE,EAAKO,EAAGkK,EAAM8F,EAAKzN,CAAI,EAAIwJ,EAAS,MAAM,KAAK,EAC7D,OAAO,IAAIkO,GAAK,CACd,MAAA1a,EACA,IAAK,SAASE,EAAK,EAAE,EACrB,MAAOO,EACP,KAAAkK,EACA,SAAU,SAAS8F,EAAK,EAAE,EAC1B,cAAezN,EACf,OAAQwJ,EAAS,MAAM,KAAK,EAAE,MAAM,CAAC,EAAE,KAAK,GAAG,EAAE,KAAK,CACxD,CAAC,CACH,CAEA,YAAY,CAAE,SAAA3M,CAAS,EAAG,CACxB,KAAM,CAAE,MAAAG,EAAO,OAAAM,EAAQ,MAAAL,EAAO,IAAAC,EAAK,UAAAC,EAAW,SAAAC,CAAS,EAAI,KAAK,iBAAiBP,CAAQ,EACrFS,GAAU,KAAK,UAAU,GAAG,KAAK,UAAU,6BAA6B,EAC5E,KAAM,CAAE,SAAAO,EAAU,WAAA6P,EAAY,OAAAC,CAAO,EAAIjQ,GAAmBT,EAAO,MAAM,EAEzE,OAAO,IAAIya,GAAK,CACd,MAAA1a,EACA,IAAAE,EACA,KAAM,OACN,SAAUW,EACV,cAAe6P,EACf,OAAQC,EACR,UAAAxQ,EACA,SAAAC,CACF,CAAC,CACH,CAIA,WAAY,CACV,MAAMwQ,EAAS,IAAI,OAAO,eAAgB,GAAG,EAE7C,OAAO,KAAK,kBACV/M,EAAc,KAAK,IAAI,UAAU,CAAC,EAChCd,EAAe,KAAK,IAAI,aAAa,CAAC,EACtCrB,EAAYkP,EAAQ,KAAK,IAAI,QAAQ,CAAC,CAC1C,CACF,CAEA,cAAe,CACb,MAAMC,EAAc,KAAK,eAAe,KAAK,IAAI,aAAa,CAAC,EACzDC,EAAcxJ,GAAgB,KAAK,IAAI,QAAQ,CAAC,EAChD/F,EAAS,IAAI,WAAW,EAAIsP,EAAY,OAASC,EAAY,MAAM,EACzE,WAAI,SAASvP,EAAO,MAAM,EAAE,UAAU,EAAG,KAAK,IAAI,UAAU,CAAC,EAC7DA,EAAO,IAAIsP,EAAa,CAAC,EACzBtP,EAAO,IAAIuP,EAAa,EAAID,EAAY,MAAM,EACvCtP,CACT,CACF,CAEA,MAAMoZ,WAAatR,CAAG,CACpB,OAAO,SAAW,OAClB,OAAO,OAAS,GAChB,OAAO,KAAO,CAAC,KAAM,IAAI,EACzB,OAAO,YAAc,CACnB,CAAC,oBAAqB,IAAI,EAC1B,CAAC,WAAY,IAAI,EACjB,CAAC,gBAAiB,IAAI,EACtB,CAAC,+BAAgC,KAAK,CACxC,EACA,OAAO,KAAO,CAAC,UAAU,EAEzB,YAAYP,EAAM,CAChB,MAAMA,CAAI,CACZ,CAGA,oBAAoBrH,EAAK,CAClB,KAAK,2BAA2B,EAAE,IAAIA,CAAG,GAAG,KAAK,UAAU,iCAAiC,EAEjG,KAAK,IAAI,oBAAqBA,CAAG,CACnC,CAEA,4BAA6B,CAC3B,OAAO,IAAI,IAAI,CACb,CAAC,EAAG,gBAAgB,EACpB,CAAC,EAAG,2BAA2B,EAC/B,CAAC,EAAG,kBAAkB,EACtB,CAAC,EAAG,2BAA2B,CACjC,CAAC,CACH,CAEA,YAAYA,EAAK,CACV,KAAK,mBAAmB,EAAE,IAAIA,CAAG,GAAG,KAAK,UAAU,wBAAwB,EAEhF,KAAK,IAAI,WAAYA,CAAG,CAC1B,CAEA,oBAAqB,CACnB,OAAO,IAAI,IAAI,CACb,CAAC,EAAG,kBAAkB,EACtB,CAAC,EAAG,sBAAsB,CAC5B,CAAC,CACH,CAEA,gBAAgBA,EAAK,CACd,KAAK,uBAAuB,EAAE,IAAIA,CAAG,GAAG,KAAK,UAAU,qBAAqB,EAEjF,KAAK,IAAI,gBAAiBA,CAAG,CAC/B,CAEA,wBAAyB,CACvB,OAAO,IAAI,IAAI,CACb,CAAC,EAAG,aAAa,EACjB,CAAC,EAAG,cAAc,EAClB,CAAC,EAAG,cAAc,CACpB,CAAC,CACH,CAEA,8BAA8BA,EAAK,CACjC,KAAK,IAAI,+BAAgCA,CAAG,CAC9C,CAEA,gBAAiB,CACf,MAAO,8BACT,CAEA,cAAe,CACb,MAAO,CACL,MAAO,6BACP,IAAK,KACL,MAAO,KACP,KAAM,OACN,oBAAqB,EACrB,SAAU,EACV,gBAAiB,EACjB,+BAAgC,WAClC,CACF,CAIA,SAAS,CAAE,SAAA+K,CAAS,EAAG,CAErB,MAAMiC,EACJ,yIACIC,EAAQlC,EAAS,KAAK,EAAE,MAAMiC,CAAK,EACpCC,GAAO,KAAK,UAAU,yBAAyBlC,CAAQ,EAAE,EAC9D,KAAM,CAAE,MAAAxM,EAAO,IAAAE,EAAK,IAAAsG,EAAK,KAAAmE,EAAM,MAAAkO,EAAO,SAAAC,EAAU,UAAA8B,EAAW,IAAAC,CAAI,EAAInM,EAAM,OAEzE,OAAO,IAAIiM,GAAK,CACd,MAAO,KAAK,aAAa3a,CAAK,EAC9B,IAAK,SAASE,EAAK,EAAE,EACrB,MAAOsG,EAAI,YAAY,EACvB,KAAMmE,EAAK,YAAY,EACvB,oBAAqB,SAASkO,EAAO,EAAE,EACvC,SAAU,SAASC,EAAU,EAAE,EAC/B,gBAAiB,SAAS8B,EAAW,EAAE,EACvC,+BAAgCC,EAAI,KAAK,CAC3C,CAAC,CACH,CAEA,YAAY,CAAE,SAAAhb,CAAS,EAAG,CACxB,KAAM,CAAE,MAAAG,EAAO,OAAAM,EAAQ,MAAAL,EAAO,IAAAC,EAAK,UAAAC,EAAW,SAAAC,CAAS,EAAI,KAAK,iBAAiBP,CAAQ,EACrFS,GAAU,KAAK,UAAU,GAAG,KAAK,UAAU,6BAA6B,EAE5E,MAAMsE,EAAQrE,EAAkBN,CAAK,EAErC,OAAO,IAAI0a,GAAK,CACd,MAAA3a,EACA,IAAAE,EACA,KAAM,OACN,oBAAqB0E,EAAM,CAAC,EAC5B,SAAUA,EAAM,CAAC,EACjB,gBAAiBA,EAAM,CAAC,EACxB,+BAAgCI,EAAWJ,EAAM,SAAS,CAAC,CAAC,EAC5D,UAAAzE,EACA,SAAAC,CACF,CAAC,CACH,CAGA,WAAY,CACV,OAAO,KAAK,kBACVsC,EAAa,KAAK,IAAI,mBAAmB,CAAC,EACxCA,EAAa,KAAK,IAAI,UAAU,CAAC,EACjCA,EAAa,KAAK,IAAI,eAAe,CAAC,EACtCgB,EAAQ,KAAK,IAAI,8BAA8B,EAAE,QAAQ,UAAW,EAAE,CAAC,CAC3E,CACF,CAEA,cAAe,CACb,MAAMqV,EAAWlU,EAAW,KAAK,IAAI,8BAA8B,EAAE,QAAQ,UAAW,EAAE,CAAC,EACrFD,EAAQ,IAAI,WAAW,EAAImU,EAAS,MAAM,EAChD,OAAAnU,EAAM,CAAC,EAAI,KAAK,IAAI,mBAAmB,EACvCA,EAAM,CAAC,EAAI,KAAK,IAAI,UAAU,EAC9BA,EAAM,CAAC,EAAI,KAAK,IAAI,eAAe,EACnCA,EAAM,IAAImU,EAAU,CAAC,EACdnU,CACT,CACF,CAEA,MAAMkW,UAAazR,CAAG,CACpB,OAAO,SAAW,OAClB,OAAO,OAAS,IAChB,OAAO,KAAO,CAAC,KAAM,IAAI,EACzB,OAAO,YAAc,CAAC,iBAAkB,cAAe,QAAS,MAAO,cAAe,QAAS,OAAO,EAEtG,YAAYP,EAAM,CAChB,MAAMA,CAAI,CAEZ,CAIA,gBAAiB,CACf,MAAO,uBACT,CAEA,cAAe,CACb,MAAO,CACL,MAAO,gBACP,IAAK,EACL,MAAO,MACP,KAAM,OACN,iBAAkB,eAClB,cAAe,SACf,MAAO,IACP,IAAK,YACL,cAAe,MACf,MAAO,EACP,MAAO,EACT,CACF,CAEA,SAAS,EAAG,CACN,IAAM,OAAO,KAAK,UAAU,mCAAmC,EACnE,KAAK,IAAI,QAAS,CAAC,CACrB,CAEA,OAAO,EAAG,CACJ,IAAM,GAAG,KAAK,UAAU,+BAA+B,EAC3D,KAAK,IAAI,MAAO,CAAC,CACnB,CAEA,iBAAiBrH,EAAK,CACfA,GAAK,KAAK,UAAU,oCAAoC,EAC7D,KAAK,IAAI,iBAAkBA,CAAG,CAChC,CAEA,cAAcA,EAAK,CAEbA,IAAQ,QAAW,KAAK,UAAU,iCAAiC,EACvE,KAAK,IAAI,cAAeA,CAAG,CAC7B,CAEA,SAASA,EAAK,CAEZ,KAAK,WAAW,OAAQ,QAASA,CAAG,EACpC,KAAK,IAAI,QAASA,CAAG,CACvB,CAEA,OAAOA,EAAK,CACV,KAAK,IAAI,MAAOA,GAAO,EAAE,CAC3B,CAEA,cAAcA,EAAK,CACjB,KAAK,WAAW,OAAQ,cAAeA,CAAG,EAC1C,KAAK,IAAI,cAAeA,CAAG,CAC7B,CAEA,SAASA,EAAK,CACZ,KAAK,WAAW,OAAQ,QAASA,CAAG,EACpC,KAAK,IAAI,QAASA,CAAG,CACvB,CAEA,SAASA,EAAK,CACZ,KAAK,IAAI,QAASA,GAAO,EAAE,CAC7B,CAIA,SAAS,CAAE,SAAA+K,CAAS,EAAG,CAErB,MAAMzM,EAAQyM,EAAS,QAAQ,EAAE,MAAM,GAAI,EACrC,CAACxM,EAAOE,EAAKsG,EAAKmE,EAAMoQ,EAAKC,EAAMC,EAAO,CAAEC,EAAKC,EAAQC,CAAK,EAAIrb,EAExE,OAAO,IAAI+a,EAAK,CACd,MAAA9a,EACA,IAAK,SAASE,EAAK,EAAE,EACrB,MAAOsG,EACP,KAAMmE,EAAK,YAAY,EACvB,iBAAkBoQ,EAClB,cAAe,SAASC,EAAM,EAAE,EAChC,MAAO,SAASC,EAAO,EAAE,EACzB,IAAKC,GAAO,GACZ,cAAe,SAASC,EAAQ,EAAE,EAClC,MAAO,SAASC,EAAO,EAAE,EACzB,MAAO,EACT,CAAC,CACH,CAEA,YAAY,CAAE,SAAAvb,CAAS,EAAG,CACxB,KAAM,CAACG,EAAOmU,EAASlU,EAAOC,EAAKyL,EAAIC,CAAG,EAAI/L,EAAS,MAAM,CAAC,EAAE,MAAM,GAAG,EAEnEwb,EAAcjY,EAAiBnD,CAAK,EACpCqb,EAAeD,EAAY,CAAC,EAE5BzW,EAAQ,WAAW,KAAKpE,EAAYP,CAAK,EAAIQ,GAAMA,EAAE,WAAW,CAAC,CAAC,EAClEoG,EAAK,IAAI,SAASjC,EAAM,OAAQA,EAAM,WAAYA,EAAM,UAAU,EACxE,IAAI2W,EAAOD,EAEX,MAAME,EAAa3U,EAAG,UAAU0U,CAAI,EACpCA,GAAQ,EACR,MAAMN,EAAQpU,EAAG,UAAU0U,CAAI,EAC/BA,GAAQ,EACR,MAAME,EAAU5U,EAAG,UAAU0U,CAAI,EACjCA,GAAQ,EACR,MAAML,EAAMO,EAAU,EAAIzW,EAAWJ,EAAM,SAAS2W,EAAMA,EAAOE,CAAO,CAAC,EAAI,GAC7EF,GAAQE,EACR,MAAMC,EAAa7U,EAAG,UAAU0U,CAAI,EACpCA,GAAQ,EACR,MAAMH,EAAQvU,EAAG,UAAU0U,CAAI,EAC/BA,GAAQ,EACR,MAAMI,EAAQJ,EAAO3W,EAAM,OAAS,IAAI,YAAY,EAAE,OAAOA,EAAM,SAAS2W,CAAI,CAAC,EAAI,GAErF,OAAO,IAAIT,EAAK,CACd,MAAO,KAAK,aAAa9a,CAAK,EAC9B,IAAK,SAASE,EAAK,EAAE,EACrB,MAAO,MACP,KAAM,OACN,iBAAkBmb,EAAY,CAAC,EAC/B,cAAeG,EACf,MAAAP,EACA,IAAAC,EACA,cAAeQ,EACf,MAAAN,EACA,MAAAO,EACA,UAAWhQ,EACX,SAAUC,GAAK,KAAK,GAAK,EAC3B,CAAC,CACH,CAEA,SAAS,CAAE,MAAA5L,EAAO,IAAAwG,EAAK,IAAAtG,EAAK,MAAAD,CAAM,EAAG,CACnC,KAAM,CAAE,KAAM2b,EAAe,IAAAvV,CAAI,EAAI,KAAK,iBAAiBpG,EAAO,CAAC,EAC7D4G,EAAK,IAAI,SAAS5G,EAAM,OAAQA,EAAM,UAAU,EACtD,IAAIa,EAAMuF,EACV,MAAMmV,EAAa3U,EAAG,UAAU/F,CAAG,EACnCA,GAAO,EACP,MAAMma,EAAQpU,EAAG,UAAU/F,CAAG,EAC9BA,GAAO,EACP,MAAM2a,EAAU5U,EAAG,UAAU/F,CAAG,EAChCA,GAAO,EACP,MAAMoa,EAAMO,EAAU,EAAIzW,EAAW/E,EAAM,SAASa,EAAKA,EAAM2a,CAAO,CAAC,EAAI,GAC3E3a,GAAO2a,EACP,MAAMC,EAAa7U,EAAG,UAAU/F,CAAG,EACnCA,GAAO,EACP,MAAMsa,EAAQvU,EAAG,UAAU/F,CAAG,EAC9BA,GAAO,EACP,MAAM6a,EAAQ7a,EAAMb,EAAM,OAAS,IAAI,YAAY,EAAE,OAAOA,EAAM,SAASa,CAAG,CAAC,EAAI,GACnF,OAAO,IAAIga,EAAK,CACd,MAAA9a,EACA,IAAK,EACL,MAAO,MACP,KAAM,OACN,iBAAkB4b,EAClB,cAAeJ,EACf,MAAAP,EACA,IAAAC,EACA,cAAeQ,EACf,MAAAN,EACA,MAAAO,CACF,CAAC,CACH,CAGA,OAAOxS,EAAW,CAChB,MAAM+R,EAAM,KAAK,IAAI,KAAK,GAAK,GACzBO,EAAUP,EAAI,OAAS,EAAIA,EAAI,OAAS,GACxCS,EAAQ,KAAK,IAAI,OAAO,GAAK,GAC7BE,EAAWF,EAAM,OAAS,EAAIA,EAAM,OAAS,EACnD,MACE,CACE,KAAK,QAAQ,QAASxS,CAAS,EAC/B,KAAK,IAAI,KAAK,EACd,KAAK,IAAI,OAAO,EAChB,KAAK,IAAI,MAAM,EACf,KAAK,IAAI,gBAAgB,EACzB,KAAK,IAAI,aAAa,EACtB,KAAK,IAAI,OAAO,EAChBsS,EACAP,EACA,KAAK,IAAI,aAAa,EACtB,KAAK,IAAI,OAAO,EAChBW,CACF,EAAE,KAAK,GAAI,EAAI;AAAA,CAEnB,CAEA,cAAe,CACb,MAAMC,EAAUvW,EAAe,KAAK,IAAI,gBAAgB,GAAK,EAAE,EACzD2V,EAAM,KAAK,IAAI,KAAK,GAAK,GACzBa,EAAWb,EAAI,OAAS,EAAIrW,EAAWqW,CAAG,EAAI,IAAI,WAClDS,EAAQ,KAAK,IAAI,OAAO,GAAK,GAC7BK,EAAaL,EAAM,OAAS,EAAI,IAAI,YAAY,EAAE,OAAOA,CAAK,EAAI,IAAI,WAEtE/W,EAAQ,IAAI,WAAWkX,EAAQ,OAAS,EAAI,EAAI,EAAIC,EAAS,OAAS,EAAI,EAAIC,EAAW,MAAM,EAC/FnV,EAAK,IAAI,SAASjC,EAAM,OAAQA,EAAM,UAAU,EACtD,IAAI9D,EAAM,EAEV,OAAA8D,EAAM,IAAIkX,EAAShb,CAAG,EACtBA,GAAOgb,EAAQ,OACfjV,EAAG,UAAU/F,EAAK,KAAK,IAAI,aAAa,GAAK,CAAC,EAC9CA,GAAO,EACP+F,EAAG,UAAU/F,EAAK,KAAK,IAAI,OAAO,GAAK,CAAC,EACxCA,GAAO,EACP+F,EAAG,UAAU/F,EAAKib,EAAS,MAAM,EACjCjb,GAAO,EACHib,EAAS,OAAS,IACpBnX,EAAM,IAAImX,EAAUjb,CAAG,EACvBA,GAAOib,EAAS,QAElBlV,EAAG,UAAU/F,EAAK,KAAK,IAAI,aAAa,GAAK,CAAC,EAC9CA,GAAO,EACP+F,EAAG,UAAU/F,EAAK,KAAK,IAAI,OAAO,GAAK,CAAC,EACxCA,GAAO,EACHkb,EAAW,OAAS,GAAGpX,EAAM,IAAIoX,EAAYlb,CAAG,EAE7C8D,CACT,CAEA,WAAY,CACV,MAAMmW,EAAM,KAAK,IAAI,gBAAgB,GAAK,GACpCG,EAAM,KAAK,IAAI,KAAK,GAAK,GACzBe,EAAaf,EAAI,OAAS,EAAIA,EAAI,OAAS,EAAI,EAErD,OAAO,KAAK,kBACVnY,EAAegY,CAAG,EAChBjX,EAAc,KAAK,IAAI,aAAa,GAAK,CAAC,EAC1CD,EAAc,KAAK,IAAI,OAAO,CAAC,EAC/BA,EAAcoY,CAAU,GACvBA,EAAa,EAAIvY,EAAQwX,CAAG,EAAI,IACjCrX,EAAc,KAAK,IAAI,aAAa,GAAK,CAAC,EAC1CA,EAAc,KAAK,IAAI,OAAO,GAAK,CAAC,GACnC,KAAK,IAAI,OAAO,EAAE,OAAS,EACxBnC,EAAY,IAAI,OAAO,eAAgB,GAAG,EAAG,KAAK,IAAI,OAAO,CAAC,EAC9D,GACR,CACF,CACF,CAEA,MAAMwa,WAAY7S,CAAG,CACnB,OAAO,SAAW,MAClB,OAAO,OAAS,IAChB,OAAO,KAAO,CAAC,IAAI,EACnB,OAAO,YAAc,CACnB,CAAC,WAAY,KAAK,EAClB,CAAC,SAAU,KAAK,EAChB,CAAC,SAAU,MAAM,CACnB,EAEA,YAAYP,EAAM,CAChB,MAAMA,CAAI,CACZ,CAGA,YAAYrH,EAAK,CACf,KAAK,WAAW,MAAO,WAAYA,CAAG,EAEtC,KAAK,IAAI,WAAYA,CAAG,CAC1B,CAEA,UAAUA,EAAK,CACb,KAAK,WAAW,MAAO,SAAUA,CAAG,EAEpC,KAAK,IAAI,SAAUA,CAAG,CACxB,CAEA,UAAUA,EAAK,CACRA,GAAK,KAAK,UAAU,yBAAyB,EAElD,KAAK,IAAI,SAAUA,CAAG,CACxB,CAGA,YAAY,CAAE,SAAA5B,CAAS,EAAG,CAExB,KAAM,CAACmD,EAAMY,EAAG3D,EAAOC,EAAKyL,EAAIC,CAAG,EAAI/L,EAAS,MAAM,CAAC,EAAE,MAAM,GAAG,EAClE,OAAI+D,GAAK,KAAK,KAAK,UAAU,4BAA4B,EAElD,IAAIsY,GAAI,CACb,KAAM,MACN,MAAO,KAAK,aAAalZ,CAAI,EAC7B,SAAUd,EAAcjC,EAAM,MAAM,EAAG,CAAC,CAAC,EACzC,OAAQiC,EAAcjC,EAAM,MAAM,EAAG,EAAE,CAAC,EACxC,OAAQO,EAAYP,EAAM,MAAM,EAAE,CAAC,EACnC,IAAK,SAASC,EAAK,EAAE,EACrB,UAAWyL,EACX,SAAUC,GAAK,KAAK,GAAK,EAC3B,CAAC,CACH,CAGA,gBAAiB,CACf,MAAO,KACT,CAEA,cAAe,CACb,MAAO,CACL,MAAO,mBACP,IAAK,KACL,MAAO,KACP,KAAM,MACN,SAAU,GACV,OAAQ,GACR,OAAQ,yBACV,CACF,CAIA,cAAe,CACb,MAAM4O,EAAS,IAAI,YAAY,EAAE,OAAO,KAAK,IAAI,QAAQ,CAAC,EACpDjZ,EAAS,IAAI,WAAW,EAAIiZ,EAAO,MAAM,EACzC3T,EAAK,IAAI,SAAStF,EAAO,MAAM,EACrC,OAAAsF,EAAG,UAAU,EAAG,KAAK,IAAI,UAAU,CAAC,EACpCA,EAAG,UAAU,EAAG,KAAK,IAAI,QAAQ,CAAC,EAClCtF,EAAO,IAAIiZ,EAAQ,CAAC,EACbjZ,CACT,CAEA,WAAY,CACV,MAAMqP,EAAS,IAAI,OAAO,eAAgB,GAAG,EAC7C,IAAI3Q,EAAQ,GAEZ,UAAW4H,IAAK,CAAC,WAAY,QAAQ,EACnC5H,GAAS4D,EAAc,KAAK,IAAIgE,CAAC,CAAC,EAGpC,OAAA5H,GAASyB,EAAYkP,EAAQ,KAAK,IAAI,QAAQ,CAAC,EACxC,KAAK,kBAAkB3Q,CAAK,CACrC,CACF,CAEA,MAAMkc,GAAmB,CACvB,KAAM,EACN,QAAS,EACT,OAAQ,GACR,QAAS,GACT,QAAS,GACT,SAAU,GACV,IAAK,GACL,IAAK,GACL,OAAQ,GACR,KAAM,GACN,KAAM,GACN,IAAK,GACL,WAAY,GACZ,QAAS,GACT,OAAQ,GACR,IAAK,GACL,OAAQ,GACR,OAAQ,GACR,KAAM,GACN,OAAQ,GACR,IAAK,GACL,OAAQ,GACR,KAAM,GACN,KAAM,GACN,OAAQ,GACR,UAAW,IACX,SAAU,IACV,SAAU,IACV,MAAO,IACP,KAAM,IACN,OAAQ,IACR,KAAM,IACN,KAAM,IACN,UAAW,IACX,KAAM,IACN,IAAK,IACL,WAAY,IACZ,YAAa,IACb,YAAa,IACb,KAAM,IACN,QAAS,IACT,KAAM,IACN,UAAW,IACX,SAAU,IACV,WAAY,IACZ,MAAO,IACP,SAAU,IACV,IAAK,IACL,SAAU,IACV,IAAK,IACL,KAAM,IACN,QAAS,IACT,OAAQ,IACR,QAAS,IACT,OAAQ,IACR,KAAM,IACN,MAAO,IACP,IAAK,IACL,MAAO,IACP,UAAW,IACX,MAAO,IACP,KAAM,IACN,aAAc,IACd,QAAS,IACT,IAAK,IACL,KAAM,IACN,OAAQ,IACR,KAAM,IACN,KAAM,IACN,MAAO,IACP,IAAK,IACL,IAAK,IACL,OAAQ,IACR,QAAS,IACT,KAAM,IACN,MAAO,IACP,MAAO,IACP,MAAO,IACP,MAAO,IACP,QAAS,IACT,QAAS,IACT,QAAS,IACT,KAAM,IACN,SAAU,IACV,MAAO,IACP,KAAM,GACR,EAEA,MAAMC,UAAY/S,CAAG,CACnB,OAAO,SAAW,MAClB,OAAO,OAAS,GAChB,OAAO,KAAO,CAAC,IAAK,IAAI,EACxB,OAAO,YAAc,CAAC,UAAW,WAAY,SAAS,EACtD,OAAO,KAAO,CAAC,UAAU,EAEzB,YAAYP,EAAM,CAChB,MAAMA,CAAI,CACZ,CAGA,WAAWrH,EAAK,CACTA,GAAK,KAAK,UAAU,0BAA0B,EAC9C,KAAK,OAAOA,CAAG,GAAG,KAAK,UAAU,0BAA0B,EAChE,KAAK,IAAI,UAAWA,CAAG,CACzB,CAEA,YAAYA,EAAK,CACVA,GAAK,KAAK,UAAU,2BAA2B,EACpD,MAAM4a,EAAQ,OAAO5a,GAAQ,SAAWA,EAAI,YAAY,EAAIA,EACvD,CAAC,MAAO,MAAO,EAAG,EAAE,EAAE,SAAS4a,CAAK,GAAG,KAAK,UAAU,iCAAiC,EAC5F,KAAK,IAAI,WAAYA,CAAK,CAC5B,CAEA,UAAU5a,EAAK,CACb,KAAK,IAAI,UAAWA,GAAO,EAAE,CAC/B,CAEA,gBAAiB,CACf,MAAO,oBACT,CAEA,cAAe,CACb,MAAO,CACL,MAAO,oBACP,IAAK,KACL,MAAO,KACP,KAAM,MACN,QAAS,YACT,SAAU,MACV,UAAW,UACb,CACF,CAIA,SAAS,CAAE,SAAA+K,CAAS,EAAG,CAErB,MAAMzM,EAAQyM,EAAS,MAAM,KAAK,EAC5B,CAACxM,EAAOE,EAAKO,EAAGkK,EAAM2R,EAAS3N,CAAQ,EAAI5O,EACjD,OAAO,IAAIqc,EAAI,CACb,MAAApc,EACA,IAAK,SAASE,EAAK,EAAE,EACrB,MAAOO,EACP,KAAAkK,EACA,QAAA2R,EACA,SAAA3N,EACA,UAAW5O,EAAM,MAAM,CAAC,EAAE,KAAK,GAAG,EAAE,KAAK,CAC3C,CAAC,CACH,CAEA,YAAY,CAAE,SAAAF,CAAS,EAAG,CACxB,KAAM,CAACG,EAAOmU,EAASlU,EAAOC,EAAKyL,EAAIC,CAAG,EAAI/L,EAAS,MAAM,CAAC,EAAE,MAAM,GAAG,EAEnEe,EAAS,WAAW,KAAKJ,EAAYP,CAAK,EAAIQ,GAAMA,EAAE,WAAW,CAAC,CAAC,EACnE6b,EAAU,CAAC1b,EAAO,CAAC,EAAGA,EAAO,CAAC,EAAGA,EAAO,CAAC,EAAGA,EAAO,CAAC,CAAC,EAAE,KAAK,GAAG,EAC/D2b,EAAW3b,EAAO,CAAC,EAEnB+N,EADW,CAAE,EAAG,MAAO,GAAI,KAAM,EACb4N,CAAQ,GAAKA,EACjCzH,EAAS,IAAI,YAAY,EAAE,OAAOlU,EAAO,SAAS,CAAC,CAAC,EAE1D,OAAO,IAAIwb,EAAI,CACb,MAAO,KAAK,aAAapc,CAAK,EAC9B,IAAK,SAASE,EAAK,EAAE,EACrB,KAAM,MACN,QAAAoc,EACA,SAAA3N,EACA,UAAWmG,EACX,UAAWnJ,EACX,SAAUC,GAAK,KAAK,GAAK,EAC3B,CAAC,CACH,CAEA,SAAS,CAAE,MAAA5L,EAAO,IAAAwG,EAAK,IAAAtG,EAAK,MAAAD,CAAM,EAAG,CACnC,MAAMqc,EAAU,CAAC,GAAGrc,EAAM,SAAS,EAAG,CAAC,CAAC,EAAE,KAAK,GAAG,EAC5Csc,EAAWtc,EAAM,CAAC,EAElB0O,EADW,CAAE,EAAG,MAAO,GAAI,KAAM,EACb4N,CAAQ,GAAK,OAAOA,CAAQ,EAChDC,EAAa,OAAO,YAAY,OAAO,QAAQL,EAAgB,EAAE,IAAI,CAAC,CAAC1V,EAAGiD,CAAC,IAAM,CAACA,EAAGjD,CAAC,CAAC,CAAC,EACxFqO,EAAS7U,EAAM,SAAS,CAAC,EACzBwc,EAAQ,CAAC,EACf,QAASjb,EAAI,EAAGA,EAAIsT,EAAO,OAAQtT,IACjC,QAAS4T,EAAM,EAAGA,EAAM,EAAGA,IACzB,GAAIN,EAAOtT,CAAC,EAAK,KAAQ4T,EAAM,CAC7B,MAAMkF,EAAO9Y,EAAI,EAAI4T,EACrBqH,EAAM,KAAKD,EAAWlC,CAAI,GAAK,OAAOA,CAAI,CAAC,CAC7C,CAGJ,OAAO,IAAI8B,EAAI,CACb,MAAApc,EACA,IAAAE,EACA,MAAOsG,EACP,KAAM,MACN,QAAA8V,EACA,SAAA3N,EACA,UAAW8N,EAAM,KAAK,GAAG,CAC3B,CAAC,CACH,CAIA,WAAY,CACV,MAAM7L,EAAS,IAAI,OAAO,eAAgB,GAAG,EAEvC2L,EADW,CAAE,IAAK,EAAG,IAAK,GAAI,EAAG,EAAG,GAAI,EAAG,EACvB,KAAK,IAAI,UAAU,CAAC,EAE9C,OAAO,KAAK,kBACVxY,GAAY,KAAK,IAAI,SAAS,CAAC,EAC7BrB,EAAa6Z,CAAQ,EACrB7a,EAAYkP,EAAQ,KAAK,IAAI,SAAS,CAAC,CAC3C,CACF,CAEA,cAAe,CACb,MAAM8L,EAAW,CAAE,IAAK,EAAG,IAAK,GAAI,EAAG,EAAG,GAAI,EAAG,EAC3CrQ,EAAY,KAAK,IAAI,SAAS,EAAE,MAAM,GAAG,EAAE,IAAI,MAAM,EACrDkQ,EAAWG,EAAS,KAAK,IAAI,UAAU,CAAC,EAExCC,EAAW,KAAK,IAAI,SAAS,EAChC,KAAK,EACL,MAAM,KAAK,EACX,IAAKla,GACA,QAAQ,KAAKA,CAAC,EAAU,SAASA,EAAG,EAAE,EACnC0Z,GAAiB1Z,EAAE,YAAY,CAAC,CACxC,EACA,OAAQgD,GAAMA,IAAM,MAAS,EAEhC,GAAIkX,EAAS,SAAW,EAAG,OAAO,IAAI,WAAW,CAAC,GAAGtQ,EAAWkQ,CAAQ,CAAC,EAEzE,MAAMK,EAAU,KAAK,IAAI,GAAGD,CAAQ,EAC9BzH,EAAY,KAAK,MAAM0H,EAAU,CAAC,EAAI,EACtC9H,EAAS,IAAI,WAAWI,CAAS,EACvC,UAAWoF,KAAQqC,EAAU7H,EAAO,KAAK,MAAMwF,EAAO,CAAC,CAAC,GAAK,KAASA,EAAO,EAE7E,MAAM/Y,EAAS,IAAI,WAAW,EAAI2T,CAAS,EAC3C,OAAA3T,EAAO,IAAI8K,CAAS,EACpB9K,EAAO,CAAC,EAAIgb,EACZhb,EAAO,IAAIuT,EAAQ,CAAC,EACbvT,CACT,CACF,CAEA,MAAMsb,GAAU,CAAC,EACXC,GAAU,CACdrR,GACAC,GACAI,EACAyB,GACAM,EACAQ,GACAC,GACAC,GACAC,GACAO,GACAG,GACAG,EACAmB,GACAO,EACAa,GACAC,GACAI,EACAc,GACAK,GACAY,GACAE,EACA4B,EACAe,GACAI,EACAK,GACAE,GACAC,GACAI,GACAa,GACAE,GACA6B,GACAzB,GACAoB,GACAC,GACAK,GACAC,GACAG,EACAvB,GACA2C,GACAE,CACF,EAEA,UAAW3b,KAAKqc,GAAS,CACvB,MAAMtH,EAAK/U,EAAE,UAAU,EACvBoc,GAAQrH,CAAE,EAAI/U,EAAE,SAChBoc,GAAQpc,EAAE,QAAQ,EAAI+U,CACxB,CAEA,OAAS/J,MAAA,EAAGC,MAAA,KAAMI,KAAA,IAAKyB,MAAA,IAAKM,KAAA,KAAMQ,MAAA,MAAOC,MAAA,MAAOC,MAAA,MAAOC,MAAA,OAAQO,MAAA,GAAIG,MAAA,MAAOG,KAAA,IAAKmB,MAAA,MAAOO,KAAA,SAAUa,MAAA,IAAKC,MAAA,GAAII,KAAA,IAAKc,MAAA,GAAIK,MAAA,MAAOY,MAAA,GAAIE,KAAA,KAAM4B,KAAA,MAAOe,MAAA,WAAYI,KAAA,IAAKK,MAAA,WAAYE,MAAA,IAAKC,MAAA,GAAII,MAAA,MAAOa,MAAA,IAAKE,MAAA,OAAQI,MAAA,IAAKoB,MAAA,IAAKC,MAAA,IAAKI,MAAA,MAAOC,MAAA,KAAMC,MAAA,KAAMG,KAAA,KAAMvB,MAAA,IAAK2C,MAAA,IAAKE,KAAA,IAAK/S,KAAM,QAASwT,MAAA", + "names": ["octalRe", "textDecoder", "parseFields", "tinyline", "rdataCount", "parts", "owner", "rdata", "ttl", "timestamp", "location", "parseGenericLine", "typeId", "octalRdataToBytes", "octalToChar", "c", "parseSvcbLikeRdata", "recordType", "binary", "priority", "pos", "labels", "len", "to", "rrInstance", "f", "bytesToOctalString", "fromGeneric", "fields", "result", "i", "val", "escapeOctal", "re", "str", "escaped", "charToOctal", "o", "octalToHex", "octalToUInt8", "octalToUInt16", "octalToUInt32", "b0", "b1", "b2", "b3", "packString", "s", "UInt8toOctal", "unpackString", "asBuf", "dec", "res", "packDomainName", "fqdn", "labelRegEx", "packed", "label", "unpackDomainName", "binaryLen", "getNextByte", "value", "lengthByte", "char", "packHex", "r", "n", "UInt16toOctal", "UInt32toOctal", "ipv4toOctal", "ip", "int", "octalToIPv4", "asInt", "expandIPv6", "delimiter", "colons", "ipv6toOctal", "octalToIPv6", "base64toOctal", "b", "octalToBase64", "bytes", "hexToBytes", "hex", "_", "bytesToHex", "bytesToBase64", "base64ToBytes", "b64", "DNS_TYPE_IDS", "wireUnpackDomain", "offset", "wirePackDomain", "enc", "p", "buf", "getWireRdata", "line", "toWire", "RRClasses", "meta", "fromWireBytes", "RRConstructor", "wireBytes", "wireUnpackFn", "instance", "end", "view", "classNum", "cls", "k", "rdlen", "fromWireGeneric", "rdataFields", "dv", "entry", "fieldName", "certTypeNum", "reverse", "strLen", "svcParamsFromWire", "j", "SVCPARAM_KEYS", "svcParamsToWire", "paramsStr", "m", "key", "keyId", "valBytes", "entries", "e", "total", "addrs", "a", "addr", "param", "SVCPARAM_KEY_NAMES", "valLen", "keyName", "dv16", "groups", "parseBindLine", "cleanLine", "inQuote", "tokens", "token", "fromBind", "opts", "rdataDefs", "def", "fieldType", "toBind", "zone_opts", "customInspect", "RR", "fnName", "parsed", "#reserved", "obj", "v", "depth", "options", "nextInspect", "w", "l", "typeName", "example", "hostname", "origin", "classVal", "rrTTL", "prop", "arg", "commonFields", "field", "fq", "type", "certTypes", "allowed", "matches", "string", "segments", "bestStart", "bestLen", "curStart", "curLen", "head", "tail", "octalStr", "quotedTypes", "A", "AAAA", "ts", "loc", "arr", "APL", "items", "afi", "prefix", "adfLenByte", "neg", "addrLen", "addrBytes", "padded", "paddedDv", "bindline", "item", "bare", "colonIdx", "rest", "slashIdx", "dblIdx", "left", "right", "hexStr", "g", "afdPart", "itemBytes", "totalLen", "sum", "CAA", "flags", "taglen", "unescaped", "tag", "fingerprint", "CERT", "typeNum", "certType", "certtype", "keytag", "algo", "certificate", "certBytes", "CNAME", "DHCID", "DNAME", "DNSKEY", "regex", "match", "protocol", "algorithm", "publickey", "keyBytes", "DS", "binRdata", "digestBytes", "HINFO", "cpu", "os", "HIP", "hitLen", "pkAlgorithm", "pkLen", "hit", "publicKey", "rvsNames", "name", "newPos", "keyParts", "rvsParts", "rs", "rsPart", "hitHex", "hitBytes", "pkBytes", "rsDomains", "rsTotalLen", "rdomain", "HTTPS", "pri", "targetName", "params", "dataRe", "targetBytes", "paramsBytes", "IPSECKEY", "gwErr", "prec", "gwt", "gateway", "precedence", "gwType", "octalKey", "keyStart", "rdataRe", "pubkeyBytes", "gwBytes", "part", "KEY", "KX", "exchanger", "REF", "CONV", "LOC", "dms", "alt", "locRe", "retval", "rawmsec", "latlon", "msec", "deg", "min", "sec", "hem", "mantissa", "exponent", "MX", "_ip", "x", "preference", "domain", "NAPTR", "rec", "idx", "flagsLength", "serviceLen", "regexpLen", "replaceLen", "order", "service", "regexp", "replacement", "replacementBytes", "NS", "dname", "NSEC", "_typeId", "binaryRdata", "nextDomain", "_escapedLen", "next", "removeParens$1", "typeBitMaps", "nsecBitmapToTypes", "nameBytes", "bitmapBytes", "typesToNsecBitmap", "bitmap", "DNS_TYPE_NAMES", "types", "windowNum", "bitmapLen", "byte", "bit", "typeNamesStr", "typeIds", "t", "id", "windows", "blocks", "wNum", "bits", "maxBit", "NSEC3", "ha", "iterations", "salt", "rdataStr", "hashAlgorithm", "nextHashedOwnerName", "parseNSEC3Buffer", "tailBytes", "expectedLen", "maxSl", "sl", "candNext", "saltCandidate", "saltMatch", "NSEC3PARAM", "saltLen", "saltOctal", "saltBytes", "NXT", "removeParens", "typeBitMap", "nxtBitmapToTypes", "typesToNxtBitmap", "OPENPGPKEY", "keyStr", "PTR", "RP", "mbox", "consumed", "txt", "RRSIG", "typeNN", "typeCoveredStr", "typeCovered", "originalTtl", "signatureExpiration", "signatureInception", "keyTag", "labelArr", "signersName", "signature", "signerBytes", "sigBytes", "SIG", "labelsArr", "SMIMEA", "usage", "selector", "cadBytes", "SOA", "mname", "rname", "ser", "ref", "ret", "exp", "TXT", "data", "asQuotedStrings", "buffers", "packStringWire", "out", "off", "chunkByBytes", "maxBytes", "chunks", "start", "encoded", "chunk", "SPF", "SRV", "port", "weight", "target", "SSHFP", "SVCB", "TLSA", "matchtype", "cad", "TSIG", "alg", "time", "fudge", "mac", "origId", "error", "algUnpacked", "algBinaryLen", "bpos", "timeSigned", "macSize", "originalId", "other", "algorithmName", "otherLen", "algWire", "macBytes", "otherBytes", "macByteLen", "URI", "WELL_KNOWN_PORTS", "WKS", "upper", "address", "protoNum", "PORT_NAMES", "ports", "protoMap", "portNums", "maxPort", "typeMap", "classes"] } diff --git a/lib/bind.js b/lib/bind.js index 29d4d09..70810fe 100644 --- a/lib/bind.js +++ b/lib/bind.js @@ -61,15 +61,17 @@ export function fromBind(rrInstance, opts) { } const fields = rrInstance.getFields('rdata') + const rdataDefs = rrInstance.constructor.rdataFields ?? [] for (let i = 0; i < fields.length; i++) { const isLastField = i === fields.length - 1 if (isLastField && rrInstance.isQuotedField(fields[i])) { // Collect all remaining tokens for TXT/etc - const val = rdata - .slice(i) - .map((s) => s.replace(/^"|"$/g, '')) - .join('') - result[fields[i]] = val + const tokens = rdata.slice(i).map((s) => s.replace(/^"|"$/g, '')) + // For `charstrs` (TXT), preserve multi-string boundaries (RFC 1035 §3.3.14). + // For `qstr`/`qcharstr` (single character-string), join into one string. + const def = rdataDefs[i] + const fieldType = Array.isArray(def) ? def[1] : null + result[fields[i]] = fieldType === 'charstrs' && tokens.length > 1 ? tokens : tokens.join('') break } diff --git a/lib/wire.js b/lib/wire.js index dbee785..e460af7 100644 --- a/lib/wire.js +++ b/lib/wire.js @@ -15,29 +15,59 @@ export function encodeName(name) { /** * Read a (possibly pointer-compressed) DNS name from a packet. * Returns { bytes: Buffer (uncompressed wire name), end: offset after name }. + * + * Bounded to defend against malicious or truncated packets: + * - rejects pointer cycles via a visited-offset set + * - caps total pointer dereferences at 128 + * - caps the decoded name at 255 bytes (RFC 1035 §3.1) + * - rejects truncated pointers, pointer targets past the packet end, + * truncated labels, and unterminated names */ export function readWireName(packet, offset) { + if (offset < 0 || offset >= packet.length) { + throw new Error('readWireName: offset out of bounds') + } + const labels = [] + const visited = new Set() let pos = offset let end = -1 + let nameLen = 0 + let terminated = false while (pos < packet.length) { const len = packet[pos] if (len === 0) { if (end === -1) end = pos + 1 labels.push(Buffer.from([0])) + terminated = true break } if ((len & 0xc0) === 0xc0) { + if (pos + 1 >= packet.length) throw new Error('readWireName: truncated pointer') if (end === -1) end = pos + 2 - pos = ((len & 0x3f) << 8) | packet[pos + 1] + if (visited.has(pos)) throw new Error('readWireName: pointer cycle detected') + visited.add(pos) + if (visited.size > 128) throw new Error('readWireName: pointer chain too long') + const target = ((len & 0x3f) << 8) | packet[pos + 1] + if (target >= packet.length) throw new Error('readWireName: pointer target out of bounds') + pos = target continue } + // Top two bits not 00 → reserved (RFC 1035 §4.1.4 / RFC 6891) + if ((len & 0xc0) !== 0) throw new Error('readWireName: reserved label type') + if (len > 63) throw new Error('readWireName: label exceeds 63 bytes') + if (pos + 1 + len > packet.length) throw new Error('readWireName: truncated label') const label = packet.slice(pos, pos + 1 + len) labels.push(label) + // RFC 1035 §3.1: octets of the full domain name (labels + length octets + + // final zero) MUST NOT exceed 255 — count the root terminator too. + nameLen += 1 + len + if (nameLen + 1 > 255) throw new Error('readWireName: name exceeds 255 bytes') pos += 1 + len } + if (!terminated) throw new Error('readWireName: unterminated name') return { bytes: Buffer.concat(labels), end } } @@ -207,6 +237,81 @@ export function wirePackDomain(fqdn) { return buf } +/** + * Pack a fully qualified domain name into wire format with RFC 1035 §4.1.4 + * name compression. `dict` is a `Map` shared across all names + * emitted into a single outbound message; `currentOffset` is the absolute + * offset at which the caller intends to place the returned bytes. + * + * Walks labels from longest suffix to shortest: when a suffix already has an + * offset in `dict`, emits a 2-byte pointer and stops; otherwise emits the label + * verbatim and records the new suffix offset for later reuse. + */ +export function wirePackDomainCompressed(fqdn, dict, currentOffset) { + if (fqdn === '.') return new Uint8Array([0]) + const enc = new TextEncoder() + const labels = fqdn + .split('.') + .filter((p) => p.length > 0) + .map((p) => { + const b = enc.encode(p) + if (b.length > 63) throw new Error(`DNS label exceeds 63 bytes: ${p}`) + return b + }) + + // Pre-compute the absolute write offset of each label and the suffix it begins. + const suffixes = [] + let prefixBytes = 0 + for (let i = 0; i < labels.length; i++) { + suffixes.push({ + key: + labels + .slice(i) + .map((b) => new TextDecoder().decode(b)) + .join('.') + '.', + writeOffset: currentOffset + prefixBytes, + }) + prefixBytes += 1 + labels[i].length + } + + // Find the longest existing suffix in the dict; everything to its right gets + // replaced by a single pointer. + let pointerAt = labels.length + let pointerOffset = -1 + for (let i = 0; i < suffixes.length; i++) { + const hit = dict.get(suffixes[i].key) + if (hit !== undefined && hit < 0x4000) { + pointerAt = i + pointerOffset = hit + break + } + } + + // Compute output size and allocate. + let outSize = 0 + for (let i = 0; i < pointerAt; i++) outSize += 1 + labels[i].length + outSize += pointerAt < labels.length ? 2 : 1 // pointer (2 bytes) or root terminator (1) + const buf = new Uint8Array(outSize) + + let off = 0 + for (let i = 0; i < pointerAt; i++) { + // Record this suffix for future reuse before writing past it. + if (suffixes[i].writeOffset < 0x4000 && !dict.has(suffixes[i].key)) { + dict.set(suffixes[i].key, suffixes[i].writeOffset) + } + buf[off++] = labels[i].length + buf.set(labels[i], off) + off += labels[i].length + } + if (pointerAt < labels.length) { + buf[off++] = 0xc0 | ((pointerOffset >> 8) & 0x3f) + buf[off] = pointerOffset & 0xff + } else { + buf[off] = 0 + } + return buf +} + /** * Get wire format rdata for an RR instance. * Derived classes should override this with direct RFC 1035 wire encoding. @@ -332,13 +437,18 @@ export function fromWireGeneric(rrInstance, { owner, cls, ttl, rdata }) { break } case 'charstrs': { + // RFC 1035 §3.3.14: each on the wire is len-prefixed. + // Preserve multi-string boundaries by returning an array when >1. const parts = [] while (pos < rdata.length) { const strLen = rdata[pos++] + if (pos + strLen > rdata.length) { + throw new Error('fromWireGeneric: truncated character-string in rdata') + } parts.push(new TextDecoder().decode(rdata.subarray(pos, pos + strLen))) pos += strLen } - result[fieldName] = parts.join('') + result[fieldName] = parts.length > 1 ? parts : (parts[0] ?? '') break } case 'svcparams': diff --git a/package.json b/package.json index 9ce2c2b..f1f3eae 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,13 @@ { "name": "@nictool/dns-resource-record", - "version": "1.7.0", + "version": "1.8.0", "description": "DNS Resource Records", "main": "index.js", "exports": { ".": { "browser": "./dist/dns-rr.min.js", + "import": "./index.js", + "require": "./dist/dns-rr.cjs", "default": "./index.js" } }, @@ -18,8 +20,9 @@ ], "type": "module", "scripts": { - "build": "npm run build:browser", + "build": "npm run build:browser && npm run build:cjs", "build:browser": "npx rollup -i index.js -o dist/dns-rr.js -f es && esbuild dist/dns-rr.js --minify --sourcemap --outfile=dist/dns-rr.min.js && rm dist/dns-rr.js", + "build:cjs": "npx rollup -i index.js -o dist/dns-rr.cjs -f cjs --exports named", "clean": "rm -rf coverage dist node_modules package-lock.json", "format:check": "npm run prettier; npm run lint", "format": "npm run prettier -- --write && npm run lint:fix", @@ -58,7 +61,7 @@ }, "homepage": "https://github.com/NicTool/dns-resource-record#readme", "engines": { - "node": ">=22" + "node": ">=20" }, "browserslist": [ "chrome >= 74", @@ -68,8 +71,8 @@ ], "devDependencies": { "@eslint/js": "^10.0.1", - "eslint": "^10.2.1", - "globals": "^17.5.0" + "eslint": "^10.4.0", + "globals": "^17.6.0" }, "prettier": { "printWidth": 110, diff --git a/rr/cert.js b/rr/cert.js index d58a326..74fbcb5 100644 --- a/rr/cert.js +++ b/rr/cert.js @@ -58,6 +58,14 @@ export default class CERT extends RR { this.throwHelp(`CERT: unknown cert type mnemonic: ${val}`) } + setKeyTag(val) { + this.setTypedValue('u16', 'key tag', val) + } + + setAlgorithm(val) { + this.setTypedValue('u8', 'algorithm', val) + } + setCertificate(val) { // certificate/CRL portion is represented in base 64 [16] and may be // divided into any number of white-space-separated substrings diff --git a/rr/cname.js b/rr/cname.js index da7d726..67099e7 100644 --- a/rr/cname.js +++ b/rr/cname.js @@ -12,6 +12,11 @@ export default class CNAME extends RR { super(opts) } + /****** Resource record specific setters *******/ + setCname(val) { + this.setTypedValue('fqdn', 'cname', val) + } + getDescription() { return 'Canonical Name' } diff --git a/rr/dname.js b/rr/dname.js index b96f0af..efb3722 100644 --- a/rr/dname.js +++ b/rr/dname.js @@ -11,6 +11,11 @@ export default class DNAME extends RR { super(opts) } + /****** Resource record specific setters *******/ + setTarget(val) { + this.setTypedValue('fqdn', 'target', val) + } + getDescription() { return 'Delegation Name' } diff --git a/rr/ds.js b/rr/ds.js index ffad86f..1bc18c6 100644 --- a/rr/ds.js +++ b/rr/ds.js @@ -15,6 +15,14 @@ export default class DS extends RR { } /****** Resource record specific setters *******/ + setKeyTag(val) { + this.setTypedValue('u16', 'key tag', val) + } + + setDigest(val) { + this.setTypedValue('str', 'digest', val) + } + setAlgorithm(val) { if (!this.getAlgorithmOptions().has(val)) this.throwHelp(`DS: algorithm invalid`) @@ -22,19 +30,30 @@ export default class DS extends RR { } getAlgorithmOptions() { + // IANA DNSSEC Algorithm Numbers + // https://www.iana.org/assignments/dns-sec-alg-numbers/ return new Map([ [1, 'RSA/MD5'], [2, 'DH'], [3, 'DSA/SHA-1'], [4, 'EC'], [5, 'RSA/SHA-1'], + [6, 'DSA-NSEC3-SHA1'], + [7, 'RSASHA1-NSEC3-SHA1'], + [8, 'RSA/SHA-256'], + [10, 'RSA/SHA-512'], + [13, 'ECDSA P-256/SHA-256'], + [14, 'ECDSA P-384/SHA-384'], + [15, 'Ed25519'], + [16, 'Ed448'], [253, ''], [254, ''], ]) } setDigestType(val) { - if (![1, 2].includes(val)) this.throwHelp(`DS: digest type invalid`) + // 1=SHA-1 (RFC 4034), 2=SHA-256 (RFC 4509), 4=SHA-384 (RFC 6605) + if (![1, 2, 4].includes(val)) this.throwHelp(`DS: digest type invalid`) this.set('digest type', val) } diff --git a/rr/mx.js b/rr/mx.js index 1bd795d..73b9b1d 100644 --- a/rr/mx.js +++ b/rr/mx.js @@ -23,6 +23,10 @@ export default class MX extends RR { this.set('preference', val) } + setExchange(val) { + this.setTypedValue('fqdn', 'exchange', val) + } + getDescription() { return 'Mail Exchanger' } diff --git a/rr/rrsig.js b/rr/rrsig.js index cbf3f9b..fcd2480 100644 --- a/rr/rrsig.js +++ b/rr/rrsig.js @@ -49,13 +49,51 @@ export default class RRSIG extends RR { this.set('algorithm', val) } + setLabels(val) { + this.setTypedValue('u8', 'labels', val) + } + + setOriginalTtl(val) { + this.setTypedValue('u32', 'original ttl', val) + } + + setSignatureExpiration(val) { + this.setTypedValue('u32', 'signature expiration', val) + } + + setSignatureInception(val) { + this.setTypedValue('u32', 'signature inception', val) + } + + setKeyTag(val) { + this.setTypedValue('u16', 'key tag', val) + } + + setSignersName(val) { + this.setTypedValue('fqdn', 'signers name', val) + } + + setSignature(val) { + this.setTypedValue('str', 'signature', val) + } + getAlgorithmOptions() { + // IANA DNSSEC Algorithm Numbers + // https://www.iana.org/assignments/dns-sec-alg-numbers/ return new Map([ [1, 'RSA/MD5'], [2, 'DH'], - [3, 'RRSIGA/SHA-1'], + [3, 'DSA/SHA-1'], [4, 'EC'], [5, 'RSA/SHA-1'], + [6, 'DSA-NSEC3-SHA1'], + [7, 'RSASHA1-NSEC3-SHA1'], + [8, 'RSA/SHA-256'], + [10, 'RSA/SHA-512'], + [13, 'ECDSA P-256/SHA-256'], + [14, 'ECDSA P-384/SHA-384'], + [15, 'Ed25519'], + [16, 'Ed448'], [253], [254], ]) diff --git a/rr/spf.js b/rr/spf.js index fadaa48..d928b76 100644 --- a/rr/spf.js +++ b/rr/spf.js @@ -55,7 +55,11 @@ export default class SPF extends TXT { } toTinydns() { - const rdata = TINYDNS.escapeOctal(new RegExp(/[\r\n\t:\\/]/, 'g'), this.get('data')) + // `data` may be a string or an array of s (RFC 1035 §3.3.14). + // tinydns generic format stores rdata as a flat byte stream, so join here. + let data = this.get('data') + if (Array.isArray(data)) data = data.join('') + const rdata = TINYDNS.escapeOctal(new RegExp(/[\r\n\t:\\/]/, 'g'), data) return this.getTinydnsGeneric(rdata) } } diff --git a/rr/srv.js b/rr/srv.js index f280582..82a4fc6 100644 --- a/rr/srv.js +++ b/rr/srv.js @@ -17,6 +17,23 @@ export default class SRV extends RR { super(opts) } + /****** Resource record specific setters *******/ + setPriority(val) { + this.setTypedValue('u16', 'priority', val) + } + + setWeight(val) { + this.setTypedValue('u16', 'weight', val) + } + + setPort(val) { + this.setTypedValue('u16', 'port', val) + } + + setTarget(val) { + this.setTypedValue('fqdn', 'target', val) + } + getDescription() { return 'Service' } diff --git a/rr/sshfp.js b/rr/sshfp.js index 9c59dae..9762830 100644 --- a/rr/sshfp.js +++ b/rr/sshfp.js @@ -17,6 +17,21 @@ export default class SSHFP extends RR { super(opts) } + /****** Resource record specific setters *******/ + setAlgorithm(val) { + if (!this.getAlgorithmOptions().has(val)) this.throwHelp(`SSHFP: algorithm invalid`) + this.setTypedValue('u8', 'algorithm', val) + } + + setFptype(val) { + if (!this.getFptypeOptions().has(val)) this.throwHelp(`SSHFP: fptype invalid`) + this.setTypedValue('u8', 'fptype', val) + } + + setFingerprint(val) { + this.setTypedValue('hex', 'fingerprint', val) + } + getAlgorithmOptions() { return new Map([ [0, 'reserved'], diff --git a/rr/txt.js b/rr/txt.js index 1ccdb3f..51283be 100644 --- a/rr/txt.js +++ b/rr/txt.js @@ -62,15 +62,20 @@ export default class TXT extends RR { if (n != 16) this.throwHelp('TXT fromTinydns, invalid n') rdata = TINYDNS.octalToChar(rdata) - let s = '' - let len = rdata[0].charCodeAt(0) - let pos = 1 + // Walk RFC 1035 §3.3.14 len-prefixed segments. + const parts = [] + let pos = 0 while (pos < rdata.length) { - s += rdata.slice(pos, +(len + pos)) - pos = len + pos - len = rdata.charCodeAt(pos + 1) + const len = rdata.charCodeAt(pos) + pos += 1 + if (pos + len > rdata.length) { + this.throwHelp('TXT fromTinydnsGeneric: truncated character-string in rdata') + } + parts.push(rdata.slice(pos, pos + len)) + pos += len } - return [fqdn, s, ttl, ts, loc] + const data = parts.length > 1 ? parts : (parts[0] ?? '') + return [fqdn, data, ttl, ts, loc] } /****** EXPORTERS *******/ @@ -84,8 +89,31 @@ export default class TXT extends RR { } getWireRdata() { - let data = this.get('data') - if (Array.isArray(data)) data = data.join('') + // RFC 1035 §3.3.14: TXT rdata is one or more s, each up + // to 255 bytes. An array preserves explicit boundaries between strings; + // each element MUST be <= 255 UTF-8 bytes, otherwise we would silently + // split it and the boundary the caller asked us to preserve would be lost. + // A single string is auto-chunked at 255-byte UTF-8 boundaries. + const data = this.get('data') + if (Array.isArray(data)) { + const enc = new TextEncoder() + const buffers = data.map((s, i) => { + if (enc.encode(s).length > 255) { + this.throwHelp( + `TXT: array element ${i} exceeds 255 bytes; split it yourself or pass a single string to auto-chunk`, + ) + } + return packStringWire(s) + }) + const total = buffers.reduce((n, b) => n + b.length, 0) + const out = new Uint8Array(total) + let off = 0 + for (const b of buffers) { + out.set(b, off) + off += b.length + } + return out + } return packStringWire(data) } diff --git a/test/base.js b/test/base.js index 70a6730..bde65cc 100644 --- a/test/base.js +++ b/test/base.js @@ -101,8 +101,14 @@ function checkFromNS(type, validRecords, nsName, nsLineName) { for (const f of r.getFields()) { if (f === 'class') continue let expected = val[f] - if (f === 'data' && Array.isArray(expected)) expected = expected.join('') // TXT - assert.deepEqual(r.get(f), expected, `${f}: ${r.get(f)} !== ${expected}`) + let actual = r.get(f) + // TXT can be stored as string or as array of character-strings (RFC 1035 §3.3.14). + // Normalize both sides to the joined string for legacy fixtures. + if (f === 'data') { + if (Array.isArray(expected)) expected = expected.join('') + if (Array.isArray(actual)) actual = actual.join('') + } + assert.deepEqual(actual, expected, `${f}: ${actual} !== ${expected}`) } }) } diff --git a/test/rr/ds.js b/test/rr/ds.js index 25bb3a6..2310b98 100644 --- a/test/rr/ds.js +++ b/test/rr/ds.js @@ -1,4 +1,5 @@ -import { describe } from 'node:test' +import { describe, it } from 'node:test' +import assert from 'node:assert/strict' import * as base from '../base.js' import DS from '../../rr/ds.js' @@ -22,7 +23,7 @@ const invalidRecords = [ { ...defaults, owner: 'test.example.com.', - algorithm: 6, + algorithm: 99, msg: /algorithm/, }, { @@ -31,6 +32,13 @@ const invalidRecords = [ 'key tag': 65536, msg: /must be a 16-bit integer/, }, + { + ...defaults, + owner: 'test.example.com.', + digest: '00', + 'digest type': 3, + msg: /digest type invalid/, + }, ] describe('DS record', function () { @@ -51,4 +59,29 @@ describe('DS record', function () { base.fromBind(DS, validRecords) base.fromTinydns(DS, validRecords) base.fromWire(DS, validRecords) + + // RFC 6605: SHA-384 digest type + it('accepts digest type 4 (SHA-384)', function () { + const r = new DS({ + ...defaults, + owner: 'dskey.example.com.', + 'digest type': 4, + digest: + '72D7B62976CE06438E9C0BF319013CF801F09ECC84B8D7E9495F27E305C6A9B0563A9B5F4D288405C3008A946DF983D6', + }) + assert.equal(r.get('digest type'), 4) + }) + + // Modern DNSSEC algorithms must be accepted (parity with RRSIG) + for (const algo of [6, 7, 8, 10, 13, 14, 15, 16]) { + it(`accepts DNSSEC algorithm ${algo}`, function () { + const r = new DS({ + ...defaults, + owner: 'dskey.example.com.', + algorithm: algo, + digest: '2BB183AF5F22588179A53B0A98631FAD1A292118', + }) + assert.equal(r.get('algorithm'), algo) + }) + } }) diff --git a/test/rr/rrsig.js b/test/rr/rrsig.js index 08c1bb5..48b458c 100644 --- a/test/rr/rrsig.js +++ b/test/rr/rrsig.js @@ -112,4 +112,16 @@ describe('RRSIG record', function () { const r = RRSIG.fromBind(bindline) assert.equal(r.get('type covered'), 28) }) + + // RFC 5155, 5702, 5933, 6605, 8080 — modern DNSSEC algorithms must be accepted + for (const algo of [6, 7, 8, 10, 13, 14, 15, 16]) { + it(`accepts DNSSEC algorithm ${algo}`, function () { + const r = new RRSIG({ ...defaults, 'type covered': 1, algorithm: algo }) + assert.equal(r.get('algorithm'), algo) + }) + } + + it('rejects an unassigned algorithm', function () { + assert.throws(() => new RRSIG({ ...defaults, 'type covered': 1, algorithm: 99 }), /algorithm invalid/i) + }) }) diff --git a/test/rr/spf.js b/test/rr/spf.js index 556a77b..42d3ef7 100644 --- a/test/rr/spf.js +++ b/test/rr/spf.js @@ -49,4 +49,14 @@ describe('SPF record', function () { } }) } + + it('toTinydns accepts array-form data (multi-string charstrs)', function () { + const r = new SPF({ + ...defaults, + owner: 'example.com.', + data: ['v=spf1 ', 'mx -all'], + }) + const line = r.toTinydns() + assert.match(line, /v=spf1 mx -all/) + }) }) diff --git a/test/rr/sshfp.js b/test/rr/sshfp.js index c6e2d6c..f178df5 100644 --- a/test/rr/sshfp.js +++ b/test/rr/sshfp.js @@ -99,7 +99,7 @@ const invalidRecords = [ algorithm: 256, fptype: 1, fingerprint: 'ed8c6e16fdae4f633eee6a7b8f64fdd356bbb32841d535565d777014c9ea4c26', - msg: /SSHFP algorithm must be a 8-bit integer/i, + msg: /SSHFP: algorithm invalid/i, }, { ...common, @@ -107,7 +107,25 @@ const invalidRecords = [ algorithm: 1, fptype: 999, fingerprint: 'ed8c6e16fdae4f633eee6a7b8f64fdd356bbb32841d535565d777014c9ea4c26', - msg: /SSHFP fptype must be a 8-bit integer/i, + msg: /SSHFP: fptype invalid/i, + }, + // 5 is in the u8 range but unassigned in the IANA SSHFP Algorithm registry + { + ...common, + owner: 'mail.example.com.', + algorithm: 5, + fptype: 1, + fingerprint: 'ed8c6e16fdae4f633eee6a7b8f64fdd356bbb32841d535565d777014c9ea4c26', + msg: /SSHFP: algorithm invalid/i, + }, + // 3 is in the u8 range but not in the SSHFP fptype registry + { + ...common, + owner: 'mail.example.com.', + algorithm: 1, + fptype: 3, + fingerprint: 'ed8c6e16fdae4f633eee6a7b8f64fdd356bbb32841d535565d777014c9ea4c26', + msg: /SSHFP: fptype invalid/i, }, ] diff --git a/test/rr/txt.js b/test/rr/txt.js index 35e0985..9e4f496 100644 --- a/test/rr/txt.js +++ b/test/rr/txt.js @@ -118,4 +118,75 @@ describe('TXT record', function () { const r = new TXT({ owner: 'example.com.', ttl: 3600, class: 'IN', type: 'TXT', data: 'v=spf1 mx -all' }) assert.equal(r.toMaraDNS(), "example.com.\t+3600\tTXT\t'v=spf1 mx -all' ~\n") }) + + // RFC 1035 §3.3.14: multi-string TXT records are wire-distinct from one + // concatenated string. Boundaries must round-trip through encode/decode. + describe('multi-string boundary preservation', function () { + const owner = 'example.com.' + const segments = ['hello', 'world'] + + it('encodes array as N len-prefixed character-strings on the wire', function () { + const r = new TXT({ owner, ttl: 3600, class: 'IN', type: 'TXT', data: segments }) + const rdata = r.getWireRdata() + // Expect [5, h, e, l, l, o, 5, w, o, r, l, d] + assert.deepEqual([...rdata], [5, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 5, 0x77, 0x6f, 0x72, 0x6c, 0x64]) + }) + + it('decodes multi-string wire form back to array', function () { + const r = new TXT({ owner, ttl: 3600, class: 'IN', type: 'TXT', data: segments }) + const wire = r.toWire() + const r2 = TXT.fromWire(wire) + assert.deepEqual(r2.get('data'), segments) + }) + + it('decodes a single-string wire form back to a plain string', function () { + const r = new TXT({ owner, ttl: 3600, class: 'IN', type: 'TXT', data: 'just one' }) + const r2 = TXT.fromWire(r.toWire()) + assert.equal(r2.get('data'), 'just one') + }) + + it('fromBind on "a" "b" returns the array form', function () { + const bindline = 'example.com.\t3600\tIN\tTXT\t"hello" "world"\n' + const r = TXT.fromBind(bindline) + assert.deepEqual(r.get('data'), segments) + }) + + it('rejects an array element longer than 255 bytes (boundary not preservable)', function () { + const r = new TXT({ + owner, + ttl: 3600, + class: 'IN', + type: 'TXT', + data: ['ok', 'x'.repeat(256)], + }) + assert.throws(() => r.getWireRdata(), /exceeds 255 bytes/) + }) + + it('fromTinydnsGeneric rejects a truncated len-prefixed segment', function () { + // tinydns generic with declared length 5 but only 2 trailing bytes. + // Use octal escape so the length byte survives the tinydns parser. + const truncated = ':example.com:16:\\005ab:3600::\n' + assert.throws(() => new TXT(null).fromTinydnsGeneric(truncated), /truncated character-string/) + }) + + it('fromWire rejects a truncated charstr in rdata', function () { + // Hand-craft a wire record whose final character-string length byte + // claims more bytes than remain in rdata. + // owner = "example.com." (uncompressed), type 16, class 1, ttl 3600, + // rdlen 4, then rdata = [\x05 a b c] (declared 5, only 3 follow). + const wire = Buffer.concat([ + Buffer.from([7]), + Buffer.from('example'), + Buffer.from([3]), + Buffer.from('com'), + Buffer.from([0]), + Buffer.from([0x00, 0x10]), // type 16 + Buffer.from([0x00, 0x01]), // class 1 + Buffer.from([0x00, 0x00, 0x0e, 0x10]), // ttl 3600 + Buffer.from([0x00, 0x04]), // rdlen 4 + Buffer.from([5, 0x61, 0x62, 0x63]), // declared len 5, only 3 chars + ]) + assert.throws(() => TXT.fromWire(wire), /truncated character-string/) + }) + }) }) diff --git a/test/wire.js b/test/wire.js index 006c467..3982397 100644 --- a/test/wire.js +++ b/test/wire.js @@ -8,6 +8,8 @@ import { buildQuery, parseResponse, svcParamsToWire, + wirePackDomain, + wirePackDomainCompressed, } from '../lib/wire.js' // ── encodeName ──────────────────────────────────────────────────────────────── @@ -62,6 +64,135 @@ describe('readWireName', () => { const { end } = readWireName(packet, 10) assert.equal(end, 12) // two bytes consumed for the pointer }) + + test('rejects a self-referential pointer', () => { + // offset 0: \xc0\x00 — points to itself + const packet = Buffer.from([0xc0, 0x00]) + assert.throws(() => readWireName(packet, 0), /pointer cycle detected/) + }) + + test('rejects a two-pointer cycle', () => { + // offset 0: \xc0\x02 offset 2: \xc0\x00 + const packet = Buffer.from([0xc0, 0x02, 0xc0, 0x00]) + assert.throws(() => readWireName(packet, 0), /pointer cycle detected/) + }) + + test('rejects an over-long pointer chain', () => { + // 200 unique-offset pointers, each pointing to the next two bytes ahead. + // Final slot terminates with a zero byte so a non-protected reader would + // still finish; the guard fires on chain length. + const len = 200 * 2 + 1 + const packet = Buffer.alloc(len) + for (let i = 0; i < 200; i++) { + const next = (i + 1) * 2 + packet[i * 2] = 0xc0 | ((next >> 8) & 0x3f) + packet[i * 2 + 1] = next & 0xff + } + // last pointer (offset 398) points to offset 400 which holds \x00 + packet[400] = 0 + assert.throws(() => readWireName(packet, 0), /pointer chain too long/) + }) + + test('rejects a name longer than 255 bytes', () => { + // 5 chained 63-byte labels (5 * 64 = 320 bytes) + terminator + const label = Buffer.concat([Buffer.from([63]), Buffer.alloc(63, 0x61)]) + const packet = Buffer.concat([label, label, label, label, label, Buffer.from([0])]) + assert.throws(() => readWireName(packet, 0), /name exceeds 255 bytes/) + }) + + test('rejects a truncated pointer (high byte at end of packet)', () => { + // Single 0xc0 byte with no second byte + const packet = Buffer.from([0xc0]) + assert.throws(() => readWireName(packet, 0), /truncated pointer/) + }) + + test('rejects a pointer whose target is past the packet end', () => { + // 0xc0 0x80 → target offset 0x80 = 128, packet is only 2 bytes + const packet = Buffer.from([0xc0, 0x80]) + assert.throws(() => readWireName(packet, 0), /pointer target out of bounds/) + }) + + test('rejects a truncated label (declared length exceeds packet)', () => { + // \x05 with only 2 bytes following — declared label longer than packet + const packet = Buffer.from([5, 0x61, 0x61]) + assert.throws(() => readWireName(packet, 0), /truncated label/) + }) + + test('rejects an unterminated name (no zero, no pointer)', () => { + // \x02 a a — well-formed label, no terminator, no pointer + const packet = Buffer.from([2, 0x61, 0x61]) + assert.throws(() => readWireName(packet, 0), /unterminated name/) + }) + + test('rejects a reserved label-type code (top two bits = 01 or 10)', () => { + // \x40 is binary 01000000 — reserved per RFC 1035 §4.1.4 + const packet = Buffer.from([0x40, 0, 0]) + assert.throws(() => readWireName(packet, 0), /reserved label type/) + }) + + test('rejects offset out of bounds', () => { + const packet = Buffer.from([0]) + assert.throws(() => readWireName(packet, 5), /offset out of bounds/) + }) + + test('rejects a name whose total wire length equals 256 octets (255 labels + terminator)', () => { + // 4 × 63-byte labels: 4 × 64 = 256 octets before the terminator → 257 with it. + // Even before adding the terminator, 256 > 255 trips the §3.1 cap. + const label = Buffer.concat([Buffer.from([63]), Buffer.alloc(63, 0x61)]) + const packet = Buffer.concat([label, label, label, label, Buffer.from([0])]) + assert.throws(() => readWireName(packet, 0), /name exceeds 255 bytes/) + }) +}) + +// ── wirePackDomainCompressed ────────────────────────────────────────────────── + +describe('wirePackDomainCompressed', () => { + test('first name writes uncompressed and matches wirePackDomain', () => { + const dict = new Map() + const buf = wirePackDomainCompressed('www.example.com.', dict, 12) + assert.deepEqual([...buf], [...wirePackDomain('www.example.com.')]) + }) + + test('second name with shared suffix emits a pointer', () => { + const dict = new Map() + // First, place "www.example.com." at offset 12. + const first = wirePackDomainCompressed('www.example.com.', dict, 12) + // Second name shares the "example.com." suffix. + const second = wirePackDomainCompressed('mail.example.com.', dict, 12 + first.length) + // Second name should be: \x04 m a i l + // "example.com." starts at offset 12 + 4 (skip "\x03www") = 16. + assert.deepEqual([...second.slice(0, 5)], [4, 0x6d, 0x61, 0x69, 0x6c]) + assert.equal(second[5], 0xc0) + assert.equal(second[6], 16) + assert.equal(second.length, 7) + }) + + test('full-name reuse emits only a pointer', () => { + const dict = new Map() + const first = wirePackDomainCompressed('example.com.', dict, 12) + const second = wirePackDomainCompressed('example.com.', dict, 12 + first.length) + assert.equal(second.length, 2) + assert.equal(second[0], 0xc0) + assert.equal(second[1], 12) + }) + + test('root name (".") encodes as a single zero byte without compression', () => { + const dict = new Map([['.', 0]]) + const buf = wirePackDomainCompressed('.', dict, 50) + assert.deepEqual([...buf], [0]) + }) + + test('round-trips through readWireName', () => { + const dict = new Map() + const a = wirePackDomainCompressed('foo.example.com.', dict, 0) + const b = wirePackDomainCompressed('bar.example.com.', dict, a.length) + const packet = Buffer.concat([Buffer.from(a), Buffer.from(b)]) + const read1 = readWireName(packet, 0) + const read2 = readWireName(packet, a.length) + // Both decoded names should round-trip to the original uncompressed wire form. + assert.deepEqual([...read1.bytes], [...wirePackDomain('foo.example.com.')]) + assert.deepEqual([...read2.bytes], [...wirePackDomain('bar.example.com.')]) + }) }) // ── decompressRdata ───────────────────────────────────────────────────────────