ness
Version:
✪ No-effort static sites deployed to your AWS account.
256 lines • 30.1 kB
JavaScript
;
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