'use strict';Object.defineProperty(exports,Symbol.toStringTag,{value:'Module'});const base=require('../../../_virtual/base.cjs'),trie=require('../trie.cjs'),require$$6=require('foxts/guard'),require$$2=require('fast-cidr-tools'),require$$3=require('foxts/retrie'),require$$0=require('node:path'),surge=require('../writing-strategy/surge.cjs');var hasRequiredBase; function requireBase () { if (hasRequiredBase) return base.__exports; hasRequiredBase = 1; (function (exports) { Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "FileOutput", { enumerable: true, get: function() { return FileOutput; } }); const _trie = /*@__PURE__*/ trie.__require(); const _guard = require$$6; const _fastcidrtools = require$$2; const _retrie = require$$3; const _nodepath = /*#__PURE__*/ _interop_require_default(require$$0); const _surge = /*@__PURE__*/ surge.__require(); function _interop_require_default(obj) { return obj && obj.__esModule ? obj : { default: obj }; } class FileOutput { id; strategies; domainTrie; domainKeywords; domainWildcard; userAgent; processName; processPath; urlRegex; ipcidr; ipcidrNoResolve; ipasn; ipasnNoResolve; ipcidr6; ipcidr6NoResolve; geoip; groipNoResolve; sourceIpOrCidr; sourcePort; destPort; otherRules; pendingPromise; whitelistDomain; span; constructor($span, id){ this.id = id; this.strategies = []; this.domainTrie = new _trie.HostnameSmolTrie(null); this.domainKeywords = new Set(); this.domainWildcard = new Set(); this.userAgent = new Set(); this.processName = new Set(); this.processPath = new Set(); this.urlRegex = new Set(); this.ipcidr = new Set(); this.ipcidrNoResolve = new Set(); this.ipasn = new Set(); this.ipasnNoResolve = new Set(); this.ipcidr6 = new Set(); this.ipcidr6NoResolve = new Set(); this.geoip = new Set(); this.groipNoResolve = new Set(); this.sourceIpOrCidr = new Set(); this.sourcePort = new Set(); this.destPort = new Set(); this.otherRules = []; this.pendingPromise = null; this.whitelistDomain = (domain)=>{ this.domainTrie.whitelist(domain); return this; }; this.title = null; this.description = null; this.date = new Date(); this.strategiesWritten = false; this.span = $span.traceChild('RuleOutput#' + id); } title; withTitle(title) { this.title = title; return this; } withStrategies(strategies) { this.strategies = strategies; return this; } withExtraStrategies(strategy) { if (strategy) { this.strategies.push(strategy); } } description; withDescription(description) { this.description = description; return this; } date; withDate(date) { this.date = date; return this; } addDomain(domain) { this.domainTrie.add(domain); return this; } bulkAddDomain(domains) { let d; for(let i = 0, len = domains.length; i < len; i++){ d = domains[i]; if (d !== null) { this.domainTrie.add(d, false, null, 0); } } return this; } addDomainSuffix(domain, lineFromDot = domain[0] === '.') { this.domainTrie.add(domain, true, lineFromDot ? 1 : 0); return this; } bulkAddDomainSuffix(domains) { for(let i = 0, len = domains.length; i < len; i++){ this.addDomainSuffix(domains[i]); } return this; } addDomainKeyword(keyword) { this.domainKeywords.add(keyword); return this; } addIPASN(asn) { this.ipasn.add(asn); return this; } bulkAddIPASN(asns) { for(let i = 0, len = asns.length; i < len; i++){ this.ipasn.add(asns[i]); } return this; } async addFromDomainsetPromise(source) { for await (const line of source){ if (line[0] === '.') { this.addDomainSuffix(line, true); } else { this.domainTrie.add(line, false, null, 0); } } } addFromDomainset(source) { if (this.pendingPromise) { if ('then' in source) { this.pendingPromise = this.pendingPromise.then(()=>source).then((src)=>this.addFromDomainsetPromise(src)); return this; } this.pendingPromise = this.pendingPromise.then(()=>this.addFromDomainsetPromise(source)); return this; } if ('then' in source) { this.pendingPromise = source.then((src)=>this.addFromDomainsetPromise(src)); return this; } this.pendingPromise = this.addFromDomainsetPromise(source); return this; } async addFromRulesetPromise(source) { for await (const line of source){ const splitted = line.split(','); const type = splitted[0]; const value = splitted[1]; const arg = splitted[2]; switch(type){ case 'DOMAIN': this.domainTrie.add(value, false, null, 0); break; case 'DOMAIN-SUFFIX': this.addDomainSuffix(value, false); break; case 'DOMAIN-KEYWORD': this.addDomainKeyword(value); break; case 'DOMAIN-WILDCARD': this.domainWildcard.add(value); break; case 'USER-AGENT': this.userAgent.add(value); break; case 'PROCESS-NAME': if (value.includes('/') || value.includes('\\')) { this.processPath.add(value); } else { this.processName.add(value); } break; case 'URL-REGEX': { const [, ...rest] = splitted; this.urlRegex.add(rest.join(',')); break; } case 'IP-CIDR': (arg === 'no-resolve' ? this.ipcidrNoResolve : this.ipcidr).add(value); break; case 'IP-CIDR6': (arg === 'no-resolve' ? this.ipcidr6NoResolve : this.ipcidr6).add(value); break; case 'IP-ASN': (arg === 'no-resolve' ? this.ipasnNoResolve : this.ipasn).add(value); break; case 'GEOIP': (arg === 'no-resolve' ? this.groipNoResolve : this.geoip).add(value); break; case 'SRC-IP': this.sourceIpOrCidr.add(value); break; case 'SRC-PORT': this.sourcePort.add(value); break; case 'DEST-PORT': this.destPort.add(value); break; default: this.otherRules.push(line); break; } } } addFromRuleset(source) { if (this.pendingPromise) { if ('then' in source) { this.pendingPromise = this.pendingPromise.then(()=>source).then((src)=>this.addFromRulesetPromise(src)); return this; } this.pendingPromise = this.pendingPromise.then(()=>this.addFromRulesetPromise(source)); return this; } if ('then' in source) { this.pendingPromise = source.then((src)=>this.addFromRulesetPromise(src)); return this; } this.pendingPromise = this.addFromRulesetPromise(source); return this; } static ipToCidr = (ip, version)=>{ if (ip.includes('/')) return ip; if (version === 4) { return ip + '/32'; } return ip + '/128'; }; bulkAddCIDR4(cidrs) { for(let i = 0, len = cidrs.length; i < len; i++){ this.ipcidr.add(FileOutput.ipToCidr(cidrs[i], 4)); } return this; } bulkAddCIDR4NoResolve(cidrs) { for(let i = 0, len = cidrs.length; i < len; i++){ this.ipcidrNoResolve.add(FileOutput.ipToCidr(cidrs[i], 4)); } return this; } bulkAddCIDR6(cidrs) { for(let i = 0, len = cidrs.length; i < len; i++){ this.ipcidr6.add(FileOutput.ipToCidr(cidrs[i], 6)); } return this; } bulkAddCIDR6NoResolve(cidrs) { for(let i = 0, len = cidrs.length; i < len; i++){ this.ipcidr6NoResolve.add(FileOutput.ipToCidr(cidrs[i], 6)); } return this; } async done() { await this.pendingPromise; this.pendingPromise = null; return this; } // private guardPendingPromise() { // // reverse invariant // if (this.pendingPromise !== null) { // console.trace('Pending promise:', this.pendingPromise); // throw new Error('You should call done() before calling this method'); // } // } // async writeClash(outputDir?: null | string) { // await this.done(); // invariant(this.title, 'Missing title'); // invariant(this.description, 'Missing description'); // return compareAndWriteFile( // this.span, // withBannerArray( // this.title, // this.description, // this.date, // this.clash() // ), // path.join(outputDir ?? OUTPUT_CLASH_DIR, this.type, this.id + '.txt') // ); // } strategiesWritten; writeToStrategies() { if (this.pendingPromise) { throw new Error('You should call done() before calling writeToStrategies()'); } if (this.strategiesWritten) { throw new Error('Strategies already written'); } this.strategiesWritten = true; const kwfilter = (0, _retrie.createRetrieKeywordFilter)(Array.from(this.domainKeywords)); if (this.strategies.filter((0, _guard.not)(false)).length === 0) { throw new Error('No strategies to write ' + this.id); } this.domainTrie.dumpWithoutDot((domain, includeAllSubdomain)=>{ if (kwfilter(domain)) { return; } for(let i = 0, len = this.strategies.length; i < len; i++){ const strategy = this.strategies[i]; if (strategy) { if (includeAllSubdomain) { strategy.writeDomainSuffix(domain); } else { strategy.writeDomain(domain); } } } }, true); for(let i = 0, len = this.strategies.length; i < len; i++){ const strategy = this.strategies[i]; if (!strategy) continue; if (this.domainKeywords.size) { strategy.writeDomainKeywords(this.domainKeywords); } if (this.domainWildcard.size) { strategy.writeDomainWildcards(this.domainWildcard); } if (this.userAgent.size) { strategy.writeUserAgents(this.userAgent); } if (this.processName.size) { strategy.writeProcessNames(this.processName); } if (this.processPath.size) { strategy.writeProcessPaths(this.processPath); } } if (this.sourceIpOrCidr.size) { const sourceIpOrCidr = Array.from(this.sourceIpOrCidr); for(let i = 0, len = this.strategies.length; i < len; i++){ const strategy = this.strategies[i]; if (strategy) { strategy.writeSourceIpCidrs(sourceIpOrCidr); } } } for(let i = 0, len = this.strategies.length; i < len; i++){ const strategy = this.strategies[i]; if (strategy) { if (this.sourcePort.size) { strategy.writeSourcePorts(this.sourcePort); } if (this.destPort.size) { strategy.writeDestinationPorts(this.destPort); } if (this.otherRules.length) { strategy.writeOtherRules(this.otherRules); } if (this.urlRegex.size) { strategy.writeUrlRegexes(this.urlRegex); } } } let ipcidr = null; let ipcidrNoResolve = null; let ipcidr6 = null; let ipcidr6NoResolve = null; if (this.ipcidr.size) { ipcidr = (0, _fastcidrtools.merge)(Array.from(this.ipcidr), true); } if (this.ipcidrNoResolve.size) { ipcidrNoResolve = (0, _fastcidrtools.merge)(Array.from(this.ipcidrNoResolve), true); } if (this.ipcidr6.size) { ipcidr6 = Array.from(this.ipcidr6); } if (this.ipcidr6NoResolve.size) { ipcidr6NoResolve = Array.from(this.ipcidr6NoResolve); } for(let i = 0, len = this.strategies.length; i < len; i++){ const strategy = this.strategies[i]; if (strategy) { // no-resolve if (ipcidrNoResolve?.length) { strategy.writeIpCidrs(ipcidrNoResolve, true); } if (ipcidr6NoResolve?.length) { strategy.writeIpCidr6s(ipcidr6NoResolve, true); } if (this.ipasnNoResolve.size) { strategy.writeIpAsns(this.ipasnNoResolve, true); } if (this.groipNoResolve.size) { strategy.writeGeoip(this.groipNoResolve, true); } // triggers DNS resolution if (ipcidr?.length) { strategy.writeIpCidrs(ipcidr, false); } if (ipcidr6?.length) { strategy.writeIpCidr6s(ipcidr6, false); } if (this.ipasn.size) { strategy.writeIpAsns(this.ipasn, false); } if (this.geoip.size) { strategy.writeGeoip(this.geoip, false); } } } } write() { return this.span.traceChildAsync('write all', async (childSpan)=>{ await this.done(); childSpan.traceChildSync('write to strategies', this.writeToStrategies.bind(this)); return childSpan.traceChildAsync('output to disk', (childSpan)=>{ const promises = []; (0, _guard.invariant)(this.title, 'Missing title'); (0, _guard.invariant)(this.description, 'Missing description'); for(let i = 0, len = this.strategies.length; i < len; i++){ const strategy = this.strategies[i]; if (strategy) { const basename = (strategy.overwriteFilename || this.id) + '.' + strategy.fileExtension; promises.push(strategy.output(childSpan, this.title, this.description, this.date, _nodepath.default.join(strategy.outputDir, strategy.type ? _nodepath.default.join(strategy.type, basename) : basename))); } } return Promise.all(promises); }); }); } async compile() { await this.done(); this.writeToStrategies(); return this.strategies.reduce((acc, strategy)=>{ if (strategy) { acc.push(strategy.content); } else { acc.push(null); } return acc; }, []); } withMitmSgmodulePath(moduleName) { if (moduleName) { this.withExtraStrategies(new _surge.SurgeMitmSgmodule(moduleName)); } return this; } } } (base.__exports)); return base.__exports; }exports.__require=requireBase;