oidc-client
Version:
OpenID Connect (OIDC) & OAuth2 client library
268 lines (266 loc) • 39.9 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
const source_map_1 = require("source-map");
// Matches <%= expr %>. This does not support structural JavaScript (for/if/...).
const kInterpolateRe = /<%=([\s\S]+?)%>/g;
// Matches <%# text %>. It's a comment and will be entirely ignored.
const kCommentRe = /<%#([\s\S]+?)%>/g;
// Used to match template delimiters.
// <%- expr %>: HTML escape the value.
// <% ... %>: Structural template code.
const kEscapeRe = /<%-([\s\S]+?)%>/g;
const kEvaluateRe = /<%([\s\S]+?)%>/g;
/** Used to map characters to HTML entities. */
const kHtmlEscapes = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": ''',
'`': '`',
};
// Used to match HTML entities and HTML characters.
const reUnescapedHtml = new RegExp(`[${Object.keys(kHtmlEscapes).join('')}]`, 'g');
function _positionFor(content, offset) {
let line = 1;
let column = 0;
for (let i = 0; i < offset - 1; i++) {
if (content[i] == '\n') {
line++;
column = 0;
}
else {
column++;
}
}
return {
line,
column,
};
}
/**
* Given a source text (and a fileName), returns a TemplateAst.
*/
function templateParser(sourceText, fileName) {
const children = [];
// Compile the regexp to match each delimiter.
const reExpressions = [kEscapeRe, kCommentRe, kInterpolateRe, kEvaluateRe];
const reDelimiters = RegExp(reExpressions.map(x => x.source).join('|') + '|$', 'g');
const parsed = sourceText.split(reDelimiters);
let offset = 0;
// Optimization that uses the fact that the end of a node is always the beginning of the next
// node, so we keep the positioning of the nodes in memory.
let start = _positionFor(sourceText, offset);
let end;
const increment = reExpressions.length + 1;
for (let i = 0; i < parsed.length; i += increment) {
const [content, escape, comment, interpolate, evaluate] = parsed.slice(i, i + increment);
if (content) {
end = _positionFor(sourceText, offset + content.length);
offset += content.length;
children.push({ kind: 'content', content, start, end });
start = end;
}
if (escape) {
end = _positionFor(sourceText, offset + escape.length + 5);
offset += escape.length + 5;
children.push({ kind: 'escape', expression: escape, start, end });
start = end;
}
if (comment) {
end = _positionFor(sourceText, offset + comment.length + 5);
offset += comment.length + 5;
children.push({ kind: 'comment', text: comment, start, end });
start = end;
}
if (interpolate) {
end = _positionFor(sourceText, offset + interpolate.length + 5);
offset += interpolate.length + 5;
children.push({
kind: 'interpolate',
expression: interpolate,
start,
end,
});
start = end;
}
if (evaluate) {
end = _positionFor(sourceText, offset + evaluate.length + 5);
offset += evaluate.length + 5;
children.push({ kind: 'evaluate', expression: evaluate, start, end });
start = end;
}
}
return {
fileName,
content: sourceText,
children,
};
}
exports.templateParser = templateParser;
/**
* Fastest implementation of the templating algorithm. It only add strings and does not bother
* with source maps.
*/
function templateFast(ast, options) {
const module = options && options.module ? 'module.exports.default =' : '';
const reHtmlEscape = reUnescapedHtml.source.replace(/[']/g, '\\\\\\\'');
return `
return ${module} function(obj) {
obj || (obj = {});
let __t;
let __p = '';
const __escapes = ${JSON.stringify(kHtmlEscapes)};
const __escapesre = new RegExp('${reHtmlEscape}', 'g');
const __e = function(s) {
return s ? s.replace(__escapesre, function(key) { return __escapes[key]; }) : '';
};
with (obj) {
${ast.children.map(node => {
switch (node.kind) {
case 'content':
return `__p += ${JSON.stringify(node.content)};`;
case 'interpolate':
return `__p += ((__t = (${node.expression})) == null) ? '' : __t;`;
case 'escape':
return `__p += __e(${node.expression});`;
case 'evaluate':
return node.expression;
}
}).join('\n')}
}
return __p;
};
`;
}
/**
* Templating algorithm with source map support. The map is outputted as //# sourceMapUrl=...
*/
function templateWithSourceMap(ast, options) {
const sourceUrl = ast.fileName;
const module = options && options.module ? 'module.exports.default =' : '';
const reHtmlEscape = reUnescapedHtml.source.replace(/[']/g, '\\\\\\\'');
const preamble = (new source_map_1.SourceNode(1, 0, sourceUrl, ''))
.add(new source_map_1.SourceNode(1, 0, sourceUrl, [
`return ${module} function(obj) {\n`,
' obj || (obj = {});\n',
' let __t;\n',
' let __p = "";\n',
` const __escapes = ${JSON.stringify(kHtmlEscapes)};\n`,
` const __escapesre = new RegExp('${reHtmlEscape}', 'g');\n`,
`\n`,
` const __e = function(s) { `,
` return s ? s.replace(__escapesre, function(key) { return __escapes[key]; }) : '';`,
` };\n`,
` with (obj) {\n`,
]));
const end = ast.children.length
? ast.children[ast.children.length - 1].end
: { line: 0, column: 0 };
const nodes = ast.children.reduce((chunk, node) => {
let code = '';
switch (node.kind) {
case 'content':
code = [
new source_map_1.SourceNode(node.start.line, node.start.column, sourceUrl, '__p = __p'),
...node.content.split('\n').map((line, i, arr) => {
return new source_map_1.SourceNode(node.start.line + i, i == 0 ? node.start.column : 0, sourceUrl, '\n + '
+ JSON.stringify(line + (i == arr.length - 1 ? '' : '\n')));
}),
new source_map_1.SourceNode(node.end.line, node.end.column, sourceUrl, ';\n'),
];
break;
case 'interpolate':
code = [
new source_map_1.SourceNode(node.start.line, node.start.column, sourceUrl, '__p += ((__t = '),
...node.expression.split('\n').map((line, i, arr) => {
return new source_map_1.SourceNode(node.start.line + i, i == 0 ? node.start.column : 0, sourceUrl, line + ((i == arr.length - 1) ? '' : '\n'));
}),
new source_map_1.SourceNode(node.end.line, node.end.column, sourceUrl, ') == null ? "" : __t);\n'),
];
break;
case 'escape':
code = [
new source_map_1.SourceNode(node.start.line, node.start.column, sourceUrl, '__p += __e('),
...node.expression.split('\n').map((line, i, arr) => {
return new source_map_1.SourceNode(node.start.line + i, i == 0 ? node.start.column : 0, sourceUrl, line + ((i == arr.length - 1) ? '' : '\n'));
}),
new source_map_1.SourceNode(node.end.line, node.end.column, sourceUrl, ');\n'),
];
break;
case 'evaluate':
code = [
...node.expression.split('\n').map((line, i, arr) => {
return new source_map_1.SourceNode(node.start.line + i, i == 0 ? node.start.column : 0, sourceUrl, line + ((i == arr.length - 1) ? '' : '\n'));
}),
new source_map_1.SourceNode(node.end.line, node.end.column, sourceUrl, '\n'),
];
break;
}
return chunk.add(new source_map_1.SourceNode(node.start.line, node.start.column, sourceUrl, code));
}, preamble)
.add(new source_map_1.SourceNode(end.line, end.column, sourceUrl, [
' };\n',
'\n',
' return __p;\n',
'}\n',
]));
const code = nodes.toStringWithSourceMap({
file: sourceUrl,
sourceRoot: options && options.sourceRoot || '.',
});
// Set the source content in the source map, otherwise the sourceUrl is not enough
// to find the content.
code.map.setSourceContent(sourceUrl, ast.content);
return code.code
+ '\n//# sourceMappingURL=data:application/json;base64,'
+ Buffer.from(code.map.toString()).toString('base64');
}
/**
* An equivalent of EJS templates, which is based on John Resig's `tmpl` implementation
* (http://ejohn.org/blog/javascript-micro-templating/) and Laura Doktorova's doT.js
* (https://github.com/olado/doT).
*
* This version differs from lodash by removing support from ES6 quasi-literals, and making the
* code slightly simpler to follow. It also does not depend on any third party, which is nice.
*
* Finally, it supports SourceMap, if you ever need to debug, which is super nice.
*
* @param content The template content.
* @param options Optional Options. See TemplateOptions for more description.
* @return {(input: T) => string} A function that accept an input object and returns the content
* of the template with the input applied.
*/
function template(content, options) {
const sourceUrl = options && options.sourceURL || 'ejs';
const ast = templateParser(content, sourceUrl);
let source;
// If there's no need for source map support, we revert back to the fast implementation.
if (options && options.sourceMap) {
source = templateWithSourceMap(ast, options);
}
else {
source = templateFast(ast, options);
}
// We pass a dummy module in case the module option is passed. If `module: true` is passed, we
// need to only use the source, not the function itself. Otherwise expect a module object to be
// passed, and we use that one.
const fn = Function('module', source);
const module = options && options.module
? (options.module === true ? { exports: {} } : options.module)
: null;
const result = fn(module);
// Provide the compiled function's source by its `toString` method or
// the `source` property as a convenience for inlining compiled templates.
result.source = source;
return result;
}
exports.template = template;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVtcGxhdGUuanMiLCJzb3VyY2VSb290IjoiLi8iLCJzb3VyY2VzIjpbInBhY2thZ2VzL2FuZ3VsYXJfZGV2a2l0L2NvcmUvc3JjL3V0aWxzL3RlbXBsYXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUE7Ozs7OztHQU1HO0FBQ0gsMkNBQWtEO0FBRWxELGlGQUFpRjtBQUNqRixNQUFNLGNBQWMsR0FBRyxrQkFBa0IsQ0FBQztBQUMxQyxvRUFBb0U7QUFDcEUsTUFBTSxVQUFVLEdBQUcsa0JBQWtCLENBQUM7QUFFdEMscUNBQXFDO0FBQ3JDLHNDQUFzQztBQUN0Qyx1Q0FBdUM7QUFDdkMsTUFBTSxTQUFTLEdBQUcsa0JBQWtCLENBQUM7QUFDckMsTUFBTSxXQUFXLEdBQUcsaUJBQWlCLENBQUM7QUFFdEMsK0NBQStDO0FBQy9DLE1BQU0sWUFBWSxHQUE2QjtJQUM3QyxHQUFHLEVBQUUsT0FBTztJQUNaLEdBQUcsRUFBRSxNQUFNO0lBQ1gsR0FBRyxFQUFFLE1BQU07SUFDWCxHQUFHLEVBQUUsUUFBUTtJQUNiLEdBQUcsRUFBRSxPQUFPO0lBQ1osR0FBRyxFQUFFLE9BQU87Q0FDYixDQUFDO0FBRUYsbURBQW1EO0FBQ25ELE1BQU0sZUFBZSxHQUFHLElBQUksTUFBTSxDQUFDLElBQUksTUFBTSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsQ0FBQztBQVluRixTQUFTLFlBQVksQ0FBQyxPQUFlLEVBQUUsTUFBYztJQUNuRCxJQUFJLElBQUksR0FBRyxDQUFDLENBQUM7SUFDYixJQUFJLE1BQU0sR0FBRyxDQUFDLENBQUM7SUFDZixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRTtRQUNuQyxJQUFJLE9BQU8sQ0FBQyxDQUFDLENBQUMsSUFBSSxJQUFJLEVBQUU7WUFDdEIsSUFBSSxF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cmlnaHQgR29vZ2xlIEluYy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGUgbGljZW5zZSB0aGF0IGNhbiBiZVxuICogZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBhdCBodHRwczovL2FuZ3VsYXIuaW8vbGljZW5zZVxuICovXG5pbXBvcnQgeyBQb3NpdGlvbiwgU291cmNlTm9kZSB9IGZyb20gJ3NvdXJjZS1tYXAnO1xuXG4vLyBNYXRjaGVzIDwlPSBleHByICU+LiBUaGlzIGRvZXMgbm90IHN1cHBvcnQgc3RydWN0dXJhbCBKYXZhU2NyaXB0IChmb3IvaWYvLi4uKS5cbmNvbnN0IGtJbnRlcnBvbGF0ZVJlID0gLzwlPShbXFxzXFxTXSs/KSU+L2c7XG4vLyBNYXRjaGVzIDwlIyB0ZXh0ICU+LiBJdCdzIGEgY29tbWVudCBhbmQgd2lsbCBiZSBlbnRpcmVseSBpZ25vcmVkLlxuY29uc3Qga0NvbW1lbnRSZSA9IC88JSMoW1xcc1xcU10rPyklPi9nO1xuXG4vLyBVc2VkIHRvIG1hdGNoIHRlbXBsYXRlIGRlbGltaXRlcnMuXG4vLyA8JS0gZXhwciAlPjogSFRNTCBlc2NhcGUgdGhlIHZhbHVlLlxuLy8gPCUgLi4uICU+OiBTdHJ1Y3R1cmFsIHRlbXBsYXRlIGNvZGUuXG5jb25zdCBrRXNjYXBlUmUgPSAvPCUtKFtcXHNcXFNdKz8pJT4vZztcbmNvbnN0IGtFdmFsdWF0ZVJlID0gLzwlKFtcXHNcXFNdKz8pJT4vZztcblxuLyoqIFVzZWQgdG8gbWFwIGNoYXJhY3RlcnMgdG8gSFRNTCBlbnRpdGllcy4gKi9cbmNvbnN0IGtIdG1sRXNjYXBlczoge1tjaGFyOiBzdHJpbmddOiBzdHJpbmd9ID0ge1xuICAnJic6ICcmYW1wOycsXG4gICc8JzogJyZsdDsnLFxuICAnPic6ICcmZ3Q7JyxcbiAgJ1wiJzogJyZxdW90OycsXG4gIFwiJ1wiOiAnJiMzOTsnLFxuICAnYCc6ICcmIzk2OycsXG59O1xuXG4vLyBVc2VkIHRvIG1hdGNoIEhUTUwgZW50aXRpZXMgYW5kIEhUTUwgY2hhcmFjdGVycy5cbmNvbnN0IHJlVW5lc2NhcGVkSHRtbCA9IG5ldyBSZWdFeHAoYFske09iamVjdC5rZXlzKGtIdG1sRXNjYXBlcykuam9pbignJyl9XWAsICdnJyk7XG5cbi8vIE9wdGlvbnMgdG8gcGFzcyB0byB0ZW1wbGF0ZS5cbmV4cG9ydCBpbnRlcmZhY2UgVGVtcGxhdGVPcHRpb25zIHtcbiAgc291cmNlVVJMPzogc3RyaW5nO1xuICBzb3VyY2VNYXA/OiBib29sZWFuO1xuICBtb2R1bGU/OiBib29sZWFuIHwgeyBleHBvcnRzOiB7fSB9O1xuICBzb3VyY2VSb290Pzogc3RyaW5nO1xuICBmaWxlTmFtZT86IHN0cmluZztcbn1cblxuXG5mdW5jdGlvbiBfcG9zaXRpb25Gb3IoY29udGVudDogc3RyaW5nLCBvZmZzZXQ6IG51bWJlcik6IFBvc2l0aW9uIHtcbiAgbGV0IGxpbmUgPSAxO1xuICBsZXQgY29sdW1uID0gMDtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBvZmZzZXQgLSAxOyBpKyspIHtcbiAgICBpZiAoY29udGVudFtpXSA9PSAnXFxuJykge1xuICAgICAgbGluZSsrO1xuICAgICAgY29sdW1uID0gMDtcbiAgICB9IGVsc2Uge1xuICAgICAgY29sdW1uKys7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBsaW5lLFxuICAgIGNvbHVtbixcbiAgfTtcbn1cblxuLyoqXG4gKiBBIHNpbXBsZSBBU1QgZm9yIHRlbXBsYXRlcy4gVGhlcmUncyBvbmx5IG9uZSBsZXZlbCBvZiBBU1Qgbm9kZXMsIGJ1dCBpdCdzIHN0aWxsIHVzZWZ1bFxuICogdG8gaGF2ZSB0aGUgaW5mb3JtYXRpb24geW91J3JlIGxvb2tpbmcgZm9yLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFRlbXBsYXRlQXN0IHtcbiAgZmlsZU5hbWU6IHN0cmluZztcbiAgY29udGVudDogc3RyaW5nO1xuICBjaGlsZHJlbjogVGVtcGxhdGVBc3ROb2RlW107XG59XG5cbi8qKlxuICogVGhlIGJhc2UsIHdoaWNoIGNvbnRhaW5zIHBvc2l0aW9ucy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBUZW1wbGF0ZUFzdEJhc2Uge1xuICBzdGFydDogUG9zaXRpb247XG4gIGVuZDogUG9zaXRpb247XG59XG5cbi8qKlxuICogQSBzdGF0aWMgY29udGVudCBub2RlLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFRlbXBsYXRlQXN0Q29udGVudCBleHRlbmRzIFRlbXBsYXRlQXN0QmFzZSB7XG4gIGtpbmQ6ICdjb250ZW50JztcbiAgY29udGVudDogc3RyaW5nO1xufVxuXG4vKipcbiAqIEEgY29tbWVudCBub2RlLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFRlbXBsYXRlQXN0Q29tbWVudCBleHRlbmRzIFRlbXBsYXRlQXN0QmFzZSB7XG4gIGtpbmQ6ICdjb21tZW50JztcbiAgdGV4dDogc3RyaW5nO1xufVxuXG4vKipcbiAqIEFuIGV2YWx1YXRlIG5vZGUsIHdoaWNoIGlzIHRoZSBjb2RlIGJldHdlZW4gYDwlIC4uLiAlPmAuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgVGVtcGxhdGVBc3RFdmFsdWF0ZSBleHRlbmRzIFRlbXBsYXRlQXN0QmFzZSB7XG4gIGtpbmQ6ICdldmFsdWF0ZSc7XG4gIGV4cHJlc3Npb246IHN0cmluZztcbn1cblxuLyoqXG4gKiBBbiBlc2NhcGUgbm9kZSwgd2hpY2ggaXMgdGhlIGNvZGUgYmV0d2VlbiBgPCUtIC4uLiAlPmAuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgVGVtcGxhdGVBc3RFc2NhcGUgZXh0ZW5kcyBUZW1wbGF0ZUFzdEJhc2Uge1xuICBraW5kOiAnZXNjYXBlJztcbiAgZXhwcmVzc2lvbjogc3RyaW5nO1xufVxuXG4vKipcbiAqIEFuIGludGVycG9sYXRpb24gbm9kZSwgd2hpY2ggaXMgdGhlIGNvZGUgYmV0d2VlbiBgPCU9IC4uLiAlPmAuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgVGVtcGxhdGVBc3RJbnRlcnBvbGF0ZSBleHRlbmRzIFRlbXBsYXRlQXN0QmFzZSB7XG4gIGtpbmQ6ICdpbnRlcnBvbGF0ZSc7XG4gIGV4cHJlc3Npb246IHN0cmluZztcbn1cblxuZXhwb3J0IHR5cGUgVGVtcGxhdGVBc3ROb2RlID0gVGVtcGxhdGVBc3RDb250ZW50XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfCBUZW1wbGF0ZUFzdEV2YWx1YXRlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfCBUZW1wbGF0ZUFzdENvbW1lbnRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IFRlbXBsYXRlQXN0RXNjYXBlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfCBUZW1wbGF0ZUFzdEludGVycG9sYXRlO1xuXG4vKipcbiAqIEdpdmVuIGEgc291cmNlIHRleHQgKGFuZCBhIGZpbGVOYW1lKSwgcmV0dXJucyBhIFRlbXBsYXRlQXN0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gdGVtcGxhdGVQYXJzZXIoc291cmNlVGV4dDogc3RyaW5nLCBmaWxlTmFtZTogc3RyaW5nKTogVGVtcGxhdGVBc3Qge1xuICBjb25zdCBjaGlsZHJlbiA9IFtdO1xuXG4gIC8vIENvbXBpbGUgdGhlIHJlZ2V4cCB0byBtYXRjaCBlYWNoIGRlbGltaXRlci5cbiAgY29uc3QgcmVFeHByZXNzaW9ucyA9IFtrRXNjYXBlUmUsIGtDb21tZW50UmUsIGtJbnRlcnBvbGF0ZVJlLCBrRXZhbHVhdGVSZV07XG4gIGNvbnN0IHJlRGVsaW1pdGVycyA9IFJlZ0V4cChyZUV4cHJlc3Npb25zLm1hcCh4ID0+IHguc291cmNlKS5qb2luKCd8JykgKyAnfCQnLCAnZycpO1xuXG4gIGNvbnN0IHBhcnNlZCA9IHNvdXJjZVRleHQuc3BsaXQocmVEZWxpbWl0ZXJzKTtcbiAgbGV0IG9mZnNldCA9IDA7XG4gIC8vIE9wdGltaXphdGlvbiB0aGF0IHVzZXMgdGhlIGZhY3QgdGhhdCB0aGUgZW5kIG9mIGEgbm9kZSBpcyBhbHdheXMgdGhlIGJlZ2lubmluZyBvZiB0aGUgbmV4dFxuICAvLyBub2RlLCBzbyB3ZSBrZWVwIHRoZSBwb3NpdGlvbmluZyBvZiB0aGUgbm9kZXMgaW4gbWVtb3J5LlxuICBsZXQgc3RhcnQgPSBfcG9zaXRpb25Gb3Ioc291cmNlVGV4dCwgb2Zmc2V0KTtcbiAgbGV0IGVuZDogUG9zaXRpb24gfCBudWxsO1xuXG4gIGNvbnN0IGluY3JlbWVudCA9IHJlRXhwcmVzc2lvbnMubGVuZ3RoICsgMTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBwYXJzZWQubGVuZ3RoOyBpICs9IGluY3JlbWVudCkge1xuICAgIGNvbnN0IFtjb250ZW50LCBlc2NhcGUsIGNvbW1lbnQsIGludGVycG9sYXRlLCBldmFsdWF0ZV0gPSBwYXJzZWQuc2xpY2UoaSwgaSArIGluY3JlbWVudCk7XG4gICAgaWYgKGNvbnRlbnQpIHtcbiAgICAgIGVuZCA9IF9wb3NpdGlvbkZvcihzb3VyY2VUZXh0LCBvZmZzZXQgKyBjb250ZW50Lmxlbmd0aCk7XG4gICAgICBvZmZzZXQgKz0gY29udGVudC5sZW5ndGg7XG4gICAgICBjaGlsZHJlbi5wdXNoKHsga2luZDogJ2NvbnRlbnQnLCBjb250ZW50LCBzdGFydCwgZW5kIH0gYXMgVGVtcGxhdGVBc3RDb250ZW50KTtcbiAgICAgIHN0YXJ0ID0gZW5kO1xuICAgIH1cbiAgICBpZiAoZXNjYXBlKSB7XG4gICAgICBlbmQgPSBfcG9zaXRpb25Gb3Ioc291cmNlVGV4dCwgb2Zmc2V0ICsgZXNjYXBlLmxlbmd0aCArIDUpO1xuICAgICAgb2Zmc2V0ICs9IGVzY2FwZS5sZW5ndGggKyA1O1xuICAgICAgY2hpbGRyZW4ucHVzaCh7IGtpbmQ6ICdlc2NhcGUnLCBleHByZXNzaW9uOiBlc2NhcGUsIHN0YXJ0LCBlbmQgfSBhcyBUZW1wbGF0ZUFzdEVzY2FwZSk7XG4gICAgICBzdGFydCA9IGVuZDtcbiAgICB9XG4gICAgaWYgKGNvbW1lbnQpIHtcbiAgICAgIGVuZCA9IF9wb3NpdGlvbkZvcihzb3VyY2VUZXh0LCBvZmZzZXQgKyBjb21tZW50Lmxlbmd0aCArIDUpO1xuICAgICAgb2Zmc2V0ICs9IGNvbW1lbnQubGVuZ3RoICsgNTtcbiAgICAgIGNoaWxkcmVuLnB1c2goeyBraW5kOiAnY29tbWVudCcsIHRleHQ6IGNvbW1lbnQsIHN0YXJ0LCBlbmQgfSBhcyBUZW1wbGF0ZUFzdENvbW1lbnQpO1xuICAgICAgc3RhcnQgPSBlbmQ7XG4gICAgfVxuICAgIGlmIChpbnRlcnBvbGF0ZSkge1xuICAgICAgZW5kID0gX3Bvc2l0aW9uRm9yKHNvdXJjZVRleHQsIG9mZnNldCArIGludGVycG9sYXRlLmxlbmd0aCArIDUpO1xuICAgICAgb2Zmc2V0ICs9IGludGVycG9sYXRlLmxlbmd0aCArIDU7XG4gICAgICBjaGlsZHJlbi5wdXNoKHtcbiAgICAgICAga2luZDogJ2ludGVycG9sYXRlJyxcbiAgICAgICAgZXhwcmVzc2lvbjogaW50ZXJwb2xhdGUsXG4gICAgICAgIHN0YXJ0LFxuICAgICAgICBlbmQsXG4gICAgICB9IGFzIFRlbXBsYXRlQXN0SW50ZXJwb2xhdGUpO1xuICAgICAgc3RhcnQgPSBlbmQ7XG4gICAgfVxuICAgIGlmIChldmFsdWF0ZSkge1xuICAgICAgZW5kID0gX3Bvc2l0aW9uRm9yKHNvdXJjZVRleHQsIG9mZnNldCArIGV2YWx1YXRlLmxlbmd0aCArIDUpO1xuICAgICAgb2Zmc2V0ICs9IGV2YWx1YXRlLmxlbmd0aCArIDU7XG4gICAgICBjaGlsZHJlbi5wdXNoKHsga2luZDogJ2V2YWx1YXRlJywgZXhwcmVzc2lvbjogZXZhbHVhdGUsIHN0YXJ0LCBlbmQgfSBhcyBUZW1wbGF0ZUFzdEV2YWx1YXRlKTtcbiAgICAgIHN0YXJ0ID0gZW5kO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB7XG4gICAgZmlsZU5hbWUsXG4gICAgY29udGVudDogc291cmNlVGV4dCxcbiAgICBjaGlsZHJlbixcbiAgfTtcbn1cblxuLyoqXG4gKiBGYXN0ZXN0IGltcGxlbWVudGF0aW9uIG9mIHRoZSB0ZW1wbGF0aW5nIGFsZ29yaXRobS4gSXQgb25seSBhZGQgc3RyaW5ncyBhbmQgZG9lcyBub3QgYm90aGVyXG4gKiB3aXRoIHNvdXJjZSBtYXBzLlxuICovXG5mdW5jdGlvbiB0ZW1wbGF0ZUZhc3QoYXN0OiBUZW1wbGF0ZUFzdCwgb3B0aW9ucz86IFRlbXBsYXRlT3B0aW9ucyk6IHN0cmluZyB7XG4gIGNvbnN0IG1vZHVsZSA9IG9wdGlvbnMgJiYgb3B0aW9ucy5tb2R1bGUgPyAnbW9kdWxlLmV4cG9ydHMuZGVmYXVsdCA9JyA6ICcnO1xuICBjb25zdCByZUh0bWxFc2NhcGUgPSByZVVuZXNjYXBlZEh0bWwuc291cmNlLnJlcGxhY2UoL1snXS9nLCAnXFxcXFxcXFxcXFxcXFwnJyk7XG5cbiAgcmV0dXJuIGBcbiAgICByZXR1cm4gJHttb2R1bGV9IGZ1bmN0aW9uKG9iaikge1xuICAgICAgb2JqIHx8IChvYmogPSB7fSk7XG4gICAgICBsZXQgX190O1xuICAgICAgbGV0IF9fcCA9ICcnO1xuICAgICAgY29uc3QgX19lc2NhcGVzID0gJHtKU09OLnN0cmluZ2lmeShrSHRtbEVzY2FwZXMpfTtcbiAgICAgIGNvbnN0IF9fZXNjYXBlc3JlID0gbmV3IFJlZ0V4cCgnJHtyZUh0bWxFc2NhcGV9JywgJ2cnKTtcblxuICAgICAgY29uc3QgX19lID0gZnVuY3Rpb24ocykge1xuICAgICAgICByZXR1cm4gcyA/IHMucmVwbGFjZShfX2VzY2FwZXNyZSwgZnVuY3Rpb24oa2V5KSB7IHJldHVybiBfX2VzY2FwZXNba2V5XTsgfSkgOiAnJztcbiAgICAgIH07XG4gICAgICB3aXRoIChvYmopIHtcbiAgICAgICAgJHthc3QuY2hpbGRyZW4ubWFwKG5vZGUgPT4ge1xuICAgICAgICAgICAgc3dpdGNoIChub2RlLmtpbmQpIHtcbiAgICAgICAgICAgICAgY2FzZSAnY29udGVudCc6XG4gICAgICAgICAgICAgICAgcmV0dXJuIGBfX3AgKz0gJHtKU09OLnN0cmluZ2lmeShub2RlLmNvbnRlbnQpfTtgO1xuICAgICAgICAgICAgICBjYXNlICdpbnRlcnBvbGF0ZSc6XG4gICAgICAgICAgICAgICAgcmV0dXJuIGBfX3AgKz0gKChfX3QgPSAoJHtub2RlLmV4cHJlc3Npb259KSkgPT0gbnVsbCkgPyAnJyA6IF9fdDtgO1xuICAgICAgICAgICAgICBjYXNlICdlc2NhcGUnOlxuICAgICAgICAgICAgICAgIHJldHVybiBgX19wICs9IF9fZSgke25vZGUuZXhwcmVzc2lvbn0pO2A7XG4gICAgICAgICAgICAgIGNhc2UgJ2V2YWx1YXRlJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gbm9kZS5leHByZXNzaW9uO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pLmpvaW4oJ1xcbicpXG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIF9fcDtcbiAgICB9O1xuICBgO1xufVxuXG4vKipcbiAqIFRlbXBsYXRpbmcgYWxnb3JpdGhtIHdpdGggc291cmNlIG1hcCBzdXBwb3J0LiBUaGUgbWFwIGlzIG91dHB1dHRlZCBhcyAvLyMgc291cmNlTWFwVXJsPS4uLlxuICovXG5mdW5jdGlvbiB0ZW1wbGF0ZVdpdGhTb3VyY2VNYXAoYXN0OiBUZW1wbGF0ZUFzdCwgb3B0aW9ucz86IFRlbXBsYXRlT3B0aW9ucyk6IHN0cmluZyB7XG4gIGNvbnN0IHNvdXJjZVVybCA9IGFzdC5maWxlTmFtZTtcbiAgY29uc3QgbW9kdWxlID0gb3B0aW9ucyAmJiBvcHRpb25zLm1vZHVsZSA/ICdtb2R1bGUuZXhwb3J0cy5kZWZhdWx0ID0nIDogJyc7XG4gIGNvbnN0IHJlSHRtbEVzY2FwZSA9IHJlVW5lc2NhcGVkSHRtbC5zb3VyY2UucmVwbGFjZSgvWyddL2csICdcXFxcXFxcXFxcXFxcXCcnKTtcblxuICBjb25zdCBwcmVhbWJsZSA9IChuZXcgU291cmNlTm9kZSgxLCAwLCBzb3VyY2VVcmwsICcnKSlcbiAgICAuYWRkKG5ldyBTb3VyY2VOb2RlKDEsIDAsIHNvdXJjZVVybCwgW1xuICAgICAgYHJldHVybiAke21vZHVsZX0gZnVuY3Rpb24ob2JqKSB7XFxuYCxcbiAgICAgICcgIG9iaiB8fCAob2JqID0ge30pO1xcbicsXG4gICAgICAnICBsZXQgX190O1xcbicsXG4gICAgICAnICBsZXQgX19wID0gXCJcIjtcXG4nLFxuICAgICAgYCAgY29uc3QgX19lc2NhcGVzID0gJHtKU09OLnN0cmluZ2lmeShrSHRtbEVzY2FwZXMpfTtcXG5gLFxuICAgICAgYCAgY29uc3QgX19lc2NhcGVzcmUgPSBuZXcgUmVnRXhwKCcke3JlSHRtbEVzY2FwZX0nLCAnZycpO1xcbmAsXG4gICAgICBgXFxuYCxcbiAgICAgIGAgIGNvbnN0IF9fZSA9IGZ1bmN0aW9uKHMpIHsgYCxcbiAgICAgIGAgICAgcmV0dXJuIHMgPyBzLnJlcGxhY2UoX19lc2NhcGVzcmUsIGZ1bmN0aW9uKGtleSkgeyByZXR1cm4gX19lc2NhcGVzW2tleV07IH0pIDogJyc7YCxcbiAgICAgIGAgIH07XFxuYCxcbiAgICAgIGAgIHdpdGggKG9iaikge1xcbmAsXG4gICAgXSkpO1xuXG4gIGNvbnN0IGVuZCA9IGFzdC5jaGlsZHJlbi5sZW5ndGhcbiAgICA/IGFzdC5jaGlsZHJlblthc3QuY2hpbGRyZW4ubGVuZ3RoIC0gMV0uZW5kXG4gICAgOiB7IGxpbmU6IDAsIGNvbHVtbjogMCB9O1xuICBjb25zdCBub2RlcyA9IGFzdC5jaGlsZHJlbi5yZWR1Y2UoKGNodW5rLCBub2RlKSA9PiB7XG4gICAgbGV0IGNvZGU6IHN0cmluZyB8IFNvdXJjZU5vZGUgfCAoU291cmNlTm9kZSB8IHN0cmluZylbXSA9ICcnO1xuICAgIHN3aXRjaCAobm9kZS5raW5kKSB7XG4gICAgICBjYXNlICdjb250ZW50JzpcbiAgICAgICAgY29kZSA9IFtcbiAgICAgICAgICBuZXcgU291cmNlTm9kZShub2RlLnN0YXJ0LmxpbmUsIG5vZGUuc3RhcnQuY29sdW1uLCBzb3VyY2VVcmwsICdfX3AgPSBfX3AnKSxcbiAgICAgICAgICAuLi5ub2RlLmNvbnRlbnQuc3BsaXQoJ1xcbicpLm1hcCgobGluZSwgaSwgYXJyKSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IFNvdXJjZU5vZGUoXG4gICAgICAgICAgICAgIG5vZGUuc3RhcnQubGluZSArIGksXG4gICAgICAgICAgICAgIGkgPT0gMCA/IG5vZGUuc3RhcnQuY29sdW1uIDogMCxcbiAgICAgICAgICAgICAgc291cmNlVXJsLFxuICAgICAgICAgICAgICAnXFxuICAgICsgJ1xuICAgICAgICAgICAgICArIEpTT04uc3RyaW5naWZ5KGxpbmUgKyAoaSA9PSBhcnIubGVuZ3RoIC0gMSA/ICcnIDogJ1xcbicpKSxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfSksXG4gICAgICAgICAgbmV3IFNvdXJjZU5vZGUobm9kZS5lbmQubGluZSwgbm9kZS5lbmQuY29sdW1uLCBzb3VyY2VVcmwsICc7XFxuJyksXG4gICAgICAgIF07XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnaW50ZXJwb2xhdGUnOlxuICAgICAgICBjb2RlID0gW1xuICAgICAgICAgIG5ldyBTb3VyY2VOb2RlKG5vZGUuc3RhcnQubGluZSwgbm9kZS5zdGFydC5jb2x1bW4sIHNvdXJjZVVybCwgJ19fcCArPSAoKF9fdCA9ICcpLFxuICAgICAgICAgIC4uLm5vZGUuZXhwcmVzc2lvbi5zcGxpdCgnXFxuJykubWFwKChsaW5lLCBpLCBhcnIpID0+IHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgU291cmNlTm9kZShcbiAgICAgICAgICAgICAgbm9kZS5zdGFydC5saW5lICsgaSxcbiAgICAgICAgICAgICAgaSA9PSAwID8gbm9kZS5zdGFydC5jb2x1bW4gOiAwLFxuICAgICAgICAgICAgICBzb3VyY2VVcmwsXG4gICAgICAgICAgICAgIGxpbmUgKyAoKGkgPT0gYXJyLmxlbmd0aCAtIDEpID8gJycgOiAnXFxuJyksXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH0pLFxuICAgICAgICAgIG5ldyBTb3VyY2VOb2RlKG5vZGUuZW5kLmxpbmUsIG5vZGUuZW5kLmNvbHVtbiwgc291cmNlVXJsLCAnKSA9PSBudWxsID8gXCJcIiA6IF9fdCk7XFxuJyksXG4gICAgICAgIF07XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnZXNjYXBlJzpcbiAgICAgICAgY29kZSA9IFtcbiAgICAgICAgICBuZXcgU291cmNlTm9kZShub2RlLnN0YXJ0LmxpbmUsIG5vZGUuc3RhcnQuY29sdW1uLCBzb3VyY2VVcmwsICdfX3AgKz0gX19lKCcpLFxuICAgICAgICAgIC4uLm5vZGUuZXhwcmVzc2lvbi5zcGxpdCgnXFxuJykubWFwKChsaW5lLCBpLCBhcnIpID0+IHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgU291cmNlTm9kZShcbiAgICAgICAgICAgICAgbm9kZS5zdGFydC5saW5lICsgaSxcbiAgICAgICAgICAgICAgaSA9PSAwID8gbm9kZS5zdGFydC5jb2x1bW4gOiAwLFxuICAgICAgICAgICAgICBzb3VyY2VVcmwsXG4gICAgICAgICAgICAgIGxpbmUgKyAoKGkgPT0gYXJyLmxlbmd0aCAtIDEpID8gJycgOiAnXFxuJyksXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH0pLFxuICAgICAgICAgIG5ldyBTb3VyY2VOb2RlKG5vZGUuZW5kLmxpbmUsIG5vZGUuZW5kLmNvbHVtbiwgc291cmNlVXJsLCAnKTtcXG4nKSxcbiAgICAgICAgXTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdldmFsdWF0ZSc6XG4gICAgICAgIGNvZGUgPSBbXG4gICAgICAgICAgLi4ubm9kZS5leHByZXNzaW9uLnNwbGl0KCdcXG4nKS5tYXAoKGxpbmUsIGksIGFycikgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBTb3VyY2VOb2RlKFxuICAgICAgICAgICAgICBub2RlLnN0YXJ0LmxpbmUgKyBpLFxuICAgICAgICAgICAgICBpID09IDAgPyBub2RlLnN0YXJ0LmNvbHVtbiA6IDAsXG4gICAgICAgICAgICAgIHNvdXJjZVVybCxcbiAgICAgICAgICAgICAgbGluZSArICgoaSA9PSBhcnIubGVuZ3RoIC0gMSkgPyAnJyA6ICdcXG4nKSxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfSksXG4gICAgICAgICAgbmV3IFNvdXJjZU5vZGUobm9kZS5lbmQubGluZSwgbm9kZS5lbmQuY29sdW1uLCBzb3VyY2VVcmwsICdcXG4nKSxcbiAgICAgICAgXTtcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNodW5rLmFkZChuZXcgU291cmNlTm9kZShub2RlLnN0YXJ0LmxpbmUsIG5vZGUuc3RhcnQuY29sdW1uLCBzb3VyY2VVcmwsIGNvZGUpKTtcbiAgfSwgcHJlYW1ibGUpXG4gIC5hZGQobmV3IFNvdXJjZU5vZGUoZW5kLmxpbmUsIGVuZC5jb2x1bW4sIHNvdXJjZVVybCwgW1xuICAgICcgIH07XFxuJyxcbiAgICAnXFxuJyxcbiAgICAnICByZXR1cm4gX19wO1xcbicsXG4gICAgJ31cXG4nLFxuICBdKSk7XG5cbiAgY29uc3QgY29kZSA9IG5vZGVzLnRvU3RyaW5nV2l0aFNvdXJjZU1hcCh7XG4gICAgZmlsZTogc291cmNlVXJsLFxuICAgIHNvdXJjZVJvb3Q6IG9wdGlvbnMgJiYgb3B0aW9ucy5zb3VyY2VSb290IHx8ICcuJyxcbiAgfSk7XG5cbiAgLy8gU2V0IHRoZSBzb3VyY2UgY29udGVudCBpbiB0aGUgc291cmNlIG1hcCwgb3RoZXJ3aXNlIHRoZSBzb3VyY2VVcmwgaXMgbm90IGVub3VnaFxuICAvLyB0byBmaW5kIHRoZSBjb250ZW50LlxuICBjb2RlLm1hcC5zZXRTb3VyY2VDb250ZW50KHNvdXJjZVVybCwgYXN0LmNvbnRlbnQpO1xuXG4gIHJldHVybiBjb2RlLmNvZGVcbiAgICAgICArICdcXG4vLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LCdcbiAgICAgICArIEJ1ZmZlci5mcm9tKGNvZGUubWFwLnRvU3RyaW5nKCkpLnRvU3RyaW5nKCdiYXNlNjQnKTtcbn1cblxuXG4vKipcbiAqIEFuIGVxdWl2YWxlbnQgb2YgRUpTIHRlbXBsYXRlcywgd2hpY2ggaXMgYmFzZWQgb24gSm9obiBSZXNpZydzIGB0bXBsYCBpbXBsZW1lbnRhdGlvblxuICogKGh0dHA6Ly9lam9obi5vcmcvYmxvZy9qYXZhc2NyaXB0LW1pY3JvLXRlbXBsYXRpbmcvKSBhbmQgTGF1cmEgRG9rdG9yb3ZhJ3MgZG9ULmpzXG4gKiAoaHR0cHM6Ly9naXRodWIuY29tL29sYWRvL2RvVCkuXG4gKlxuICogVGhpcyB2ZXJzaW9uIGRpZmZlcnMgZnJvbSBsb2Rhc2ggYnkgcmVtb3Zpbmcgc3VwcG9ydCBmcm9tIEVTNiBxdWFzaS1saXRlcmFscywgYW5kIG1ha2luZyB0aGVcbiAqIGNvZGUgc2xpZ2h0bHkgc2ltcGxlciB0byBmb2xsb3cuIEl0IGFsc28gZG9lcyBub3QgZGVwZW5kIG9uIGFueSB0aGlyZCBwYXJ0eSwgd2hpY2ggaXMgbmljZS5cbiAqXG4gKiBGaW5hbGx5LCBpdCBzdXBwb3J0cyBTb3VyY2VNYXAsIGlmIHlvdSBldmVyIG5lZWQgdG8gZGVidWcsIHdoaWNoIGlzIHN1cGVyIG5pY2UuXG4gKlxuICogQHBhcmFtIGNvbnRlbnQgVGhlIHRlbXBsYXRlIGNvbnRlbnQuXG4gKiBAcGFyYW0gb3B0aW9ucyBPcHRpb25hbCBPcHRpb25zLiBTZWUgVGVtcGxhdGVPcHRpb25zIGZvciBtb3JlIGRlc2NyaXB0aW9uLlxuICogQHJldHVybiB7KGlucHV0OiBUKSA9PiBzdHJpbmd9IEEgZnVuY3Rpb24gdGhhdCBhY2NlcHQgYW4gaW5wdXQgb2JqZWN0IGFuZCByZXR1cm5zIHRoZSBjb250ZW50XG4gKiAgICAgICAgIG9mIHRoZSB0ZW1wbGF0ZSB3aXRoIHRoZSBpbnB1dCBhcHBsaWVkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gdGVtcGxhdGU8VD4oY29udGVudDogc3RyaW5nLCBvcHRpb25zPzogVGVtcGxhdGVPcHRpb25zKTogKGlucHV0OiBUKSA9PiBzdHJpbmcge1xuICBjb25zdCBzb3VyY2VVcmwgPSBvcHRpb25zICYmIG9wdGlvbnMuc291cmNlVVJMIHx8ICdlanMnO1xuICBjb25zdCBhc3QgPSB0ZW1wbGF0ZVBhcnNlcihjb250ZW50LCBzb3VyY2VVcmwpO1xuXG4gIGxldCBzb3VyY2U6IHN0cmluZztcbiAgLy8gSWYgdGhlcmUncyBubyBuZWVkIGZvciBzb3VyY2UgbWFwIHN1cHBvcnQsIHdlIHJldmVydCBiYWNrIHRvIHRoZSBmYXN0IGltcGxlbWVudGF0aW9uLlxuICBpZiAob3B0aW9ucyAmJiBvcHRpb25zLnNvdXJjZU1hcCkge1xuICAgIHNvdXJjZSA9IHRlbXBsYXRlV2l0aFNvdXJjZU1hcChhc3QsIG9wdGlvbnMpO1xuICB9IGVsc2Uge1xuICAgIHNvdXJjZSA9IHRlbXBsYXRlRmFzdChhc3QsIG9wdGlvbnMpO1xuICB9XG5cbiAgLy8gV2UgcGFzcyBhIGR1bW15IG1vZHVsZSBpbiBjYXNlIHRoZSBtb2R1bGUgb3B0aW9uIGlzIHBhc3NlZC4gSWYgYG1vZHVsZTogdHJ1ZWAgaXMgcGFzc2VkLCB3ZVxuICAvLyBuZWVkIHRvIG9ubHkgdXNlIHRoZSBzb3VyY2UsIG5vdCB0aGUgZnVuY3Rpb24gaXRzZWxmLiBPdGhlcndpc2UgZXhwZWN0IGEgbW9kdWxlIG9iamVjdCB0byBiZVxuICAvLyBwYXNzZWQsIGFuZCB3ZSB1c2UgdGhhdCBvbmUuXG4gIGNvbnN0IGZuID0gRnVuY3Rpb24oJ21vZHVsZScsIHNvdXJjZSk7XG4gIGNvbnN0IG1vZHVsZSA9IG9wdGlvbnMgJiYgb3B0aW9ucy5tb2R1bGVcbiAgICAgICAgICAgICAgID8gKG9wdGlvbnMubW9kdWxlID09PSB0cnVlID8geyBleHBvcnRzOiB7fSB9IDogb3B0aW9ucy5tb2R1bGUpXG4gICAgICAgICAgICAgICA6IG51bGw7XG4gIGNvbnN0IHJlc3VsdCA9IGZuKG1vZHVsZSk7XG5cbiAgLy8gUHJvdmlkZSB0aGUgY29tcGlsZWQgZnVuY3Rpb24ncyBzb3VyY2UgYnkgaXRzIGB0b1N0cmluZ2AgbWV0aG9kIG9yXG4gIC8vIHRoZSBgc291cmNlYCBwcm9wZXJ0eSBhcyBhIGNvbnZlbmllbmNlIGZvciBpbmxpbmluZyBjb21waWxlZCB0ZW1wbGF0ZXMuXG4gIHJlc3VsdC5zb3VyY2UgPSBzb3VyY2U7XG5cbiAgcmV0dXJuIHJlc3VsdDtcbn1cbiJdfQ==