UNPKG

hfs

Version:
175 lines (174 loc) 6.91 kB
"use strict"; // This file is part of HFS - Copyright 2021-2023, Massimo Melina <a@rejetto.com> - License https://www.gnu.org/licenses/gpl-3.0.txt var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __exportStar = (this && this.__exportStar) || function(m, exports) { for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.AsapStream = void 0; exports.pattern2filter = pattern2filter; exports.isLocalHost = isLocalHost; exports.netMatches = netMatches; exports.makeNetMatcher = makeNetMatcher; exports.same = same; exports.asyncGeneratorToReadable = asyncGeneratorToReadable; exports.apiAssertTypes = apiAssertTypes; exports.createStreamLimiter = createStreamLimiter; const path_1 = require("path"); __exportStar(require("./util-http"), exports); __exportStar(require("./util-files"), exports); __exportStar(require("./fileAttr"), exports); __exportStar(require("./cross"), exports); __exportStar(require("./debounceAsync"), exports); const stream_1 = require("stream"); const node_net_1 = require("node:net"); const apiMiddleware_1 = require("./apiMiddleware"); const const_1 = require("./const"); const cross_1 = require("./cross"); const net_1 = require("net"); const lodash_1 = __importDefault(require("lodash")); function pattern2filter(pattern) { const matcher = (0, cross_1.makeMatcher)(pattern.includes('*') ? pattern // if you specify *, we'll respect its position : pattern.split('|').map(x => `*${x}*`).join('|')); return (s) => !pattern || matcher((0, path_1.basename)(s || '')); } function isLocalHost(c) { const ip = typeof c === 'string' ? c : c.socket.remoteAddress; // don't use Context.ip as it is subject to proxied ips, and that's no use for localhost detection return ip && (0, cross_1.isIpLocalHost)(ip); } // this will memory-leak over mask, so be careful with what you use this. Object is 3x faster than _.memoize function netMatches(ip, mask, emptyMaskReturns = false) { var _a, _b; const cache = (_a = netMatches).cache || (_a.cache = {}); return (cache[_b = mask + (emptyMaskReturns ? '1' : '0')] || (cache[_b] = makeNetMatcher(mask, emptyMaskReturns)))(ip); // cache the matcher } function makeNetMatcher(mask, emptyMaskReturns = false) { var _a; if (!mask) return () => emptyMaskReturns; mask = mask.replaceAll(' ', ''); mask = mask.replace('localhost', '::1|127.0.0.1'); try { if (!/\/|-(?![^\[]*\])/.test(mask)) { // when no CIDR and no ranges are used, then we use standard matcher, otherwise BlockList. For "-" we must skip those inside [] if (/[^.:\da-fA-F*?|()!]/.test(mask)) throw mask; return (0, cross_1.makeMatcher)(mask); } const all = mask.split('|'); const neg = ((_a = all[0]) === null || _a === void 0 ? void 0 : _a[0]) === '!'; if (neg) all[0] = all[0].slice(1); const bl = new node_net_1.BlockList(); for (const x of all) { const m = /^([.:\da-f]+)(?:\/(\d+)|-([.:\da-f]+)|)$/i.exec(x); // parse cidr or range if (!m) throw x; // we don't support wildcards in this case const address = (0, cross_1.try_)(() => parseAddress(m[1]), () => { throw m[1]; }); if (!address) continue; if (m[2]) try { bl.addSubnet(address, Number(m[2])); } catch (_b) { throw x; } else if (m[3]) try { bl.addRange(address, parseAddress(m[2])); } catch (_c) { throw m[2]; } else bl.addAddress(address); } return (ip) => { try { return neg !== bl.check(parseAddress(ip)); } catch (_a) { console.error("invalid address ", ip); return false; } }; } catch (e) { throw "error in net-mask: " + e; } } // can throw ERR_INVALID_ADDRESS function parseAddress(s) { return new node_net_1.SocketAddress({ address: s, family: (0, net_1.isIPv6)(s) ? 'ipv6' : 'ipv4' }); } function same(a, b) { return lodash_1.default.isEqual(a, b); } function asyncGeneratorToReadable(generator) { const iterator = generator[Symbol.asyncIterator](); return new stream_1.Readable({ objectMode: true, destroy() { var _a; void ((_a = iterator.return) === null || _a === void 0 ? void 0 : _a.call(iterator)); }, read() { iterator.next().then(it => { if (it.done) this.emit('ending'); return this.push(it.done ? null : it.value); }); } }); } // produces as promises resolve, not sequentially class AsapStream extends stream_1.Readable { constructor(promises) { super({ objectMode: true }); this.promises = promises; this.finished = false; } _read() { if (this.finished) return; this.finished = true; for (const p of this.promises) p.then(x => x !== undefined && this.push(x), e => this.emit('error', e)); Promise.allSettled(this.promises).then(() => this.push(null)); } } exports.AsapStream = AsapStream; function apiAssertTypes(paramsByType) { for (const [types, params] of Object.entries(paramsByType)) for (const [name, val] of Object.entries(params)) if (!types.split('_').some(type => type === 'array' ? Array.isArray(val) : typeof val === type)) throw new apiMiddleware_1.ApiError(const_1.HTTP_BAD_REQUEST, 'bad ' + name); } function createStreamLimiter(limit) { let got = 0; return new stream_1.Transform({ transform(chunk, enc, done) { const left = limit - got; got += chunk.length; if (left > 0) { this.push(chunk.length > left ? chunk.slice(0, left) : chunk); if (got >= limit) this.end(); } done(); } }); }