UNPKG

ness

Version:

✪ No-effort static sites deployed to your AWS account.

256 lines 30.1 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.generateCsp = void 0; const fs = __importStar(require("fs-extra")); const path = __importStar(require("path")); const crypto = __importStar(require("crypto")); const url_1 = require("url"); const got_1 = __importDefault(require("got")); const cheerio = __importStar(require("cheerio")); const css = __importStar(require("css")); const file_1 = require("./file"); const self = "'self'"; const https = 'https:'; const wss = 'wss:'; const defaultSrc = 'default-src'; const scriptSrc = 'script-src'; const styleSrc = 'style-src'; const fontSrc = 'font-src'; const imgSrc = 'img-src'; const childSrc = 'child-src'; const connectSrc = 'connect-src'; function isUrlSpecialProtocol(url) { try { const protocol = new url_1.URL(url).protocol; return protocol && !/https?/.test(protocol); } catch (_a) { return false; } } function isUrlAbsolute(url) { return url.indexOf('://') > 0 || url.indexOf('//') === 0; } function isUrlRelative(url) { return !isUrlAbsolute(url); } function extractUrls(value) { const re = /(?:url\(['"]?)(.*?)(?:['"]?\))/g; const urls = []; let match; do { match = re.exec(value); if (match) urls.push(match[1]); } while (match); return urls; } function getRelativePath(entry, url) { return path.resolve(entry, url.replace(/^\//, '')); } function resolveUrl(entry, url) { if (isUrlSpecialProtocol(url) || isUrlAbsolute(url)) return url; return getRelativePath(entry, url); } async function fetchAsset(url) { if (isUrlSpecialProtocol(url)) return undefined; if (isUrlAbsolute(url)) { const { body } = await (0, got_1.default)(url); return body; } else { return fs.readFile(url, 'utf-8'); } } /** * Get settings from local configuration file. * * @param entry Path to the publish directory. */ async function generateCsp(entry) { var _a; const csp = { [defaultSrc]: [self], [scriptSrc]: [self], [styleSrc]: [self], [fontSrc]: [self], [imgSrc]: [self, https], [childSrc]: [https], [connectSrc]: [https, wss], }; const docs = await (0, file_1.walk)(entry, /\.html?$/); const addUrl = (key, url) => { // Handle protocols like blob: and data: if (isUrlSpecialProtocol(url)) { csp[key].push(new url_1.URL(url).protocol); return; } // Already allowing self, so ignore relative paths if (isUrlRelative(url)) return; // Add absolute URL origins csp[key].push(new url_1.URL(url).origin); }; const processStylesheet = async (style, location) => { var _a; const parsed = css.parse(style); const { rules } = parsed.stylesheet || {}; if (!rules) return; const imports = rules.filter((rule) => rule.type === 'import'); for (const cssImport of imports) { const value = cssImport.import || ''; const urls = value.startsWith('url') ? extractUrls(value) : [value.replace(/['"]+/g, '').split(' ')[0]]; for (const url of urls) { try { const root = url.startsWith('/') ? entry : location; const resolvedUrl = resolveUrl(root, url); const style = await fetchAsset(resolvedUrl); if (style) await processStylesheet(style, location); } catch (_b) { } addUrl(styleSrc, url); } } const fontFaces = rules.filter((rule) => rule.type === 'font-face'); for (const fontFace of fontFaces) { // @ts-ignore for (const dec of ((_a = fontFace.declarations) === null || _a === void 0 ? void 0 : _a.filter((dec) => dec.property === 'src')) || []) { // @ts-ignore for (const url of extractUrls(dec.value)) { addUrl(fontSrc, url); } } } const canHaveImageUrl = [ 'background', 'background-image', 'list-style', 'list-style-image', 'content', 'cursor', 'border', 'border-image', 'border-image-source', 'mask', 'mask-image', ]; const imageUrls = rules .filter((rule) => rule) .map((rule) => rule) .flatMap((rule) => rule.declarations) .filter((dec) => dec) .map((dec) => dec) .filter((dec) => dec.value && dec.property && canHaveImageUrl.includes(dec.property)) .flatMap((dec) => extractUrls(dec.value)); for (const imageUrl of imageUrls) { addUrl(imgSrc, imageUrl); } }; for (const doc of docs) { const contents = fs.readFileSync(doc); const $ = cheerio.load(contents); const dir = path.dirname(doc); for (const element of $('script, style').toArray()) { const isScript = element.type === 'script'; const isStyle = element.type === 'style'; const key = isScript ? scriptSrc : styleSrc; const inline = element.children.length > 0; if (inline) { // @ts-ignore const content = (_a = element.firstChild) === null || _a === void 0 ? void 0 : _a.data; const hash = crypto.createHash('sha256').update(content).digest('base64'); csp[key].push(`'sha256-${hash}'`); if (isStyle) { await processStylesheet(content, dir); } continue; } const { src } = element.attribs; if (isStyle) { try { const root = src.startsWith('/') ? entry : dir; const resolvedUrl = resolveUrl(root, src); const style = await fetchAsset(resolvedUrl); if (style) await processStylesheet(style, path.dirname(resolvedUrl)); } catch (_b) { } } else if (isScript && isUrlAbsolute(src) && !element.attribs['integrity']) { // Generate SRI hashes for external scripts const content = await fetchAsset(src); if (content) { const hash = crypto.createHash('sha384').update(content).digest('base64'); element.attribs['integrity'] = `sha384-${hash}`; element.attribs['crossorigin'] = 'anonymous'; } } addUrl(key, src); } for (const element of $('*').toArray()) { const style = element.attribs['style']; if (style) { const hash = crypto.createHash('sha256').update(style).digest('base64'); csp[styleSrc].push("'unsafe-hashes'"); csp[styleSrc].push(`'sha256-${hash}'`); } } for (const link of $('link').toArray()) { if (link.attribs['as'] !== 'stylesheet') continue; const { href } = link.attribs; try { const root = href.startsWith('/') ? entry : dir; const resolvedUrl = resolveUrl(root, href); const style = await fetchAsset(resolvedUrl); if (style) await processStylesheet(style, path.dirname(resolvedUrl)); } catch (_c) { } addUrl(styleSrc, href); } for (const image of $('img').toArray()) { const { src } = image.attribs; addUrl(imgSrc, src); } for (const frame of $('frame, iframe').toArray()) { const { src } = frame.attribs; addUrl(childSrc, src); } fs.writeFileSync(doc, $.html()); } return Object.keys(csp) .filter((key) => csp[key].length > 0) .map((key) => `${key} ${[...new Set(csp[key])].join(' ')}`) .join('; '); } exports.generateCsp = generateCsp; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3NwLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3V0aWxzL2NzcC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsNkNBQThCO0FBQzlCLDJDQUE0QjtBQUM1QiwrQ0FBZ0M7QUFDaEMsNkJBQXVCO0FBRXZCLDhDQUFxQjtBQUNyQixpREFBa0M7QUFDbEMseUNBQTBCO0FBRTFCLGlDQUEyQjtBQUUzQixNQUFNLElBQUksR0FBRyxRQUFRLENBQUE7QUFDckIsTUFBTSxLQUFLLEdBQUcsUUFBUSxDQUFBO0FBQ3RCLE1BQU0sR0FBRyxHQUFHLE1BQU0sQ0FBQTtBQUVsQixNQUFNLFVBQVUsR0FBRyxhQUFhLENBQUE7QUFDaEMsTUFBTSxTQUFTLEdBQUcsWUFBWSxDQUFBO0FBQzlCLE1BQU0sUUFBUSxHQUFHLFdBQVcsQ0FBQTtBQUM1QixNQUFNLE9BQU8sR0FBRyxVQUFVLENBQUE7QUFDMUIsTUFBTSxNQUFNLEdBQUcsU0FBUyxDQUFBO0FBQ3hCLE1BQU0sUUFBUSxHQUFHLFdBQVcsQ0FBQTtBQUM1QixNQUFNLFVBQVUsR0FBRyxhQUFhLENBQUE7QUFFaEMsU0FBUyxvQkFBb0IsQ0FBQyxHQUFXO0lBQ3ZDLElBQUk7UUFDRixNQUFNLFFBQVEsR0FBRyxJQUFJLFNBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxRQUFRLENBQUE7UUFDdEMsT0FBTyxRQUFRLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFBO0tBQzVDO0lBQUMsV0FBTTtRQUNOLE9BQU8sS0FBSyxDQUFBO0tBQ2I7QUFDSCxDQUFDO0FBRUQsU0FBUyxhQUFhLENBQUMsR0FBVztJQUNoQyxPQUFPLEdBQUcsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxJQUFJLEdBQUcsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFBO0FBQzFELENBQUM7QUFFRCxTQUFT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Q0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztTQUMxRCxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUE7QUFDZixDQUFDO0FBaExELGtDQWdMQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGZzIGZyb20gJ2ZzLWV4dHJhJ1xuaW1wb3J0ICogYXMgcGF0aCBmcm9tICdwYXRoJ1xuaW1wb3J0ICogYXMgY3J5cHRvIGZyb20gJ2NyeXB0bydcbmltcG9ydCB7VVJMfSBmcm9tICd1cmwnXG5cbmltcG9ydCBnb3QgZnJvbSAnZ290J1xuaW1wb3J0ICogYXMgY2hlZXJpbyBmcm9tICdjaGVlcmlvJ1xuaW1wb3J0ICogYXMgY3NzIGZyb20gJ2NzcydcblxuaW1wb3J0IHt3YWxrfSBmcm9tICcuL2ZpbGUnXG5cbmNvbnN0IHNlbGYgPSBcIidzZWxmJ1wiXG5jb25zdCBodHRwcyA9ICdodHRwczonXG5jb25zdCB3c3MgPSAnd3NzOidcblxuY29uc3QgZGVmYXVsdFNyYyA9ICdkZWZhdWx0LXNyYydcbmNvbnN0IHNjcmlwdFNyYyA9ICdzY3JpcHQtc3JjJ1xuY29uc3Qgc3R5bGVTcmMgPSAnc3R5bGUtc3JjJ1xuY29uc3QgZm9udFNyYyA9ICdmb250LXNyYydcbmNvbnN0IGltZ1NyYyA9ICdpbWctc3JjJ1xuY29uc3QgY2hpbGRTcmMgPSAnY2hpbGQtc3JjJ1xuY29uc3QgY29ubmVjdFNyYyA9ICdjb25uZWN0LXNyYydcblxuZnVuY3Rpb24gaXNVcmxTcGVjaWFsUHJvdG9jb2wodXJsOiBzdHJpbmcpIHtcbiAgdHJ5IHtcbiAgICBjb25zdCBwcm90b2NvbCA9IG5ldyBVUkwodXJsKS5wcm90b2NvbFxuICAgIHJldHVybiBwcm90b2NvbCAmJiAhL2h0dHBzPy8udGVzdChwcm90b2NvbClcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIGZhbHNlXG4gIH1cbn1cblxuZnVuY3Rpb24gaXNVcmxBYnNvbHV0ZSh1cmw6IHN0cmluZykge1xuICByZXR1cm4gdXJsLmluZGV4T2YoJzovLycpID4gMCB8fCB1cmwuaW5kZXhPZignLy8nKSA9PT0gMFxufVxuXG5mdW5jdGlvbiBpc1VybFJlbGF0aXZlKHVybDogc3RyaW5nKSB7XG4gIHJldHVybiAhaXNVcmxBYnNvbHV0ZSh1cmwpXG59XG5cbmZ1bmN0aW9uIGV4dHJhY3RVcmxzKHZhbHVlOiBzdHJpbmcpIHtcbiAgY29uc3QgcmUgPSAvKD86dXJsXFwoWydcIl0/KSguKj8pKD86WydcIl0/XFwpKS9nXG4gIGNvbnN0IHVybHMgPSBbXVxuXG4gIGxldCBtYXRjaFxuXG4gIGRvIHtcbiAgICBtYXRjaCA9IHJlLmV4ZWModmFsdWUpXG4gICAgaWYgKG1hdGNoKSB1cmxzLnB1c2gobWF0Y2hbMV0pXG4gIH0gd2hpbGUgKG1hdGNoKVxuXG4gIHJldHVybiB1cmxzXG59XG5cbmZ1bmN0aW9uIGdldFJlbGF0aXZlUGF0aChlbnRyeTogc3RyaW5nLCB1cmw6IHN0cmluZykge1xuICByZXR1cm4gcGF0aC5yZXNvbHZlKGVudHJ5LCB1cmwucmVwbGFjZSgvXlxcLy8sICcnKSlcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVVybChlbnRyeTogc3RyaW5nLCB1cmw6IHN0cmluZyk6IHN0cmluZyB7XG4gIGlmIChpc1VybFNwZWNpYWxQcm90b2NvbCh1cmwpIHx8IGlzVXJsQWJzb2x1dGUodXJsKSkgcmV0dXJuIHVybFxuXG4gIHJldHVybiBnZXRSZWxhdGl2ZVBhdGgoZW50cnksIHVybClcbn1cblxuYXN5bmMgZnVuY3Rpb24gZmV0Y2hBc3NldCh1cmw6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nIHwgdW5kZWZpbmVkPiB7XG4gIGlmIChpc1VybFNwZWNpYWxQcm90b2NvbCh1cmwpKSByZXR1cm4gdW5kZWZpbmVkXG5cbiAgaWYgKGlzVXJsQWJzb2x1dGUodXJsKSkge1xuICAgIGNvbnN0IHtib2R5fSA9IGF3YWl0IGdvdCh1cmwpXG4gICAgcmV0dXJuIGJvZHlcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gZnMucmVhZEZpbGUodXJsLCAndXRmLTgnKVxuICB9XG59XG5cbi8qKlxuICogR2V0IHNldHRpbmdzIGZyb20gbG9jYWwgY29uZmlndXJhdGlvbiBmaWxlLlxuICpcbiAqIEBwYXJhbSBlbnRyeSBQYXRoIHRvIHRoZSBwdWJsaXNoIGRpcmVjdG9yeS5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGdlbmVyYXRlQ3NwKGVudHJ5OiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz4ge1xuICBjb25zdCBjc3A6IFJlY29yZDxzdHJpbmcsIEFycmF5PHN0cmluZz4+ID0ge1xuICAgIFtkZWZhdWx0U3JjXTogW3NlbGZdLFxuICAgIFtzY3JpcHRTcmNdOiBbc2VsZl0sXG4gICAgW3N0eWxlU3JjXTogW3NlbGZdLFxuICAgIFtmb250U3JjXTogW3NlbGZdLFxuICAgIFtpbWdTcmNdOiBbc2VsZiwgaHR0cHNdLFxuICAgIFtjaGlsZFNyY106IFtodHRwc10sXG4gICAgW2Nvbm5lY3RTcmNdOiBbaHR0cHMsIHdzc10sXG4gIH1cblxuICBjb25zdCBkb2NzID0gYXdhaXQgd2FsayhlbnRyeSwgL1xcLmh0bWw/JC8pXG5cbiAgY29uc3QgYWRkVXJsID0gKGtleTogc3RyaW5nLCB1cmw6IHN0cmluZykgPT4ge1xuICAgIC8vIEhhbmRsZSBwcm90b2NvbHMgbGlrZSBibG9iOiBhbmQgZGF0YTpcbiAgICBpZiAoaXNVcmxTcGVjaWFsUHJvdG9jb2wodXJsKSkge1xuICAgICAgY3NwW2tleV0ucHVzaChuZXcgVVJMKHVybCkucHJvdG9jb2wpXG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICAvLyBBbHJlYWR5IGFsbG93aW5nIHNlbGYsIHNvIGlnbm9yZSByZWxhdGl2ZSBwYXRoc1xuICAgIGlmIChpc1VybFJlbGF0aXZlKHVybCkpIHJldHVyblxuXG4gICAgLy8gQWRkIGFic29sdXRlIFVSTCBvcmlnaW5zXG4gICAgY3NwW2tleV0ucHVzaChuZXcgVVJMKHVybCkub3JpZ2luKVxuICB9XG5cbiAgY29uc3QgcHJvY2Vzc1N0eWxlc2hlZXQgPSBhc3luYyAoc3R5bGU6IHN0cmluZywgbG9jYXRpb246IHN0cmluZyk6IFByb21pc2U8dm9pZD4gPT4ge1xuICAgIGNvbnN0IHBhcnNlZCA9IGNzcy5wYXJzZShzdHlsZSlcbiAgICBjb25zdCB7cnVsZXN9ID0gcGFyc2VkLnN0eWxlc2hlZXQgfHwge31cbiAgICBpZiAoIXJ1bGVzKSByZXR1cm5cblxuICAgIGNvbnN0IGltcG9ydHM6IGNzcy5JbXBvcnRbXSA9IHJ1bGVzLmZpbHRlcigocnVsZSkgPT4gcnVsZS50eXBlID09PSAnaW1wb3J0JylcbiAgICBmb3IgKGNvbnN0IGNzc0ltcG9ydCBvZiBpbXBvcnRzKSB7XG4gICAgICBjb25zdCB2YWx1ZSA9IGNzc0ltcG9ydC5pbXBvcnQgfHwgJydcbiAgICAgIGNvbnN0IHVybHMgPSB2YWx1ZS5zdGFydHNXaXRoKCd1cmwnKVxuICAgICAgICA/IGV4dHJhY3RVcmxzKHZhbHVlKVxuICAgICAgICA6IFt2YWx1ZS5yZXBsYWNlKC9bJ1wiXSsvZywgJycpLnNwbGl0KCcgJylbMF1dXG5cbiAgICAgIGZvciAoY29uc3QgdXJsIG9mIHVybHMpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCByb290ID0gdXJsLnN0YXJ0c1dpdGgoJy8nKSA/IGVudHJ5IDogbG9jYXRpb25cbiAgICAgICAgICBjb25zdCByZXNvbHZlZFVybCA9IHJlc29sdmVVcmwocm9vdCwgdXJsKVxuICAgICAgICAgIGNvbnN0IHN0eWxlID0gYXdhaXQgZmV0Y2hBc3NldChyZXNvbHZlZFVybClcbiAgICAgICAgICBpZiAoc3R5bGUpIGF3YWl0IHByb2Nlc3NTdHlsZXNoZWV0KHN0eWxlLCBsb2NhdGlvbilcbiAgICAgICAgfSBjYXRjaCB7fVxuXG4gICAgICAgIGFkZFVybChzdHlsZVNyYywgdXJsKVxuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IGZvbnRGYWNlczogY3NzLkZvbnRGYWNlW10gPSBydWxlcy5maWx0ZXIoKHJ1bGUpID0+IHJ1bGUudHlwZSA9PT0gJ2ZvbnQtZmFjZScpXG4gICAgZm9yIChjb25zdCBmb250RmFjZSBvZiBmb250RmFjZXMpIHtcbiAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgIGZvciAoY29uc3QgZGVjIG9mIGZvbnRGYWNlLmRlY2xhcmF0aW9ucz8uZmlsdGVyKChkZWMpID0+IGRlYy5wcm9wZXJ0eSA9PT0gJ3NyYycpIHx8IFtdKSB7XG4gICAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgICAgZm9yIChjb25zdCB1cmwgb2YgZXh0cmFjdFVybHMoZGVjLnZhbHVlKSkge1xuICAgICAgICAgIGFkZFVybChmb250U3JjLCB1cmwpXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBjYW5IYXZlSW1hZ2VVcmwgPSBbXG4gICAgICAnYmFja2dyb3VuZCcsXG4gICAgICAnYmFja2dyb3VuZC1pbWFnZScsXG4gICAgICAnbGlzdC1zdHlsZScsXG4gICAgICAnbGlzdC1zdHlsZS1pbWFnZScsXG4gICAgICAnY29udGVudCcsXG4gICAgICAnY3Vyc29yJyxcbiAgICAgICdib3JkZXInLFxuICAgICAgJ2JvcmRlci1pbWFnZScsXG4gICAgICAnYm9yZGVyLWltYWdlLXNvdXJjZScsXG4gICAgICAnbWFzaycsXG4gICAgICAnbWFzay1pbWFnZScsXG4gICAgXVxuXG4gICAgY29uc3QgaW1hZ2VVcmxzID0gcnVsZXNcbiAgICAgIC5maWx0ZXIoKHJ1bGUpID0+IHJ1bGUgYXMgY3NzLlJ1bGUpXG4gICAgICAubWFwKChydWxlKSA9PiBydWxlIGFzIGNzcy5SdWxlKVxuICAgICAgLmZsYXRNYXAoKHJ1bGUpID0+IHJ1bGUuZGVjbGFyYXRpb25zKVxuICAgICAgLmZpbHRlcigoZGVjKSA9PiBkZWMgYXMgY3NzLkRlY2xhcmF0aW9uKVxuICAgICAgLm1hcCgoZGVjKSA9PiBkZWMgYXMgY3NzLkRlY2xhcmF0aW9uKVxuICAgICAgLmZpbHRlcigoZGVjKSA9PiBkZWMudmFsdWUgJiYgZGVjLnByb3BlcnR5ICYmIGNhbkhhdmVJbWFnZVVybC5pbmNsdWRlcyhkZWMucHJvcGVydHkpKVxuICAgICAgLmZsYXRNYXAoKGRlYykgPT4gZXh0cmFjdFVybHMoZGVjLnZhbHVlISkpXG5cbiAgICBmb3IgKGNvbnN0IGltYWdlVXJsIG9mIGltYWdlVXJscykge1xuICAgICAgYWRkVXJsKGltZ1NyYywgaW1hZ2VVcmwpXG4gICAgfVxuICB9XG5cbiAgZm9yIChjb25zdCBkb2Mgb2YgZG9jcykge1xuICAgIGNvbnN0IGNvbnRlbnRzID0gZnMucmVhZEZpbGVTeW5jKGRvYylcbiAgICBjb25zdCAkID0gY2hlZXJpby5sb2FkKGNvbnRlbnRzKVxuICAgIGNvbnN0IGRpciA9IHBhdGguZGlybmFtZShkb2MpXG5cbiAgICBmb3IgKGNvbnN0IGVsZW1lbnQgb2YgJCgnc2NyaXB0LCBzdHlsZScpLnRvQXJyYXkoKSkge1xuICAgICAgY29uc3QgaXNTY3JpcHQgPSBlbGVtZW50LnR5cGUgPT09ICdzY3JpcHQnXG4gICAgICBjb25zdCBpc1N0eWxlID0gZWxlbWVudC50eXBlID09PSAnc3R5bGUnXG4gICAgICBjb25zdCBrZXkgPSBpc1NjcmlwdCA/IHNjcmlwdFNyYyA6IHN0eWxlU3JjXG5cbiAgICAgIGNvbnN0IGlubGluZSA9IGVsZW1lbnQuY2hpbGRyZW4ubGVuZ3RoID4gMFxuICAgICAgaWYgKGlubGluZSkge1xuICAgICAgICAvLyBAdHMtaWdub3JlXG4gICAgICAgIGNvbnN0IGNvbnRlbnQgPSBlbGVtZW50LmZpcnN0Q2hpbGQ/LmRhdGFcbiAgICAgICAgY29uc3QgaGFzaCA9IGNyeXB0by5jcmVhdGVIYXNoKCdzaGEyNTYnKS51cGRhdGUoY29udGVudCkuZGlnZXN0KCdiYXNlNjQnKVxuICAgICAgICBjc3Bba2V5XS5wdXNoKGAnc2hhMjU2LSR7aGFzaH0nYClcblxuICAgICAgICBpZiAoaXNTdHlsZSkge1xuICAgICAgICAgIGF3YWl0IHByb2Nlc3NTdHlsZXNoZWV0KGNvbnRlbnQsIGRpcilcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHtzcmN9ID0gZWxlbWVudC5hdHRyaWJzXG5cbiAgICAgIGlmIChpc1N0eWxlKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3Qgcm9vdCA9IHNyYy5zdGFydHNXaXRoKCcvJykgPyBlbnRyeSA6IGRpclxuICAgICAgICAgIGNvbnN0IHJlc29sdmVkVXJsID0gcmVzb2x2ZVVybChyb290LCBzcmMpXG4gICAgICAgICAgY29uc3Qgc3R5bGUgPSBhd2FpdCBmZXRjaEFzc2V0KHJlc29sdmVkVXJsKVxuICAgICAgICAgIGlmIChzdHlsZSkgYXdhaXQgcHJvY2Vzc1N0eWxlc2hlZXQoc3R5bGUsIHBhdGguZGlybmFtZShyZXNvbHZlZFVybCkpXG4gICAgICAgIH0gY2F0Y2gge31cbiAgICAgIH0gZWxzZSBpZiAoaXNTY3JpcHQgJiYgaXNVcmxBYnNvbHV0ZShzcmMpICYmICFlbGVtZW50LmF0dHJpYnNbJ2ludGVncml0eSddKSB7XG4gICAgICAgIC8vIEdlbmVyYXRlIFNSSSBoYXNoZXMgZm9yIGV4dGVybmFsIHNjcmlwdHNcbiAgICAgICAgY29uc3QgY29udGVudCA9IGF3YWl0IGZldGNoQXNzZXQoc3JjKVxuICAgICAgICBpZiAoY29udGVudCkge1xuICAgICAgICAgIGNvbnN0IGhhc2ggPSBjcnlwdG8uY3JlYXRlSGFzaCgnc2hhMzg0JykudXBkYXRlKGNvbnRlbnQpLmRpZ2VzdCgnYmFzZTY0JylcbiAgICAgICAgICBlbGVtZW50LmF0dHJpYnNbJ2ludGVncml0eSddID0gYHNoYTM4NC0ke2hhc2h9YFxuICAgICAgICAgIGVsZW1lbnQuYXR0cmlic1snY3Jvc3NvcmlnaW4nXSA9ICdhbm9ueW1vdXMnXG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgYWRkVXJsKGtleSwgc3JjKVxuICAgIH1cblxuICAgIGZvciAoY29uc3QgZWxlbWVudCBvZiAkKCcqJykudG9BcnJheSgpKSB7XG4gICAgICBjb25zdCBzdHlsZSA9IGVsZW1lbnQuYXR0cmlic1snc3R5bGUnXVxuICAgICAgaWYgKHN0eWxlKSB7XG4gICAgICAgIGNvbnN0IGhhc2ggPSBjcnlwdG8uY3JlYXRlSGFzaCgnc2hhMjU2JykudXBkYXRlKHN0eWxlKS5kaWdlc3QoJ2Jhc2U2NCcpXG4gICAgICAgIGNzcFtzdHlsZVNyY10ucHVzaChcIid1bnNhZmUtaGFzaGVzJ1wiKVxuICAgICAgICBjc3Bbc3R5bGVTcmNdLnB1c2goYCdzaGEyNTYtJHtoYXNofSdgKVxuICAgICAgfVxuICAgIH1cblxuICAgIGZvciAoY29uc3QgbGluayBvZiAkKCdsaW5rJykudG9BcnJheSgpKSB7XG4gICAgICBpZiAobGluay5hdHRyaWJzWydhcyddICE9PSAnc3R5bGVzaGVldCcpIGNvbnRpbnVlXG5cbiAgICAgIGNvbnN0IHtocmVmfSA9IGxpbmsuYXR0cmlic1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3Qgcm9vdCA9IGhyZWYuc3RhcnRzV2l0aCgnLycpID8gZW50cnkgOiBkaXJcbiAgICAgICAgY29uc3QgcmVzb2x2ZWRVcmwgPSByZXNvbHZlVXJsKHJvb3QsIGhyZWYpXG4gICAgICAgIGNvbnN0IHN0eWxlID0gYXdhaXQgZmV0Y2hBc3NldChyZXNvbHZlZFVybClcbiAgICAgICAgaWYgKHN0eWxlKSBhd2FpdCBwcm9jZXNzU3R5bGVzaGVldChzdHlsZSwgcGF0aC5kaXJuYW1lKHJlc29sdmVkVXJsKSlcbiAgICAgIH0gY2F0Y2gge31cblxuICAgICAgYWRkVXJsKHN0eWxlU3JjLCBocmVmKVxuICAgIH1cblxuICAgIGZvciAoY29uc3QgaW1hZ2Ugb2YgJCgnaW1nJykudG9BcnJheSgpKSB7XG4gICAgICBjb25zdCB7c3JjfSA9IGltYWdlLmF0dHJpYnNcbiAgICAgIGFkZFVybChpbWdTcmMsIHNyYylcbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IGZyYW1lIG9mICQoJ2ZyYW1lLCBpZnJhbWUnKS50b0FycmF5KCkpIHtcbiAgICAgIGNvbnN0IHtzcmN9ID0gZnJhbWUuYXR0cmlic1xuICAgICAgYWRkVXJsKGNoaWxkU3JjLCBzcmMpXG4gICAgfVxuXG4gICAgZnMud3JpdGVGaWxlU3luYyhkb2MsICQuaHRtbCgpKVxuICB9XG5cbiAgcmV0dXJuIE9iamVjdC5rZXlzKGNzcClcbiAgICAuZmlsdGVyKChrZXkpID0+IGNzcFtrZXldLmxlbmd0aCA+IDApXG4gICAgLm1hcCgoa2V5KSA9PiBgJHtrZXl9ICR7Wy4uLm5ldyBTZXQoY3NwW2tleV0pXS5qb2luKCcgJyl9YClcbiAgICAuam9pbignOyAnKVxufVxuIl19