Files
pantosite/src/content/.obsidian/plugins/astro-composer/main.js
T
2026-04-11 00:41:28 +02:00

4468 lines
638 KiB
JavaScript

/*
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
if you want to view the source, please visit the github repository of this plugin
*/
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/main.ts
var main_exports = {};
__export(main_exports, {
default: () => AstroComposerPlugin
});
module.exports = __toCommonJS(main_exports);
var import_obsidian14 = require("obsidian");
// src/types.ts
var KNOWN_ARRAY_KEYS = ["tags", "aliases", "cssclasses"];
var CONSTANTS = {
DEBOUNCE_MS: 500,
STAT_MTIME_THRESHOLD: 5e3,
EDITOR_STABILIZE_DELAY: 100,
FILE_EXPLORER_REVEAL_DELAY: 200
};
// src/settings.ts
var DEFAULT_SETTINGS = {
defaultTemplate: '---\ntitle: "{{title}}"\ndate: {{date}}\ntags: []\n---\n',
autoInsertProperties: true,
dateFormat: "YYYY-MM-DD",
enableCopyHeadingLink: true,
copyHeadingLinkFormat: "obsidian",
addTrailingSlashToLinks: false,
enableOpenTerminalCommand: false,
terminalProjectRootPath: "",
terminalApplicationName: "",
enableTerminalDebugLogging: false,
enableTerminalRibbonIcon: false,
enableOpenConfigFileCommand: false,
configFilePath: "",
enableConfigRibbonIcon: false,
contentTypes: [],
migrationCompleted: false,
helpButtonReplacement: {
enabled: false,
commandId: "edit-astro-config",
iconId: "rocket"
},
showMdxFilesInExplorer: false,
processBackgroundFileChanges: true,
syncDraftDate: false,
draftDetectionMode: "property",
draftProperty: "",
draftLogic: "true-is-draft",
publishDateField: "",
renameOnTitleClick: false
};
// src/commands/index.ts
var import_obsidian5 = require("obsidian");
// src/utils/file-operations.ts
var import_obsidian = require("obsidian");
// src/utils/path-matching.ts
function matchesFolderPattern(filePath, folderPattern) {
const normalizedFilePath = filePath.toLowerCase();
const normalizedPattern = folderPattern.toLowerCase().replace(/^\/|\/$/g, "");
if (!normalizedPattern || normalizedPattern.trim() === "") {
return !normalizedFilePath.includes("/") || normalizedFilePath.split("/").length === 1;
}
if (!normalizedPattern.includes("*")) {
return normalizedFilePath === normalizedPattern || normalizedFilePath.startsWith(normalizedPattern + "/");
}
const escapedPattern = normalizedPattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, "[^/]+");
const regexPattern = `^${escapedPattern}(?:/|$)`;
const regex = new RegExp(regexPattern);
return regex.test(normalizedFilePath);
}
function getPatternDepth(folderPattern) {
if (!folderPattern || folderPattern.trim() === "") return 0;
return folderPattern.split("/").length;
}
function sortByPatternSpecificity(types) {
return [...types].sort((a, b) => {
const depthA = getPatternDepth(a.folder);
const depthB = getPatternDepth(b.folder);
return depthB - depthA;
});
}
// src/utils/string-utils.ts
function toKebabCase(str) {
return str.replace(/([a-z0-9])([A-Z])/g, "$1-$2").replace(/([A-Z])([A-Z][a-z])/g, "$1-$2$3").toLowerCase().replace(/[^a-z0-9\s-]/g, "").trim().replace(/\s+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
}
// src/utils/file-operations.ts
var FileOperations = class {
constructor(app, settings, plugin) {
this.app = app;
this.settings = settings;
this.plugin = plugin;
}
// Get fresh settings from plugin if available, otherwise use stored settings
getSettings() {
var _a;
if ((_a = this.plugin) == null ? void 0 : _a.settings) {
return this.plugin.settings;
}
return this.settings;
}
generateFilename(title, enableUnderscorePrefix = false) {
const kebabTitle = toKebabCase(title);
const safeKebabTitle = kebabTitle || "untitled";
const prefix = enableUnderscorePrefix ? "_" : "";
return `${prefix}${safeKebabTitle}`;
}
determineType(file) {
const filePath = file.path;
const settings = this.getSettings();
const contentTypes = settings.contentTypes || [];
const sortedTypes = sortByPatternSpecificity(contentTypes);
for (const contentType of sortedTypes) {
if (!contentType.enabled) continue;
if (!contentType.folder || contentType.folder.trim() === "") {
if (!filePath.includes("/") || filePath.split("/").length === 1) {
return contentType.id;
}
} else if (matchesFolderPattern(filePath, contentType.folder)) {
if (contentType.ignoreSubfolders) {
const pathSegments = filePath.split("/");
const pathDepth = pathSegments.length;
const patternSegments = contentType.folder.split("/");
const expectedDepth = patternSegments.length;
if (contentType.creationMode === "folder") {
const folderDepth = pathDepth - 1;
if (folderDepth === expectedDepth || folderDepth === expectedDepth + 1) {
return contentType.id;
}
} else {
if (pathDepth === expectedDepth) {
return contentType.id;
}
}
} else {
return contentType.id;
}
}
}
return "note";
}
getContentType(typeId) {
const settings = this.getSettings();
const contentTypes = settings.contentTypes || [];
return contentTypes.find((ct) => ct.id === typeId) || null;
}
/**
* Helper to get content type for a given file path
*/
getContentTypeByPath(filePath) {
const dummyFile = { path: filePath };
const typeId = this.determineType(dummyFile);
if (typeId === "note") return null;
return this.getContentType(typeId);
}
getTitleKey(type) {
if (type === "note") return "title";
const contentType = this.getContentType(type);
if (!contentType) return "title";
const template = contentType.template;
const lines = template.split("\n");
let inProperties = false;
for (const line of lines) {
const trimmed = line.trim();
if (trimmed === "---") {
inProperties = !inProperties;
continue;
}
if (inProperties) {
const match = trimmed.match(/^(\w+):\s*(.+)$/);
if (match) {
const key = match[1];
const value = match[2];
if (value.includes("{{title}}")) {
return key;
}
}
}
}
return "title";
}
async createFile(options) {
var _a;
const { file, title, type } = options;
if (!title) {
new import_obsidian.Notice(`Title is required to create a ${type}.`);
return null;
}
const contentType = this.getContentType(type);
if (!contentType && type !== "note") {
new import_obsidian.Notice(`Content type ${type} not found.`);
return null;
}
const kebabTitle = toKebabCase(title);
const enableUnderscorePrefix = (contentType == null ? void 0 : contentType.enableUnderscorePrefix) || false;
const prefix = enableUnderscorePrefix ? "_" : "";
let targetFolder = "";
if (type === "note") {
targetFolder = "";
} else if (contentType) {
const originalDir = ((_a = file.parent) == null ? void 0 : _a.path) || "";
if (originalDir === "" || originalDir === "/") {
targetFolder = contentType.folder || "";
} else {
targetFolder = originalDir;
}
}
if (targetFolder) {
const folder = this.app.vault.getAbstractFileByPath(targetFolder);
if (!(folder instanceof import_obsidian.TFolder)) {
await this.app.vault.createFolder(targetFolder);
}
}
const creationMode = (contentType == null ? void 0 : contentType.creationMode) || "file";
if (creationMode === "folder") {
return this.createFolderStructure(file, kebabTitle, prefix, targetFolder, type, contentType);
} else {
return this.createFileStructure(file, kebabTitle, prefix, targetFolder, contentType);
}
}
async createFolderStructure(file, kebabTitle, prefix, targetFolder, type, contentType) {
const folderName = `${prefix}${kebabTitle}`;
let folderPath;
if (targetFolder) {
folderPath = `${targetFolder}/${folderName}`;
} else {
const currentDir = file.parent ? file.parent.path : "";
if (currentDir && currentDir !== "/") {
folderPath = `${currentDir}/${folderName}`;
} else {
folderPath = folderName;
}
}
try {
const folder = this.app.vault.getAbstractFileByPath(folderPath);
if (!(folder instanceof import_obsidian.TFolder)) {
await this.app.vault.createFolder(folderPath);
}
} catch (e) {
}
const indexFileName = (contentType == null ? void 0 : contentType.indexFileName) || "index";
const extension = (contentType == null ? void 0 : contentType.useMdxExtension) ? ".mdx" : ".md";
const fileName = `${indexFileName}${extension}`;
const newPath = `${folderPath}/${fileName}`;
const existingFile = this.app.vault.getAbstractFileByPath(newPath);
if (existingFile instanceof import_obsidian.TFile) {
new import_obsidian.Notice(`File already exists at ${newPath}.`);
return null;
}
if (this.plugin) {
this.plugin.pluginCreatedFiles.set(newPath, Date.now());
}
try {
await this.app.fileManager.renameFile(file, newPath);
const newFile = this.app.vault.getAbstractFileByPath(newPath);
if (!(newFile instanceof import_obsidian.TFile)) {
return null;
}
setTimeout(() => {
const fileExplorer = this.app.workspace.getLeavesOfType("file-explorer")[0];
if (fileExplorer && fileExplorer.view) {
const view = fileExplorer.view;
if (view && typeof view === "object" && "tree" in view) {
const fileTree = view.tree;
if (fileTree && newFile instanceof import_obsidian.TFile && typeof fileTree.revealFile === "function") {
fileTree.revealFile(newFile);
}
}
}
}, 200);
const leaf = this.app.workspace.getLeaf(false);
await leaf.openFile(newFile);
const positionCursor = () => {
var _a;
const view = leaf.view;
if (view && "editor" in view) {
const editor = view.editor;
if (editor) {
const content = editor.getValue();
if (content) {
const lines = content.split("\n");
const lastLine = lines.length - 1;
const lastLineLength = ((_a = lines[lastLine]) == null ? void 0 : _a.length) || 0;
editor.setCursor({ line: lastLine, ch: lastLineLength });
editor.focus();
return true;
}
}
}
return false;
};
setTimeout(() => {
if (!positionCursor()) {
setTimeout(() => {
positionCursor();
}, 200);
}
}, 100);
return newFile;
} catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
new import_obsidian.Notice(`Failed to create folder structure: ${errorMessage}.`);
return null;
}
}
async createFileStructure(file, kebabTitle, prefix, targetFolder, contentType) {
const extension = (contentType == null ? void 0 : contentType.useMdxExtension) ? ".mdx" : ".md";
const newName = `${prefix}${kebabTitle}${extension}`;
let newPath;
if (targetFolder) {
newPath = `${targetFolder}/${newName}`;
} else {
const currentDir = file.parent ? file.parent.path : "";
if (currentDir && currentDir !== "/") {
newPath = `${currentDir}/${newName}`;
} else {
newPath = newName;
}
}
const existingFile = this.app.vault.getAbstractFileByPath(newPath);
if (existingFile instanceof import_obsidian.TFile && existingFile !== file) {
new import_obsidian.Notice(`File with name "${newName}" already exists.`);
return null;
}
if (this.plugin) {
this.plugin.pluginCreatedFiles.set(newPath, Date.now());
}
try {
await this.app.fileManager.renameFile(file, newPath);
const newFile = this.app.vault.getAbstractFileByPath(newPath);
if (!(newFile instanceof import_obsidian.TFile)) {
new import_obsidian.Notice("Failed to locate renamed file.");
return null;
}
const leaf = this.app.workspace.getLeaf(false);
await leaf.openFile(newFile);
const positionCursor = () => {
var _a;
const view = leaf.view;
if (view && "editor" in view) {
const editor = view.editor;
if (editor) {
const content = editor.getValue();
if (content) {
const lines = content.split("\n");
const lastLine = lines.length - 1;
const lastLineLength = ((_a = lines[lastLine]) == null ? void 0 : _a.length) || 0;
editor.setCursor({ line: lastLine, ch: lastLineLength });
editor.focus();
return true;
}
}
}
return false;
};
setTimeout(() => {
if (!positionCursor()) {
setTimeout(() => {
positionCursor();
}, 200);
}
}, 100);
return newFile;
} catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
new import_obsidian.Notice(`Failed to rename file: ${errorMessage}.`);
return null;
}
}
async renameFile(options) {
const { file, title, type } = options;
if (!title) {
new import_obsidian.Notice(`Title is required to rename the content.`);
return null;
}
const contentType = this.getContentType(type);
if (!contentType && type !== "note") {
new import_obsidian.Notice(`Content type ${type} not found.`);
return null;
}
const kebabTitle = toKebabCase(title);
const prefix = "";
const creationMode = (contentType == null ? void 0 : contentType.creationMode) || "file";
if (creationMode === "folder") {
return this.renameFolderStructure(file, kebabTitle, prefix, type, contentType);
} else {
return this.renameFileStructure(file, kebabTitle, prefix, contentType);
}
}
async renameFolderStructure(file, kebabTitle, prefix, type, contentType) {
const indexFileName = (contentType == null ? void 0 : contentType.indexFileName) || "index";
const isIndex = file.basename === indexFileName;
if (isIndex) {
if (!file.parent) {
new import_obsidian.Notice("Cannot rename: file has no parent folder.");
return null;
}
prefix = file.parent.name.startsWith("_") ? "_" : "";
const newFolderName = `${prefix}${kebabTitle}`;
const parentFolder = file.parent.parent;
if (!parentFolder) {
new import_obsidian.Notice("Cannot rename: parent folder has no parent.");
return null;
}
let newFolderPath;
if (parentFolder.path === "" || parentFolder.path === "/") {
newFolderPath = newFolderName;
} else {
newFolderPath = `${parentFolder.path}/${newFolderName}`;
}
const existingFolder = this.app.vault.getAbstractFileByPath(newFolderPath);
if (existingFolder instanceof import_obsidian.TFolder) {
new import_obsidian.Notice(`Folder already exists at ${newFolderPath}.`);
return null;
}
try {
await this.app.fileManager.renameFile(file.parent, newFolderPath);
} catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
new import_obsidian.Notice(`Failed to rename folder: ${errorMessage}.`);
return null;
}
const newFilePath = `${newFolderPath}/${file.name}`;
const newFile = this.app.vault.getAbstractFileByPath(newFilePath);
if (!(newFile instanceof import_obsidian.TFile)) {
new import_obsidian.Notice("Failed to locate renamed file.");
return null;
}
return newFile;
} else {
if (!file.parent) {
new import_obsidian.Notice("Cannot rename: file has no parent folder.");
return null;
}
prefix = file.basename.startsWith("_") ? "_" : "";
const extension = file.extension;
const newName = `${prefix}${kebabTitle}.${extension}`;
const newPath = `${file.parent.path}/${newName}`;
const existingFile = this.app.vault.getAbstractFileByPath(newPath);
if (existingFile instanceof import_obsidian.TFile && existingFile !== file) {
new import_obsidian.Notice(`File already exists at ${newPath}.`);
return null;
}
await this.app.fileManager.renameFile(file, newPath);
const newFile = this.app.vault.getAbstractFileByPath(newPath);
if (!(newFile instanceof import_obsidian.TFile)) {
new import_obsidian.Notice("Failed to locate renamed file.");
return null;
}
return newFile;
}
}
async renameFileStructure(file, kebabTitle, prefix, contentType) {
if (!file.parent) {
new import_obsidian.Notice("Cannot rename: file has no parent folder.");
return null;
}
const indexFileName = (contentType == null ? void 0 : contentType.indexFileName) || "";
const isIndex = indexFileName && indexFileName.trim() !== "" && file.basename === indexFileName;
if (isIndex) {
prefix = file.parent.name.startsWith("_") ? "_" : "";
const newFolderName = `${prefix}${kebabTitle}`;
const parentFolder = file.parent.parent;
if (!parentFolder) {
new import_obsidian.Notice("Cannot rename: parent folder has no parent.");
return null;
}
let newFolderPath;
if (parentFolder.path === "" || parentFolder.path === "/") {
newFolderPath = newFolderName;
} else {
newFolderPath = `${parentFolder.path}/${newFolderName}`;
}
const existingFolder = this.app.vault.getAbstractFileByPath(newFolderPath);
if (existingFolder instanceof import_obsidian.TFolder) {
new import_obsidian.Notice(`Folder already exists at ${newFolderPath}.`);
return null;
}
const newFilePath = `${newFolderPath}/${file.name}`;
if (this.plugin) {
this.plugin.pluginCreatedFiles.set(newFilePath, Date.now());
}
try {
await this.app.fileManager.renameFile(file.parent, newFolderPath);
} catch (error) {
console.error("FileOperations: Folder rename failed:", error);
const errorMessage = error instanceof Error ? error.message : String(error);
new import_obsidian.Notice(`Failed to rename folder: ${errorMessage}.`);
return null;
}
const newFile2 = this.app.vault.getAbstractFileByPath(newFilePath);
if (!(newFile2 instanceof import_obsidian.TFile)) {
new import_obsidian.Notice("Failed to locate renamed file.");
return null;
}
return newFile2;
}
prefix = file.basename.startsWith("_") ? "_" : "";
const extension = file.extension;
const newName = `${prefix}${kebabTitle}.${extension}`;
let newPath;
if (file.parent.path === "" || file.parent.path === "/") {
newPath = newName;
} else {
newPath = `${file.parent.path}/${newName}`;
}
const existingFile = this.app.vault.getAbstractFileByPath(newPath);
if (existingFile instanceof import_obsidian.TFile && existingFile !== file) {
new import_obsidian.Notice(`File already exists at ${newPath}.`);
return null;
}
if (this.plugin) {
this.plugin.pluginCreatedFiles.set(newPath, Date.now());
}
try {
await this.app.fileManager.renameFile(file, newPath);
} catch (error) {
console.error("FileOperations: File rename failed:", error);
const errorMessage = error instanceof Error ? error.message : String(error);
new import_obsidian.Notice(`Failed to rename file: ${errorMessage}.`);
return null;
}
const newFile = this.app.vault.getAbstractFileByPath(newPath);
if (!(newFile instanceof import_obsidian.TFile)) {
new import_obsidian.Notice("Failed to locate renamed file.");
return null;
}
return newFile;
}
};
// src/utils/template-parsing.ts
var import_obsidian2 = require("obsidian");
var TemplateParser = class {
constructor(app, settings, plugin) {
this.app = app;
this.settings = settings;
this.plugin = plugin;
}
// Get fresh settings from plugin if available, otherwise use stored settings
getSettings() {
var _a;
if ((_a = this.plugin) == null ? void 0 : _a.settings) {
return this.plugin.settings;
}
return this.settings;
}
/**
* Convert a string to kebab-case for slug generation
*/
toKebabCase(str) {
return str.toLowerCase().replace(/[^a-z0-9\s-]/g, "").trim().replace(/\s+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
}
parseFrontmatter(content) {
let propertiesEnd = 0;
let propertiesText = "";
const existingProperties = {};
if (content.startsWith("---")) {
propertiesEnd = content.indexOf("\n---", 3);
if (propertiesEnd === -1) {
propertiesEnd = content.length;
} else {
propertiesEnd += 4;
}
propertiesText = content.slice(4, propertiesEnd - 4).trim();
try {
let currentKey = null;
const arrayKeys = /* @__PURE__ */ new Set();
propertiesText.split("\n").forEach((line) => {
const trimmedLine = line.trim();
const match = trimmedLine.match(/^([a-zA-Z_][a-zA-Z0-9_-]*):\s*(.*)$/);
if (match) {
const [, key, value] = match;
currentKey = key;
const trimmedValue = value ? value.trim() : "";
const bracketArrayMatch = trimmedValue.match(/^\[(.*)\]$/);
if (bracketArrayMatch) {
const arrayContent = bracketArrayMatch[1].trim();
existingProperties[key] = [];
arrayKeys.add(key);
if (arrayContent) {
const items = [];
let currentItem = "";
let inQuotes = false;
let quoteChar = "";
for (let i = 0; i < arrayContent.length; i++) {
const char = arrayContent[i];
if (!inQuotes && (char === '"' || char === "'")) {
inQuotes = true;
quoteChar = char;
} else if (inQuotes && char === quoteChar) {
if (i > 0 && arrayContent[i - 1] === "\\") {
currentItem += char;
} else {
inQuotes = false;
quoteChar = "";
}
} else if (!inQuotes && char === ",") {
const trimmedItem = currentItem.trim();
if (trimmedItem) {
const unquoted = trimmedItem.replace(/^["']|["']$/g, "");
items.push(unquoted);
}
currentItem = "";
} else {
currentItem += char;
}
}
if (currentItem.trim()) {
const trimmedItem = currentItem.trim();
const unquoted = trimmedItem.replace(/^["']|["']$/g, "");
items.push(unquoted);
}
existingProperties[key] = items;
}
} else {
const isKnownArrayKey = KNOWN_ARRAY_KEYS.includes(key);
const isEmptyArray = !trimmedValue || trimmedValue === "";
const isArrayProperty = isKnownArrayKey || isEmptyArray;
if (isArrayProperty) {
existingProperties[key] = [];
arrayKeys.add(key);
} else {
const unquotedValue = trimmedValue.replace(/^["']|["']$/g, "");
existingProperties[key] = [unquotedValue];
}
}
} else if (currentKey && trimmedLine.startsWith("- ")) {
const isArrayProperty = arrayKeys.has(currentKey);
if (isArrayProperty) {
const item = trimmedLine.replace(/^-\s*/, "");
if (item) existingProperties[currentKey].push(item);
}
} else if (trimmedLine && !trimmedLine.startsWith("- ") && !trimmedLine.startsWith("#")) {
const keyMatch = trimmedLine.match(/^([^:]+):\s*(.*)$/);
if (keyMatch) {
const [, key, value] = keyMatch;
if (!existingProperties[key]) {
existingProperties[key] = [value ? value.trim() : ""];
}
}
}
});
KNOWN_ARRAY_KEYS.forEach((key) => {
if (propertiesText.includes(key + ":") && !existingProperties[key]) {
existingProperties[key] = [];
}
});
} catch (e) {
new import_obsidian2.Notice("Falling back to template due to parsing error.");
}
}
const bodyContent = content.slice(propertiesEnd);
return {
properties: existingProperties,
propertiesText,
propertiesEnd,
bodyContent
};
}
parseTemplate(templateString, title) {
const templateLines = templateString.split("\n");
const templateProps = [];
const templateValues = {};
let inProperties = false;
for (let i = 0; i < templateLines.length; i++) {
const line = templateLines[i].trim();
if (line === "---") {
inProperties = !inProperties;
if (!inProperties) {
break;
}
continue;
}
if (inProperties) {
const match = line.match(/^(\w+):\s*(.*)$/);
if (match) {
const [, key, value] = match;
templateProps.push(key);
const isKnownArrayKey = KNOWN_ARRAY_KEYS.includes(key);
const isEmptyArray = !value || value.trim() === "" || value.trim() === "[]";
const isArrayProperty = isKnownArrayKey || isEmptyArray;
if (isArrayProperty) {
if (value && value.startsWith("[")) {
const items = value.replace(/[[\]]/g, "").split(",").map((t) => t.trim()).filter((t) => t);
templateValues[key] = items;
} else {
templateValues[key] = [];
for (let j = i + 1; j < templateLines.length; j++) {
const nextLine = templateLines[j].trim();
if (nextLine.startsWith("- ")) {
const item = nextLine.replace(/^-\s*/, "").trim();
if (item) {
const arrayValue = templateValues[key];
if (Array.isArray(arrayValue)) {
arrayValue.push(item);
}
}
} else if (nextLine === "---" || nextLine && !nextLine.startsWith("- ") && nextLine.includes(":")) {
break;
}
}
}
} else {
const slug = this.toKebabCase(title);
const settings = this.getSettings();
const stringValue = (value || "").replace(/\{\{title\}\}/g, title).replace(/\{\{date\}\}/g, window.moment(/* @__PURE__ */ new Date()).format(settings.dateFormat)).replace(/\{\{slug\}\}/g, slug);
templateValues[key] = stringValue;
}
}
}
}
return { templateProps, templateValues };
}
buildFrontmatterContent(finalProps, arrayKeys) {
let newContent = "---\n";
for (const key in finalProps) {
const isArrayProperty = KNOWN_ARRAY_KEYS.includes(key) || arrayKeys && arrayKeys.has(key);
if (isArrayProperty) {
newContent += `${key}:
`;
if (finalProps[key].length > 0) {
finalProps[key].forEach((item) => {
newContent += ` - ${item}
`;
});
}
} else {
newContent += `${key}: ${finalProps[key][0] || ""}
`;
}
}
newContent += "---";
return newContent;
}
async updateTitleInFrontmatter(file, newTitle, type) {
const titleKey = this.getTitleKey(type);
const hasTitleInTemplate = this.templateHasTitle(type);
if (!hasTitleInTemplate) {
return;
}
const content = await this.app.vault.read(file);
let propertiesEnd = 0;
let propertiesText = "";
let hasFrontmatter = false;
if (content.startsWith("---")) {
hasFrontmatter = true;
propertiesEnd = content.indexOf("\n---", 3);
if (propertiesEnd === -1) {
propertiesEnd = content.length;
} else {
propertiesEnd += 4;
}
propertiesText = content.slice(4, propertiesEnd - 4).trim();
}
const propOrder = [];
const existing = {};
let currentKey = null;
let titleKeyPosition = -1;
const arrayKeys = /* @__PURE__ */ new Set();
propertiesText.split("\n").forEach((line, index) => {
const trimmedLine = line.trim();
const match = trimmedLine.match(/^([a-zA-Z_][a-zA-Z0-9_-]*):\s*(.*)$/);
if (match) {
const [, key, value] = match;
propOrder.push(key);
currentKey = key;
if (key === titleKey) {
titleKeyPosition = index;
}
const isKnownArrayKey = KNOWN_ARRAY_KEYS.includes(key);
const isEmptyArray = !value || value.trim() === "" || value.trim() === "[]";
const isArrayProperty = isKnownArrayKey || isEmptyArray;
if (isArrayProperty) {
existing[key] = [];
arrayKeys.add(key);
} else {
existing[key] = value ? value.trim() : "";
}
} else if (currentKey && arrayKeys.has(currentKey) && trimmedLine.startsWith("- ")) {
const item = trimmedLine.replace(/^-\s*/, "");
if (item) existing[currentKey].push(item);
} else if (trimmedLine && !trimmedLine.startsWith("- ") && !trimmedLine.startsWith("#")) {
const keyMatch = trimmedLine.match(/^([^:]+):\s*(.*)$/);
if (keyMatch) {
const [, key, value] = keyMatch;
if (!propOrder.includes(key)) {
propOrder.push(key);
existing[key] = value ? value.trim() : "";
}
}
}
});
let titleVal;
if (newTitle.includes('"') || newTitle.includes("'") || newTitle.includes("\n") || newTitle.includes("\\")) {
titleVal = `'${newTitle.replace(/'/g, "''")}'`;
} else if (newTitle.includes(" ") || newTitle.includes(":") || newTitle.includes("#") || newTitle.includes("@")) {
titleVal = `"${newTitle.replace(/"/g, '\\"')}"`;
} else {
titleVal = newTitle;
}
existing[titleKey] = titleVal;
if ("slug" in existing) {
const newSlug = this.toKebabCase(newTitle);
existing["slug"] = newSlug;
}
if (titleKeyPosition === -1) {
propOrder.push(titleKey);
}
if (!hasFrontmatter) {
return;
}
let newContent = "---\n";
for (const key of propOrder) {
const val = existing[key];
if (Array.isArray(val)) {
newContent += `${key}:
`;
if (val.length > 0) {
val.forEach((item) => {
newContent += ` - ${item}
`;
});
}
} else {
newContent += `${key}: ${val || ""}
`;
}
}
newContent += "---\n";
const bodyContent = content.slice(propertiesEnd);
newContent += bodyContent;
await this.app.vault.modify(file, newContent);
}
getTitleKey(type) {
if (type === "note") return "title";
const settings = this.getSettings();
const contentTypes = settings.contentTypes || [];
const contentType = contentTypes.find((ct) => ct.id === type);
if (!contentType) return "title";
const template = contentType.template;
const lines = template.split("\n");
let inProperties = false;
for (const line of lines) {
const trimmed = line.trim();
if (trimmed === "---") {
inProperties = !inProperties;
continue;
}
if (inProperties) {
const match = trimmed.match(/^(\w+):\s*(.+)$/);
if (match) {
const key = match[1];
const value = match[2];
if (value.includes("{{title}}")) {
return key;
}
}
}
}
return "title";
}
// Check if the template for this content type has {{title}}
templateHasTitle(type) {
if (type === "note") return true;
const settings = this.getSettings();
const contentTypes = settings.contentTypes || [];
const contentType = contentTypes.find((ct) => ct.id === type);
if (!contentType) return true;
const template = contentType.template;
return template.includes("{{title}}");
}
};
// src/utils/link-conversion.ts
var import_obsidian3 = require("obsidian");
var LinkConverter = class {
constructor(settings, plugin) {
this.settings = settings;
this.plugin = plugin;
}
// Get fresh settings from plugin if available, otherwise use stored settings
getSettings() {
var _a;
if ((_a = this.plugin) == null ? void 0 : _a.settings) {
return this.plugin.settings;
}
return this.settings;
}
// Local toKebabCase removed, using imported one instead
getAstroUrlFromInternalLink(link) {
const hashIndex = link.indexOf("#");
let path = hashIndex >= 0 ? link.slice(0, hashIndex) : link;
const anchor = hashIndex >= 0 ? link.slice(hashIndex) : "";
path = decodeURIComponent(path);
path = path.replace(/\.(md|mdx)$/, "");
const fileExtension = link.endsWith(".mdx") ? ".mdx" : ".md";
const contentTypeInfo = this.getContentTypeForPath(path + fileExtension);
let basePath = contentTypeInfo.basePath || "";
let contentFolder = contentTypeInfo.contentFolder || "";
let indexFileName = contentTypeInfo.indexFileName || "";
if (contentFolder) {
path = path.slice(contentFolder.length + 1);
}
let addTrailingSlash = false;
const parts = path.split("/");
const lastPart = parts[parts.length - 1];
if (indexFileName && indexFileName.trim() !== "" && lastPart === indexFileName) {
parts.pop();
path = parts.join("/");
addTrailingSlash = true;
} else if ((!indexFileName || indexFileName.trim() === "") && lastPart === "index") {
parts.pop();
path = parts.join("/");
addTrailingSlash = true;
}
const slugParts = path.split("/").map((part) => toKebabCase(part));
const slug = slugParts.join("/");
if (basePath) {
if (!basePath.startsWith("/")) {
basePath = "/" + basePath;
}
if (!basePath.endsWith("/")) {
basePath += "/";
}
} else {
basePath = "/";
}
const settings = this.getSettings();
const shouldAddTrailingSlash = (settings.addTrailingSlashToLinks || addTrailingSlash) && !anchor;
return `${basePath}${slug}${shouldAddTrailingSlash ? "/" : ""}${anchor}`;
}
getAstroUrlFromInternalLinkWithContext(link, currentFilePath, currentFileContentType) {
const hashIndex = link.indexOf("#");
let path = hashIndex >= 0 ? link.slice(0, hashIndex) : link;
const anchor = hashIndex >= 0 ? link.slice(hashIndex) : "";
path = decodeURIComponent(path);
path = path.replace(/\.(md|mdx)$/, "");
let basePath = "";
let contentFolder = "";
let indexFileName = "";
const fileExtension = link.endsWith(".mdx") ? ".mdx" : ".md";
const targetContentType = this.getContentTypeForPath(path + fileExtension);
if (!targetContentType.basePath && currentFileContentType.basePath) {
basePath = currentFileContentType.basePath;
indexFileName = currentFileContentType.indexFileName;
contentFolder = currentFileContentType.contentFolder;
} else {
basePath = targetContentType.basePath;
indexFileName = targetContentType.indexFileName;
contentFolder = targetContentType.contentFolder;
}
if (contentFolder) {
path = path.slice(contentFolder.length + 1);
}
let addTrailingSlash = false;
const parts = path.split("/");
const lastPart = parts[parts.length - 1];
if (indexFileName && indexFileName.trim() !== "" && lastPart === indexFileName) {
parts.pop();
path = parts.join("/");
addTrailingSlash = true;
} else if ((!indexFileName || indexFileName.trim() === "") && lastPart === "index") {
parts.pop();
path = parts.join("/");
addTrailingSlash = true;
}
const slugParts = path.split("/").map((part) => toKebabCase(part));
const slug = slugParts.join("/");
if (basePath) {
if (!basePath.startsWith("/")) {
basePath = "/" + basePath;
}
if (!basePath.endsWith("/")) {
basePath += "/";
}
} else {
basePath = "/";
}
const settings = this.getSettings();
const shouldAddTrailingSlash = (settings.addTrailingSlashToLinks || addTrailingSlash) && !anchor;
return `${basePath}${slug}${shouldAddTrailingSlash ? "/" : ""}${anchor}`;
}
isInConfiguredContentDirectory(filePath) {
const settings = this.getSettings();
const contentTypes = settings.contentTypes || [];
const sortedTypes = sortByPatternSpecificity(contentTypes);
for (const contentType of sortedTypes) {
if (!contentType.enabled) continue;
if (!contentType.folder || contentType.folder.trim() === "") {
if (!filePath.includes("/") || filePath.split("/").length === 1) {
return true;
}
} else if (matchesFolderPattern(filePath, contentType.folder)) {
if (contentType.ignoreSubfolders) {
const pathSegments = filePath.split("/");
const pathDepth = pathSegments.length;
const patternSegments = contentType.folder.split("/");
const expectedDepth = patternSegments.length;
if (contentType.creationMode === "folder") {
const folderDepth = pathDepth - 1;
if (folderDepth === expectedDepth || folderDepth === expectedDepth + 1) {
return true;
}
} else {
if (pathDepth === expectedDepth) {
return true;
}
}
} else {
return true;
}
}
}
return false;
}
getContentTypeForPath(filePath) {
const settings = this.getSettings();
const contentTypes = settings.contentTypes || [];
const sortedTypes = sortByPatternSpecificity(contentTypes);
for (const contentType of sortedTypes) {
if (!contentType.enabled) continue;
if (!contentType.folder || contentType.folder.trim() === "") {
if (!filePath.includes("/") || filePath.split("/").length === 1) {
return {
basePath: contentType.linkBasePath || "",
creationMode: contentType.creationMode,
indexFileName: contentType.indexFileName || "",
contentFolder: ""
};
}
} else if (matchesFolderPattern(filePath, contentType.folder)) {
if (contentType.ignoreSubfolders) {
const pathSegments = filePath.split("/");
const pathDepth = pathSegments.length;
const patternSegments = contentType.folder.split("/");
const expectedDepth = patternSegments.length;
if (contentType.creationMode === "folder") {
const folderDepth = pathDepth - 1;
if (folderDepth === expectedDepth || folderDepth === expectedDepth + 1) {
return {
basePath: contentType.linkBasePath || "",
creationMode: contentType.creationMode,
indexFileName: contentType.indexFileName || "",
contentFolder: contentType.folder
};
}
} else {
if (pathDepth === expectedDepth) {
return {
basePath: contentType.linkBasePath || "",
creationMode: contentType.creationMode,
indexFileName: contentType.indexFileName || "",
contentFolder: contentType.folder
};
}
}
} else {
return {
basePath: contentType.linkBasePath || "",
creationMode: contentType.creationMode,
indexFileName: contentType.indexFileName || "",
contentFolder: contentType.folder
};
}
}
}
return {
basePath: "",
creationMode: "file",
indexFileName: "",
contentFolder: ""
};
}
convertWikilinksForAstro(editor, file) {
var _a, _b;
if (!(file instanceof import_obsidian3.TFile)) {
new import_obsidian3.Notice("No active file.");
return;
}
const cursor = editor.getCursor();
const originalLine = cursor.line;
const originalCh = cursor.ch;
const originalContent = editor.getValue();
const originalLineCount = originalContent.split("\n").length;
const originalLineLength = ((_a = originalContent.split("\n")[originalLine]) == null ? void 0 : _a.length) || 0;
const content = editor.getValue();
let newContent = content;
let convertedCount = 0;
let skippedCount = 0;
const skippedLinks = [];
const currentFileContentType = this.getContentTypeForPath(file.path);
const imageExtensions = /\.(png|jpg|jpeg|gif|svg)$/i;
const canConvertLink = (linkText) => {
if (imageExtensions.test(linkText)) {
return false;
}
if (linkText.match(/^https?:\/\//)) {
return false;
}
if (!linkText.includes(".md") && !linkText.includes(".mdx") && !linkText.match(/^[a-zA-Z0-9_-]+(\/[a-zA-Z0-9_-]+)*$/)) {
return false;
}
let targetPath;
if (linkText.endsWith(".md") || linkText.endsWith(".mdx")) {
targetPath = linkText;
} else {
targetPath = linkText + ".md";
}
const isInConfiguredDirectory = this.isInConfiguredContentDirectory(targetPath);
const isSimpleFilename = !targetPath.includes("/");
const hasCurrentContentType = currentFileContentType.basePath !== "" || currentFileContentType.creationMode !== "file" || currentFileContentType.indexFileName !== "";
return isInConfiguredDirectory || isSimpleFilename && hasCurrentContentType;
};
newContent = newContent.replace(
/\[\[([^\]|]+)(\|([^\]]+))?\]\]/g,
(match, linkText, _pipe, displayText) => {
if (imageExtensions.test(linkText)) {
skippedCount++;
skippedLinks.push(linkText);
return match;
}
if (!canConvertLink(linkText)) {
skippedCount++;
skippedLinks.push(linkText);
return match;
}
const display = displayText || linkText.replace(/\.(md|mdx)$/, "");
const url = this.getAstroUrlFromInternalLinkWithContext(linkText, file.path, currentFileContentType);
convertedCount++;
return `[${display}](${url})`;
}
);
newContent = newContent.replace(
/\[([^\]]+)\]\(([^)]+\.(md|mdx)[^)]*)\)/g,
(match, displayText, link) => {
if (link.match(/^https?:\/\//) || imageExtensions.test(link)) {
skippedCount++;
skippedLinks.push(link);
return match;
}
if (!canConvertLink(link)) {
skippedCount++;
skippedLinks.push(link);
return match;
}
const url = this.getAstroUrlFromInternalLinkWithContext(link, file.path, currentFileContentType);
convertedCount++;
return `[${displayText}](${url})`;
}
);
newContent = newContent.replace(
/!\[(.*?)\]\(([^)]+)\)/g,
(match) => {
skippedCount++;
return match;
}
);
newContent = newContent.replace(/\{\{([^}]+)\}\}/g, (match, fileName) => {
if (imageExtensions.test(fileName)) {
skippedCount++;
skippedLinks.push(fileName);
return match;
}
if (!canConvertLink(fileName)) {
skippedCount++;
skippedLinks.push(fileName);
return match;
}
const url = this.getAstroUrlFromInternalLinkWithContext(fileName, file.path, currentFileContentType);
convertedCount++;
return `[Embedded: ${fileName}](${url})`;
});
editor.setValue(newContent);
const newLineCount = newContent.split("\n").length;
const newLineLength = ((_b = newContent.split("\n")[originalLine]) == null ? void 0 : _b.length) || 0;
let newLine = originalLine;
let newCh = originalCh;
if (newLineCount !== originalLineCount) {
if (newLine >= newLineCount) {
newLine = Math.max(0, newLineCount - 1);
}
}
if (newLineLength !== originalLineLength) {
if (newCh > newLineLength) {
newCh = Math.max(0, newLineLength);
}
}
editor.setCursor({ line: newLine, ch: newCh });
if (convertedCount > 0 && skippedCount === 0) {
new import_obsidian3.Notice(`Converted ${convertedCount} internal link${convertedCount > 1 ? "s" : ""} for Astro.`);
} else if (convertedCount > 0 && skippedCount > 0) {
new import_obsidian3.Notice(`Converted ${convertedCount} link${convertedCount > 1 ? "s" : ""} for Astro. Skipped ${skippedCount} link${skippedCount > 1 ? "s" : ""} outside configured content directories.`);
} else if (skippedCount > 0) {
new import_obsidian3.Notice(`No links converted. All ${skippedCount} link${skippedCount > 1 ? "s" : ""} are outside configured content directories or are images/external links.`);
} else {
new import_obsidian3.Notice("No internal links found to convert.");
}
}
};
// src/ui/title-modal.ts
var import_obsidian4 = require("obsidian");
var TitleModal = class extends import_obsidian4.Modal {
constructor(app, file, plugin, type, isRename = false, isNewNote = false) {
super(app);
this.file = file;
this.plugin = plugin;
this.type = type;
this.isRename = isRename;
this.isNewNote = isNewNote;
const settings = plugin.settings;
this.fileOps = new FileOperations(app, settings, plugin);
this.templateParser = new TemplateParser(app, settings);
}
async getCurrentTitleAsync() {
if (!this.file) {
return "";
}
try {
const content = await this.app.vault.read(this.file);
const titleKey = this.fileOps.getTitleKey(this.type);
const { properties } = this.templateParser.parseFrontmatter(content);
if (titleKey in properties) {
const titleValue = properties[titleKey];
if (Array.isArray(titleValue) && titleValue.length > 0) {
return String(titleValue[0]);
}
if (titleValue !== null && titleValue !== void 0) {
return String(titleValue);
}
}
} catch (error) {
console.error("Error reading file for title:", error);
}
return this.getFallbackTitle();
}
getCurrentTitle() {
if (!this.file) {
return "";
}
const titleKey = this.fileOps.getTitleKey(this.type);
const cache = this.app.metadataCache.getFileCache(this.file);
if ((cache == null ? void 0 : cache.frontmatter) && titleKey in cache.frontmatter) {
const titleValue = cache.frontmatter[titleKey];
if (typeof titleValue === "string") {
return titleValue;
}
if (Array.isArray(titleValue) && titleValue.length > 0) {
const firstValue = titleValue[0];
if (typeof firstValue === "string") {
return firstValue;
}
if (firstValue != null) {
if (typeof firstValue === "number" || typeof firstValue === "boolean") {
return String(firstValue);
}
if (typeof firstValue === "string") {
return firstValue;
}
}
}
if (titleValue == null) {
return "";
}
if (typeof titleValue === "number" || typeof titleValue === "boolean") {
return String(titleValue);
}
if (typeof titleValue === "string") {
return titleValue;
}
return "";
}
return this.getFallbackTitle();
}
getFallbackTitle() {
if (!this.file) {
return "";
}
let basename = this.file.basename;
if (this.file.parent && this.type !== "note") {
const contentType = this.fileOps.getContentType(this.type);
const indexFileName = (contentType == null ? void 0 : contentType.indexFileName) || "";
if (indexFileName.trim() !== "" && basename === indexFileName) {
basename = this.file.parent.name;
}
}
if (basename.startsWith("_")) {
basename = basename.slice(1);
}
return basename.replace(/-/g, " ").split(" ").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
}
/**
* Extracts a suggested title from the file basename for newly created files.
* This is used when a file is created from a link (e.g., [[sEfsleif]]).
* Preserves the original text as much as possible.
*/
getSuggestedTitleFromBasename() {
if (!this.file) {
return "";
}
let basename = this.file.basename;
if (this.file.parent && this.type !== "note") {
const contentType = this.fileOps.getContentType(this.type);
const indexFileName = (contentType == null ? void 0 : contentType.indexFileName) || "";
if (indexFileName.trim() !== "" && basename === indexFileName) {
basename = this.file.parent.name;
}
}
if (basename.startsWith("_")) {
basename = basename.slice(1);
}
return basename;
}
onOpen() {
const { contentEl } = this;
contentEl.empty();
const isMobile = window.innerWidth <= 768 || import_obsidian4.Platform.isMobile;
if (isMobile) {
this.modalEl.addClass("astro-composer-mobile-modal");
}
if (this.isRename) {
const typeName = this.getTypeDisplayName();
if (this.type === "note") {
contentEl.createEl("h2", { text: "Rename content" });
contentEl.createEl("p", { text: "Enter a title for this content:" });
} else {
contentEl.createEl("h2", { text: `Rename ${typeName} content` });
contentEl.createEl("p", { text: `Enter new title for your ${typeName} content:` });
}
this.titleInput = contentEl.createEl("input", {
type: "text",
placeholder: "New Title",
cls: "astro-composer-title-input"
});
void this.getCurrentTitleAsync().then((title) => {
this.titleInput.value = title;
});
} else if (this.isNewNote) {
const typeName = this.getTypeDisplayName();
if (this.type === "note") {
contentEl.createEl("h2", { text: "New content" });
contentEl.createEl("p", { text: "Enter a title for this content:" });
} else {
contentEl.createEl("h2", { text: `Create new ${typeName} content` });
contentEl.createEl("p", { text: `Enter a title for your new ${typeName} content:` });
}
this.titleInput = contentEl.createEl("input", {
type: "text",
placeholder: "New Title",
cls: "astro-composer-title-input"
});
} else {
const typeName = this.getTypeDisplayName();
if (this.type === "note") {
contentEl.createEl("h2", { text: "New content" });
contentEl.createEl("p", { text: "Enter a title for this content:" });
} else {
contentEl.createEl("h2", { text: `Create new ${typeName} content` });
contentEl.createEl("p", { text: `Enter a title for your new ${typeName} content:` });
}
this.titleInput = contentEl.createEl("input", {
type: "text",
placeholder: "New Title",
cls: "astro-composer-title-input"
});
if (this.file) {
const suggestedTitle = this.getSuggestedTitleFromBasename();
if (suggestedTitle) {
this.titleInput.value = suggestedTitle;
}
}
}
this.titleInput.focus();
if (this.isNewNote) {
setTimeout(() => {
this.titleInput.setSelectionRange(0, 0);
}, 0);
}
const buttonContainer = contentEl.createDiv({ cls: "astro-composer-button-container" });
const cancelButton = buttonContainer.createEl("button", { text: "Cancel", cls: "astro-composer-cancel-button" });
cancelButton.onclick = () => this.close();
const submitButton = buttonContainer.createEl("button", { text: this.isRename ? "Rename" : "Create", cls: ["astro-composer-create-button", "mod-cta"] });
submitButton.onclick = () => this.submit();
this.titleInput.addEventListener("keypress", (e) => {
if (e.key === "Enter") void this.submit();
});
}
async submit() {
const title = this.titleInput.value.trim();
if (!title) {
new import_obsidian4.Notice("Please enter a title.");
return;
}
try {
let newFile = null;
if (this.isRename) {
newFile = await this.fileOps.renameFile({ file: this.file, title, type: this.type });
if (newFile) {
await this.templateParser.updateTitleInFrontmatter(newFile, title, this.type);
} else {
this.close();
return;
}
} else if (this.isNewNote) {
if (this.file) {
newFile = await this.fileOps.createFile({ file: this.file, title, type: this.type });
const shouldInsertProperties = this.plugin.settings.autoInsertProperties;
if (newFile && shouldInsertProperties) {
await this.addPropertiesToFile(newFile, title, this.type);
this.positionCursorAtEnd(newFile);
}
}
} else if (this.file) {
newFile = await this.fileOps.createFile({ file: this.file, title, type: this.type });
const shouldInsertProperties = this.plugin.settings.autoInsertProperties;
if (newFile && shouldInsertProperties) {
await this.addPropertiesToFile(newFile, title, this.type);
this.positionCursorAtEnd(newFile);
}
} else {
newFile = await this.createNewFile(title);
}
if (!newFile) {
new import_obsidian4.Notice(`Failed to ${this.isRename ? "rename" : "create"} ${this.type}.`);
this.close();
return;
}
} catch (error) {
console.error("TitleModal: Error during process:", error);
const errorMessage = error instanceof Error ? error.message : String(error);
new import_obsidian4.Notice(`Error ${this.isRename ? "renaming" : "creating"} ${this.type}: ${errorMessage}.`);
this.close();
return;
}
this.close();
}
getTypeDisplayName() {
if (this.type === "note") {
return "Content";
}
const contentType = this.fileOps.getContentType(this.type);
return contentType ? contentType.name : "Content";
}
async createNewFile(title) {
var _a, _b;
let targetFolder;
const originalDir = ((_b = (_a = this.file) == null ? void 0 : _a.parent) == null ? void 0 : _b.path) || "";
if (this.type !== "note") {
const contentType2 = this.fileOps.getContentType(this.type);
if (originalDir === "" || originalDir === "/") {
targetFolder = (contentType2 == null ? void 0 : contentType2.folder) || "";
} else {
targetFolder = originalDir;
}
} else {
targetFolder = originalDir;
}
const filename = this.fileOps.generateFilename(title);
const contentType = this.fileOps.getContentType(this.type);
const extension = (contentType == null ? void 0 : contentType.useMdxExtension) ? ".mdx" : ".md";
const filePath = targetFolder ? `${targetFolder}/${filename}${extension}` : `${filename}${extension}`;
if (this.plugin) {
this.plugin.pluginCreatedFiles.set(filePath, Date.now());
}
let initialContent = "";
if (this.plugin.settings.autoInsertProperties) {
initialContent = this.generateInitialContent(title);
}
try {
const newFile = await this.app.vault.create(filePath, initialContent);
const leaf = this.app.workspace.getLeaf();
await leaf.openFile(newFile);
const positionCursor = () => {
var _a2;
const view = leaf.view;
if (view instanceof import_obsidian4.MarkdownView && view.editor) {
const editor = view.editor;
const content = editor.getValue();
if (content) {
const lines = content.split("\n");
const lastLine = lines.length - 1;
const lastLineLength = ((_a2 = lines[lastLine]) == null ? void 0 : _a2.length) || 0;
editor.setCursor({ line: lastLine, ch: lastLineLength });
editor.focus();
return true;
}
}
return false;
};
setTimeout(() => {
if (!positionCursor()) {
setTimeout(() => {
positionCursor();
}, 200);
}
}, 100);
return newFile;
} catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
throw new Error(`Failed to create file: ${errorMessage}`);
}
}
generateInitialContent(title) {
const now = /* @__PURE__ */ new Date();
const dateString = window.moment(now).format(this.plugin.settings.dateFormat);
const slug = toKebabCase(title);
let template;
if (this.type === "note") {
const escapedTitle = this.escapeYamlString(title);
template = `---
title: ${escapedTitle}
date: ${dateString}
---
`;
} else {
const contentType = this.fileOps.getContentType(this.type);
if (!contentType) {
const escapedTitle = this.escapeYamlString(title);
template = `---
title: ${escapedTitle}
date: ${dateString}
---
`;
} else {
template = contentType.template;
}
}
template = template.replace(/\{\{title\}\}/g, title);
template = template.replace(/\{\{date\}\}/g, dateString);
template = template.replace(/\{\{slug\}\}/g, slug);
return template;
}
async addPropertiesToFile(file, title, type) {
const now = /* @__PURE__ */ new Date();
const dateString = window.moment(now).format(this.plugin.settings.dateFormat);
const slug = toKebabCase(title);
let template;
if (type === "note") {
const escapedTitle = this.escapeYamlString(title);
template = `---
title: ${escapedTitle}
date: ${dateString}
---
`;
} else {
const contentType = this.fileOps.getContentType(type);
if (!contentType) {
const escapedTitle = this.escapeYamlString(title);
template = `---
title: ${escapedTitle}
date: ${dateString}
---
`;
} else {
template = contentType.template;
}
}
template = template.replace(/\{\{title\}\}/g, title);
template = template.replace(/\{\{date\}\}/g, dateString);
template = template.replace(/\{\{slug\}\}/g, slug);
await this.app.vault.modify(file, template);
}
positionCursorAtEnd(file) {
const positionCursor = () => {
var _a;
const view = this.app.workspace.getActiveViewOfType(import_obsidian4.MarkdownView);
if (view && view.file === file && view.editor) {
const editor = view.editor;
const content = editor.getValue();
if (content) {
const lines = content.split("\n");
const lastLine = lines.length - 1;
const lastLineLength = ((_a = lines[lastLine]) == null ? void 0 : _a.length) || 0;
editor.setCursor({ line: lastLine, ch: lastLineLength });
editor.focus();
return true;
}
}
return false;
};
setTimeout(() => {
if (!positionCursor()) {
setTimeout(() => {
positionCursor();
}, 200);
}
}, 100);
}
escapeYamlString(str) {
if (str.includes('"') || str.includes("'") || str.includes("\n") || str.includes("\\")) {
return `'${str.replace(/'/g, "''")}'`;
} else if (str.includes(" ") || str.includes(":") || str.includes("#") || str.includes("@")) {
return `"${str.replace(/"/g, '\\"')}"`;
} else {
return str;
}
}
onClose() {
const { contentEl } = this;
contentEl.empty();
}
};
// src/commands/index.ts
function registerCommands(plugin, settings) {
const isMobile = import_obsidian5.Platform.isMobile;
if (isMobile) {
let hasMatchingContentType2 = function(file, settings2) {
const type = fileOps.determineType(file);
if (type === "note") {
return false;
}
const contentType = fileOps.getContentType(type);
return contentType !== null && contentType.enabled;
};
var hasMatchingContentType = hasMatchingContentType2;
const pluginInterface2 = plugin;
const fileOps = new FileOperations(plugin.app, settings, pluginInterface2);
const linkConverter = new LinkConverter(settings, pluginInterface2);
plugin.addCommand({
id: "standardize-properties",
name: "Standardize properties",
icon: "file-check",
editorCallback: (editor, ctx) => {
const file = ctx instanceof import_obsidian5.MarkdownView ? ctx.file : ctx.file;
if (file instanceof import_obsidian5.TFile) {
const currentSettings = pluginInterface2.settings || settings;
void standardizeProperties(plugin.app, currentSettings, file, pluginInterface2, editor);
}
}
});
plugin.addCommand({
id: "convert-wikilinks-astro",
name: "Convert internal links for astro",
icon: "link-2",
editorCallback: (editor, ctx) => {
const file = ctx instanceof import_obsidian5.MarkdownView ? ctx.file : ctx.file;
if (file instanceof import_obsidian5.TFile) {
linkConverter.convertWikilinksForAstro(editor, file);
}
}
});
plugin.addCommand({
id: "rename-content",
name: "Rename current content",
icon: "pencil",
editorCallback: (editor, ctx) => {
const file = ctx instanceof import_obsidian5.MarkdownView ? ctx.file : ctx.file;
if (file instanceof import_obsidian5.TFile) {
if (!hasMatchingContentType2(file, settings)) {
new import_obsidian5.Notice("Cannot rename: this file is not part of a configured content type folder.");
return;
}
const type = fileOps.determineType(file);
const cache = plugin.app.metadataCache.getFileCache(file);
const titleKey = fileOps.getTitleKey(type);
if (!(cache == null ? void 0 : cache.frontmatter) || !(titleKey in cache.frontmatter)) {
new import_obsidian5.Notice(`Cannot rename: No ${titleKey} found in properties`);
return;
}
new TitleModal(plugin.app, file, plugin, type, true).open();
}
}
});
return;
}
const pluginInterface = plugin;
function hasMatchingContentType(file, settings2) {
const currentSettings = (plugin == null ? void 0 : plugin.settings) || settings2;
const tempFileOps = new FileOperations(plugin.app, currentSettings, plugin);
const type = tempFileOps.determineType(file);
if (type === "note") {
return false;
}
const contentType = tempFileOps.getContentType(type);
return contentType !== null && contentType.enabled;
}
plugin.addCommand({
id: "standardize-properties",
name: "Standardize properties",
icon: "file-check",
editorCallback: (editor, ctx) => {
const file = ctx instanceof import_obsidian5.MarkdownView ? ctx.file : ctx.file;
if (file instanceof import_obsidian5.TFile) {
void standardizeProperties(plugin.app, settings, file, plugin, editor);
}
}
});
plugin.addCommand({
id: "convert-wikilinks-astro",
name: "Convert internal links for astro",
icon: "link-2",
editorCallback: (editor, ctx) => {
const file = ctx instanceof import_obsidian5.MarkdownView ? ctx.file : ctx.file;
if (file instanceof import_obsidian5.TFile) {
const currentSettings = pluginInterface.settings || settings;
const currentLinkConverter = new LinkConverter(currentSettings, pluginInterface);
currentLinkConverter.convertWikilinksForAstro(editor, file);
}
}
});
plugin.addCommand({
id: "rename-content",
name: "Rename current content",
icon: "pencil",
editorCallback: (editor, ctx) => {
const file = ctx instanceof import_obsidian5.MarkdownView ? ctx.file : ctx.file;
if (file instanceof import_obsidian5.TFile) {
const currentSettings = pluginInterface.settings || settings;
const currentFileOps = new FileOperations(plugin.app, currentSettings, pluginInterface);
if (!hasMatchingContentType(file, currentSettings)) {
new import_obsidian5.Notice("Cannot rename: this file is not part of a configured content type folder.");
return;
}
const type = currentFileOps.determineType(file);
new TitleModal(plugin.app, file, pluginInterface, type, true).open();
}
}
});
if (!isMobile) {
plugin.addCommand({
id: "open-project-terminal",
name: "Open project terminal",
icon: "terminal-square",
callback: () => {
const currentSettings = plugin.settings;
if (!currentSettings.enableOpenTerminalCommand) {
new import_obsidian5.Notice("Open terminal command is disabled. Enable it in settings to use this command.");
return;
}
openTerminalInProjectRoot(plugin.app, currentSettings);
}
});
}
if (!isMobile) {
plugin.addCommand({
id: "edit-astro-config",
name: "Edit astro config",
icon: "rocket",
callback: async () => {
const currentSettings = plugin.settings;
if (!currentSettings.enableOpenConfigFileCommand) {
new import_obsidian5.Notice("Edit config file command is disabled. Enable it in settings to use this command.");
return;
}
await openConfigFile(plugin.app, currentSettings);
}
});
}
}
async function standardizeProperties(app, settings, file, plugin, editor) {
var _a;
const currentSettings = (plugin == null ? void 0 : plugin.settings) || settings;
const templateParser = new TemplateParser(app, currentSettings);
const fileOps = new FileOperations(app, currentSettings, plugin);
let cursorPosition = null;
let originalContent = "";
if (editor) {
const cursor = editor.getCursor();
cursorPosition = { line: cursor.line, ch: cursor.ch };
originalContent = editor.getValue();
}
const type = fileOps.determineType(file);
if (type === "note") {
new import_obsidian5.Notice("No properties template specified for this content. This file doesn't match any configured content type folders.");
return;
}
let templateString;
if (type === "note") {
new import_obsidian5.Notice("No properties template specified for this content. This file doesn't match any configured content type folders.");
return;
}
const contentType = fileOps.getContentType(type);
if (!contentType) {
new import_obsidian5.Notice("Content type not found.");
return;
}
templateString = contentType.template;
await new Promise((resolve) => setTimeout(resolve, 100));
const content = await app.vault.read(file);
const title = file.basename.replace(/^_/, "");
const parsed = templateParser.parseFrontmatter(content);
const { templateProps, templateValues } = templateParser.parseTemplate(templateString, title);
const finalProps = { ...parsed.properties };
const arrayKeys = /* @__PURE__ */ new Set();
const slug = toKebabCase(title);
for (const key of templateProps) {
if (!(key in parsed.properties)) {
const templateValue = templateValues[key];
if (Array.isArray(templateValue)) {
finalProps[key] = templateValue;
arrayKeys.add(key);
} else {
finalProps[key] = [templateValue || ""];
}
} else {
const templateValue = templateValues[key];
const isArrayValue = Array.isArray(templateValue);
if (isArrayValue) {
const existingItems = parsed.properties[key] || [];
const newItems = templateValue.filter((item) => !existingItems.includes(item));
finalProps[key] = [...existingItems, ...newItems];
arrayKeys.add(key);
} else {
if (key === "slug") {
const existingSlug = parsed.properties[key][0] || "";
if (!existingSlug || existingSlug.trim() === "") {
finalProps[key] = [slug];
}
}
}
}
}
if ("slug" in parsed.properties && templateString.includes("{{slug}}")) {
const existingSlug = parsed.properties["slug"][0] || "";
if (!existingSlug || existingSlug.trim() === "") {
finalProps["slug"] = [slug];
}
}
for (const key in parsed.properties) {
if (parsed.properties[key].length > 1) {
arrayKeys.add(key);
}
}
const newContent = templateParser.buildFrontmatterContent(finalProps, arrayKeys) + parsed.bodyContent;
await app.vault.modify(file, newContent);
if (editor && cursorPosition) {
await new Promise((resolve) => setTimeout(resolve, 50));
const activeView = app.workspace.getActiveViewOfType(import_obsidian5.MarkdownView);
if (activeView && activeView.file === file && activeView.editor) {
const activeEditor = activeView.editor;
const newLineCount = newContent.split("\n").length;
const originalLineCount = originalContent.split("\n").length;
let newLine = cursorPosition.line;
let newCh = cursorPosition.ch;
if (newLineCount !== originalLineCount) {
if (newLine >= newLineCount) {
newLine = Math.max(0, newLineCount - 1);
}
}
const newLineLength = ((_a = newContent.split("\n")[newLine]) == null ? void 0 : _a.length) || 0;
if (newCh > newLineLength) {
newCh = Math.max(0, newLineLength);
}
activeEditor.setCursor({ line: newLine, ch: newCh });
}
}
new import_obsidian5.Notice("Properties standardized using template.");
}
function renameContentByPath(app, filePath, settings, plugin) {
const file = app.vault.getAbstractFileByPath(filePath);
if (!(file instanceof import_obsidian5.TFile)) {
new import_obsidian5.Notice(`File not found: ${filePath}`);
return;
}
const fileOps = new FileOperations(app, settings, plugin);
function hasMatchingContentType(file2, settings2) {
const type2 = fileOps.determineType(file2);
if (type2 === "note") {
return false;
}
const contentType = fileOps.getContentType(type2);
return contentType !== null && contentType.enabled;
}
if (!hasMatchingContentType(file, settings)) {
new import_obsidian5.Notice("Cannot rename: this file is not part of a configured content type folder.");
return;
}
const type = fileOps.determineType(file);
new TitleModal(app, file, plugin, type, true).open();
}
function registerContentTypeCommands(plugin, settings) {
const pluginInterface = plugin;
const contentTypes = settings.contentTypes || [];
for (const contentType of contentTypes) {
if (!contentType.enabled) {
continue;
}
const commandId = `create-content-type-${contentType.id}`;
const commandName = `Create new content type: ${contentType.name}`;
plugin.addCommand({
id: commandId,
name: commandName,
callback: async () => {
let targetFolder = contentType.folder || "";
if (targetFolder && targetFolder.trim() !== "") {
const folder = plugin.app.vault.getAbstractFileByPath(targetFolder);
if (!(folder instanceof import_obsidian5.TFolder)) {
try {
await plugin.app.vault.createFolder(targetFolder);
} catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
new import_obsidian5.Notice(`Failed to create folder: ${errorMessage}`);
return;
}
}
}
const tempFileName = "Untitled.md";
const filePath = targetFolder ? `${targetFolder}/${tempFileName}` : tempFileName;
const existingFile = plugin.app.vault.getAbstractFileByPath(filePath);
if (existingFile instanceof import_obsidian5.TFile) {
new TitleModal(plugin.app, existingFile, pluginInterface, contentType.id, false, true).open();
return;
}
if (pluginInterface && "pluginCreatedFiles" in pluginInterface) {
pluginInterface.pluginCreatedFiles.set(filePath, Date.now());
}
try {
const tempFile = await plugin.app.vault.create(filePath, "");
new TitleModal(plugin.app, tempFile, pluginInterface, contentType.id, false, true).open();
} catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
new import_obsidian5.Notice(`Failed to create file: ${errorMessage}`);
if (pluginInterface && "pluginCreatedFiles" in pluginInterface) {
pluginInterface.pluginCreatedFiles.delete(filePath);
}
}
}
});
}
}
var terminalLogger = {
enabled: false,
setEnabled(value) {
this.enabled = value;
},
log(...args) {
if (this.enabled) {
console.debug("[astro-composer:terminal]", ...args);
}
}
};
function getDefaultTerminalApp() {
if (!import_obsidian5.Platform.isDesktopApp) {
return "";
}
if (import_obsidian5.Platform.isMacOS) {
return "Terminal";
}
if (import_obsidian5.Platform.isWin) {
try {
const os = require("os");
const release = os.release();
const majorVersion = parseInt(release.split(".")[0]);
const buildNumber = parseInt(release.split(".")[2]);
if (majorVersion > 10 || majorVersion === 10 && buildNumber >= 22e3) {
return "wt.exe";
}
} catch (e) {
}
return "cmd.exe";
}
if (import_obsidian5.Platform.isLinux) {
return "gnome-terminal";
}
return "";
}
function sanitizeTerminalApp(value) {
return value.trim();
}
function escapeDoubleQuotes(value) {
return value.replace(/"/g, '\\"');
}
function openTerminalInProjectRoot(app, settings) {
terminalLogger.setEnabled(settings.enableTerminalDebugLogging);
try {
const { exec } = require("child_process");
const path = require("path");
const fs = require("fs");
const adapter = app.vault.adapter;
const vaultPath = adapter.basePath || adapter.path;
const vaultPathString = typeof vaultPath === "string" ? vaultPath : String(vaultPath);
let projectPath;
if (settings.terminalProjectRootPath && settings.terminalProjectRootPath.trim()) {
projectPath = path.resolve(vaultPathString, settings.terminalProjectRootPath);
} else {
projectPath = vaultPathString;
}
if (!fs.existsSync(projectPath)) {
new import_obsidian5.Notice(`Project root directory not found at: ${projectPath}`);
return;
}
const configuredApp = sanitizeTerminalApp(settings.terminalApplicationName || "");
const terminalApp = configuredApp || getDefaultTerminalApp();
if (!configuredApp && !terminalApp) {
new import_obsidian5.Notice("Terminal application name is empty. Please configure it in settings.");
return;
}
const platform = process.platform;
terminalLogger.log("Opening terminal", { platform, terminalApp, projectPath });
if (platform === "win32") {
const escapedPath = projectPath.replace(/"/g, '"');
const lowerApp = terminalApp.toLowerCase();
if (lowerApp === "wt.exe" || lowerApp === "wt" || lowerApp === "windows terminal") {
exec("where wt", (error) => {
if (!error) {
const command = `start "" wt.exe -d "${escapedPath}"`;
terminalLogger.log("Windows launch (wt)", { command, projectPath });
exec(command, (execError) => {
if (execError) {
terminalLogger.log("Windows Terminal failed, falling back to cmd", { error: execError.message });
const fallbackCommand = `start "" cmd.exe /K "cd /d "${escapedPath}""`;
exec(fallbackCommand, (cmdError) => {
if (cmdError) {
new import_obsidian5.Notice(`Error opening terminal: ${cmdError.message || "Unknown error"}`);
}
});
}
});
} else {
terminalLogger.log("Windows Terminal not found, using cmd", {});
const fallbackCommand = `start "" cmd.exe /K "cd /d "${escapedPath}""`;
exec(fallbackCommand, (cmdError) => {
if (cmdError) {
new import_obsidian5.Notice(`Error opening terminal: ${cmdError.message || "Unknown error"}`);
}
});
}
});
} else if (lowerApp === "powershell" || lowerApp === "powershell.exe") {
const escapedPathForPS = projectPath.replace(/'/g, "''");
const command = `start "" powershell -NoExit -Command "Set-Location '${escapedPathForPS}';"`;
terminalLogger.log("Windows launch (powershell)", { command, projectPath });
exec(command, (error) => {
if (error) {
new import_obsidian5.Notice(`Error opening terminal: ${error.message || "Unknown error"}`);
}
});
} else if (lowerApp === "cmd.exe" || lowerApp === "cmd") {
const command = `start "" cmd.exe /K "cd /d "${escapedPath}""`;
terminalLogger.log("Windows launch (cmd)", { command, projectPath });
exec(command, (error) => {
if (error) {
new import_obsidian5.Notice(`Error opening terminal: ${error.message || "Unknown error"}`);
}
});
} else {
const command = `start "" "${terminalApp}"`;
terminalLogger.log("Windows launch (generic)", { command, terminalApp, projectPath });
exec(command, (error) => {
if (error) {
terminalLogger.log("Generic terminal failed, falling back to cmd", { error: error.message });
const fallbackCommand = `start "" cmd.exe /K "cd /d "${escapedPath}""`;
exec(fallbackCommand, (cmdError) => {
if (cmdError) {
new import_obsidian5.Notice(`Error opening terminal: ${cmdError.message || "Unknown error"}`);
}
});
}
});
}
} else if (platform === "darwin") {
const escapedApp = escapeDoubleQuotes(terminalApp);
const escapedPath = escapeDoubleQuotes(projectPath);
const command = `open -na "${escapedApp}" "${escapedPath}"`;
terminalLogger.log("macOS launch", { command, terminalApp, projectPath });
exec(command, (error) => {
if (error) {
new import_obsidian5.Notice(`Error opening terminal: ${error.message || "Unknown error"}`);
}
});
} else {
const terminals = terminalApp ? [terminalApp] : ["gnome-terminal", "konsole", "xterm"];
const projectPathEscaped = projectPath.replace(/"/g, '\\"');
const tryTerminal = (index) => {
if (index >= terminals.length) {
new import_obsidian5.Notice("No supported terminal found. Please install a terminal application or configure one in settings.");
return;
}
const currentTerminal = terminals[index];
const terminalName = currentTerminal.split(" ")[0];
exec(`which ${terminalName}`, (error) => {
if (!error) {
let command;
if (currentTerminal.includes("gnome-terminal")) {
command = `gnome-terminal --working-directory="${projectPathEscaped}"`;
} else if (currentTerminal.includes("konsole")) {
command = `konsole --workdir "${projectPathEscaped}"`;
} else {
command = `${currentTerminal} -e "cd \\"${projectPathEscaped}\\" && bash"`;
}
terminalLogger.log("Linux launch", { command, terminal: currentTerminal, projectPath });
exec(command, (execError) => {
if (execError && index < terminals.length - 1) {
terminalLogger.log("Terminal launch failed, trying next", { terminal: currentTerminal, error: execError.message });
tryTerminal(index + 1);
} else if (execError) {
new import_obsidian5.Notice(`Error opening terminal: ${execError.message || "Unknown error"}`);
}
});
} else {
terminalLogger.log("Terminal not found, trying next", { terminal: currentTerminal });
tryTerminal(index + 1);
}
});
};
tryTerminal(0);
}
} catch (error) {
terminalLogger.log("Unexpected error", { error });
new import_obsidian5.Notice(`Error opening terminal: ${error instanceof Error ? error.message : String(error)}`);
}
}
async function openConfigFile(app, settings) {
try {
const fs = require("fs");
const path = require("path");
const { shell } = require("electron");
const adapter = app.vault.adapter;
const vaultPath = adapter.basePath || adapter.path;
const vaultPathString = typeof vaultPath === "string" ? vaultPath : String(vaultPath);
if (!settings.configFilePath || !settings.configFilePath.trim()) {
new import_obsidian5.Notice("Please specify a config file path in settings.");
return;
}
const configPath = path.resolve(vaultPathString, settings.configFilePath);
if (!fs.existsSync(configPath)) {
new import_obsidian5.Notice(`Config file not found at: ${configPath}`);
return;
}
await shell.openPath(configPath);
} catch (error) {
new import_obsidian5.Notice(`Error opening config file: ${error instanceof Error ? error.message : String(error)}`);
}
}
// src/ui/settings-tab.ts
var import_obsidian9 = require("obsidian");
// src/ui/components/CommandPickerModal.ts
var import_obsidian6 = require("obsidian");
var CommandPickerModal = class extends import_obsidian6.FuzzySuggestModal {
constructor(app, onSelect) {
super(app);
this.onSelect = onSelect;
}
getItems() {
const commandRegistry = this.app.commands;
const commandMap = /* @__PURE__ */ new Map();
if (commandRegistry && typeof commandRegistry.listCommands === "function") {
try {
const commands = commandRegistry.listCommands();
for (const command of commands) {
if (command && command.id && command.name && !commandMap.has(command.id)) {
commandMap.set(command.id, {
id: command.id,
name: command.name
});
}
}
} catch (e) {
console.warn("[Astro Composer] Error getting commands via listCommands():", e);
}
}
try {
const registry = commandRegistry == null ? void 0 : commandRegistry.commands;
if (registry && typeof registry === "object") {
const allCommands = Object.values(registry);
for (const command of allCommands) {
if (command && command.id && command.name && !commandMap.has(command.id)) {
commandMap.set(command.id, {
id: command.id,
name: command.name
});
}
}
}
} catch (e) {
console.warn("[Astro Composer] Error getting commands via registry:", e);
}
try {
const internalRegistry = commandRegistry == null ? void 0 : commandRegistry.commandRegistry;
if (internalRegistry && typeof internalRegistry === "object") {
const allCommands = Object.values(internalRegistry);
for (const command of allCommands) {
if (command && command.id && command.name && !commandMap.has(command.id)) {
commandMap.set(command.id, {
id: command.id,
name: command.name
});
}
}
}
} catch (e) {
console.warn("[Astro Composer] Error getting commands via internal registry:", e);
}
const commandOptions = Array.from(commandMap.values());
commandOptions.sort((a, b) => a.name.localeCompare(b.name));
return commandOptions;
}
getItemText(item) {
return item.name;
}
onChooseItem(item, evt) {
this.onSelect(item.id);
}
// Override to show command name only
renderSuggestion(match, el) {
const item = match.item;
el.createDiv({ cls: "suggestion-title", text: item.name });
}
};
// src/ui/components/IconPickerModal.ts
var import_obsidian7 = require("obsidian");
var getIconList = () => {
if (import_obsidian7.requireApiVersion && (0, import_obsidian7.requireApiVersion)("1.7.3") && import_obsidian7.getIconIds) {
try {
return (0, import_obsidian7.getIconIds)();
} catch (e) {
console.warn("[Astro Composer] Error getting icon IDs from Obsidian:", e);
}
}
return [
"settings-2",
"settings",
"help-circle",
"info",
"star",
"heart",
"bookmark",
"home",
"search",
"bell",
"mail",
"user",
"users",
"folder",
"file",
"file-text",
"image",
"video",
"music",
"calendar",
"clock",
"edit",
"pencil",
"trash",
"copy",
"cut",
"paste",
"download",
"upload",
"save",
"share",
"link",
"external-link",
"lock",
"unlock",
"eye",
"eye-off",
"key",
"shield",
"check",
"x",
"plus",
"minus",
"arrow-left",
"arrow-right",
"arrow-up",
"arrow-down",
"chevron-left",
"chevron-right",
"chevron-up",
"chevron-down",
"menu",
"more-horizontal",
"more-vertical",
"grid",
"list",
"layout",
"columns",
"rows",
"maximize",
"minimize",
"zoom-in",
"zoom-out",
"refresh-cw",
"play",
"pause",
"stop",
"sun",
"moon",
"cloud",
"zap",
"wand-2",
"wand",
"wand-sparkles",
"palette",
"brush",
"sliders",
"power",
"wifi",
"bluetooth",
"monitor",
"laptop",
"smartphone",
"camera",
"mic",
"headphones",
"code",
"terminal",
"terminal-square",
"github",
"gitlab",
"git-branch",
"git-commit",
"database",
"server",
"cloud-download",
"cloud-upload",
"tag",
"tags",
"flag",
"pin",
"map-pin",
"compass",
"globe",
"rocket",
"car",
"bike",
"robot",
"apple",
"windows",
"linux",
"chrome",
"firefox",
"safari",
"credit-card",
"wallet",
"coins",
"book",
"book-open",
"award",
"trophy",
"badge",
"wrench",
"tool",
"package",
"box",
"archive",
"send",
"reply",
"forward",
"mail-open",
"tag-plus",
"tag-minus",
"flag-off",
"pin-off",
"map-pin-off",
"navigation",
"map",
"earth",
"plane",
"ship",
"anchor",
"helicopter",
"drone",
"android",
"keyhole",
"keys",
"fingerprint",
"scan",
"qr-code",
"barcode",
"receipt",
"piggy-bank",
"banknote"
];
};
var LUCIDE_ICONS = getIconList().map((id) => ({
id,
name: id.replace(/^lucide-/, "").replace(/-/g, " ").replace(/(^\w{1})|(\s+\w{1})/g, (letter) => letter.toUpperCase())
})).sort((a, b) => a.name.localeCompare(b.name));
var IconPickerModal = class extends import_obsidian7.FuzzySuggestModal {
constructor(app, onSelect) {
super(app);
this.onSelect = onSelect;
}
getItems() {
return LUCIDE_ICONS;
}
getItemText(item) {
return item.name;
}
onChooseItem(item, evt) {
const normalizedId = item.id.replace(/^lucide-/, "");
this.onSelect(normalizedId);
}
// Override to show icon preview
renderSuggestion(match, el) {
const item = match.item;
el.addClass("mod-complex");
const content = el.createDiv({ cls: "suggestion-content" });
content.createDiv({ cls: "suggestion-title", text: item.name });
const aux = el.createDiv({ cls: "suggestion-aux" });
(0, import_obsidian7.setIcon)(aux.createSpan({ cls: "suggestion-flair" }), item.id);
}
};
// src/ui/components/ConfirmModal.ts
var import_obsidian8 = require("obsidian");
var ConfirmModal = class extends import_obsidian8.Modal {
constructor(app, message, confirmText = "Confirm", cancelText = "Cancel") {
super(app);
this.message = message;
this.confirmText = confirmText;
this.cancelText = cancelText;
this.result = false;
this.resolvePromise = null;
}
onOpen() {
const { contentEl } = this;
contentEl.empty();
contentEl.addClass("astro-composer-confirm-modal");
contentEl.createEl("p", { text: this.message });
const buttonContainer = contentEl.createDiv({ cls: "modal-button-container" });
const cancelButton = buttonContainer.createEl("button", {
text: this.cancelText
});
cancelButton.onclick = () => {
this.result = false;
this.close();
};
const confirmButton = buttonContainer.createEl("button", {
text: this.confirmText,
cls: "mod-cta mod-warning"
});
confirmButton.onclick = () => {
this.result = true;
this.close();
};
}
onClose() {
const { contentEl } = this;
contentEl.empty();
if (this.resolvePromise) {
this.resolvePromise(this.result);
}
}
async waitForResult() {
return new Promise((resolve) => {
this.resolvePromise = resolve;
this.open();
});
}
};
// src/ui/settings-tab.ts
var AstroComposerSettingTab = class extends import_obsidian9.PluginSettingTab {
constructor(app, plugin) {
super(app, plugin);
this.icon = "lucide-pencil-line";
this.autoRenameContainer = null;
this.postsFolderContainer = null;
this.onlyAutomateContainer = null;
this.creationModeContainer = null;
this.indexFileContainer = null;
this.excludedDirsContainer = null;
this.underscorePrefixContainer = null;
this.autoInsertContainer = null;
this.pagesFieldsContainer = null;
this.pagesIndexFileContainer = null;
this.pagesOnlyAutomateContainer = null;
this.terminalCommandContainer = null;
this.configCommandContainer = null;
this.customContentTypesContainer = null;
this.terminalRibbonToggle = null;
this.configRibbonToggle = null;
this.terminalRibbonToggleComponent = null;
this.configRibbonToggleComponent = null;
this.plugin = plugin;
}
/**
* Refresh just the content types section
* More efficient than refreshing the entire settings tab
*/
refreshContentTypes() {
if (this.customContentTypesContainer) {
this.renderCustomContentTypes();
}
}
display() {
const { containerEl } = this;
containerEl.empty();
const settings = this.plugin.settings;
this.renderSettingsTab(containerEl, settings);
}
renderSettingsTab(containerEl, settings) {
var _a;
const generalGroup = new import_obsidian9.SettingGroup(containerEl);
generalGroup.addSetting((setting) => {
setting.setName("Date format").setDesc("Format for the date in properties (yyyy-mm-dd, MMMM D, yyyy, yyyy-mm-dd HH:mm)").addText(
(text) => text.setPlaceholder("YYYY-MM-DD").setValue(settings.dateFormat).onChange(async (value) => {
settings.dateFormat = value || "YYYY-MM-DD";
await this.plugin.saveSettings();
})
);
});
generalGroup.addSetting((setting) => {
setting.setName("Enable copy heading links").setDesc("Add right-click context menu option to copy heading links in various formats.").addToggle(
(toggle) => toggle.setValue(settings.enableCopyHeadingLink).onChange(async (value) => {
settings.enableCopyHeadingLink = value;
await this.plugin.saveSettings();
this.updateCopyHeadingFields();
})
);
});
generalGroup.addSetting((setting) => {
setting.setName("Default heading link format").setDesc("Choose the default format for copied heading links. Obsidian format respects your Obsidian settings for wikilink vs markdown preference. Astro link uses your link base path from above and converts the heading into kebab-case format as an anchor link").addDropdown(
(dropdown) => dropdown.addOption("obsidian", "Obsidian link").addOption("astro", "Astro link").setValue(settings.copyHeadingLinkFormat).onChange(async (value) => {
settings.copyHeadingLinkFormat = value;
await this.plugin.saveSettings();
})
);
setting.settingEl.classList.toggle("astro-composer-setting-container-visible", settings.enableCopyHeadingLink);
setting.settingEl.classList.toggle("astro-composer-setting-container-hidden", !settings.enableCopyHeadingLink);
});
generalGroup.addSetting((setting) => {
setting.setName("Add trailing slash to links").setDesc("Add trailing slashes to all converted internal links (/about/ instead of /about).").addToggle(
(toggle) => toggle.setValue(settings.addTrailingSlashToLinks).onChange(async (value) => {
settings.addTrailingSlashToLinks = value;
await this.plugin.saveSettings();
})
);
});
generalGroup.addSetting((setting) => {
setting.setName("Process background file changes").setDesc("Automatically process new files when they're changed in the background (by Git or other plugins). Disable to prevent modal spam when files are already processed on other devices during a sync.").addToggle(
(toggle) => toggle.setValue(settings.processBackgroundFileChanges).onChange(async (value) => {
settings.processBackgroundFileChanges = value;
await this.plugin.saveSettings();
})
);
});
generalGroup.addSetting((setting) => {
setting.setName("Show MDX files in file explorer").setDesc("Make .mdx files visible in Obsidian's file explorer. Requires reload to take effect.").addToggle(
(toggle) => toggle.setValue(settings.showMdxFilesInExplorer).onChange(async (value) => {
settings.showMdxFilesInExplorer = value;
await this.plugin.saveSettings();
})
);
});
const automationGroup = new import_obsidian9.SettingGroup(containerEl).setHeading("Property automation");
automationGroup.addSetting((setting) => {
setting.setName("Auto-insert properties").setDesc("Automatically insert the properties template when creating new files.").addToggle(
(toggle) => toggle.setValue(settings.autoInsertProperties).onChange(async (value) => {
settings.autoInsertProperties = value;
await this.plugin.saveSettings();
})
);
});
automationGroup.addSetting((setting) => {
setting.setName("Rename file on title property click").setDesc("When enabled, clicking into the title property will trigger the rename file command, keeping the file slug in sync.").addToggle(
(toggle) => toggle.setValue(settings.renameOnTitleClick).onChange(async (value) => {
settings.renameOnTitleClick = value;
await this.plugin.saveSettings();
})
);
});
automationGroup.addSetting((setting) => {
setting.setName("Update date on publish").setDesc("Update 'date' property when switching from draft to published status.").addToggle(
(toggle) => toggle.setValue(settings.syncDraftDate).onChange(async (value) => {
settings.syncDraftDate = value;
await this.plugin.saveSettings();
const scrollTop = this.containerEl.scrollTop;
this.display();
this.containerEl.scrollTop = scrollTop;
})
);
});
if (settings.syncDraftDate) {
automationGroup.addSetting((setting) => {
setting.setName("Draft detection mode").setDesc("How draft status is determined. Property-based uses a boolean property (draft: true). Underscore prefix uses the file name (_my-post.md = draft).").addDropdown(
(dropdown) => dropdown.addOption("property", "Property-based").addOption("underscore-prefix", "Underscore prefix").setValue(settings.draftDetectionMode || "property").onChange(async (value) => {
var _a2;
settings.draftDetectionMode = value;
await this.plugin.saveSettings();
(_a2 = this.plugin.frontmatterService) == null ? void 0 : _a2.initializeDraftStatusMap();
const scrollTop = this.containerEl.scrollTop;
this.display();
this.containerEl.scrollTop = scrollTop;
})
);
});
if (settings.draftDetectionMode !== "underscore-prefix") {
automationGroup.addSetting((setting) => {
setting.setName("Draft property name").setDesc("The property field to use for draft status.").addText(
(text) => text.setPlaceholder("draft").setValue(settings.draftProperty || "").onChange(async (value) => {
var _a2;
settings.draftProperty = value;
await this.plugin.saveSettings();
(_a2 = this.plugin.frontmatterService) == null ? void 0 : _a2.initializeDraftStatusMap();
})
);
});
automationGroup.addSetting((setting) => {
setting.setName("Draft logic").setDesc("Whether the property value 'true' means it is a draft or published.").addDropdown(
(dropdown) => dropdown.addOption("true-is-draft", "True = Draft").addOption("false-is-draft", "True = Published").setValue(settings.draftLogic || "true-is-draft").onChange(async (value) => {
var _a2;
settings.draftLogic = value;
await this.plugin.saveSettings();
(_a2 = this.plugin.frontmatterService) == null ? void 0 : _a2.initializeDraftStatusMap();
})
);
});
}
automationGroup.addSetting((setting) => {
setting.setName("Published date property name").setDesc("The property field to update when published ('date' or 'pubDate').").addText(
(text) => text.setPlaceholder("date").setValue(settings.publishDateField || "").onChange(async (value) => {
settings.publishDateField = value;
await this.plugin.saveSettings();
})
);
});
}
const contentTypesGroup = new import_obsidian9.SettingGroup(containerEl).setHeading("Content types");
contentTypesGroup.addSetting((setting) => {
setting.settingEl.addClass("astro-composer-setting-hidden-elements");
setting.settingEl.addClass("astro-composer-setting-container-full-width");
this.customContentTypesContainer = setting.settingEl.createDiv({
cls: "custom-content-types-container astro-composer-custom-types-container-visible"
});
});
if (this.customContentTypesContainer) {
this.renderCustomContentTypes();
}
if (!import_obsidian9.Platform.isMobile) {
const developerGroup = new import_obsidian9.SettingGroup(containerEl).setHeading("Developer commands");
developerGroup.addSetting((setting) => {
setting.setName("Enable open terminal command").setDesc("Enable command to open terminal in project root directory.").addToggle(
(toggle) => toggle.setValue(settings.enableOpenTerminalCommand).onChange(async (value) => {
settings.enableOpenTerminalCommand = value;
await this.plugin.saveSettings();
this.updateTerminalCommandFields();
if (this.plugin.registerRibbonIcons) {
this.plugin.registerRibbonIcons();
}
})
);
});
this.terminalCommandContainer = containerEl.createDiv({ cls: "terminal-command-fields" });
this.terminalCommandContainer.classList.toggle("astro-composer-setting-container-visible", settings.enableOpenTerminalCommand);
this.terminalCommandContainer.classList.toggle("astro-composer-setting-container-hidden", !settings.enableOpenTerminalCommand);
developerGroup.addSetting((setting) => {
const descFragment = document.createDocumentFragment();
descFragment.createEl("div", { text: "Path relative to the Obsidian vault root folder. Use ../.. for two levels up. Leave blank to use the vault folder" });
descFragment.createEl("div", { text: "This is where the terminal will open. Absolute paths work also." });
setting.setName("Project root directory path").setDesc(descFragment).addText(
(text) => text.setPlaceholder("../..").setValue(settings.terminalProjectRootPath).onChange(async (value) => {
settings.terminalProjectRootPath = value;
await this.plugin.saveSettings();
})
);
setting.settingEl.classList.toggle("astro-composer-setting-container-visible", settings.enableOpenTerminalCommand);
setting.settingEl.classList.toggle("astro-composer-setting-container-hidden", !settings.enableOpenTerminalCommand);
});
developerGroup.addSetting((setting) => {
const descFragment = document.createDocumentFragment();
descFragment.createEl("div", { text: "Leave blank to use platform defaults. On macOS, the default is Terminal. On Windows, it's Windows Terminal (Win 11) or cmd.exe (Win 10). On Linux, it's gnome-terminal, konsole, or xterm" });
descFragment.createEl("div", { text: "Examples include Terminal, iTerm, PowerShell, and Alacritty" });
setting.setName("Terminal application name").setDesc(descFragment).addText(
(text) => text.setPlaceholder("Terminal").setValue(settings.terminalApplicationName).onChange(async (value) => {
settings.terminalApplicationName = value;
await this.plugin.saveSettings();
})
);
setting.settingEl.classList.toggle("astro-composer-setting-container-visible", settings.enableOpenTerminalCommand);
setting.settingEl.classList.toggle("astro-composer-setting-container-hidden", !settings.enableOpenTerminalCommand);
});
developerGroup.addSetting((setting) => {
setting.setName("Enable debug logging").setDesc("Log terminal launch commands and platform decisions to the developer console for troubleshooting.").addToggle(
(toggle) => toggle.setValue(settings.enableTerminalDebugLogging).onChange(async (value) => {
settings.enableTerminalDebugLogging = value;
await this.plugin.saveSettings();
})
);
setting.settingEl.classList.toggle("astro-composer-setting-container-visible", settings.enableOpenTerminalCommand);
setting.settingEl.classList.toggle("astro-composer-setting-container-hidden", !settings.enableOpenTerminalCommand);
});
developerGroup.addSetting((setting) => {
setting.setName("Show open terminal ribbon icon").setDesc("Add a ribbon icon to launch the terminal command.").addToggle((toggle) => {
this.terminalRibbonToggleComponent = toggle;
toggle.setValue(settings.enableTerminalRibbonIcon).setDisabled(!settings.enableOpenTerminalCommand).onChange(async (value) => {
this.plugin.settings.enableTerminalRibbonIcon = value;
settings.enableTerminalRibbonIcon = value;
await this.plugin.saveSettings();
setTimeout(() => {
if (this.plugin.registerRibbonIcons) {
this.plugin.registerRibbonIcons();
}
}, 50);
});
});
setting.settingEl.classList.toggle("astro-composer-setting-container-visible", settings.enableOpenTerminalCommand);
setting.settingEl.classList.toggle("astro-composer-setting-container-hidden", !settings.enableOpenTerminalCommand);
this.terminalRibbonToggle = setting;
});
developerGroup.addSetting((setting) => {
setting.setName("Enable edit config file command").setDesc("Enable command to open astro config file in default editor.").addToggle(
(toggle) => toggle.setValue(settings.enableOpenConfigFileCommand).onChange(async (value) => {
settings.enableOpenConfigFileCommand = value;
await this.plugin.saveSettings();
this.updateConfigCommandFields();
if (this.plugin.registerRibbonIcons) {
this.plugin.registerRibbonIcons();
}
})
);
});
this.configCommandContainer = containerEl.createDiv({ cls: "config-command-fields" });
this.configCommandContainer.classList.toggle("astro-composer-setting-container-visible", settings.enableOpenConfigFileCommand);
this.configCommandContainer.classList.toggle("astro-composer-setting-container-hidden", !settings.enableOpenConfigFileCommand);
developerGroup.addSetting((setting) => {
const descFragment = document.createDocumentFragment();
descFragment.createEl("div", { text: "Path to the config file relative to the vault root. Use ../config.ts or ../../astro.config.mjs." });
descFragment.createEl("div", { text: "Absolute paths work also." });
setting.setName("Config file path").setDesc(descFragment).addText(
(text) => text.setPlaceholder("../config.ts").setValue(settings.configFilePath).onChange(async (value) => {
settings.configFilePath = value;
await this.plugin.saveSettings();
})
);
setting.settingEl.classList.toggle("astro-composer-setting-container-visible", settings.enableOpenConfigFileCommand);
setting.settingEl.classList.toggle("astro-composer-setting-container-hidden", !settings.enableOpenConfigFileCommand);
});
developerGroup.addSetting((setting) => {
setting.setName("Show open config ribbon icon").setDesc("Add a ribbon icon to launch the config file command.").addToggle((toggle) => {
this.configRibbonToggleComponent = toggle;
toggle.setValue(settings.enableConfigRibbonIcon).setDisabled(!settings.enableOpenConfigFileCommand).onChange(async (value) => {
this.plugin.settings.enableConfigRibbonIcon = value;
settings.enableConfigRibbonIcon = value;
await this.plugin.saveSettings();
setTimeout(() => {
if (this.plugin.registerRibbonIcons) {
this.plugin.registerRibbonIcons();
}
}, 50);
});
});
setting.settingEl.classList.toggle("astro-composer-setting-container-visible", settings.enableOpenConfigFileCommand);
setting.settingEl.classList.toggle("astro-composer-setting-container-hidden", !settings.enableOpenConfigFileCommand);
this.configRibbonToggle = setting;
});
developerGroup.addSetting((setting) => {
setting.setName("Swap out help button for custom action").setDesc("Replace the help button in the vault profile area with a custom action.").addToggle((toggle) => {
var _a2, _b;
return toggle.setValue((_b = (_a2 = settings.helpButtonReplacement) == null ? void 0 : _a2.enabled) != null ? _b : false).onChange(async (value) => {
if (!settings.helpButtonReplacement) {
settings.helpButtonReplacement = {
enabled: false,
commandId: "edit-astro-config",
iconId: "rocket"
};
}
settings.helpButtonReplacement.enabled = value;
await this.plugin.saveSettings();
if (this.plugin.updateHelpButton) {
await this.plugin.updateHelpButton();
}
this.display();
});
});
});
if ((_a = settings.helpButtonReplacement) == null ? void 0 : _a.enabled) {
const commandName = this.getCommandName(settings.helpButtonReplacement.commandId);
developerGroup.addSetting((setting) => {
setting.setName("Command").setDesc("Select the command to execute when the button is clicked.").addButton((button) => button.setButtonText(commandName || "Select command").onClick(() => {
const modal = new CommandPickerModal(this.app, (commandId) => {
void (async () => {
if (!settings.helpButtonReplacement) {
settings.helpButtonReplacement = {
enabled: true,
commandId: "edit-astro-config",
iconId: "rocket"
};
}
settings.helpButtonReplacement.commandId = commandId;
await this.plugin.saveSettings();
if (this.plugin.updateHelpButton) {
await this.plugin.updateHelpButton();
}
this.display();
})();
});
modal.open();
}));
});
const iconName = this.getIconName(settings.helpButtonReplacement.iconId);
developerGroup.addSetting((setting) => {
setting.setName("Icon").setDesc("Select the icon to display on the button.").addButton((button) => button.setButtonText(iconName || "Select icon...").onClick(() => {
const modal = new IconPickerModal(this.app, (iconId) => {
void (async () => {
if (!settings.helpButtonReplacement) {
settings.helpButtonReplacement = {
enabled: true,
commandId: "edit-astro-config",
iconId: "rocket"
};
}
settings.helpButtonReplacement.iconId = iconId;
await this.plugin.saveSettings();
if (this.plugin.updateHelpButton) {
await this.plugin.updateHelpButton();
}
this.display();
})();
});
modal.open();
}));
});
}
}
this.updateCopyHeadingFields();
if (!import_obsidian9.Platform.isMobile) {
this.updateTerminalCommandFields();
this.updateConfigCommandFields();
}
}
updateCopyHeadingFields() {
const settings = this.plugin.settings;
const isVisible = settings.enableCopyHeadingLink;
const containerEl = this.containerEl;
const allSettings = containerEl.querySelectorAll(".setting-item");
allSettings.forEach((settingEl) => {
var _a;
const nameEl = settingEl.querySelector(".setting-item-name");
if (nameEl && ((_a = nameEl.textContent) == null ? void 0 : _a.trim()) === "Default heading link format") {
settingEl.classList.toggle("astro-composer-setting-container-visible", isVisible);
settingEl.classList.toggle("astro-composer-setting-container-hidden", !isVisible);
}
});
}
updateTerminalCommandFields() {
const settings = this.plugin.settings;
const isVisible = settings.enableOpenTerminalCommand;
if (this.terminalCommandContainer) {
this.terminalCommandContainer.classList.toggle("astro-composer-setting-container-visible", isVisible);
this.terminalCommandContainer.classList.toggle("astro-composer-setting-container-hidden", !isVisible);
}
const containerEl = this.containerEl;
const allSettings = containerEl.querySelectorAll(".setting-item");
allSettings.forEach((settingEl) => {
var _a;
const nameEl = settingEl.querySelector(".setting-item-name");
if (nameEl) {
const name = (_a = nameEl.textContent) == null ? void 0 : _a.trim();
if (name === "Project root directory path" || name === "Show open terminal ribbon icon") {
settingEl.classList.toggle("astro-composer-setting-container-visible", isVisible);
settingEl.classList.toggle("astro-composer-setting-container-hidden", !isVisible);
}
}
});
if (this.terminalRibbonToggleComponent) {
this.terminalRibbonToggleComponent.setDisabled(!this.plugin.settings.enableOpenTerminalCommand);
}
}
updateConfigCommandFields() {
const settings = this.plugin.settings;
const isVisible = settings.enableOpenConfigFileCommand;
if (this.configCommandContainer) {
this.configCommandContainer.classList.toggle("astro-composer-setting-container-visible", isVisible);
this.configCommandContainer.classList.toggle("astro-composer-setting-container-hidden", !isVisible);
}
const containerEl = this.containerEl;
const allSettings = containerEl.querySelectorAll(".setting-item");
allSettings.forEach((settingEl) => {
var _a;
const nameEl = settingEl.querySelector(".setting-item-name");
if (nameEl) {
const name = (_a = nameEl.textContent) == null ? void 0 : _a.trim();
if (name === "Config file path" || name === "Show open config ribbon icon") {
settingEl.classList.toggle("astro-composer-setting-container-visible", isVisible);
settingEl.classList.toggle("astro-composer-setting-container-hidden", !isVisible);
}
}
});
if (this.configRibbonToggleComponent) {
this.configRibbonToggleComponent.setDisabled(!this.plugin.settings.enableOpenConfigFileCommand);
}
}
checkForFolderConflicts() {
const settings = this.plugin.settings;
const blankFolders = [];
const folderConflicts = {};
const contentTypes = settings.contentTypes || [];
for (const contentType of contentTypes) {
if (contentType.enabled) {
if (!contentType.folder || contentType.folder.trim() === "") {
blankFolders.push(contentType.name || "Content");
} else {
if (!folderConflicts[contentType.folder]) {
folderConflicts[contentType.folder] = [];
}
folderConflicts[contentType.folder].push(contentType.name || "Content");
}
}
}
}
addCustomContentType() {
const settings = this.plugin.settings;
const contentTypes = settings.contentTypes || [];
const newType = {
id: `content-${Date.now()}`,
name: `Content ${contentTypes.length + 1}`,
folder: "",
linkBasePath: "",
template: '---\ntitle: "{{title}}"\ndate: {{date}}\n---\n',
enabled: true,
creationMode: "file",
indexFileName: "",
ignoreSubfolders: false,
enableUnderscorePrefix: false,
useMdxExtension: false,
modifiedDateField: ""
};
contentTypes.push(newType);
settings.contentTypes = contentTypes;
void this.plugin.saveSettings();
this.renderCustomContentTypes();
this.plugin.registerCreateEvent();
registerContentTypeCommands(this.plugin, settings);
}
renderCustomContentTypes() {
if (!this.customContentTypesContainer) return;
this.customContentTypesContainer.empty();
const settings = this.plugin.settings;
const contentTypes = settings.contentTypes || [];
contentTypes.forEach((customType, index) => {
var _a, _b;
if (!this.customContentTypesContainer) return;
const typeContainer = this.customContentTypesContainer.createDiv({
cls: "custom-content-type-item",
attr: { "data-type-id": customType.id }
});
const header = typeContainer.createDiv({ cls: "custom-content-type-header" });
header.classList.add("astro-composer-custom-type-header");
const collapseButton = header.createEl("button", {
cls: "astro-composer-collapse-button",
attr: { "aria-label": "Collapse/expand" }
});
const isCollapsed = (_a = customType.collapsed) != null ? _a : false;
(0, import_obsidian9.setIcon)(collapseButton, "chevron-down");
if (isCollapsed) {
collapseButton.classList.add("is-collapsed");
}
collapseButton.addEventListener("click", () => {
void this.toggleContentTypeCollapse(customType.id);
const updatedType = this.plugin.settings.contentTypes.find((ct) => ct.id === customType.id);
if (updatedType) {
if (updatedType.collapsed) {
collapseButton.classList.add("is-collapsed");
} else {
collapseButton.classList.remove("is-collapsed");
}
}
});
const headerName = header.createDiv({ cls: "astro-composer-header-name" });
headerName.createEl("div", { text: customType.name || `Content ${index + 1}`, cls: "setting-item-name" });
const reorderContainer = header.createDiv({ cls: "astro-composer-reorder-buttons" });
const upButton = reorderContainer.createEl("button", {
cls: "astro-composer-reorder-button",
attr: { "aria-label": "Move up" }
});
(0, import_obsidian9.setIcon)(upButton, "chevron-up");
upButton.disabled = index === 0;
upButton.addEventListener("click", () => {
void this.moveContentTypeUp(customType.id);
});
const downButton = reorderContainer.createEl("button", {
cls: "astro-composer-reorder-button",
attr: { "aria-label": "Move down" }
});
(0, import_obsidian9.setIcon)(downButton, "chevron-down");
downButton.disabled = index === contentTypes.length - 1;
downButton.addEventListener("click", () => {
void this.moveContentTypeDown(customType.id);
});
const toggleContainer = header.createDiv({ cls: "checkbox-container" });
if (customType.enabled) {
toggleContainer.classList.add("is-enabled");
}
const toggle = toggleContainer.createEl("input", { type: "checkbox", cls: "checkbox-input" });
toggle.checked = customType.enabled;
toggleContainer.addEventListener("click", (e) => {
void (async () => {
e.preventDefault();
const newValue = !customType.enabled;
customType.enabled = newValue;
toggle.checked = newValue;
await this.plugin.saveSettings();
this.plugin.registerCreateEvent();
if (newValue) {
toggleContainer.classList.add("is-enabled");
} else {
toggleContainer.classList.remove("is-enabled");
}
this.updateCustomContentTypeVisibility(customType.id, newValue);
registerContentTypeCommands(this.plugin, this.plugin.settings);
})();
});
toggle.addEventListener("change", (e) => {
void (async () => {
const value = e.target.checked;
customType.enabled = value;
await this.plugin.saveSettings();
this.plugin.registerCreateEvent();
if (value) {
toggleContainer.classList.add("is-enabled");
} else {
toggleContainer.classList.remove("is-enabled");
}
this.updateCustomContentTypeVisibility(customType.id, value);
registerContentTypeCommands(this.plugin, this.plugin.settings);
})();
});
const settingsContainer = typeContainer.createDiv({
cls: "custom-content-type-settings",
attr: { "data-type-id": customType.id }
});
const initiallyCollapsed = (_b = customType.collapsed) != null ? _b : false;
const initiallyVisible = customType.enabled && !initiallyCollapsed;
if (initiallyVisible) {
settingsContainer.classList.add("astro-composer-setting-container-visible");
} else {
settingsContainer.classList.add("astro-composer-setting-container-hidden");
}
const nameContainer = settingsContainer.createDiv();
new import_obsidian9.Setting(nameContainer).setName("Content type name").setDesc("Display name for this content type ('projects', 'notes', 'tutorials')").addText((text) => {
text.setPlaceholder("Enter content type name").setValue(customType.name).onChange(async (value) => {
customType.name = value;
await this.plugin.saveSettings();
registerContentTypeCommands(this.plugin, this.plugin.settings);
});
});
const folderContainer = settingsContainer.createDiv();
const folderSetting = new import_obsidian9.Setting(folderContainer).setName("Folder location").setDesc("Folder path where this content type will be created. Leave blank to use the vault folder. Supports wildcards like directory/* or directory/*/* to match specific folder depths.").addText((text) => {
text.setPlaceholder("Enter folder path ('docs', 'docs/*', 'docs/*/*') or leave blank for vault root").setValue(customType.folder).onChange(async (value) => {
customType.folder = value;
await this.plugin.saveSettings();
this.plugin.registerCreateEvent();
this.updateCustomContentTypeIgnoreSubfoldersField(customType.id);
const allContentTypes = this.plugin.settings.contentTypes || [];
for (const ct of allContentTypes) {
this.updateFolderConflictWarning(ct.id, null);
}
});
});
folderContainer.createDiv({ cls: "astro-composer-conflict-warning hidden", attr: { "data-type-id": customType.id } });
this.updateFolderConflictWarning(customType.id, folderSetting);
const ignoreSubfoldersContainer = settingsContainer.createDiv({ cls: "custom-ignore-subfolders-field" });
ignoreSubfoldersContainer.setAttribute("data-type-id", customType.id);
ignoreSubfoldersContainer.classList.toggle("astro-composer-setting-container-visible", !!customType.folder);
ignoreSubfoldersContainer.classList.toggle("astro-composer-setting-container-hidden", !customType.folder);
new import_obsidian9.Setting(ignoreSubfoldersContainer).setName("Ignore subfolders").setDesc("When enabled, automation will only trigger for new .md files within this content type's folder and one level down (for folder-based content). Files in deeper subfolders will be ignored.").addToggle(
(toggle2) => toggle2.setValue(customType.ignoreSubfolders || false).onChange(async (value) => {
customType.ignoreSubfolders = value;
await this.plugin.saveSettings();
})
);
const underscorePrefixContainer = settingsContainer.createDiv();
new import_obsidian9.Setting(underscorePrefixContainer).setName("Use underscore prefix for drafts").setDesc("Add an underscore prefix (_content-title) to new notes by default when enabled. This hides them from astro, which can be helpful for drafts").addToggle(
(toggle2) => toggle2.setValue(customType.enableUnderscorePrefix || false).onChange(async (value) => {
customType.enableUnderscorePrefix = value;
await this.plugin.saveSettings();
})
);
const linkContainer = settingsContainer.createDiv();
new import_obsidian9.Setting(linkContainer).setName("Link base path").setDesc("Base path for converted links ('/projects/', '/notes/tutorials/', leave blank for root /).").addText((text) => {
text.setPlaceholder("Enter link base path").setValue(customType.linkBasePath || "").onChange(async (value) => {
customType.linkBasePath = value;
await this.plugin.saveSettings();
});
});
const creationModeContainer = settingsContainer.createDiv();
new import_obsidian9.Setting(creationModeContainer).setName("Creation mode").setDesc("How to create new entries: file-based or folder-based with an index file.").addDropdown(
(dropdown) => dropdown.addOption("file", "File-based (content-title.md)").addOption("folder", "Folder-based (content-title/index.md)").setValue(customType.creationMode).onChange(async (value) => {
customType.creationMode = value;
await this.plugin.saveSettings();
this.updateCustomContentTypeIndexFileField(customType.id);
})
);
const indexFileContainer = settingsContainer.createDiv({ cls: "custom-index-file-field" });
indexFileContainer.classList.toggle("astro-composer-setting-container-visible", customType.creationMode === "folder");
indexFileContainer.classList.toggle("astro-composer-setting-container-hidden", customType.creationMode !== "folder");
new import_obsidian9.Setting(indexFileContainer).setName("Index file name").setDesc("Name for index files in folder-based content (without .md extension). Defaults to 'index' if left blank.").addText(
(text) => text.setPlaceholder("index").setValue(customType.indexFileName).onChange(async (value) => {
customType.indexFileName = value;
await this.plugin.saveSettings();
})
);
const useMdxContainer = settingsContainer.createDiv();
new import_obsidian9.Setting(useMdxContainer).setName("Use MDX instead of MD").setDesc("Create files with .mdx extension instead of .md extension.").addToggle(
(toggle2) => toggle2.setValue(customType.useMdxExtension || false).onChange(async (value) => {
customType.useMdxExtension = value;
await this.plugin.saveSettings();
})
);
const modifiedDateContainer = settingsContainer.createDiv();
new import_obsidian9.Setting(modifiedDateContainer).setName("Modified date property").setDesc("The property field to update with the modified date for this content type. Leave blank to disable.").addText(
(text) => text.setPlaceholder("modified").setValue(customType.modifiedDateField || "").onChange(async (value) => {
customType.modifiedDateField = value;
await this.plugin.saveSettings();
})
);
const templateContainer = settingsContainer.createDiv();
new import_obsidian9.Setting(templateContainer).setName("Properties template").addTextArea((text) => {
text.setPlaceholder('---\ntitle: "{{title}}"\ndate: {{date}}\n---\n').setValue(customType.template).onChange(async (value) => {
customType.template = value;
await this.plugin.saveSettings();
});
text.inputEl.classList.add("astro-composer-template-textarea");
return text;
}).then((setting) => {
setting.descEl.empty();
const descDiv = setting.descEl.createEl("div");
descDiv.createEl("div", { text: "Template for new files of this content type." });
descDiv.createEl("div", { text: "Variables include {{title}}, {{date}}, and {{slug}}." });
descDiv.createEl("div", { text: "Do not wrap {{date}} in quotes as it represents a datetime value, not a string." });
});
const removeContainer = settingsContainer.createDiv();
const removeSetting = new import_obsidian9.Setting(removeContainer).setName("").addButton((button) => {
button.setButtonText("Remove").setWarning().onClick(async () => {
const contentType = this.plugin.settings.contentTypes.find((ct) => ct.id === customType.id);
const typeName = (contentType == null ? void 0 : contentType.name) || "content type";
const modal = new ConfirmModal(
this.app,
`Are you sure you want to remove "${typeName}"? This action cannot be undone.`,
"Remove",
"Cancel"
);
const confirmed = await modal.waitForResult();
if (confirmed) {
await this.removeCustomContentType(customType.id);
}
});
});
removeSetting.settingEl.classList.add("astro-composer-remove-setting");
this.updateCustomContentTypeVisibility(customType.id, customType.enabled);
});
contentTypes.forEach((customType) => {
this.updateFolderConflictWarning(customType.id, null);
});
const addButtonContainer = this.customContentTypesContainer.createDiv({ cls: "astro-composer-add-button-container" });
const addButton = addButtonContainer.createEl("button", {
cls: "mod-cta",
text: "Add content type"
});
addButton.addEventListener("click", () => {
this.addCustomContentType();
});
}
updateCustomContentTypeVisibility(typeId, enabled) {
var _a, _b;
const settingsContainer = (_a = this.customContentTypesContainer) == null ? void 0 : _a.querySelector(`[data-type-id="${typeId}"].custom-content-type-settings`);
if (settingsContainer) {
const contentTypes = this.plugin.settings.contentTypes || [];
const contentType = contentTypes.find((ct) => ct.id === typeId);
const isCollapsed = (_b = contentType == null ? void 0 : contentType.collapsed) != null ? _b : false;
const shouldBeVisible = enabled && !isCollapsed;
settingsContainer.classList.toggle("astro-composer-setting-container-visible", shouldBeVisible);
settingsContainer.classList.toggle("astro-composer-setting-container-hidden", !shouldBeVisible);
}
}
updateCustomContentTypeIndexFileField(typeId) {
var _a;
const contentTypes = this.plugin.settings.contentTypes || [];
const customType = contentTypes.find((type) => type.id === typeId);
if (!customType) return;
const indexFileContainer = (_a = this.customContentTypesContainer) == null ? void 0 : _a.querySelector(`[data-type-id="${typeId}"] .custom-index-file-field`);
if (indexFileContainer) {
indexFileContainer.classList.toggle("astro-composer-setting-container-visible", customType.creationMode === "folder");
indexFileContainer.classList.toggle("astro-composer-setting-container-hidden", customType.creationMode !== "folder");
}
}
updateCustomContentTypeIgnoreSubfoldersField(typeId) {
var _a;
const contentTypes = this.plugin.settings.contentTypes || [];
const customType = contentTypes.find((type) => type.id === typeId);
if (!customType) return;
const ignoreSubfoldersContainer = (_a = this.customContentTypesContainer) == null ? void 0 : _a.querySelector(`[data-type-id="${typeId}"].custom-ignore-subfolders-field`);
if (ignoreSubfoldersContainer) {
ignoreSubfoldersContainer.classList.toggle("astro-composer-setting-container-visible", !!customType.folder && customType.folder.trim() !== "");
ignoreSubfoldersContainer.classList.toggle("astro-composer-setting-container-hidden", !customType.folder || customType.folder.trim() === "");
}
}
updateFolderConflictWarning(typeId, setting) {
var _a;
const contentTypes = this.plugin.settings.contentTypes || [];
const currentType = contentTypes.find((type) => type.id === typeId);
if (!currentType) return;
const conflictWarningEl = (_a = this.customContentTypesContainer) == null ? void 0 : _a.querySelector(`[data-type-id="${typeId}"].astro-composer-conflict-warning`);
if (!conflictWarningEl) return;
const currentFolder = (currentType.folder || "").trim();
const conflictingTypes = [];
for (const otherType of contentTypes) {
if (otherType.id === typeId || !otherType.enabled) continue;
const otherFolder = (otherType.folder || "").trim();
if (currentFolder === "" && otherFolder === "") {
conflictingTypes.push(otherType.name || "Unnamed");
} else if (currentFolder === otherFolder && currentFolder !== "") {
conflictingTypes.push(otherType.name || "Unnamed");
}
}
if (conflictingTypes.length > 0) {
conflictWarningEl.removeClass("hidden");
conflictWarningEl.textContent = `Conflict: ${conflictingTypes.join(", ")} also use${conflictingTypes.length === 1 ? "s" : ""} this folder. More specific patterns will take priority.`;
} else {
conflictWarningEl.addClass("hidden");
}
}
async moveContentTypeUp(typeId) {
const settings = this.plugin.settings;
const contentTypes = settings.contentTypes || [];
const currentIndex = contentTypes.findIndex((ct) => ct.id === typeId);
if (currentIndex <= 0) return;
[contentTypes[currentIndex], contentTypes[currentIndex - 1]] = [contentTypes[currentIndex - 1], contentTypes[currentIndex]];
settings.contentTypes = contentTypes;
await this.plugin.saveSettings();
this.renderCustomContentTypes();
}
async moveContentTypeDown(typeId) {
const settings = this.plugin.settings;
const contentTypes = settings.contentTypes || [];
const currentIndex = contentTypes.findIndex((ct) => ct.id === typeId);
if (currentIndex < 0 || currentIndex >= contentTypes.length - 1) return;
[contentTypes[currentIndex], contentTypes[currentIndex + 1]] = [contentTypes[currentIndex + 1], contentTypes[currentIndex]];
settings.contentTypes = contentTypes;
await this.plugin.saveSettings();
this.renderCustomContentTypes();
}
async toggleContentTypeCollapse(typeId) {
const settings = this.plugin.settings;
const contentTypes = settings.contentTypes || [];
const contentType = contentTypes.find((ct) => ct.id === typeId);
if (!contentType) return;
contentType.collapsed = !contentType.collapsed;
await this.plugin.saveSettings();
this.updateCustomContentTypeVisibility(typeId, contentType.enabled);
}
async removeCustomContentType(typeId) {
const settings = this.plugin.settings;
const contentTypes = settings.contentTypes || [];
settings.contentTypes = contentTypes.filter((ct) => ct.id !== typeId);
await this.plugin.saveSettings();
this.renderCustomContentTypes();
this.plugin.registerCreateEvent();
registerContentTypeCommands(this.plugin, settings);
}
getCommandName(commandId) {
if (!commandId) return "";
try {
const commandRegistry = this.app.commands;
if (commandRegistry && typeof commandRegistry.listCommands === "function") {
try {
const allCommands = commandRegistry.listCommands();
const command = allCommands.find((cmd) => cmd.id === commandId);
if (command == null ? void 0 : command.name) {
return command.name;
}
} catch (e) {
console.warn("[Astro Composer] Error getting command name via listCommands():", e);
}
}
try {
const registry = commandRegistry == null ? void 0 : commandRegistry.commands;
if (registry && typeof registry === "object") {
const command = registry[commandId];
if (command == null ? void 0 : command.name) {
return command.name;
}
}
} catch (e) {
console.warn("[Astro Composer] Error getting command name via registry:", e);
}
} catch (e) {
console.warn("[Astro Composer] Error getting command name:", e);
}
return "";
}
getIconName(iconId) {
if (!iconId) return "";
return iconId.replace(/^lucide-/, "").split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
}
};
// src/utils/heading-link-generator.ts
var HeadingLinkGenerator = class {
constructor(settings, plugin) {
this.settings = settings;
this.plugin = plugin;
}
// Get fresh settings from plugin if available, otherwise use stored settings
getSettings() {
var _a;
if ((_a = this.plugin) == null ? void 0 : _a.settings) {
return this.plugin.settings;
}
return this.settings;
}
/**
* Converts text to kebab-case slug for URLs
*/
// Local toKebabCase removed, using imported one instead
/**
* Gets the Astro-compatible URL from an internal link (copied from LinkConverter)
*/
getAstroUrlFromInternalLink(link) {
const hashIndex = link.indexOf("#");
let path = hashIndex >= 0 ? link.slice(0, hashIndex) : link;
const anchor = hashIndex >= 0 ? link.slice(hashIndex) : "";
path = path.replace(/\.md$/, "");
let basePath = "";
let contentFolder = "";
let creationMode = "file";
let indexFileName = "";
const settings = this.getSettings();
const contentTypes = settings.contentTypes || [];
const sortedTypes = sortByPatternSpecificity(contentTypes);
for (const contentType of sortedTypes) {
if (!contentType.enabled) continue;
let matches = false;
if (!contentType.folder || contentType.folder.trim() === "") {
if (!path.includes("/") || path.split("/").length === 1) {
matches = true;
}
} else if (matchesFolderPattern(path, contentType.folder)) {
matches = true;
}
if (matches) {
contentFolder = contentType.folder || "";
basePath = contentType.linkBasePath || "";
creationMode = contentType.creationMode;
indexFileName = contentType.indexFileName || "";
break;
}
}
if (contentFolder) {
path = path.slice(contentFolder.length + 1);
}
let addTrailingSlash = false;
if (indexFileName && indexFileName.trim() !== "") {
const parts = path.split("/");
if (parts[parts.length - 1] === indexFileName) {
parts.pop();
path = parts.join("/");
addTrailingSlash = true;
}
} else if (creationMode === "folder") {
const defaultIndexName = "index";
const parts = path.split("/");
if (parts[parts.length - 1] === defaultIndexName) {
parts.pop();
path = parts.join("/");
addTrailingSlash = true;
}
}
const slugParts = path.split("/").map((part) => toKebabCase(part));
const slug = slugParts.join("/");
if (basePath) {
if (!basePath.startsWith("/")) basePath = "/" + basePath;
if (!basePath.endsWith("/")) basePath += "/";
}
const shouldAddTrailingSlash = (settings.addTrailingSlashToLinks || addTrailingSlash) && !anchor;
return `${basePath}${slug}${shouldAddTrailingSlash ? "/" : ""}${anchor}`;
}
/**
* Generates a standard Obsidian link to a heading, respecting user's link format preference
*/
generateObsidianLink(app, file, heading) {
const headingText = heading.heading;
const testLink = app.fileManager.generateMarkdownLink(file, "", "");
if (testLink.startsWith("[[")) {
const fileName = file.basename;
return `[[${fileName}#${headingText}|${headingText}]]`;
} else {
const baseLink = app.fileManager.generateMarkdownLink(file, "", "");
if (baseLink.startsWith("[[")) {
const fileName = file.basename;
return `[[${fileName}#${headingText}|${headingText}]]`;
} else {
const match = baseLink.match(/\[([^\]]+)\]\(([^)]+)\)/);
if (match) {
const [, , path] = match;
return `[${headingText}](${path}#${encodeURIComponent(headingText)})`;
} else {
const encodedFilename = encodeURIComponent(file.name);
return `[${headingText}](${encodedFilename}#${encodeURIComponent(headingText)})`;
}
}
}
}
/**
* Generates a standard Obsidian wikilink to a heading
*/
generateObsidianWikilink(file, heading) {
const headingText = heading.heading;
const fileName = file.basename;
return `[[${fileName}#${headingText}|${headingText}]]`;
}
/**
* Generates an Astro-compatible markdown link to a heading
*/
generateAstroLink(file, heading) {
const headingText = heading.heading;
const anchor = toKebabCase(headingText);
const internalLink = `${file.path}#${anchor}`;
const astroUrl = this.getAstroUrlFromInternalLink(internalLink);
return `[${headingText}](${astroUrl})`;
}
/**
* Generates an Astro-compatible wikilink to a heading
*/
generateAstroWikilink(file, heading) {
const headingText = heading.heading;
const anchor = toKebabCase(headingText);
const internalLink = `${file.path}#${anchor}`;
const astroUrl = this.getAstroUrlFromInternalLink(internalLink);
return `[[${headingText}|${astroUrl}]]`;
}
/**
* Extracts the URL from a markdown link or wikilink
*/
extractUrl(link) {
const markdownMatch = link.match(/\[([^\]]+)\]\(([^)]+)\)/);
if (markdownMatch) {
return markdownMatch[2];
}
const wikilinkMatch = link.match(/\[\[([^\]]+)\]\]/);
if (wikilinkMatch) {
const content = wikilinkMatch[1];
const pathPart = content.split("|")[0];
return pathPart;
}
return link;
}
/**
* Generates the appropriate link format based on settings
*/
generateLink(app, file, heading) {
const settings = this.getSettings();
if (settings.copyHeadingLinkFormat === "astro") {
return this.generateAstroLink(file, heading);
} else {
return this.generateObsidianLink(app, file, heading);
}
}
/**
* Finds the heading at a specific line in a file
*/
findHeadingAtLine(app, file, line) {
const cache = app.metadataCache.getFileCache(file);
if (!cache || !cache.headings) {
return null;
}
for (let i = cache.headings.length - 1; i >= 0; i--) {
const heading = cache.headings[i];
if (heading.position.start.line <= line) {
return heading;
}
}
return null;
}
};
// src/services/MigrationService.ts
var import_obsidian11 = require("obsidian");
// src/ui/components/MigrationModal.ts
var import_obsidian10 = require("obsidian");
var MigrationModal = class extends import_obsidian10.Modal {
constructor(app, conflicts) {
super(app);
this.result = null;
this.resolvePromise = null;
}
onOpen() {
const { contentEl } = this;
contentEl.empty();
contentEl.addClass("astro-composer-migration-modal");
contentEl.createEl("h2", { text: "Migration conflict detected" });
contentEl.createEl("p", {
text: "You have existing content types with names that conflict with posts or pages. How would you like to proceed?"
});
const conflictList = contentEl.createEl("ul");
conflictList.createEl("li", { text: "Skip migration: keep your existing posts/pages settings (they will be ignored)" });
conflictList.createEl("li", { text: "Migrate with renamed types: create 'posts (migrated)' and 'pages (migrated)' content types" });
const buttonContainer = contentEl.createDiv({ cls: "modal-button-container" });
const skipButton = buttonContainer.createEl("button", {
text: "Skip migration",
cls: "mod-cta"
});
skipButton.onclick = () => {
this.result = { action: "skip" };
this.close();
};
const migrateButton = buttonContainer.createEl("button", {
text: "Migrate with renamed types",
cls: "mod-cta"
});
migrateButton.onclick = () => {
this.result = { action: "migrate" };
this.close();
};
}
onClose() {
const { contentEl } = this;
contentEl.empty();
if (this.resolvePromise && this.result) {
this.resolvePromise(this.result);
}
}
async waitForResult() {
return new Promise((resolve) => {
this.resolvePromise = resolve;
this.open();
});
}
};
// src/services/MigrationService.ts
var MigrationService = class {
constructor(app, plugin) {
this.app = app;
this.plugin = plugin;
}
/**
* Migrate old posts/pages settings to unified content types
*/
async migrateSettingsIfNeeded() {
const settings = this.plugin.settings;
if (settings.migrationCompleted) {
return;
}
const hasPostsSettings = settings.automatePostCreation !== void 0 && settings.automatePostCreation;
const hasPagesSettings = settings.enablePages !== void 0 && settings.enablePages;
if (!hasPostsSettings && !hasPagesSettings) {
settings.migrationCompleted = true;
await this.plugin.saveSettings();
return;
}
const legacyContentTypes = settings.customContentTypes;
const existingContentTypes = settings.contentTypes || legacyContentTypes || [];
const conflicts = [];
if (existingContentTypes.some((ct) => ct.name === "Posts")) {
conflicts.push("Posts");
}
if (existingContentTypes.some((ct) => ct.name === "Pages")) {
conflicts.push("Pages");
}
let shouldMigrate = true;
if (conflicts.length > 0) {
await new Promise((resolve) => {
setTimeout(() => {
void (async () => {
try {
const modal = new MigrationModal(this.app, conflicts);
const timeoutPromise = new Promise((timeoutResolve) => {
setTimeout(() => {
timeoutResolve({ action: "skip" });
}, 3e4);
});
const result = await Promise.race([
modal.waitForResult(),
timeoutPromise
]);
if (result.action === "skip") {
shouldMigrate = false;
new import_obsidian11.Notice("Migration skipped. Old posts/pages settings will be ignored.");
}
} catch (error) {
console.warn("Migration modal error:", error);
shouldMigrate = false;
new import_obsidian11.Notice("Migration skipped due to error. You can migrate manually in settings.");
}
resolve();
})();
}, 500);
});
}
if (!shouldMigrate) {
settings.migrationCompleted = true;
await this.plugin.saveSettings();
return;
}
const migratedTypes = [];
if (hasPostsSettings && !conflicts.includes("Posts")) {
const postsType = {
id: `posts-${Date.now()}`,
name: "Posts",
folder: settings.postsFolder || "",
linkBasePath: settings.postsLinkBasePath || "",
template: settings.defaultTemplate || '---\ntitle: "{{title}}"\ndate: {{date}}\ntags: []\n---\n',
enabled: true,
creationMode: settings.creationMode || "file",
indexFileName: settings.indexFileName || "",
ignoreSubfolders: settings.onlyAutomateInPostsFolder || false,
enableUnderscorePrefix: settings.enableUnderscorePrefix || false,
useMdxExtension: false,
modifiedDateField: ""
};
migratedTypes.push(postsType);
}
if (hasPagesSettings && !conflicts.includes("Pages")) {
const pagesType = {
id: `pages-${Date.now()}`,
name: "Pages",
folder: settings.pagesFolder || "",
linkBasePath: settings.pagesLinkBasePath || "",
template: settings.pageTemplate || '---\ntitle: "{{title}}"\ndescription: ""\n---\n',
enabled: true,
creationMode: settings.pagesCreationMode || "file",
indexFileName: settings.pagesIndexFileName || "",
ignoreSubfolders: settings.onlyAutomateInPagesFolder || false,
enableUnderscorePrefix: false,
useMdxExtension: false,
modifiedDateField: ""
};
migratedTypes.push(pagesType);
}
const existingFromNew = settings.contentTypes || [];
const existingFromLegacy = legacyContentTypes || [];
let existingTypes = existingFromNew.length > 0 ? existingFromNew : existingFromLegacy;
let finalTypes = [...existingTypes];
if (migratedTypes.length > 0) {
const existingNames = new Set(existingTypes.map((ct) => ct.name));
const newMigratedTypes = migratedTypes.filter((mt) => !existingNames.has(mt.name));
if (newMigratedTypes.length > 0) {
finalTypes = [...existingTypes, ...newMigratedTypes];
}
}
settings.contentTypes = finalTypes;
const legacyFields = [
"customContentTypes",
"enableUnderscorePrefix",
"postsFolder",
"postsLinkBasePath",
"automatePostCreation",
"creationMode",
"indexFileName",
"excludedDirectories",
"onlyAutomateInPostsFolder",
"enablePages",
"pagesFolder",
"pagesLinkBasePath",
"pagesCreationMode",
"pagesIndexFileName",
"pageTemplate",
"onlyAutomateInPagesFolder"
];
const settingsRecord = settings;
for (const field of legacyFields) {
delete settingsRecord[field];
}
settings.migrationCompleted = true;
await this.plugin.saveSettings();
await this.plugin.loadSettings();
if (migratedTypes.length > 0) {
new import_obsidian11.Notice(`Migration completed: ${migratedTypes.length} content type(s) migrated.`);
setTimeout(() => {
if (this.plugin.settingsTab instanceof AstroComposerSettingTab) {
const settingsTab = this.plugin.settingsTab;
try {
if (settingsTab.customContentTypesContainer || settingsTab.containerEl) {
settingsTab.display();
}
} catch (e) {
console.warn("Could not refresh settings tab after migration:", e);
}
}
}, 300);
}
}
};
// src/services/CreateEventService.ts
var import_obsidian12 = require("obsidian");
var CreateEventService = class {
constructor(app, plugin) {
this.app = app;
this.plugin = plugin;
this.lastProcessedFiles = /* @__PURE__ */ new Map();
}
handleCreate(file) {
void (async () => {
const now = Date.now();
if (!(file instanceof import_obsidian12.TFile) || file.extension !== "md" && file.extension !== "mdx") {
return;
}
const filePath = file.path;
const createdTime = this.plugin.pluginCreatedFiles.get(filePath);
if (createdTime && now - createdTime < 5 * 60 * 1e3) {
return;
}
const lastProcessed = this.lastProcessedFiles.get(filePath) || 0;
if (lastProcessed > 0 && now - lastProcessed < CONSTANTS.DEBOUNCE_MS) {
return;
}
if (lastProcessed > 0 && now - lastProcessed > 2e3) {
this.lastProcessedFiles.delete(filePath);
}
const periodicCutoff = now - CONSTANTS.DEBOUNCE_MS * 2;
for (const [path, time] of this.lastProcessedFiles.entries()) {
if (time < periodicCutoff) {
this.lastProcessedFiles.delete(path);
}
}
const contentTypes = this.plugin.settings.contentTypes || [];
const hasEnabledContentTypes = contentTypes.some((ct) => ct.enabled);
if (!hasEnabledContentTypes) {
return;
}
const sortedContentTypes = sortByPatternSpecificity(contentTypes);
let matchedContentTypeId = null;
const matchingTypes = [];
for (const contentType of sortedContentTypes) {
if (!contentType.enabled) continue;
let matches = false;
if (!contentType.folder || contentType.folder.trim() === "") {
if (!filePath.includes("/") || filePath.split("/").length === 1) {
matches = true;
}
} else if (matchesFolderPattern(filePath, contentType.folder)) {
if (contentType.ignoreSubfolders) {
const pathSegments = filePath.split("/");
const pathDepth = pathSegments.length;
const patternSegments = contentType.folder.split("/");
const expectedDepth = patternSegments.length;
if (contentType.creationMode === "folder") {
const folderDepth = pathDepth - 1;
if (folderDepth === expectedDepth || folderDepth === expectedDepth + 1) {
matches = true;
}
} else {
if (pathDepth === expectedDepth) {
matches = true;
}
}
} else {
matches = true;
}
}
if (matches) {
matchingTypes.push(contentType);
if (!matchedContentTypeId) {
matchedContentTypeId = contentType.id;
}
}
}
if (matchingTypes.length > 1) {
const typeNames = matchingTypes.map((ct) => ct.name || "Unnamed").join(", ");
new import_obsidian12.Notice(`Multiple content types (${typeNames}) match this file. Using most specific: ${matchingTypes[0].name || "Unnamed"}`);
}
if (!matchedContentTypeId) {
return;
}
const fileName = file.basename;
const isUntitled = /^Untitled(\s\d+)?$/.test(fileName);
if (!isUntitled) {
if (!this.plugin.settings.processBackgroundFileChanges) {
return;
}
const stat = await this.app.vault.adapter.stat(file.path);
const isRecent = (stat == null ? void 0 : stat.mtime) && now - stat.mtime < CONSTANTS.STAT_MTIME_THRESHOLD;
if (!isRecent) {
return;
}
let content;
try {
content = await this.app.vault.read(file);
} catch (e) {
return;
}
if (content.trim().length > 0) {
const contentWithoutFrontmatter = content.startsWith("---") ? content.slice(content.indexOf("\n---", 3) + 4).trim() : content.trim();
if (contentWithoutFrontmatter.length > 0) {
return;
}
}
}
await new Promise((resolve) => setTimeout(resolve, 100));
this.lastProcessedFiles.set(file.path, now);
setTimeout(() => {
this.lastProcessedFiles.delete(file.path);
}, CONSTANTS.DEBOUNCE_MS + 100);
new TitleModal(this.app, file, this.plugin, matchedContentTypeId, false, true).open();
})();
}
};
// src/services/FrontmatterService.ts
var import_obsidian13 = require("obsidian");
var FrontmatterService = class {
constructor(app, plugin) {
this.app = app;
this.plugin = plugin;
this.lastProcessedFile = "";
this.lastProcessedTime = 0;
this.debounceTimeout = null;
this.draftStatusMap = /* @__PURE__ */ new Map();
this.contentHashCache = /* @__PURE__ */ new Map();
this.registerEvents();
this.app.workspace.onLayoutReady(() => {
this.initializeDraftStatusMap();
});
}
destroy() {
}
initializeDraftStatusMap() {
var _a;
this.draftStatusMap.clear();
const settings = this.plugin.settings;
const isUnderscoreMode = settings.draftDetectionMode === "underscore-prefix";
const draftProp = settings.draftProperty || "draft";
const files = this.app.vault.getFiles().filter((f) => f instanceof import_obsidian13.TFile && (f.extension === "md" || f.extension === "mdx"));
for (const file of files) {
if (isUnderscoreMode) {
this.draftStatusMap.set(file.path, file.name.startsWith("_"));
} else {
const cache = this.app.metadataCache.getFileCache(file);
const rawValue = (_a = cache == null ? void 0 : cache.frontmatter) == null ? void 0 : _a[draftProp];
this.draftStatusMap.set(file.path, this.calculateIsDraft(rawValue, settings));
}
}
}
calculateIsDraft(rawValue, settings) {
if (rawValue === void 0 || rawValue === null) return false;
const val = String(rawValue).toLowerCase();
if (settings.draftLogic === "false-is-draft") {
return val === "false" || val === "0" || rawValue === false;
} else {
return val === "true" || val === "1" || rawValue === true;
}
}
registerEvents() {
this.plugin.registerEvent(
this.app.metadataCache.on("changed", (file) => {
if (file instanceof import_obsidian13.TFile) {
this.onMetadataChange(file);
}
})
);
this.plugin.registerEvent(
this.app.vault.on("rename", (file, oldPath) => {
if (file instanceof import_obsidian13.TFile) {
this.onRename(file, oldPath);
}
})
);
this.plugin.registerEvent(
this.app.workspace.on("file-open", (file) => {
if (file instanceof import_obsidian13.TFile) {
void (async () => {
try {
const content = await this.app.vault.read(file);
this.contentHashCache.set(file.path, this.getContentHash(content));
} catch (e) {
console.error(`Failed to lazily initialize content hash for ${file.path}:`, e);
}
})();
}
})
);
}
onRename(file, oldPath) {
var _a;
const settings = this.plugin.settings;
if (!settings.syncDraftDate) return;
const oldName = oldPath.split("/").pop() || "";
const newName = file.name;
if (oldName.startsWith("_") && !newName.startsWith("_")) {
if (settings.draftDetectionMode === "underscore-prefix") {
void this.updateDate(file);
} else {
const contentType = (_a = this.plugin.fileOps) == null ? void 0 : _a.getContentTypeByPath(file.path);
if (contentType == null ? void 0 : contentType.enableUnderscorePrefix) {
void this.updateDate(file);
}
}
}
}
onMetadataChange(file) {
var _a, _b, _c;
const settings = this.plugin.settings;
if (settings.draftDetectionMode === "underscore-prefix") {
const contentType2 = (_a = this.plugin.fileOps) == null ? void 0 : _a.getContentTypeByPath(file.path);
const hasModifiedField2 = !!(contentType2 == null ? void 0 : contentType2.modifiedDateField);
if (!hasModifiedField2) return;
const activeFile2 = this.app.workspace.getActiveFile();
const isActiveFile2 = activeFile2 && activeFile2.path === file.path;
if (!settings.processBackgroundFileChanges && !isActiveFile2) return;
void this.processFile(file, false, contentType2);
return;
}
const activeFile = this.app.workspace.getActiveFile();
const isActiveFile = activeFile && activeFile.path === file.path;
if (!settings.processBackgroundFileChanges && !isActiveFile) {
return;
}
const contentType = (_b = this.plugin.fileOps) == null ? void 0 : _b.getContentTypeByPath(file.path);
const hasModifiedField = !!(contentType == null ? void 0 : contentType.modifiedDateField);
if (!settings.syncDraftDate && !hasModifiedField) {
return;
}
const cache = this.app.metadataCache.getFileCache(file);
const draftProp = settings.draftProperty || "draft";
const rawValue = (_c = cache == null ? void 0 : cache.frontmatter) == null ? void 0 : _c[draftProp];
const isCurrentlyDraft = this.calculateIsDraft(rawValue, settings);
if (!this.draftStatusMap.has(file.path)) {
this.draftStatusMap.set(file.path, isCurrentlyDraft);
return;
}
const previousDraftStatus = this.draftStatusMap.get(file.path);
let draftStatusChangedToPublished = false;
if (previousDraftStatus === true && isCurrentlyDraft === false) {
draftStatusChangedToPublished = true;
}
this.draftStatusMap.set(file.path, isCurrentlyDraft);
if (!draftStatusChangedToPublished && !hasModifiedField) {
return;
}
const now = Date.now();
if (this.lastProcessedFile === file.path && now - this.lastProcessedTime < 2e3) {
return;
}
if (this.debounceTimeout) {
window.clearTimeout(this.debounceTimeout);
}
this.debounceTimeout = window.setTimeout(async () => {
try {
const content = await this.app.vault.read(file);
const currentHash = this.getContentHash(content);
const previousHash = this.contentHashCache.get(file.path);
this.contentHashCache.set(file.path, currentHash);
if (previousHash === void 0) {
if (!draftStatusChangedToPublished) {
return;
}
} else if (previousHash === currentHash) {
if (!draftStatusChangedToPublished) {
return;
}
}
} catch (e) {
console.error(`Failed to check content hash for ${file.path}:`, e);
return;
}
void this.processFile(file, draftStatusChangedToPublished, contentType);
}, 500);
}
getContentHash(content) {
let body = content;
if (content.startsWith("---")) {
const end = content.indexOf("\n---", 3);
if (end !== -1) {
body = content.slice(end + 4);
}
}
const normalized = body.replace(/\s+/g, " ").trim();
return this.simpleHash(normalized);
}
simpleHash(str) {
let hash = 0;
for (let i = 0; i < str.length; i++) {
const char = str.charCodeAt(i);
hash = (hash << 5) - hash + char;
hash |= 0;
}
return hash.toString() + "_" + str.length;
}
async updateDate(file) {
const settings = this.plugin.settings;
const dateField = settings.publishDateField || "date";
await this.app.fileManager.processFrontMatter(file, (frontmatter) => {
const today = (0, import_obsidian13.moment)().format(settings.dateFormat);
if (frontmatter[dateField] !== today) {
frontmatter[dateField] = today;
this.lastProcessedFile = file.path;
this.lastProcessedTime = Date.now();
}
});
}
async processFile(file, draftStatusChangedToPublished, contentType) {
const settings = this.plugin.settings;
const publishDateField = settings.publishDateField || "date";
await this.app.fileManager.processFrontMatter(file, (frontmatter) => {
let changed = false;
if (settings.syncDraftDate && draftStatusChangedToPublished) {
const today = (0, import_obsidian13.moment)().format(settings.dateFormat);
if (frontmatter[publishDateField] !== today) {
frontmatter[publishDateField] = today;
changed = true;
}
}
const modifiedField = contentType == null ? void 0 : contentType.modifiedDateField;
if (modifiedField && frontmatter[modifiedField] !== void 0) {
const now = (0, import_obsidian13.moment)().format(settings.dateFormat);
if (frontmatter[modifiedField] !== now) {
frontmatter[modifiedField] = now;
changed = true;
}
}
if (changed) {
this.lastProcessedFile = file.path;
this.lastProcessedTime = Date.now();
}
});
}
};
// src/main.ts
var AstroComposerPlugin = class extends import_obsidian14.Plugin {
constructor() {
super(...arguments);
this.pluginCreatedFiles = /* @__PURE__ */ new Map();
this.processedFiles = /* @__PURE__ */ new Map();
this.terminalRibbonIcon = null;
this.configRibbonIcon = null;
}
/**
* Migrate old posts/pages settings to unified content types
*/
async migrateSettingsIfNeeded() {
if (!this.migrationService) {
this.migrationService = new MigrationService(this.app, this);
}
await this.migrationService.migrateSettingsIfNeeded();
}
async onload() {
try {
await this.loadSettings();
this.fileOps = new FileOperations(this.app, this.settings, this);
this.migrationService = new MigrationService(this.app, this);
this.createEventService = new CreateEventService(this.app, this);
this.frontmatterService = new FrontmatterService(this.app, this);
this.templateParser = new TemplateParser(this.app, this.settings, this);
this.headingLinkGenerator = new HeadingLinkGenerator(this.settings, this);
if (this.settings.showMdxFilesInExplorer) {
try {
this.registerExtensions(["mdx"], "markdown");
} catch (error) {
console.warn("[Astro Composer] MDX extension already registered:", error);
}
}
this.app.workspace.onLayoutReady(() => {
this.registerCreateEvent();
if (!import_obsidian14.Platform.isMobile) {
this.startHelpButtonMonitor();
}
this.registerTitlePropertyClickListener();
void this.migrateSettingsIfNeeded();
});
registerCommands(this, this.settings);
registerContentTypeCommands(this, this.settings);
this.settingsTab = new AstroComposerSettingTab(this.app, this);
this.addSettingTab(this.settingsTab);
this.registerContextMenu();
this.registerRibbonIcons();
this.setupRibbonContextMenuHandling();
} catch (error) {
console.error("[Astro Composer] Critical error during onload:", error);
new import_obsidian14.Notice("Astro Composer failed to load. Check console (Ctrl+Shift+I) for details.");
throw error;
}
}
registerCreateEvent() {
if (this.createEventRef) {
this.app.vault.offref(this.createEventRef);
this.createEventRef = void 0;
}
const createEventRef = this.app.vault.on("create", (file) => {
if (file instanceof import_obsidian14.TFile) {
this.createEventService.handleCreate(file);
this.cleanupPluginCreatedFiles();
}
});
this.registerEvent(createEventRef);
this.createEventRef = createEventRef;
}
registerTitlePropertyClickListener() {
this.registerDomEvent(document, "click", (evt) => {
if (!this.settings.renameOnTitleClick) return;
const target = evt.target;
const propertyEl = target.closest(".metadata-property");
if (!propertyEl) return;
const propertyKey = propertyEl.getAttribute("data-property-key");
if (!propertyKey) return;
const activeFile = this.app.workspace.getActiveFile();
if (!activeFile) return;
const typeId = this.fileOps.determineType(activeFile);
const titleKey = this.fileOps.getTitleKey(typeId);
if (propertyKey === titleKey) {
evt.preventDefault();
evt.stopPropagation();
this.renameContentByPath(activeFile.path);
}
}, true);
}
cleanupPluginCreatedFiles() {
const now = Date.now();
const ttl = 5 * 60 * 1e3;
for (const [path, timestamp] of this.pluginCreatedFiles.entries()) {
if (now - timestamp > ttl) {
this.pluginCreatedFiles.delete(path);
}
}
}
async loadSettings() {
const loadedData = await this.loadData();
if (!this.settings) {
this.settings = Object.assign({}, DEFAULT_SETTINGS, loadedData);
} else {
Object.assign(this.settings, loadedData);
}
if (!this.settings.contentTypes || !Array.isArray(this.settings.contentTypes)) {
this.settings.contentTypes = [];
}
if (!this.settings.migrationCompleted) {
const legacySettings = this.settings;
const hasLegacyTypes = legacySettings.customContentTypes && Array.isArray(legacySettings.customContentTypes) && legacySettings.customContentTypes.length > 0;
const hasNewTypes = this.settings.contentTypes && Array.isArray(this.settings.contentTypes) && this.settings.contentTypes.length > 0;
if (hasLegacyTypes && !hasNewTypes) {
this.settings.contentTypes = legacySettings.customContentTypes || [];
}
} else {
const legacyFields = [
"customContentTypes",
"enableUnderscorePrefix",
"postsFolder",
"postsLinkBasePath",
"automatePostCreation",
"creationMode",
"indexFileName",
"excludedDirectories",
"onlyAutomateInPostsFolder",
"enablePages",
"pagesFolder",
"pagesLinkBasePath",
"pagesCreationMode",
"pagesIndexFileName",
"pageTemplate",
"onlyAutomateInPagesFolder",
"linkBasePath",
"enableAutoRename",
"enableAutoInsertFrontmatter",
"draftStyle"
];
const settingsRecord = this.settings;
let fieldsRemoved = false;
for (const field of legacyFields) {
if (settingsRecord[field] !== void 0) {
delete settingsRecord[field];
fieldsRemoved = true;
}
}
if (fieldsRemoved) {
await this.saveSettings();
}
}
}
async saveSettings() {
await this.saveData(this.settings);
}
registerContextMenu() {
this.registerEvent(
this.app.workspace.on("editor-menu", (menu, editor, view) => {
if (!this.settings.enableCopyHeadingLink) {
return;
}
const cursor = editor.getCursor();
const file = view.file;
if (!(file instanceof import_obsidian14.TFile)) {
return;
}
const heading = this.headingLinkGenerator.findHeadingAtLine(this.app, file, cursor.line);
if (heading) {
const fullLink = this.headingLinkGenerator.generateLink(this.app, file, heading);
const urlOnly = this.headingLinkGenerator.extractUrl(fullLink);
menu.addItem((item) => {
item.setTitle("Copy heading link").setIcon("link-2").onClick(async () => {
await navigator.clipboard.writeText(urlOnly);
new import_obsidian14.Notice("Heading link copied to clipboard");
});
});
menu.addItem((item) => {
item.setTitle("Copy heading link with text").setIcon("heading").onClick(async () => {
await navigator.clipboard.writeText(fullLink);
new import_obsidian14.Notice("Heading link with text copied to clipboard");
});
});
}
})
);
}
renameContentByPath(filePath) {
renameContentByPath(this.app, filePath, this.settings, this);
}
registerRibbonIcons() {
if (import_obsidian14.Platform.isMobile) {
if (this.terminalRibbonIcon) {
try {
if (this.terminalRibbonIcon.parentNode) this.terminalRibbonIcon.remove();
} catch (e) {
}
this.terminalRibbonIcon = null;
}
if (this.configRibbonIcon) {
try {
if (this.configRibbonIcon.parentNode) this.configRibbonIcon.remove();
} catch (e) {
}
this.configRibbonIcon = null;
}
try {
const terminalIcons = document.querySelectorAll('.side-dock-ribbon-action[aria-label="Open project terminal"]');
terminalIcons.forEach((icon) => icon.remove());
const configIcons = document.querySelectorAll('.side-dock-ribbon-action[aria-label="Edit astro config"]');
configIcons.forEach((icon) => icon.remove());
} catch (e) {
}
return;
}
const terminalShouldExist = this.settings.enableTerminalRibbonIcon && this.settings.enableOpenTerminalCommand;
const configShouldExist = this.settings.enableConfigRibbonIcon && this.settings.enableOpenConfigFileCommand;
if (this.terminalRibbonIcon) {
try {
if (this.terminalRibbonIcon.parentNode) this.terminalRibbonIcon.remove();
} catch (e) {
}
this.terminalRibbonIcon = null;
}
if (this.configRibbonIcon) {
try {
if (this.configRibbonIcon.parentNode) this.configRibbonIcon.remove();
} catch (e) {
}
this.configRibbonIcon = null;
}
try {
document.querySelectorAll('.side-dock-ribbon-action[aria-label="Open project terminal"]').forEach((el) => el.remove());
document.querySelectorAll('.side-dock-ribbon-action[aria-label="Edit astro config"]').forEach((el) => el.remove());
} catch (e) {
}
if (terminalShouldExist) {
this.terminalRibbonIcon = this.addRibbonIcon("terminal-square", "Open project terminal", () => {
if (!this.settings.enableOpenTerminalCommand) {
new import_obsidian14.Notice("Open terminal command is disabled.");
return;
}
openTerminalInProjectRoot(this.app, this.settings);
});
if (this.terminalRibbonIcon) this.terminalRibbonIcon.setAttribute("data-astro-composer-terminal-ribbon", "true");
}
if (configShouldExist) {
this.configRibbonIcon = this.addRibbonIcon("rocket", "Edit astro config", async () => {
if (!this.settings.enableOpenConfigFileCommand) {
new import_obsidian14.Notice("Edit config file command is disabled.");
return;
}
await openConfigFile(this.app, this.settings);
});
if (this.configRibbonIcon) this.configRibbonIcon.setAttribute("data-astro-composer-config-ribbon", "true");
}
this.updateRibbonContextMenuCSS();
this.setupRibbonContextMenuObserver();
}
onunload() {
var _a;
(_a = this.frontmatterService) == null ? void 0 : _a.destroy();
if (this.terminalRibbonIcon) {
this.terminalRibbonIcon.remove();
this.terminalRibbonIcon = null;
}
if (this.configRibbonIcon) {
this.configRibbonIcon.remove();
this.configRibbonIcon = null;
}
if (this.ribbonContextMenuObserver) {
this.ribbonContextMenuObserver.disconnect();
this.ribbonContextMenuObserver = void 0;
}
document.body.removeClass("astro-composer-hide-terminal-icon");
document.body.removeClass("astro-composer-hide-config-icon");
if (this.helpButtonObserver) {
this.helpButtonObserver.disconnect();
this.helpButtonObserver = void 0;
}
if (this.customHelpButton) {
this.customHelpButton.remove();
this.customHelpButton = void 0;
}
this.helpButtonElement = void 0;
}
setupRibbonContextMenuHandling() {
this.updateRibbonContextMenuCSS();
this.setupRibbonContextMenuObserver();
}
updateRibbonContextMenuCSS() {
const terminalShouldBeHidden = !this.settings.enableTerminalRibbonIcon || !this.settings.enableOpenTerminalCommand;
const configShouldBeHidden = !this.settings.enableConfigRibbonIcon || !this.settings.enableOpenConfigFileCommand;
if (terminalShouldBeHidden) document.body.addClass("astro-composer-hide-terminal-icon");
else document.body.removeClass("astro-composer-hide-terminal-icon");
if (configShouldBeHidden) document.body.addClass("astro-composer-hide-config-icon");
else document.body.removeClass("astro-composer-hide-config-icon");
}
setupRibbonContextMenuObserver() {
if (this.ribbonContextMenuObserver) this.ribbonContextMenuObserver.disconnect();
const terminalShouldBeHidden = !this.settings.enableTerminalRibbonIcon || !this.settings.enableOpenTerminalCommand;
const configShouldBeHidden = !this.settings.enableConfigRibbonIcon || !this.settings.enableOpenConfigFileCommand;
if (!terminalShouldBeHidden && !configShouldBeHidden) return;
this.ribbonContextMenuObserver = new MutationObserver((mutations) => {
for (const mutation of mutations) {
if (mutation.addedNodes.length > 0) {
for (const node of Array.from(mutation.addedNodes)) {
if (node instanceof HTMLElement) {
if (node.classList.contains("menu") || node.querySelector(".menu")) {
this.removeRibbonIconsFromContextMenu(node);
}
}
}
}
}
});
this.ribbonContextMenuObserver.observe(document.body, { childList: true, subtree: true });
}
/**
* Starts a robust monitor that keeps the help button in sync with settings.
*/
startHelpButtonMonitor() {
if (this.helpButtonObserver) this.helpButtonObserver.disconnect();
this.syncHelpButton();
let timer = null;
let mutationCount = 0;
this.helpButtonObserver = new MutationObserver(() => {
mutationCount++;
if (timer) window.clearTimeout(timer);
const delay = mutationCount < 20 ? 0 : 100;
if (delay === 0) {
this.syncHelpButton();
} else {
timer = window.setTimeout(() => this.syncHelpButton(), delay);
}
});
this.helpButtonObserver.observe(document.body, {
childList: true,
subtree: true,
attributes: true,
attributeFilter: ["class", "src", "aria-label"]
});
}
/**
* Synchronizes the help button state based on settings.
*/
syncHelpButton() {
var _a, _b, _c, _d;
const enabled = (_a = this.settings.helpButtonReplacement) == null ? void 0 : _a.enabled;
if (enabled) document.body.addClass("astro-composer-hide-help-button");
else document.body.removeClass("astro-composer-hide-help-button");
if (!enabled) {
if (this.customHelpButton) {
this.customHelpButton.remove();
this.customHelpButton = void 0;
}
return;
}
const selectors = [
".workspace-drawer-vault-actions .clickable-icon svg.help",
".workspace-sidedock-vault-profile .clickable-icon svg.help",
".workspace-drawer .clickable-icon svg.help",
".clickable-icon svg.help"
];
let helpButtonSvg = null;
for (const selector of selectors) {
helpButtonSvg = document.querySelector(selector);
if (helpButtonSvg) break;
}
if (!helpButtonSvg) return;
const originalHelpButton = helpButtonSvg.parentElement;
if (!originalHelpButton) return;
const existingReplacement = (_b = originalHelpButton.parentElement) == null ? void 0 : _b.querySelector('[data-astro-composer-help-replacement="true"]');
if (existingReplacement) {
this.customHelpButton = existingReplacement;
return;
}
const customButton = originalHelpButton.cloneNode(true);
customButton.addClass("astro-composer-help-replacement");
customButton.removeAttribute("aria-label");
customButton.setAttribute("data-astro-composer-help-replacement", "true");
customButton.onclick = null;
const iconContainer = ((_c = customButton.querySelector("svg")) == null ? void 0 : _c.parentElement) || customButton;
try {
if (iconContainer instanceof HTMLElement) {
(0, import_obsidian14.setIcon)(iconContainer, this.settings.helpButtonReplacement.iconId);
}
} catch (error) {
console.warn("[Astro Composer] Error setting replacement icon:", error);
}
customButton.addEventListener("click", (evt) => {
var _a2, _b2;
evt.preventDefault();
evt.stopPropagation();
const commandId = (_a2 = this.settings.helpButtonReplacement) == null ? void 0 : _a2.commandId;
if (commandId) {
const appWithCommands = this.app;
if ((_b2 = appWithCommands.commands) == null ? void 0 : _b2.executeCommandById) {
void appWithCommands.commands.executeCommandById(commandId);
}
}
}, true);
(_d = originalHelpButton.parentElement) == null ? void 0 : _d.insertBefore(customButton, originalHelpButton);
this.customHelpButton = customButton;
}
restoreHelpButton() {
document.body.removeClass("astro-composer-hide-help-button");
if (this.customHelpButton) {
this.customHelpButton.remove();
this.customHelpButton = void 0;
}
this.helpButtonElement = void 0;
}
removeRibbonIconsFromContextMenu(menuElement) {
var _a, _b;
const terminalShouldBeHidden = !this.settings.enableTerminalRibbonIcon || !this.settings.enableOpenTerminalCommand;
const configShouldBeHidden = !this.settings.enableConfigRibbonIcon || !this.settings.enableOpenConfigFileCommand;
const menuItems = menuElement.querySelectorAll(".menu-item");
for (const item of Array.from(menuItems)) {
const svg = item.querySelector("svg");
if (svg) {
let iconName = svg.getAttribute("data-lucide") || svg.getAttribute("xmlns:lucide") || svg.getAttribute("data-icon") || (svg.classList.contains("lucide-terminal-square") ? "terminal-square" : null) || (svg.classList.contains("lucide-rocket") ? "rocket" : null) || (svg.classList.contains("lucide-wrench") ? "wrench" : null);
if (iconName) iconName = iconName.replace(/^lucide-/, "");
if (terminalShouldBeHidden && iconName === "terminal-square") {
if ((_a = item.textContent) == null ? void 0 : _a.toLowerCase().includes("terminal")) item.remove();
}
if (configShouldBeHidden && (iconName === "rocket" || iconName === "wrench")) {
if ((_b = item.textContent) == null ? void 0 : _b.toLowerCase().includes("config")) item.remove();
}
}
}
}
};
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsic3JjL21haW4udHMiLCAic3JjL3R5cGVzLnRzIiwgInNyYy9zZXR0aW5ncy50cyIsICJzcmMvY29tbWFuZHMvaW5kZXgudHMiLCAic3JjL3V0aWxzL2ZpbGUtb3BlcmF0aW9ucy50cyIsICJzcmMvdXRpbHMvcGF0aC1tYXRjaGluZy50cyIsICJzcmMvdXRpbHMvc3RyaW5nLXV0aWxzLnRzIiwgInNyYy91dGlscy90ZW1wbGF0ZS1wYXJzaW5nLnRzIiwgInNyYy91dGlscy9saW5rLWNvbnZlcnNpb24udHMiLCAic3JjL3VpL3RpdGxlLW1vZGFsLnRzIiwgInNyYy91aS9zZXR0aW5ncy10YWIudHMiLCAic3JjL3VpL2NvbXBvbmVudHMvQ29tbWFuZFBpY2tlck1vZGFsLnRzIiwgInNyYy91aS9jb21wb25lbnRzL0ljb25QaWNrZXJNb2RhbC50cyIsICJzcmMvdWkvY29tcG9uZW50cy9Db25maXJtTW9kYWwudHMiLCAic3JjL3V0aWxzL2hlYWRpbmctbGluay1nZW5lcmF0b3IudHMiLCAic3JjL3NlcnZpY2VzL01pZ3JhdGlvblNlcnZpY2UudHMiLCAic3JjL3VpL2NvbXBvbmVudHMvTWlncmF0aW9uTW9kYWwudHMiLCAic3JjL3NlcnZpY2VzL0NyZWF0ZUV2ZW50U2VydmljZS50cyIsICJzcmMvc2VydmljZXMvRnJvbnRtYXR0ZXJTZXJ2aWNlLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyJpbXBvcnQge1xyXG5cdFBsdWdpbixcclxuXHRURmlsZSxcclxuXHROb3RpY2UsXHJcblx0c2V0SWNvbixcclxuXHRQbGF0Zm9ybSxcclxuXHRFdmVudFJlZixcclxufSBmcm9tIFwib2JzaWRpYW5cIjtcclxuXHJcbmltcG9ydCB7IEFzdHJvQ29tcG9zZXJTZXR0aW5ncywgREVGQVVMVF9TRVRUSU5HUyB9IGZyb20gXCIuL3NldHRpbmdzXCI7XHJcbmltcG9ydCB7IEFzdHJvQ29tcG9zZXJQbHVnaW5JbnRlcmZhY2UsIENvbnRlbnRUeXBlIH0gZnJvbSBcIi4vdHlwZXNcIjtcclxuaW1wb3J0IHsgcmVnaXN0ZXJDb21tYW5kcywgcmVnaXN0ZXJDb250ZW50VHlwZUNvbW1hbmRzLCByZW5hbWVDb250ZW50QnlQYXRoIGFzIHJlbmFtZUNvbnRlbnRCeVBhdGhGdW5jdGlvbiwgb3BlblRlcm1pbmFsSW5Qcm9qZWN0Um9vdCwgb3BlbkNvbmZpZ0ZpbGUgfSBmcm9tIFwiLi9jb21tYW5kc1wiO1xyXG5pbXBvcnQgeyBBc3Ryb0NvbXBvc2VyU2V0dGluZ1RhYiB9IGZyb20gXCIuL3VpL3NldHRpbmdzLXRhYlwiO1xyXG5pbXBvcnQgeyBGaWxlT3BlcmF0aW9ucyB9IGZyb20gXCIuL3V0aWxzL2ZpbGUtb3BlcmF0aW9uc1wiO1xyXG5pbXBvcnQgeyBUZW1wbGF0ZVBhcnNlciB9IGZyb20gXCIuL3V0aWxzL3RlbXBsYXRlLXBhcnNpbmdcIjtcclxuaW1wb3J0IHsgSGVhZGluZ0xpbmtHZW5lcmF0b3IgfSBmcm9tIFwiLi91dGlscy9oZWFkaW5nLWxpbmstZ2VuZXJhdG9yXCI7XHJcbmltcG9ydCB7IE1pZ3JhdGlvblNlcnZpY2UgfSBmcm9tIFwiLi9zZXJ2aWNlcy9NaWdyYXRpb25TZXJ2aWNlXCI7XHJcbmltcG9ydCB7IENyZWF0ZUV2ZW50U2VydmljZSB9IGZyb20gXCIuL3NlcnZpY2VzL0NyZWF0ZUV2ZW50U2VydmljZVwiO1xyXG5pbXBvcnQgeyBGcm9udG1hdHRlclNlcnZpY2UgfSBmcm9tIFwiLi9zZXJ2aWNlcy9Gcm9udG1hdHRlclNlcnZpY2VcIjtcclxuaW1wb3J0IHsgd2FpdEZvckVsZW1lbnQgfSBmcm9tIFwiLi91dGlscy9kb21cIjtcclxuXHJcbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEFzdHJvQ29tcG9zZXJQbHVnaW4gZXh0ZW5kcyBQbHVnaW4gaW1wbGVtZW50cyBBc3Ryb0NvbXBvc2VyUGx1Z2luSW50ZXJmYWNlIHtcclxuXHRzZXR0aW5ncyE6IEFzdHJvQ29tcG9zZXJTZXR0aW5ncztcclxuXHRwcml2YXRlIGNyZWF0ZUV2ZW50UmVmPzogRXZlbnRSZWY7XHJcblx0cHVibGljIGZpbGVPcHMhOiBGaWxlT3BlcmF0aW9ucztcclxuXHRwdWJsaWMgdGVtcGxhdGVQYXJzZXIhOiBUZW1wbGF0ZVBhcnNlcjtcclxuXHRwdWJsaWMgaGVhZGluZ0xpbmtHZW5lcmF0b3IhOiBIZWFkaW5nTGlua0dlbmVyYXRvcjtcclxuXHRwdWJsaWMgcGx1Z2luQ3JlYXRlZEZpbGVzOiBNYXA8c3RyaW5nLCBudW1iZXI+ID0gbmV3IE1hcCgpO1xyXG5cdHByaXZhdGUgcHJvY2Vzc2VkRmlsZXM6IE1hcDxzdHJpbmcsIG51bWJlcj4gPSBuZXcgTWFwKCk7XHJcblx0cHJpdmF0ZSB0ZXJtaW5hbFJpYmJvbkljb246IEhUTUxFbGVtZW50IHwgbnVsbCA9IG51bGw7XHJcblx0cHJpdmF0ZSBjb25maWdSaWJib25JY29uOiBIVE1MRWxlbWVudCB8IG51bGwgPSBudWxsO1xyXG5cdHByaXZhdGUgcmliYm9uQ29udGV4dE1lbnVPYnNlcnZlcj86IE11dGF0aW9uT2JzZXJ2ZXI7XHJcblx0cHJpdmF0ZSBoZWxwQnV0dG9uT2JzZXJ2ZXI/OiBNdXRhdGlvbk9ic2VydmVyO1xyXG5cdHByaXZhdGUgaGVscEJ1dHRvbkVsZW1lbnQ/OiBIVE1MRWxlbWVudDtcclxuXHRwcml2YXRlIGN1c3RvbUhlbHBCdXR0b24/OiBIVE1MRWxlbWVudDtcclxuXHRwdWJsaWMgc2V0dGluZ3NUYWI/OiBBc3Ryb0NvbXBvc2VyU2V0dGluZ1RhYjtcclxuXHJcblx0cHJpdmF0ZSBtaWdyYXRpb25TZXJ2aWNlITogTWlncmF0aW9uU2VydmljZTtcclxuXHRwcml2YXRlIGNyZWF0ZUV2ZW50U2VydmljZSE6IENyZWF0ZUV2ZW50U2VydmljZTtcclxuXHRwdWJsaWMgZnJvbnRtYXR0ZXJTZXJ2aWNlITogRnJvbnRtYXR0ZXJTZXJ2aWNlO1xyXG5cclxuXHQvKipcclxuXHQgKiBNaWdyYXRlIG9sZCBwb3N0cy9wYWdlcyBzZXR0aW5ncyB0byB1bmlmaWVkIGNvbnRlbnQgdHlwZXNcclxuXHQgKi9cclxuXHRwcml2YXRlIGFzeW5jIG1pZ3JhdGVTZXR0aW5nc0lmTmVlZGVkKCk6IFByb21pc2U8dm9pZD4ge1xyXG5cdFx0aWYgKCF0aGlzLm1pZ3JhdGlvblNlcnZpY2UpIHtcclxuXHRcdFx0dGhpcy5taWdyYXRpb25TZXJ2aWNlID0gbmV3IE1pZ3JhdGlvblNlcnZpY2UodGhpcy5hcHAsIHRoaXMpO1xyXG5cdFx0fVxyXG5cdFx0YXdhaXQgdGhpcy5taWdyYXRpb25TZXJ2aWNlLm1pZ3JhdGVTZXR0aW5nc0lmTmVlZGVkKCk7XHJcblx0fVxyXG5cclxuXHRhc3luYyBvbmxvYWQoKSB7XHJcblx0XHR0cnkge1xyXG5cdFx0XHRhd2FpdCB0aGlzLmxvYWRTZXR0aW5ncygpO1xyXG5cclxuXHRcdFx0Ly8gSW5pdGlhbGl6ZSBzZXJ2aWNlcyAob3JkZXIgbWF0dGVyczogZmlsZU9wcyBmaXJzdCBhcyBpdCdzIGEgZGVwZW5kZW5jeSlcclxuXHRcdFx0dGhpcy5maWxlT3BzID0gbmV3IEZpbGVPcGVyYXRpb25zKHRoaXMuYXBwLCB0aGlzLnNldHRpbmdzLCB0aGlzKTtcclxuXHRcdFx0dGhpcy5taWdyYXRpb25TZXJ2aWNlID0gbmV3IE1pZ3JhdGlvblNlcnZpY2UodGhpcy5hcHAsIHRoaXMpO1xyXG5cdFx0XHR0aGlzLmNyZWF0ZUV2ZW50U2VydmljZSA9IG5ldyBDcmVhdGVFdmVudFNlcnZpY2UodGhpcy5hcHAsIHRoaXMpO1xyXG5cdFx0XHR0aGlzLmZyb250bWF0dGVyU2VydmljZSA9IG5ldyBGcm9udG1hdHRlclNlcnZpY2UodGhpcy5hcHAsIHRoaXMpO1xyXG5cdFx0XHR0aGlzLnRlbXBsYXRlUGFyc2VyID0gbmV3IFRlbXBsYXRlUGFyc2VyKHRoaXMuYXBwLCB0aGlzLnNldHRpbmdzLCB0aGlzKTtcclxuXHRcdFx0dGhpcy5oZWFkaW5nTGlua0dlbmVyYXRvciA9IG5ldyBIZWFkaW5nTGlua0dlbmVyYXRvcih0aGlzLnNldHRpbmdzLCB0aGlzKTtcclxuXHJcblx0XHRcdC8vIFJlZ2lzdGVyIE1EWCBmaWxlIHZpc2liaWxpdHkgaWYgZW5hYmxlZCAoc2FmZWx5IGhhbmRsZSBpZiBhbHJlYWR5IHJlZ2lzdGVyZWQpXHJcblx0XHRcdGlmICh0aGlzLnNldHRpbmdzLnNob3dNZHhGaWxlc0luRXhwbG9yZXIpIHtcclxuXHRcdFx0XHR0cnkge1xyXG5cdFx0XHRcdFx0dGhpcy5yZWdpc3RlckV4dGVuc2lvbnMoW1wibWR4XCJdLCBcIm1hcmtkb3duXCIpO1xyXG5cdFx0XHRcdH0gY2F0Y2ggKGVycm9yKSB7XHJcblx0XHRcdFx0XHRjb25zb2xlLndhcm4oXCJbQXN0cm8gQ29tcG9zZXJdIE1EWCBleHRlbnNpb24gYWxyZWFkeSByZWdpc3RlcmVkOlwiLCBlcnJvcik7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblxyXG5cdFx0XHQvLyBIYW5kbGUgbGF5b3V0LXJlYWR5IGluaXRpYWxpemF0aW9uIChkZXNrdG9wIG9ubHkpXHJcblx0XHRcdHRoaXMuYXBwLndvcmtzcGFjZS5vbkxheW91dFJlYWR5KCgpID0+IHtcclxuXHRcdFx0XHR0aGlzLnJlZ2lzdGVyQ3JlYXRlRXZlbnQoKTtcclxuXHRcdFx0XHQvLyBJbml0aWFsaXplIGhlbHAgYnV0dG9uIHJlcGxhY2VtZW50IChkZXNrdG9wIG9ubHkpXHJcblx0XHRcdFx0aWYgKCFQbGF0Zm9ybS5pc01vYmlsZSkge1xyXG5cdFx0XHRcdFx0dGhpcy5zdGFydEhlbHBCdXR0b25Nb25pdG9yKCk7XHJcblx0XHRcdFx0fVxyXG5cclxuXHRcdFx0XHR0aGlzLnJlZ2lzdGVyVGl0bGVQcm9wZXJ0eUNsaWNrTGlzdGVuZXIoKTtcclxuXHJcblx0XHRcdFx0Ly8gUnVuIG1pZ3JhdGlvbiBhZnRlciBwbHVnaW4gaXMgZnVsbHkgbG9hZGVkIChub24tYmxvY2tpbmcpXHJcblx0XHRcdFx0dm9pZCB0aGlzLm1pZ3JhdGVTZXR0aW5nc0lmTmVlZGVkKCk7XHJcblx0XHRcdH0pO1xyXG5cclxuXHRcdFx0Ly8gUmVnaXN0ZXIgY29tbWFuZHNcclxuXHRcdFx0cmVnaXN0ZXJDb21tYW5kcyh0aGlzLCB0aGlzLnNldHRpbmdzKTtcclxuXHRcdFx0cmVnaXN0ZXJDb250ZW50VHlwZUNvbW1hbmRzKHRoaXMsIHRoaXMuc2V0dGluZ3MpO1xyXG5cclxuXHRcdFx0Ly8gQWRkIHNldHRpbmdzIHRhYlxyXG5cdFx0XHR0aGlzLnNldHRpbmdzVGFiID0gbmV3IEFzdHJvQ29tcG9zZXJTZXR0aW5nVGFiKHRoaXMuYXBwLCB0aGlzKTtcclxuXHRcdFx0dGhpcy5hZGRTZXR0aW5nVGFiKHRoaXMuc2V0dGluZ3NUYWIpO1xyXG5cclxuXHRcdFx0Ly8gUmVnaXN0ZXIgVUkgZWxlbWVudHNcclxuXHRcdFx0dGhpcy5yZWdpc3RlckNvbnRleHRNZW51KCk7XHJcblx0XHRcdHRoaXMucmVnaXN0ZXJSaWJib25JY29ucygpO1xyXG5cdFx0XHR0aGlzLnNldHVwUmliYm9uQ29udGV4dE1lbnVIYW5kbGluZygpO1xyXG5cdFx0fSBjYXRjaCAoZXJyb3IpIHtcclxuXHRcdFx0Y29uc29sZS5lcnJvcihcIltBc3RybyBDb21wb3Nlcl0gQ3JpdGljYWwgZXJyb3IgZHVyaW5nIG9ubG9hZDpcIiwgZXJyb3IpO1xyXG5cdFx0XHRuZXcgTm90aWNlKFwiQXN0cm8gQ29tcG9zZXIgZmFpbGVkIHRvIGxvYWQuIENoZWNrIGNvbnNvbGUgKEN0cmwrU2hpZnQrSSkgZm9yIGRldGFpbHMuXCIpO1xyXG5cdFx0XHR0aHJvdyBlcnJvcjtcclxuXHRcdH1cclxuXHR9XHJcblxyXG5cdHB1YmxpYyByZWdpc3RlckNyZWF0ZUV2ZW50KCkge1xyXG5cdFx0aWYgKHRoaXMuY3JlYXRlRXZlbnRSZWYpIHtcclxuXHRcdFx0dGhpcy5hcHAudmF1bHQub2ZmcmVmKHRoaXMuY3JlYXRlRXZlbnRSZWYpO1xyXG5cdFx0XHR0aGlzLmNyZWF0ZUV2ZW50UmVmID0gdW5kZWZpbmVkO1xyXG5cdFx0fVxyXG5cclxuXHRcdGNvbnN0IGNyZWF0ZUV2ZW50UmVmID0gdGhpcy5hcHAudmF1bHQub24oXCJjcmVhdGVcIiwgKGZpbGUpID0+IHtcclxuXHRcdFx0aWYgKGZpbGUgaW5zdGFuY2VvZiBURmlsZSkge1xyXG5cdFx0XHRcdHRoaXMuY3JlYXRlRXZlbnRTZXJ2aWNlLmhhbmRsZUNyZWF0ZShmaWxlKTtcclxuXHRcdFx0XHR0aGlzLmNsZWFudXBQbHVnaW5DcmVhdGVkRmlsZXMoKTtcclxuXHRcdFx0fVxyXG5cdFx0fSk7XHJcblx0XHR0aGlzLnJlZ2lzdGVyRXZlbnQoY3JlYXRlRXZlbnRSZWYpO1xyXG5cdFx0dGhpcy5jcmVhdGVFdmVudFJlZiA9IGNyZWF0ZUV2ZW50UmVmO1xyXG5cdH1cclxuXHJcblx0cHJpdmF0ZSByZWdpc3RlclRpdGxlUHJvcGVydHlDbGlja0xpc3RlbmVyKCkge1xyXG5cdFx0dGhpcy5yZWdpc3RlckRvbUV2ZW50KGRvY3VtZW50LCBcImNsaWNrXCIsIChldnQ6IE1vdXNlRXZlbnQpID0+IHtcclxuXHRcdFx0aWYgKCF0aGlzLnNldHRpbmdzLnJlbmFtZU9uVGl0bGVDbGljaykgcmV0dXJuO1xyXG5cclxuXHRcdFx0Y29uc3QgdGFyZ2V0ID0gZXZ0LnRhcmdldCBhcyBIVE1MRWxlbWVudDtcclxuXHRcdFx0Y29uc3QgcHJvcGVydHlFbCA9IHRhcmdldC5jbG9zZXN0KFwiLm1ldGFkYXRhLXByb3BlcnR5XCIpO1xyXG5cdFx0XHRpZiAoIXByb3BlcnR5RWwpIHJldHVybjtcclxuXHJcblx0XHRcdGNvbnN0IHByb3BlcnR5S2V5ID0gcHJvcGVydHlFbC5nZXRBdHRyaWJ1dGUoXCJkYXRhLXByb3BlcnR5LWtleVwiKTtcclxuXHRcdFx0aWYgKCFwcm9wZXJ0eUtleSkgcmV0dXJuO1xyXG5cclxuXHRcdFx0Y29uc3QgYWN0aXZlRmlsZSA9IHRoaXMuYXBwLndvcmtzcGFjZS5nZXRBY3RpdmVGaWxlKCk7XHJcblx0XHRcdGlmICghYWN0aXZlRmlsZSkgcmV0dXJuO1xyXG5cclxuXHRcdFx0Y29uc3QgdHlwZUlkID0gdGhpcy5maWxlT3BzLmRldGVybWluZVR5cGUoYWN0aXZlRmlsZSk7XHJcblx0XHRcdGNvbnN0IHRpdGxlS2V5ID0gdGhpcy5maWxlT3BzLmdldFRpdGxlS2V5KHR5cGVJZCk7XHJcblxyXG5cdFx0XHRpZiAocHJvcGVydHlLZXkgPT09IHRpdGxlS2V5KSB7XHJcblx0XHRcdFx0ZXZ0LnByZXZlbnREZWZhdWx0KCk7XHJcblx0XHRcdFx0ZXZ0LnN0b3BQcm9wYWdhdGlvbigpO1xyXG5cdFx0XHRcdHRoaXMucmVuYW1lQ29udGVudEJ5UGF0aChhY3RpdmVGaWxlLnBhdGgpO1xyXG5cdFx0XHR9XHJcblx0XHR9LCB0cnVlKTsgLy8gdXNlIGNhcHR1cmUgcGhhc2VcclxuXHR9XHJcblxyXG5cdHByaXZhdGUgY2xlYW51cFBsdWdpbkNyZWF0ZWRGaWxlcygpIHtcclxuXHRcdGNvbnN0IG5vdyA9IERhdGUubm93KCk7XHJcblx0XHRjb25zdCB0dGwgPSA1ICogNjAgKiAxMDAwOyAvLyA1IG1pbnV0ZXNcclxuXHRcdGZvciAoY29uc3QgW3BhdGgsIHRpbWVzdGFtcF0gb2YgdGhpcy5wbHVnaW5DcmVhdGVkRmlsZXMuZW50cmllcygpKSB7XHJcblx0XHRcdGlmIChub3cgLSB0aW1lc3RhbXAgPiB0dGwpIHtcclxuXHRcdFx0XHR0aGlzLnBsdWdpbkNyZWF0ZWRGaWxlcy5kZWxldGUocGF0aCk7XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHR9XHJcblxyXG5cdGFzeW5jIGxvYWRTZXR0aW5ncygpIHtcclxuXHRcdGNvbnN0IGxvYWRlZERhdGEgPSAoYXdhaXQgdGhpcy5sb2FkRGF0YSgpKSBhcyB1bmtub3duO1xyXG5cdFx0aWYgKCF0aGlzLnNldHRpbmdzKSB7XHJcblx0XHRcdHRoaXMuc2V0dGluZ3MgPSBPYmplY3QuYXNzaWduKHt9LCBERUZBVUxUX1NFVFRJTkdTLCBsb2FkZWREYXRhIGFzIFBhcnRpYWw8QXN0cm9Db21wb3NlclNldHRpbmdzPiB8IG51bGwgfCB1bmRlZmluZWQpO1xyXG5cdFx0fSBlbHNlIHtcclxuXHRcdFx0T2JqZWN0LmFzc2lnbih0aGlzLnNldHRpbmdzLCBsb2FkZWREYXRhIGFzIFBhcnRpYWw8QXN0cm9Db21wb3NlclNldHRpbmdzPiB8IG51bGwgfCB1bmRlZmluZWQpO1xyXG5cdFx0fVxyXG5cclxuXHRcdC8vIEVuc3VyZSBjb250ZW50VHlwZXMgaXMgYWx3YXlzIGFuIGFycmF5IChuZXZlciB1bmRlZmluZWQgb3IgbnVsbClcclxuXHRcdGlmICghdGhpcy5zZXR0aW5ncy5jb250ZW50VHlwZXMgfHwgIUFycmF5LmlzQXJyYXkodGhpcy5zZXR0aW5ncy5jb250ZW50VHlwZXMpKSB7XHJcblx0XHRcdHRoaXMuc2V0dGluZ3MuY29udGVudFR5cGVzID0gW107XHJcblx0XHR9XHJcblxyXG5cdFx0aWYgKCF0aGlzLnNldHRpbmdzLm1pZ3JhdGlvbkNvbXBsZXRlZCkge1xyXG5cdFx0XHRjb25zdCBsZWdhY3lTZXR0aW5ncyA9IHRoaXMuc2V0dGluZ3MgYXMgdW5rbm93biBhcyB7IGN1c3RvbUNvbnRlbnRUeXBlcz86IENvbnRlbnRUeXBlW10gfTtcclxuXHRcdFx0Y29uc3QgaGFzTGVnYWN5VHlwZXMgPSBsZWdhY3lTZXR0aW5ncy5jdXN0b21Db250ZW50VHlwZXMgJiYgQXJyYXkuaXNBcnJheShsZWdhY3lTZXR0aW5ncy5jdXN0b21Db250ZW50VHlwZXMpICYmIGxlZ2FjeVNldHRpbmdzLmN1c3RvbUNvbnRlbnRUeXBlcy5sZW5ndGggPiAwO1xyXG5cdFx0XHRjb25zdCBoYXNOZXdUeXBlcyA9IHRoaXMuc2V0dGluZ3MuY29udGVudFR5cGVzICYmIEFycmF5LmlzQXJyYXkodGhpcy5zZXR0aW5ncy5jb250ZW50VHlwZXMpICYmIHRoaXMuc2V0dGluZ3MuY29udGVudFR5cGVzLmxlbmd0aCA+IDA7XHJcblxyXG5cdFx0XHRpZiAoaGFzTGVnYWN5VHlwZXMgJiYgIWhhc05ld1R5cGVzKSB7XHJcblx0XHRcdFx0dGhpcy5zZXR0aW5ncy5jb250ZW50VHlwZXMgPSBsZWdhY3lTZXR0aW5ncy5jdXN0b21Db250ZW50VHlwZXMgfHwgW107XHJcblx0XHRcdH1cclxuXHRcdH0gZWxzZSB7XHJcblx0XHRcdGNvbnN0IGxlZ2FjeUZpZWxkcyA9IFtcclxuXHRcdFx0XHQnY3VzdG9tQ29udGVudFR5cGVzJywgJ2VuYWJsZVVuZGVyc2NvcmVQcmVmaXgnLCAncG9zdHNGb2xkZXInLCAncG9zdHNMaW5rQmFzZVBhdGgnLFxyXG5cdFx0XHRcdCdhdXRvbWF0ZVBvc3RDcmVhdGlvbicsICdjcmVhdGlvbk1vZGUnLCAnaW5kZXhGaWxlTmFtZScsICdleGNsdWRlZERpcmVjdG9yaWVzJyxcclxuXHRcdFx0XHQnb25seUF1dG9tYXRlSW5Qb3N0c0ZvbGRlcicsICdlbmFibGVQYWdlcycsICdwYWdlc0ZvbGRlcicsICdwYWdlc0xpbmtCYXNlUGF0aCcsXHJcblx0XHRcdFx0J3BhZ2VzQ3JlYXRpb25Nb2RlJywgJ3BhZ2VzSW5kZXhGaWxlTmFtZScsICdwYWdlVGVtcGxhdGUnLCAnb25seUF1dG9tYXRlSW5QYWdlc0ZvbGRlcicsXHJcblx0XHRcdFx0J2xpbmtCYXNlUGF0aCcsICdlbmFibGVBdXRvUmVuYW1lJywgJ2VuYWJsZUF1dG9JbnNlcnRGcm9udG1hdHRlcicsICdkcmFmdFN0eWxlJ1xyXG5cdFx0XHRdO1xyXG5cclxuXHRcdFx0Y29uc3Qgc2V0dGluZ3NSZWNvcmQgPSB0aGlzLnNldHRpbmdzIGFzIHVua25vd24gYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XHJcblx0XHRcdGxldCBmaWVsZHNSZW1vdmVkID0gZmFsc2U7XHJcblx0XHRcdGZvciAoY29uc3QgZmllbGQgb2YgbGVnYWN5RmllbGRzKSB7XHJcblx0XHRcdFx0aWYgKHNldHRpbmdzUmVjb3JkW2ZpZWxkXSAhPT0gdW5kZWZpbmVkKSB7XHJcblx0XHRcdFx0XHRkZWxldGUgc2V0dGluZ3NSZWNvcmRbZmllbGRdO1xyXG5cdFx0XHRcdFx0ZmllbGRzUmVtb3ZlZCA9IHRydWU7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblx0XHRcdC8vIE9ubHkgc2F2ZSBpZiB3ZSBhY3R1YWxseSBjbGVhbmVkIHVwIGZpZWxkcyB0byBhdm9pZCByZWR1bmRhbnQgd3JpdGVzXHJcblx0XHRcdGlmIChmaWVsZHNSZW1vdmVkKSB7XHJcblx0XHRcdFx0YXdhaXQgdGhpcy5zYXZlU2V0dGluZ3MoKTtcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cdH1cclxuXHJcblx0YXN5bmMgc2F2ZVNldHRpbmdzKCkge1xyXG5cdFx0YXdhaXQgdGhpcy5zYXZlRGF0YSh0aGlzLnNldHRpbmdzKTtcclxuXHR9XHJcblxyXG5cdHByaXZhdGUgcmVnaXN0ZXJDb250ZXh0TWVudSgpIHtcclxuXHRcdHRoaXMucmVnaXN0ZXJFdmVudChcclxuXHRcdFx0dGhpcy5hcHAud29ya3NwYWNlLm9uKCdlZGl0b3ItbWVudScsIChtZW51LCBlZGl0b3IsIHZpZXcpID0+IHtcclxuXHRcdFx0XHRpZiAoIXRoaXMuc2V0dGluZ3MuZW5hYmxlQ29weUhlYWRpbmdMaW5rKSB7XHJcblx0XHRcdFx0XHRyZXR1cm47XHJcblx0XHRcdFx0fVxyXG5cclxuXHRcdFx0XHRjb25zdCBjdXJzb3IgPSBlZGl0b3IuZ2V0Q3Vyc29yKCk7XHJcblx0XHRcdFx0Y29uc3QgZmlsZSA9IHZpZXcuZmlsZTtcclxuXHJcblx0XHRcdFx0aWYgKCEoZmlsZSBpbnN0YW5jZW9mIFRGaWxlKSkge1xyXG5cdFx0XHRcdFx0cmV0dXJuO1xyXG5cdFx0XHRcdH1cclxuXHJcblx0XHRcdFx0Y29uc3QgaGVhZGluZyA9IHRoaXMuaGVhZGluZ0xpbmtHZW5lcmF0b3IuZmluZEhlYWRpbmdBdExpbmUodGhpcy5hcHAsIGZpbGUsIGN1cnNvci5saW5lKTtcclxuXHJcblx0XHRcdFx0aWYgKGhlYWRpbmcpIHtcclxuXHRcdFx0XHRcdGNvbnN0IGZ1bGxMaW5rID0gdGhpcy5oZWFkaW5nTGlua0dlbmVyYXRvci5nZW5lcmF0ZUxpbmsodGhpcy5hcHAsIGZpbGUsIGhlYWRpbmcpO1xyXG5cdFx0XHRcdFx0Y29uc3QgdXJsT25seSA9IHRoaXMuaGVhZGluZ0xpbmtHZW5lcmF0b3IuZXh0cmFjdFVybChmdWxsTGluayk7XHJcblxyXG5cdFx0XHRcdFx0bWVudS5hZGRJdGVtKChpdGVtKSA9PiB7XHJcblx0XHRcdFx0XHRcdGl0ZW1cclxuXHRcdFx0XHRcdFx0XHQuc2V0VGl0bGUoJ0NvcHkgaGVhZGluZyBsaW5rJylcclxuXHRcdFx0XHRcdFx0XHQuc2V0SWNvbignbGluay0yJylcclxuXHRcdFx0XHRcdFx0XHQub25DbGljayhhc3luYyAoKSA9PiB7XHJcblx0XHRcdFx0XHRcdFx0XHRhd2FpdCBuYXZpZ2F0b3IuY2xpcGJvYXJkLndyaXRlVGV4dCh1cmxPbmx5KTtcclxuXHRcdFx0XHRcdFx0XHRcdG5ldyBOb3RpY2UoJ0hlYWRpbmcgbGluayBjb3BpZWQgdG8gY2xpcGJvYXJkJyk7XHJcblx0XHRcdFx0XHRcdFx0fSk7XHJcblx0XHRcdFx0XHR9KTtcclxuXHJcblx0XHRcdFx0XHRtZW51LmFkZEl0ZW0oKGl0ZW0pID0+IHtcclxuXHRcdFx0XHRcdFx0aXRlbVxyXG5cdFx0XHRcdFx0XHRcdC5zZXRUaXRsZSgnQ29weSBoZWFkaW5nIGxpbmsgd2l0aCB0ZXh0JylcclxuXHRcdFx0XHRcdFx0XHQuc2V0SWNvbignaGVhZGluZycpXHJcblx0XHRcdFx0XHRcdFx0Lm9uQ2xpY2soYXN5bmMgKCkgPT4ge1xyXG5cdFx0XHRcdFx0XHRcdFx0YXdhaXQgbmF2aWdhdG9yLmNsaXBib2FyZC53cml0ZVRleHQoZnVsbExpbmspO1xyXG5cdFx0XHRcdFx0XHRcdFx0bmV3IE5vdGljZSgnSGVhZGluZyBsaW5rIHdpdGggdGV4dCBjb3BpZWQgdG8gY2xpcGJvYXJkJyk7XHJcblx0XHRcdFx0XHRcdFx0fSk7XHJcblx0XHRcdFx0XHR9KTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdH0pXHJcblx0XHQpO1xyXG5cdH1cclxuXHJcblx0cmVuYW1lQ29udGVudEJ5UGF0aChmaWxlUGF0aDogc3RyaW5nKTogdm9pZCB7XHJcblx0XHRyZW5hbWVDb250ZW50QnlQYXRoRnVuY3Rpb24odGhpcy5hcHAsIGZpbGVQYXRoLCB0aGlzLnNldHRpbmdzLCB0aGlzKTtcclxuXHR9XHJcblxyXG5cdHB1YmxpYyByZWdpc3RlclJpYmJvbkljb25zKCkge1xyXG5cdFx0aWYgKFBsYXRmb3JtLmlzTW9iaWxlKSB7XHJcblx0XHRcdGlmICh0aGlzLnRlcm1pbmFsUmliYm9uSWNvbikge1xyXG5cdFx0XHRcdHRyeSB7IGlmICh0aGlzLnRlcm1pbmFsUmliYm9uSWNvbi5wYXJlbnROb2RlKSB0aGlzLnRlcm1pbmFsUmliYm9uSWNvbi5yZW1vdmUoKTsgfSBjYXRjaCB7IC8qIElnbm9yZSAqLyB9XHJcblx0XHRcdFx0dGhpcy50ZXJtaW5hbFJpYmJvbkljb24gPSBudWxsO1xyXG5cdFx0XHR9XHJcblx0XHRcdGlmICh0aGlzLmNvbmZpZ1JpYmJvbkljb24pIHtcclxuXHRcdFx0XHR0cnkgeyBpZiAodGhpcy5jb25maWdSaWJib25JY29uLnBhcmVudE5vZGUpIHRoaXMuY29uZmlnUmliYm9uSWNvbi5yZW1vdmUoKTsgfSBjYXRjaCB7IC8qIElnbm9yZSAqLyB9XHJcblx0XHRcdFx0dGhpcy5jb25maWdSaWJib25JY29uID0gbnVsbDtcclxuXHRcdFx0fVxyXG5cdFx0XHR0cnkge1xyXG5cdFx0XHRcdGNvbnN0IHRlcm1pbmFsSWNvbnMgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCcuc2lkZS1kb2NrLXJpYmJvbi1hY3Rpb25bYXJpYS1sYWJlbD1cIk9wZW4gcHJvamVjdCB0ZXJtaW5hbFwiXScpO1xyXG5cdFx0XHRcdHRlcm1pbmFsSWNvbnMuZm9yRWFjaCgoaWNvbjogRWxlbWVudCkgPT4gaWNvbi5yZW1vdmUoKSk7XHJcblx0XHRcdFx0Y29uc3QgY29uZmlnSWNvbnMgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCcuc2lkZS1kb2NrLXJpYmJvbi1hY3Rpb25bYXJpYS1sYWJlbD1cIkVkaXQgYXN0cm8gY29uZmlnXCJdJyk7XHJcblx0XHRcdFx0Y29uZmlnSWNvbnMuZm9yRWFjaCgoaWNvbjogRWxlbWVudCkgPT4gaWNvbi5yZW1vdmUoKSk7XHJcblx0XHRcdH0gY2F0Y2ggeyAvKiBJZ25vcmUgKi8gfVxyXG5cdFx0XHRyZXR1cm47XHJcblx0XHR9XHJcblxyXG5cdFx0Y29uc3QgdGVybWluYWxTaG91bGRFeGlzdCA9IHRoaXMuc2V0dGluZ3MuZW5hYmxlVGVybWluYWxSaWJib25JY29uICYmIHRoaXMuc2V0dGluZ3MuZW5hYmxlT3BlblRlcm1pbmFsQ29tbWFuZDtcclxuXHRcdGNvbnN0IGNvbmZpZ1Nob3VsZEV4aXN0ID0gdGhpcy5zZXR0aW5ncy5lbmFibGVDb25maWdSaWJib25JY29uICYmIHRoaXMuc2V0dGluZ3MuZW5hYmxlT3BlbkNvbmZpZ0ZpbGVDb21tYW5kO1xyXG5cclxuXHRcdGlmICh0aGlzLnRlcm1pbmFsUmliYm9uSWNvbikge1xyXG5cdFx0XHR0cnkgeyBpZiAodGhpcy50ZXJtaW5hbFJpYmJvbkljb24ucGFyZW50Tm9kZSkgdGhpcy50ZXJtaW5hbFJpYmJvbkljb24ucmVtb3ZlKCk7IH0gY2F0Y2ggeyAvKiBJZ25vcmUgKi8gfVxyXG5cdFx0XHR0aGlzLnRlcm1pbmFsUmliYm9uSWNvbiA9IG51bGw7XHJcblx0XHR9XHJcblxyXG5cdFx0aWYgKHRoaXMuY29uZmlnUmliYm9uSWNvbikge1xyXG5cdFx0XHR0cnkgeyBpZiAodGhpcy5jb25maWdSaWJib25JY29uLnBhcmVudE5vZGUpIHRoaXMuY29uZmlnUmliYm9uSWNvbi5yZW1vdmUoKTsgfSBjYXRjaCB7IC8qIElnbm9yZSAqLyB9XHJcblx0XHRcdHRoaXMuY29uZmlnUmliYm9uSWNvbiA9IG51bGw7XHJcblx0XHR9XHJcblxyXG5cdFx0dHJ5IHtcclxuXHRcdFx0ZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCgnLnNpZGUtZG9jay1yaWJib24tYWN0aW9uW2FyaWEtbGFiZWw9XCJPcGVuIHByb2plY3QgdGVybWluYWxcIl0nKS5mb3JFYWNoKGVsID0+IGVsLnJlbW92ZSgpKTtcclxuXHRcdFx0ZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCgnLnNpZGUtZG9jay1yaWJib24tYWN0aW9uW2FyaWEtbGFiZWw9XCJFZGl0IGFzdHJvIGNvbmZpZ1wiXScpLmZvckVhY2goZWwgPT4gZWwucmVtb3ZlKCkpO1xyXG5cdFx0fSBjYXRjaCB7IC8qIElnbm9yZSAqLyB9XHJcblxyXG5cdFx0aWYgKHRlcm1pbmFsU2hvdWxkRXhpc3QpIHtcclxuXHRcdFx0dGhpcy50ZXJtaW5hbFJpYmJvbkljb24gPSB0aGlzLmFkZFJpYmJvbkljb24oJ3Rlcm1pbmFsLXNxdWFyZScsICdPcGVuIHByb2plY3QgdGVybWluYWwnLCAoKSA9PiB7XHJcblx0XHRcdFx0aWYgKCF0aGlzLnNldHRpbmdzLmVuYWJsZU9wZW5UZXJtaW5hbENvbW1hbmQpIHtcclxuXHRcdFx0XHRcdG5ldyBOb3RpY2UoXCJPcGVuIHRlcm1pbmFsIGNvbW1hbmQgaXMgZGlzYWJsZWQuXCIpO1xyXG5cdFx0XHRcdFx0cmV0dXJuO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0XHRvcGVuVGVybWluYWxJblByb2plY3RSb290KHRoaXMuYXBwLCB0aGlzLnNldHRpbmdzKTtcclxuXHRcdFx0fSk7XHJcblx0XHRcdGlmICh0aGlzLnRlcm1pbmFsUmliYm9uSWNvbikgdGhpcy50ZXJtaW5hbFJpYmJvbkljb24uc2V0QXR0cmlidXRlKCdkYXRhLWFzdHJvLWNvbXBvc2VyLXRlcm1pbmFsLXJpYmJvbicsICd0cnVlJyk7XHJcblx0XHR9XHJcblxyXG5cdFx0aWYgKGNvbmZpZ1Nob3VsZEV4aXN0KSB7XHJcblx0XHRcdHRoaXMuY29uZmlnUmliYm9uSWNvbiA9IHRoaXMuYWRkUmliYm9uSWNvbigncm9ja2V0JywgJ0VkaXQgYXN0cm8gY29uZmlnJywgYXN5bmMgKCkgPT4ge1xyXG5cdFx0XHRcdGlmICghdGhpcy5zZXR0aW5ncy5lbmFibGVPcGVuQ29uZmlnRmlsZUNvbW1hbmQpIHtcclxuXHRcdFx0XHRcdG5ldyBOb3RpY2UoXCJFZGl0IGNvbmZpZyBmaWxlIGNvbW1hbmQgaXMgZGlzYWJsZWQuXCIpO1xyXG5cdFx0XHRcdFx0cmV0dXJuO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0XHRhd2FpdCBvcGVuQ29uZmlnRmlsZSh0aGlzLmFwcCwgdGhpcy5zZXR0aW5ncyk7XHJcblx0XHRcdH0pO1xyXG5cdFx0XHRpZiAodGhpcy5jb25maWdSaWJib25JY29uKSB0aGlzLmNvbmZpZ1JpYmJvbkljb24uc2V0QXR0cmlidXRlKCdkYXRhLWFzdHJvLWNvbXBvc2VyLWNvbmZpZy1yaWJib24nLCAndHJ1ZScpO1xyXG5cdFx0fVxyXG5cclxuXHRcdHRoaXMudXBkYXRlUmliYm9uQ29udGV4dE1lbnVDU1MoKTtcclxuXHRcdHRoaXMuc2V0dXBSaWJib25Db250ZXh0TWVudU9ic2VydmVyKCk7XHJcblx0fVxyXG5cclxuXHRvbnVubG9hZCgpIHtcclxuXHRcdHRoaXMuZnJvbnRtYXR0ZXJTZXJ2aWNlPy5kZXN0cm95KCk7XHJcblx0XHRpZiAodGhpcy50ZXJtaW5hbFJpYmJvbkljb24pIHtcclxuXHRcdFx0dGhpcy50ZXJtaW5hbFJpYmJvbkljb24ucmVtb3ZlKCk7XHJcblx0XHRcdHRoaXMudGVybWluYWxSaWJib25JY29uID0gbnVsbDtcclxuXHRcdH1cclxuXHRcdGlmICh0aGlzLmNvbmZpZ1JpYmJvbkljb24pIHtcclxuXHRcdFx0dGhpcy5jb25maWdSaWJib25JY29uLnJlbW92ZSgpO1xyXG5cdFx0XHR0aGlzLmNvbmZpZ1JpYmJvbkljb24gPSBudWxsO1xyXG5cdFx0fVxyXG5cdFx0aWYgKHRoaXMucmliYm9uQ29udGV4dE1lbnVPYnNlcnZlcikge1xyXG5cdFx0XHR0aGlzLnJpYmJvbkNvbnRleHRNZW51T2JzZXJ2ZXIuZGlzY29ubmVjdCgpO1xyXG5cdFx0XHR0aGlzLnJpYmJvbkNvbnRleHRNZW51T2JzZXJ2ZXIgPSB1bmRlZmluZWQ7XHJcblx0XHR9XHJcblx0XHRkb2N1bWVudC5ib2R5LnJlbW92ZUNsYXNzKCdhc3Ryby1jb21wb3Nlci1oaWRlLXRlcm1pbmFsLWljb24nKTtcclxuXHRcdGRvY3VtZW50LmJvZHkucmVtb3ZlQ2xhc3MoJ2FzdHJvLWNvbXBvc2VyLWhpZGUtY29uZmlnLWljb24nKTtcclxuXHRcdGlmICh0aGlzLmhlbHBCdXR0b25PYnNlcnZlcikge1xyXG5cdFx0XHR0aGlzLmhlbHBCdXR0b25PYnNlcnZlci5kaXNjb25uZWN0KCk7XHJcblx0XHRcdHRoaXMuaGVscEJ1dHRvbk9ic2VydmVyID0gdW5kZWZpbmVkO1xyXG5cdFx0fVxyXG5cdFx0aWYgKHRoaXMuY3VzdG9tSGVscEJ1dHRvbikge1xyXG5cdFx0XHR0aGlzLmN1c3RvbUhlbHBCdXR0b24ucmVtb3ZlKCk7XHJcblx0XHRcdHRoaXMuY3VzdG9tSGVscEJ1dHRvbiA9IHVuZGVmaW5lZDtcclxuXHRcdH1cclxuXHRcdHRoaXMuaGVscEJ1dHRvbkVsZW1lbnQgPSB1bmRlZmluZWQ7XHJcblx0fVxyXG5cclxuXHRwcml2YXRlIHNldHVwUmliYm9uQ29udGV4dE1lbnVIYW5kbGluZygpIHtcclxuXHRcdHRoaXMudXBkYXRlUmliYm9uQ29udGV4dE1lbnVDU1MoKTtcclxuXHRcdHRoaXMuc2V0dXBSaWJib25Db250ZXh0TWVudU9ic2VydmVyKCk7XHJcblx0fVxyXG5cclxuXHRwcml2YXRlIHVwZGF0ZVJpYmJvbkNvbnRleHRNZW51Q1NTKCkge1xyXG5cdFx0Y29uc3QgdGVybWluYWxTaG91bGRCZUhpZGRlbiA9ICF0aGlzLnNldHRpbmdzLmVuYWJsZVRlcm1pbmFsUmliYm9uSWNvbiB8fCAhdGhpcy5zZXR0aW5ncy5lbmFibGVPcGVuVGVybWluYWxDb21tYW5kO1xyXG5cdFx0Y29uc3QgY29uZmlnU2hvdWxkQmVIaWRkZW4gPSAhdGhpcy5zZXR0aW5ncy5lbmFibGVDb25maWdSaWJib25JY29uIHx8ICF0aGlzLnNldHRpbmdzLmVuYWJsZU9wZW5Db25maWdGaWxlQ29tbWFuZDtcclxuXHJcblx0XHRpZiAodGVybWluYWxTaG91bGRCZUhpZGRlbikgZG9jdW1lbnQuYm9keS5hZGRDbGFzcygnYXN0cm8tY29tcG9zZXItaGlkZS10ZXJtaW5hbC1pY29uJyk7XHJcblx0XHRlbHNlIGRvY3VtZW50LmJvZHkucmVtb3ZlQ2xhc3MoJ2FzdHJvLWNvbXBvc2VyLWhpZGUtdGVybWluYWwtaWNvbicpO1xyXG5cclxuXHRcdGlmIChjb25maWdTaG91bGRCZUhpZGRlbikgZG9jdW1lbnQuYm9keS5hZGRDbGFzcygnYXN0cm8tY29tcG9zZXItaGlkZS1jb25maWctaWNvbicpO1xyXG5cdFx0ZWxzZSBkb2N1bWVudC5ib2R5LnJlbW92ZUNsYXNzKCdhc3Ryby1jb21wb3Nlci1oaWRlLWNvbmZpZy1pY29uJyk7XHJcblx0fVxyXG5cclxuXHRwcml2YXRlIHNldHVwUmliYm9uQ29udGV4dE1lbnVPYnNlcnZlcigpIHtcclxuXHRcdGlmICh0aGlzLnJpYmJvbkNvbnRleHRNZW51T2JzZXJ2ZXIpIHRoaXMucmliYm9uQ29udGV4dE1lbnVPYnNlcnZlci5kaXNjb25uZWN0KCk7XHJcblxyXG5cdFx0Y29uc3QgdGVybWluYWxTaG91bGRCZUhpZGRlbiA9ICF0aGlzLnNldHRpbmdzLmVuYWJsZVRlcm1pbmFsUmliYm9uSWNvbiB8fCAhdGhpcy5zZXR0aW5ncy5lbmFibGVPcGVuVGVybWluYWxDb21tYW5kO1xyXG5cdFx0Y29uc3QgY29uZmlnU2hvdWxkQmVIaWRkZW4gPSAhdGhpcy5zZXR0aW5ncy5lbmFibGVDb25maWdSaWJib25JY29uIHx8ICF0aGlzLnNldHRpbmdzLmVuYWJsZU9wZW5Db25maWdGaWxlQ29tbWFuZDtcclxuXHJcblx0XHRpZiAoIXRlcm1pbmFsU2hvdWxkQmVIaWRkZW4gJiYgIWNvbmZpZ1Nob3VsZEJlSGlkZGVuKSByZXR1cm47XHJcblxyXG5cdFx0dGhpcy5yaWJib25Db250ZXh0TWVudU9ic2VydmVyID0gbmV3IE11dGF0aW9uT2JzZXJ2ZXIoKG11dGF0aW9ucykgPT4ge1xyXG5cdFx0XHRmb3IgKGNvbnN0IG11dGF0aW9uIG9mIG11dGF0aW9ucykge1xyXG5cdFx0XHRcdGlmIChtdXRhdGlvbi5hZGRlZE5vZGVzLmxlbmd0aCA+IDApIHtcclxuXHRcdFx0XHRcdGZvciAoY29uc3Qgbm9kZSBvZiBBcnJheS5mcm9tKG11dGF0aW9uLmFkZGVkTm9kZXMpKSB7XHJcblx0XHRcdFx0XHRcdGlmIChub2RlIGluc3RhbmNlb2YgSFRNTEVsZW1lbnQpIHtcclxuXHRcdFx0XHRcdFx0XHRpZiAobm9kZS5jbGFzc0xpc3QuY29udGFpbnMoJ21lbnUnKSB8fCBub2RlLnF1ZXJ5U2VsZWN0b3IoJy5tZW51JykpIHtcclxuXHRcdFx0XHRcdFx0XHRcdHRoaXMucmVtb3ZlUmliYm9uSWNvbnNGcm9tQ29udGV4dE1lbnUobm9kZSk7XHJcblx0XHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHR9XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblx0XHR9KTtcclxuXHJcblx0XHR0aGlzLnJpYmJvbkNvbnRleHRNZW51T2JzZXJ2ZXIub2JzZXJ2ZShkb2N1bWVudC5ib2R5LCB7IGNoaWxkTGlzdDogdHJ1ZSwgc3VidHJlZTogdHJ1ZSB9KTtcclxuXHR9XHJcblxyXG5cdC8qKlxyXG5cdCAqIFN0YXJ0cyBhIHJvYnVzdCBtb25pdG9yIHRoYXQga2VlcHMgdGhlIGhlbHAgYnV0dG9uIGluIHN5bmMgd2l0aCBzZXR0aW5ncy5cclxuXHQgKi9cclxuXHRwcml2YXRlIHN0YXJ0SGVscEJ1dHRvbk1vbml0b3IoKSB7XHJcblx0XHRpZiAodGhpcy5oZWxwQnV0dG9uT2JzZXJ2ZXIpIHRoaXMuaGVscEJ1dHRvbk9ic2VydmVyLmRpc2Nvbm5lY3QoKTtcclxuXHJcblx0XHQvLyBJbW1lZGlhdGUgZmlyc3Qgc3luY1xyXG5cdFx0dGhpcy5zeW5jSGVscEJ1dHRvbigpO1xyXG5cclxuXHRcdGxldCB0aW1lcjogbnVtYmVyIHwgbnVsbCA9IG51bGw7XHJcblx0XHRsZXQgbXV0YXRpb25Db3VudCA9IDA7XHJcblxyXG5cdFx0dGhpcy5oZWxwQnV0dG9uT2JzZXJ2ZXIgPSBuZXcgTXV0YXRpb25PYnNlcnZlcigoKSA9PiB7XHJcblx0XHRcdG11dGF0aW9uQ291bnQrKztcclxuXHRcdFx0aWYgKHRpbWVyKSB3aW5kb3cuY2xlYXJUaW1lb3V0KHRpbWVyKTtcclxuXHJcblx0XHRcdC8vIEZvciB0aGUgZmlyc3QgZmV3IG11dGF0aW9ucyAoZHVyaW5nIHN0YXJ0dXApLCBiZSBzdXBlciBhZ2dyZXNzaXZlXHJcblx0XHRcdC8vIEFmdGVyIHRoYXQsIHVzZSBhIHNtYWxsIGRlYm91bmNlIHRvIHN0YXkgcGVyZm9ybWFudFxyXG5cdFx0XHRjb25zdCBkZWxheSA9IG11dGF0aW9uQ291bnQgPCAyMCA/IDAgOiAxMDA7XHJcblxyXG5cdFx0XHRpZiAoZGVsYXkgPT09IDApIHtcclxuXHRcdFx0XHR0aGlzLnN5bmNIZWxwQnV0dG9uKCk7XHJcblx0XHRcdH0gZWxzZSB7XHJcblx0XHRcdFx0dGltZXIgPSB3aW5kb3cuc2V0VGltZW91dCgoKSA9PiB0aGlzLnN5bmNIZWxwQnV0dG9uKCksIGRlbGF5KTtcclxuXHRcdFx0fVxyXG5cdFx0fSk7XHJcblxyXG5cdFx0Ly8gT2JzZXJ2ZSBib2R5IHdpdGggc3VidHJlZSBhbmQgYXR0cmlidXRlcyAoaW4gY2FzZSBpY29ucy9jbGFzc2VzIGNoYW5nZSlcclxuXHRcdHRoaXMuaGVscEJ1dHRvbk9ic2VydmVyLm9ic2VydmUoZG9jdW1lbnQuYm9keSwge1xyXG5cdFx0XHRjaGlsZExpc3Q6IHRydWUsXHJcblx0XHRcdHN1YnRyZWU6IHRydWUsXHJcblx0XHRcdGF0dHJpYnV0ZXM6IHRydWUsXHJcblx0XHRcdGF0dHJpYnV0ZUZpbHRlcjogWydjbGFzcycsICdzcmMnLCAnYXJpYS1sYWJlbCddXHJcblx0XHR9KTtcclxuXHR9XHJcblxyXG5cdC8qKlxyXG5cdCAqIFN5bmNocm9uaXplcyB0aGUgaGVscCBidXR0b24gc3RhdGUgYmFzZWQgb24gc2V0dGluZ3MuXHJcblx0ICovXHJcblx0cHJpdmF0ZSBzeW5jSGVscEJ1dHRvbigpIHtcclxuXHRcdGNvbnN0IGVuYWJsZWQgPSB0aGlzLnNldHRpbmdzLmhlbHBCdXR0b25SZXBsYWNlbWVudD8uZW5hYmxlZDtcclxuXHJcblx0XHQvLyAxLiBNYW5hZ2UgdGhlIENTUyBjbGFzcyBmb3IgaGlkaW5nIHRoZSBvcmlnaW5hbCBidXR0b25cclxuXHRcdGlmIChlbmFibGVkKSBkb2N1bWVudC5ib2R5LmFkZENsYXNzKCdhc3Ryby1jb21wb3Nlci1oaWRlLWhlbHAtYnV0dG9uJyk7XHJcblx0XHRlbHNlIGRvY3VtZW50LmJvZHkucmVtb3ZlQ2xhc3MoJ2FzdHJvLWNvbXBvc2VyLWhpZGUtaGVscC1idXR0b24nKTtcclxuXHJcblx0XHQvLyAyLiBDbGVhciBjdXN0b20gYnV0dG9uIGlmIGRpc2FibGVkXHJcblx0XHRpZiAoIWVuYWJsZWQpIHtcclxuXHRcdFx0aWYgKHRoaXMuY3VzdG9tSGVscEJ1dHRvbikge1xyXG5cdFx0XHRcdHRoaXMuY3VzdG9tSGVscEJ1dHRvbi5yZW1vdmUoKTtcclxuXHRcdFx0XHR0aGlzLmN1c3RvbUhlbHBCdXR0b24gPSB1bmRlZmluZWQ7XHJcblx0XHRcdH1cclxuXHRcdFx0cmV0dXJuO1xyXG5cdFx0fVxyXG5cclxuXHRcdC8vIDMuIExvb2sgZm9yIHRoZSBvcmlnaW5hbCBoZWxwIGJ1dHRvblxyXG5cdFx0Y29uc3Qgc2VsZWN0b3JzID0gW1xyXG5cdFx0XHQnLndvcmtzcGFjZS1kcmF3ZXItdmF1bHQtYWN0aW9ucyAuY2xpY2thYmxlLWljb24gc3ZnLmhlbHAnLFxyXG5cdFx0XHQnLndvcmtzcGFjZS1zaWRlZG9jay12YXVsdC1wcm9maWxlIC5jbGlja2FibGUtaWNvbiBzdmcuaGVscCcsXHJcblx0XHRcdCcud29ya3NwYWNlLWRyYXdlciAuY2xpY2thYmxlLWljb24gc3ZnLmhlbHAnLFxyXG5cdFx0XHQnLmNsaWNrYWJsZS1pY29uIHN2Zy5oZWxwJ1xyXG5cdFx0XTtcclxuXHJcblx0XHRsZXQgaGVscEJ1dHRvblN2ZzogU1ZHRWxlbWVudCB8IG51bGwgPSBudWxsO1xyXG5cdFx0Zm9yIChjb25zdCBzZWxlY3RvciBvZiBzZWxlY3RvcnMpIHtcclxuXHRcdFx0aGVscEJ1dHRvblN2ZyA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3Ioc2VsZWN0b3IpO1xyXG5cdFx0XHRpZiAoaGVscEJ1dHRvblN2ZykgYnJlYWs7XHJcblx0XHR9XHJcblxyXG5cdFx0aWYgKCFoZWxwQnV0dG9uU3ZnKSByZXR1cm47XHJcblx0XHRjb25zdCBvcmlnaW5hbEhlbHBCdXR0b24gPSBoZWxwQnV0dG9uU3ZnLnBhcmVudEVsZW1lbnQgYXMgSFRNTEVsZW1lbnQ7XHJcblx0XHRpZiAoIW9yaWdpbmFsSGVscEJ1dHRvbikgcmV0dXJuO1xyXG5cclxuXHRcdC8vIDQuIENoZWNrIGlmIHdlIGFscmVhZHkgaGF2ZSBhIHZhbGlkIGN1c3RvbSBidXR0b24gaW4gdGhlIHJpZ2h0IHBsYWNlXHJcblx0XHRjb25zdCBleGlzdGluZ1JlcGxhY2VtZW50ID0gb3JpZ2luYWxIZWxwQnV0dG9uLnBhcmVudEVsZW1lbnQ/LnF1ZXJ5U2VsZWN0b3IoJ1tkYXRhLWFzdHJvLWNvbXBvc2VyLWhlbHAtcmVwbGFjZW1lbnQ9XCJ0cnVlXCJdJyk7XHJcblx0XHRpZiAoZXhpc3RpbmdSZXBsYWNlbWVudCkge1xyXG5cdFx0XHR0aGlzLmN1c3RvbUhlbHBCdXR0b24gPSBleGlzdGluZ1JlcGxhY2VtZW50IGFzIEhUTUxFbGVtZW50O1xyXG5cdFx0XHRyZXR1cm47XHJcblx0XHR9XHJcblxyXG5cdFx0Ly8gNS4gQ3JlYXRlIGFuZCBpbmplY3QgdGhlIHJlcGxhY2VtZW50XHJcblx0XHRjb25zdCBjdXN0b21CdXR0b24gPSBvcmlnaW5hbEhlbHBCdXR0b24uY2xvbmVOb2RlKHRydWUpIGFzIEhUTUxFbGVtZW50O1xyXG5cdFx0Y3VzdG9tQnV0dG9uLmFkZENsYXNzKFwiYXN0cm8tY29tcG9zZXItaGVscC1yZXBsYWNlbWVudFwiKTtcclxuXHRcdGN1c3RvbUJ1dHRvbi5yZW1vdmVBdHRyaWJ1dGUoJ2FyaWEtbGFiZWwnKTtcclxuXHRcdGN1c3RvbUJ1dHRvbi5zZXRBdHRyaWJ1dGUoJ2RhdGEtYXN0cm8tY29tcG9zZXItaGVscC1yZXBsYWNlbWVudCcsICd0cnVlJyk7XHJcblx0XHRjdXN0b21CdXR0b24ub25jbGljayA9IG51bGw7XHJcblxyXG5cdFx0Y29uc3QgaWNvbkNvbnRhaW5lciA9IGN1c3RvbUJ1dHRvbi5xdWVyeVNlbGVjdG9yKCdzdmcnKT8ucGFyZW50RWxlbWVudCB8fCBjdXN0b21CdXR0b247XHJcblx0XHR0cnkge1xyXG5cdFx0XHRpZiAoaWNvbkNvbnRhaW5lciBpbnN0YW5jZW9mIEhUTUxFbGVtZW50KSB7XHJcblx0XHRcdFx0c2V0SWNvbihpY29uQ29udGFpbmVyLCB0aGlzLnNldHRpbmdzLmhlbHBCdXR0b25SZXBsYWNlbWVudCEuaWNvbklkKTtcclxuXHRcdFx0fVxyXG5cdFx0fSBjYXRjaCAoZXJyb3IpIHtcclxuXHRcdFx0Y29uc29sZS53YXJuKCdbQXN0cm8gQ29tcG9zZXJdIEVycm9yIHNldHRpbmcgcmVwbGFjZW1lbnQgaWNvbjonLCBlcnJvcik7XHJcblx0XHR9XHJcblxyXG5cdFx0Y3VzdG9tQnV0dG9uLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgKGV2dDogTW91c2VFdmVudCkgPT4ge1xyXG5cdFx0XHRldnQucHJldmVudERlZmF1bHQoKTtcclxuXHRcdFx0ZXZ0LnN0b3BQcm9wYWdhdGlvbigpO1xyXG5cclxuXHRcdFx0Y29uc3QgY29tbWFuZElkID0gdGhpcy5zZXR0aW5ncy5oZWxwQnV0dG9uUmVwbGFjZW1lbnQ/LmNvbW1hbmRJZDtcclxuXHRcdFx0aWYgKGNvbW1hbmRJZCkge1xyXG5cdFx0XHRcdGNvbnN0IGFwcFdpdGhDb21tYW5kcyA9IHRoaXMuYXBwIGFzIHVua25vd24gYXMgeyBjb21tYW5kcz86IHsgZXhlY3V0ZUNvbW1hbmRCeUlkPzogKGlkOiBzdHJpbmcpID0+IFByb21pc2U8dm9pZD4gfSB9O1xyXG5cdFx0XHRcdGlmIChhcHBXaXRoQ29tbWFuZHMuY29tbWFuZHM/LmV4ZWN1dGVDb21tYW5kQnlJZCkge1xyXG5cdFx0XHRcdFx0dm9pZCBhcHBXaXRoQ29tbWFuZHMuY29tbWFuZHMuZXhlY3V0ZUNvbW1hbmRCeUlkKGNvbW1hbmRJZCk7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblx0XHR9LCB0cnVlKTtcclxuXHJcblx0XHRvcmlnaW5hbEhlbHBCdXR0b24ucGFyZW50RWxlbWVudD8uaW5zZXJ0QmVmb3JlKGN1c3RvbUJ1dHRvbiwgb3JpZ2luYWxIZWxwQnV0dG9uKTtcclxuXHRcdHRoaXMuY3VzdG9tSGVscEJ1dHRvbiA9IGN1c3RvbUJ1dHRvbjtcclxuXHR9XHJcblxyXG5cdHByaXZhdGUgcmVzdG9yZUhlbHBCdXR0b24oKSB7XHJcblx0XHRkb2N1bWVudC5ib2R5LnJlbW92ZUNsYXNzKCdhc3Ryby1jb21wb3Nlci1oaWRlLWhlbHAtYnV0dG9uJyk7XHJcblx0XHRpZiAodGhpcy5jdXN0b21IZWxwQnV0dG9uKSB7XHJcblx0XHRcdHRoaXMuY3VzdG9tSGVscEJ1dHRvbi5yZW1vdmUoKTtcclxuXHRcdFx0dGhpcy5jdXN0b21IZWxwQnV0dG9uID0gdW5kZWZpbmVkO1xyXG5cdFx0fVxyXG5cdFx0dGhpcy5oZWxwQnV0dG9uRWxlbWVudCA9IHVuZGVmaW5lZDtcclxuXHR9XHJcblxyXG5cdHByaXZhdGUgcmVtb3ZlUmliYm9uSWNvbnNGcm9tQ29udGV4dE1lbnUobWVudUVsZW1lbnQ6IEhUTUxFbGVtZW50KSB7XHJcblx0XHRjb25zdCB0ZXJtaW5hbFNob3VsZEJlSGlkZGVuID0gIXRoaXMuc2V0dGluZ3MuZW5hYmxlVGVybWluYWxSaWJib25JY29uIHx8ICF0aGlzLnNldHRpbmdzLmVuYWJsZU9wZW5UZXJtaW5hbENvbW1hbmQ7XHJcblx0XHRjb25zdCBjb25maWdTaG91bGRCZUhpZGRlbiA9ICF0aGlzLnNldHRpbmdzLmVuYWJsZUNvbmZpZ1JpYmJvbkljb24gfHwgIXRoaXMuc2V0dGluZ3MuZW5hYmxlT3BlbkNvbmZpZ0ZpbGVDb21tYW5kO1xyXG5cclxuXHRcdGNvbnN0IG1lbnVJdGVtcyA9IG1lbnVFbGVtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoJy5tZW51LWl0ZW0nKTtcclxuXHRcdGZvciAoY29uc3QgaXRlbSBvZiBBcnJheS5mcm9tKG1lbnVJdGVtcykpIHtcclxuXHRcdFx0Y29uc3Qgc3ZnID0gaXRlbS5xdWVyeVNlbGVjdG9yKCdzdmcnKTtcclxuXHRcdFx0aWYgKHN2Zykge1xyXG5cdFx0XHRcdGxldCBpY29uTmFtZSA9IHN2Zy5nZXRBdHRyaWJ1dGUoJ2RhdGEtbHVjaWRlJykgfHwgc3ZnLmdldEF0dHJpYnV0ZSgneG1sbnM6bHVjaWRlJykgfHxcclxuXHRcdFx0XHRcdHN2Zy5nZXRBdHRyaWJ1dGUoJ2RhdGEtaWNvbicpIHx8XHJcblx0XHRcdFx0XHQoc3ZnLmNsYXNzTGlzdC5jb250YWlucygnbHVjaWRlLXRlcm1pbmFsLXNxdWFyZScpID8gJ3Rlcm1pbmFsLXNxdWFyZScgOiBudWxsKSB8fFxyXG5cdFx0XHRcdFx0KHN2Zy5jbGFzc0xpc3QuY29udGFpbnMoJ2x1Y2lkZS1yb2NrZXQnKSA/ICdyb2NrZXQnIDogbnVsbCkgfHxcclxuXHRcdFx0XHRcdChzdmcuY2xhc3NMaXN0LmNvbnRhaW5zKCdsdWNpZGUtd3JlbmNoJykgPyAnd3JlbmNoJyA6IG51bGwpO1xyXG5cclxuXHRcdFx0XHRpZiAoaWNvbk5hbWUpIGljb25OYW1lID0gaWNvbk5hbWUucmVwbGFjZSgvXmx1Y2lkZS0vLCAnJyk7XHJcblxyXG5cdFx0XHRcdGlmICh0ZXJtaW5hbFNob3VsZEJlSGlkZGVuICYmIGljb25OYW1lID09PSAndGVybWluYWwtc3F1YXJlJykge1xyXG5cdFx0XHRcdFx0aWYgKGl0ZW0udGV4dENvbnRlbnQ/LnRvTG93ZXJDYXNlKCkuaW5jbHVkZXMoJ3Rlcm1pbmFsJykpIGl0ZW0ucmVtb3ZlKCk7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdGlmIChjb25maWdTaG91bGRCZUhpZGRlbiAmJiAoaWNvbk5hbWUgPT09ICdyb2NrZXQnIHx8IGljb25OYW1lID09PSAnd3JlbmNoJykpIHtcclxuXHRcdFx0XHRcdGlmIChpdGVtLnRleHRDb250ZW50Py50b0xvd2VyQ2FzZSgpLmluY2x1ZGVzKCdjb25maWcnKSkgaXRlbS5yZW1vdmUoKTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHR9XHJcbn1cclxuIiwgImltcG9ydCB7IFRGaWxlLCBQbHVnaW5TZXR0aW5nVGFiIH0gZnJvbSBcIm9ic2lkaWFuXCI7XHJcblxyXG5leHBvcnQgaW50ZXJmYWNlIEFzdHJvQ29tcG9zZXJTZXR0aW5ncyB7XHJcblx0ZGVmYXVsdFRlbXBsYXRlOiBzdHJpbmc7IC8vIEtlcHQgdGVtcG9yYXJpbHkgZm9yIG1pZ3JhdGlvblxyXG5cdGF1dG9JbnNlcnRQcm9wZXJ0aWVzOiBib29sZWFuO1xyXG5cdGRhdGVGb3JtYXQ6IHN0cmluZztcclxuXHRlbmFibGVDb3B5SGVhZGluZ0xpbms6IGJvb2xlYW47XHJcblx0Y29weUhlYWRpbmdMaW5rRm9ybWF0OiBcIm9ic2lkaWFuXCIgfCBcImFzdHJvXCI7XHJcblx0YWRkVHJhaWxpbmdTbGFzaFRvTGlua3M6IGJvb2xlYW47XHJcblx0ZW5hYmxlT3BlblRlcm1pbmFsQ29tbWFuZDogYm9vbGVhbjtcclxuXHR0ZXJtaW5hbFByb2plY3RSb290UGF0aDogc3RyaW5nO1xyXG5cdHRlcm1pbmFsQXBwbGljYXRpb25OYW1lOiBzdHJpbmc7XHJcblx0ZW5hYmxlVGVybWluYWxEZWJ1Z0xvZ2dpbmc6IGJvb2xlYW47XHJcblx0ZW5hYmxlVGVybWluYWxSaWJib25JY29uOiBib29sZWFuO1xyXG5cdGVuYWJsZU9wZW5Db25maWdGaWxlQ29tbWFuZDogYm9vbGVhbjtcclxuXHRjb25maWdGaWxlUGF0aDogc3RyaW5nO1xyXG5cdGVuYWJsZUNvbmZpZ1JpYmJvbkljb246IGJvb2xlYW47XHJcblx0Y29udGVudFR5cGVzOiBDb250ZW50VHlwZVtdO1xyXG5cdGhlbHBCdXR0b25SZXBsYWNlbWVudDogSGVscEJ1dHRvblJlcGxhY2VtZW50U2V0dGluZ3M7XHJcblx0bWlncmF0aW9uQ29tcGxldGVkOiBib29sZWFuO1xyXG5cdHNob3dNZHhGaWxlc0luRXhwbG9yZXI6IGJvb2xlYW47XHJcblx0cHJvY2Vzc0JhY2tncm91bmRGaWxlQ2hhbmdlczogYm9vbGVhbjtcclxuXHRzeW5jRHJhZnREYXRlOiBib29sZWFuO1xyXG5cdGRyYWZ0RGV0ZWN0aW9uTW9kZTogJ3Byb3BlcnR5JyB8ICd1bmRlcnNjb3JlLXByZWZpeCc7XHJcblx0ZHJhZnRQcm9wZXJ0eTogc3RyaW5nO1xyXG5cdGRyYWZ0TG9naWM6ICd0cnVlLWlzLWRyYWZ0JyB8ICdmYWxzZS1pcy1kcmFmdCc7XHJcblx0cHVibGlzaERhdGVGaWVsZDogc3RyaW5nO1xyXG5cdHJlbmFtZU9uVGl0bGVDbGljazogYm9vbGVhbjtcclxuXHQvLyBMZWdhY3kgZmllbGRzIChrZXB0IGZvciBtaWdyYXRpb24sIGlnbm9yZWQgYWZ0ZXIgbWlncmF0aW9uKVxyXG5cdGVuYWJsZVVuZGVyc2NvcmVQcmVmaXg/OiBib29sZWFuO1xyXG5cdHBvc3RzRm9sZGVyPzogc3RyaW5nO1xyXG5cdHBvc3RzTGlua0Jhc2VQYXRoPzogc3RyaW5nO1xyXG5cdGF1dG9tYXRlUG9zdENyZWF0aW9uPzogYm9vbGVhbjtcclxuXHRjcmVhdGlvbk1vZGU/OiBcImZpbGVcIiB8IFwiZm9sZGVyXCI7XHJcblx0aW5kZXhGaWxlTmFtZT86IHN0cmluZztcclxuXHRleGNsdWRlZERpcmVjdG9yaWVzPzogc3RyaW5nO1xyXG5cdG9ubHlBdXRvbWF0ZUluUG9zdHNGb2xkZXI/OiBib29sZWFuO1xyXG5cdGVuYWJsZVBhZ2VzPzogYm9vbGVhbjtcclxuXHRwYWdlc0ZvbGRlcj86IHN0cmluZztcclxuXHRwYWdlc0xpbmtCYXNlUGF0aD86IHN0cmluZztcclxuXHRwYWdlc0NyZWF0aW9uTW9kZT86IFwiZmlsZVwiIHwgXCJmb2xkZXJcIjtcclxuXHRwYWdlc0luZGV4RmlsZU5hbWU/OiBzdHJpbmc7XHJcblx0cGFnZVRlbXBsYXRlPzogc3RyaW5nO1xyXG5cdG9ubHlBdXRvbWF0ZUluUGFnZXNGb2xkZXI/OiBib29sZWFuO1xyXG5cdGN1c3RvbUNvbnRlbnRUeXBlcz86IENvbnRlbnRUeXBlW107IC8vIExlZ2FjeSBuYW1lXHJcbn1cclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgSGVscEJ1dHRvblJlcGxhY2VtZW50U2V0dGluZ3Mge1xyXG5cdGVuYWJsZWQ6IGJvb2xlYW47XHJcblx0Y29tbWFuZElkOiBzdHJpbmc7XHJcblx0aWNvbklkOiBzdHJpbmc7XHJcbn1cclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgUGFyc2VkRnJvbnRtYXR0ZXIge1xyXG5cdHByb3BlcnRpZXM6IFJlY29yZDxzdHJpbmcsIHN0cmluZ1tdPjtcclxuXHRwcm9wZXJ0aWVzVGV4dDogc3RyaW5nO1xyXG5cdHByb3BlcnRpZXNFbmQ6IG51bWJlcjtcclxuXHRib2R5Q29udGVudDogc3RyaW5nO1xyXG59XHJcblxyXG5leHBvcnQgaW50ZXJmYWNlIFRlbXBsYXRlVmFsdWVzIHtcclxuXHRba2V5OiBzdHJpbmddOiBzdHJpbmdbXSB8IHN0cmluZztcclxufVxyXG5cclxuLy8gQ29udGVudFR5cGUgaXMgbm93IGp1c3QgYSBzdHJpbmcgSUQgLSBubyBkaXN0aW5jdGlvbiBiZXR3ZWVuIGJ1aWx0LWluIGFuZCBjdXN0b20gdHlwZXNcclxuZXhwb3J0IHR5cGUgQ29udGVudFR5cGVJZCA9IHN0cmluZztcclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgQ29udGVudFR5cGUge1xyXG5cdGlkOiBzdHJpbmc7XHJcblx0bmFtZTogc3RyaW5nO1xyXG5cdGZvbGRlcjogc3RyaW5nO1xyXG5cdGxpbmtCYXNlUGF0aDogc3RyaW5nO1xyXG5cdHRlbXBsYXRlOiBzdHJpbmc7XHJcblx0ZW5hYmxlZDogYm9vbGVhbjtcclxuXHRjcmVhdGlvbk1vZGU6IFwiZmlsZVwiIHwgXCJmb2xkZXJcIjtcclxuXHRpbmRleEZpbGVOYW1lOiBzdHJpbmc7XHJcblx0aWdub3JlU3ViZm9sZGVyczogYm9vbGVhbjtcclxuXHRlbmFibGVVbmRlcnNjb3JlUHJlZml4OiBib29sZWFuO1xyXG5cdHVzZU1keEV4dGVuc2lvbjogYm9vbGVhbjtcclxuXHRtb2RpZmllZERhdGVGaWVsZDogc3RyaW5nO1xyXG5cdGNvbGxhcHNlZD86IGJvb2xlYW47XHJcbn1cclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgRmlsZUNyZWF0aW9uT3B0aW9ucyB7XHJcblx0ZmlsZTogVEZpbGU7XHJcblx0dGl0bGU6IHN0cmluZztcclxuXHR0eXBlOiBDb250ZW50VHlwZUlkOyAvLyBDb250ZW50IHR5cGUgSUQgKHN0cmluZylcclxufVxyXG5cclxuZXhwb3J0IGludGVyZmFjZSBSZW5hbWVPcHRpb25zIHtcclxuXHRmaWxlOiBURmlsZTtcclxuXHR0aXRsZTogc3RyaW5nO1xyXG5cdHR5cGU6IENvbnRlbnRUeXBlSWQ7IC8vIENvbnRlbnQgdHlwZSBJRCAoc3RyaW5nKVxyXG59XHJcblxyXG5leHBvcnQgY29uc3QgS05PV05fQVJSQVlfS0VZUyA9IFsndGFncycsICdhbGlhc2VzJywgJ2Nzc2NsYXNzZXMnXSBhcyBjb25zdDtcclxuXHJcbmV4cG9ydCBjb25zdCBDT05TVEFOVFMgPSB7XHJcblx0REVCT1VOQ0VfTVM6IDUwMCxcclxuXHRTVEFUX01USU1FX1RIUkVTSE9MRDogNTAwMCxcclxuXHRFRElUT1JfU1RBQklMSVpFX0RFTEFZOiAxMDAsXHJcblx0RklMRV9FWFBMT1JFUl9SRVZFQUxfREVMQVk6IDIwMCxcclxufSBhcyBjb25zdDtcclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgQXN0cm9Db21wb3NlclBsdWdpbkludGVyZmFjZSB7XHJcblx0c2V0dGluZ3M6IEFzdHJvQ29tcG9zZXJTZXR0aW5ncztcclxuXHRzYXZlU2V0dGluZ3MoKTogUHJvbWlzZTx2b2lkPjtcclxuXHRsb2FkU2V0dGluZ3MoKTogUHJvbWlzZTx2b2lkPjtcclxuXHRyZWdpc3RlckNyZWF0ZUV2ZW50KCk6IHZvaWQ7XHJcblx0cmVnaXN0ZXJFdmVudChldmVudFJlZjogYW55KTogdm9pZDtcclxuXHRyZWdpc3RlckV4dGVuc2lvbnMoZXh0ZW5zaW9uczogc3RyaW5nW10sIHZpZXdUeXBlOiBzdHJpbmcpOiB2b2lkO1xyXG5cdGhlYWRpbmdMaW5rR2VuZXJhdG9yOiBhbnk7XHJcblx0ZnJvbnRtYXR0ZXJTZXJ2aWNlOiBhbnk7XHJcblx0cGx1Z2luQ3JlYXRlZEZpbGVzOiBNYXA8c3RyaW5nLCBudW1iZXI+O1xyXG5cdGZpbGVPcHM6IGFueTtcclxuXHRzZXR0aW5nc1RhYj86IFBsdWdpblNldHRpbmdUYWI7XHJcblx0cmVnaXN0ZXJSaWJib25JY29ucz8oKTogdm9pZDtcclxuXHR1cGRhdGVIZWxwQnV0dG9uPygpOiBQcm9taXNlPHZvaWQ+O1xyXG59IiwgImltcG9ydCB7IEFzdHJvQ29tcG9zZXJTZXR0aW5ncyB9IGZyb20gXCIuL3R5cGVzXCI7XHJcblxyXG5leHBvcnQgdHlwZSB7IEFzdHJvQ29tcG9zZXJTZXR0aW5ncyB9IGZyb20gXCIuL3R5cGVzXCI7XHJcbmV4cG9ydCB7IENPTlNUQU5UUyB9IGZyb20gXCIuL3R5cGVzXCI7XHJcblxyXG5leHBvcnQgY29uc3QgREVGQVVMVF9TRVRUSU5HUzogQXN0cm9Db21wb3NlclNldHRpbmdzID0ge1xyXG5cdGRlZmF1bHRUZW1wbGF0ZTpcclxuXHRcdCctLS1cXG50aXRsZTogXCJ7e3RpdGxlfX1cIlxcbmRhdGU6IHt7ZGF0ZX19XFxudGFnczogW11cXG4tLS1cXG4nLFxyXG5cdGF1dG9JbnNlcnRQcm9wZXJ0aWVzOiB0cnVlLFxyXG5cdGRhdGVGb3JtYXQ6IFwiWVlZWS1NTS1ERFwiLFxyXG5cdGVuYWJsZUNvcHlIZWFkaW5nTGluazogdHJ1ZSxcclxuXHRjb3B5SGVhZGluZ0xpbmtGb3JtYXQ6IFwib2JzaWRpYW5cIixcclxuXHRhZGRUcmFpbGluZ1NsYXNoVG9MaW5rczogZmFsc2UsXHJcblx0ZW5hYmxlT3BlblRlcm1pbmFsQ29tbWFuZDogZmFsc2UsXHJcblx0dGVybWluYWxQcm9qZWN0Um9vdFBhdGg6IFwiXCIsXHJcblx0dGVybWluYWxBcHBsaWNhdGlvbk5hbWU6IFwiXCIsXHJcblx0ZW5hYmxlVGVybWluYWxEZWJ1Z0xvZ2dpbmc6IGZhbHNlLFxyXG5cdGVuYWJsZVRlcm1pbmFsUmliYm9uSWNvbjogZmFsc2UsXHJcblx0ZW5hYmxlT3BlbkNvbmZpZ0ZpbGVDb21tYW5kOiBmYWxzZSxcclxuXHRjb25maWdGaWxlUGF0aDogXCJcIixcclxuXHRlbmFibGVDb25maWdSaWJib25JY29uOiBmYWxzZSxcclxuXHRjb250ZW50VHlwZXM6IFtdLFxyXG5cdG1pZ3JhdGlvbkNvbXBsZXRlZDogZmFsc2UsXHJcblx0aGVscEJ1dHRvblJlcGxhY2VtZW50OiB7XHJcblx0XHRlbmFibGVkOiBmYWxzZSxcclxuXHRcdGNvbW1hbmRJZDogJ2VkaXQtYXN0cm8tY29uZmlnJyxcclxuXHRcdGljb25JZDogJ3JvY2tldCcsXHJcblx0fSxcclxuXHRzaG93TWR4RmlsZXNJbkV4cGxvcmVyOiBmYWxzZSxcclxuXHRwcm9jZXNzQmFja2dyb3VuZEZpbGVDaGFuZ2VzOiB0cnVlLFxyXG5cdHN5bmNEcmFmdERhdGU6IGZhbHNlLFxyXG5cdGRyYWZ0RGV0ZWN0aW9uTW9kZTogXCJwcm9wZXJ0eVwiLFxyXG5cdGRyYWZ0UHJvcGVydHk6IFwiXCIsXHJcblx0ZHJhZnRMb2dpYzogXCJ0cnVlLWlzLWRyYWZ0XCIsXHJcblx0cHVibGlzaERhdGVGaWVsZDogXCJcIixcclxuXHRyZW5hbWVPblRpdGxlQ2xpY2s6IGZhbHNlLFxyXG59O1xyXG4iLCAiaW1wb3J0IHsgUGx1Z2luLCBFZGl0b3IsIE1hcmtkb3duVmlldywgVEZpbGUsIE5vdGljZSwgQXBwLCBNYXJrZG93bkZpbGVJbmZvLCBQbGF0Zm9ybSwgVEZvbGRlciB9IGZyb20gXCJvYnNpZGlhblwiO1xyXG5pbXBvcnQgeyBBc3Ryb0NvbXBvc2VyU2V0dGluZ3MsIEFzdHJvQ29tcG9zZXJQbHVnaW5JbnRlcmZhY2UgfSBmcm9tIFwiLi4vdHlwZXNcIjtcclxuaW1wb3J0IHsgRmlsZU9wZXJhdGlvbnMgfSBmcm9tIFwiLi4vdXRpbHMvZmlsZS1vcGVyYXRpb25zXCI7XHJcbmltcG9ydCB7IFRlbXBsYXRlUGFyc2VyIH0gZnJvbSBcIi4uL3V0aWxzL3RlbXBsYXRlLXBhcnNpbmdcIjtcclxuaW1wb3J0IHsgTGlua0NvbnZlcnRlciB9IGZyb20gXCIuLi91dGlscy9saW5rLWNvbnZlcnNpb25cIjtcclxuaW1wb3J0IHsgVGl0bGVNb2RhbCB9IGZyb20gXCIuLi91aS90aXRsZS1tb2RhbFwiO1xyXG5pbXBvcnQgeyB0b0tlYmFiQ2FzZSB9IGZyb20gXCIuLi91dGlscy9zdHJpbmctdXRpbHNcIjtcclxuXHJcbmV4cG9ydCBmdW5jdGlvbiByZWdpc3RlckNvbW1hbmRzKHBsdWdpbjogUGx1Z2luLCBzZXR0aW5nczogQXN0cm9Db21wb3NlclNldHRpbmdzKTogdm9pZCB7XHJcblx0Ly8gVGVybWluYWwgYW5kIGNvbmZpZyBjb21tYW5kcyBhcmUgZGVza3RvcC1vbmx5IC0gTkVWRVIgcmVnaXN0ZXIgb24gbW9iaWxlXHJcblx0Ly8gQ2hlY2sgUGxhdGZvcm0uaXNNb2JpbGUgLSBpZiB0cnVlLCB0aGVzZSBjb21tYW5kcyBtdXN0IE5FVkVSIGJlIHJlZ2lzdGVyZWRcclxuXHRjb25zdCBpc01vYmlsZSA9IFBsYXRmb3JtLmlzTW9iaWxlO1xyXG5cclxuXHQvLyBJZiBvbiBtb2JpbGUsIGFic29sdXRlbHkgZG8gbm90IHJlZ2lzdGVyIHRlcm1pbmFsL2NvbmZpZyBjb21tYW5kc1xyXG5cdC8vIFRoZXkgdXNlIE5vZGUuanMvRWxlY3Ryb24gQVBJcyB0aGF0IGRvbid0IGV4aXN0IG9uIG1vYmlsZVxyXG5cdGlmIChpc01vYmlsZSkge1xyXG5cdFx0Ly8gT24gbW9iaWxlLCBvbmx5IHJlZ2lzdGVyIHRoZSBzYWZlIGNvbW1hbmRzIHRoYXQgd29yayBvbiBtb2JpbGVcclxuXHRcdGNvbnN0IHBsdWdpbkludGVyZmFjZSA9IHBsdWdpbiBhcyB1bmtub3duIGFzIEFzdHJvQ29tcG9zZXJQbHVnaW5JbnRlcmZhY2U7XHJcblx0XHRjb25zdCBmaWxlT3BzID0gbmV3IEZpbGVPcGVyYXRpb25zKHBsdWdpbi5hcHAsIHNldHRpbmdzLCBwbHVnaW5JbnRlcmZhY2UpO1xyXG5cdFx0Y29uc3QgbGlua0NvbnZlcnRlciA9IG5ldyBMaW5rQ29udmVydGVyKHNldHRpbmdzLCBwbHVnaW5JbnRlcmZhY2UpO1xyXG5cclxuXHRcdC8vIFJlZ2lzdGVyIG9ubHkgbW9iaWxlLXNhZmUgY29tbWFuZHNcclxuXHRcdHBsdWdpbi5hZGRDb21tYW5kKHtcclxuXHRcdFx0aWQ6IFwic3RhbmRhcmRpemUtcHJvcGVydGllc1wiLFxyXG5cdFx0XHRuYW1lOiBcIlN0YW5kYXJkaXplIHByb3BlcnRpZXNcIixcclxuXHRcdFx0aWNvbjogXCJmaWxlLWNoZWNrXCIsXHJcblx0XHRcdGVkaXRvckNhbGxiYWNrOiAoZWRpdG9yOiBFZGl0b3IsIGN0eDogTWFya2Rvd25WaWV3IHwgTWFya2Rvd25GaWxlSW5mbykgPT4ge1xyXG5cdFx0XHRcdGNvbnN0IGZpbGUgPSBjdHggaW5zdGFuY2VvZiBNYXJrZG93blZpZXcgPyBjdHguZmlsZSA6IGN0eC5maWxlO1xyXG5cdFx0XHRcdGlmIChmaWxlIGluc3RhbmNlb2YgVEZpbGUpIHtcclxuXHRcdFx0XHRcdC8vIEdldCBmcmVzaCBzZXR0aW5ncyBmcm9tIHBsdWdpblxyXG5cdFx0XHRcdFx0Y29uc3QgY3VycmVudFNldHRpbmdzID0gcGx1Z2luSW50ZXJmYWNlLnNldHRpbmdzIHx8IHNldHRpbmdzO1xyXG5cdFx0XHRcdFx0dm9pZCBzdGFuZGFyZGl6ZVByb3BlcnRpZXMocGx1Z2luLmFwcCwgY3VycmVudFNldHRpbmdzLCBmaWxlLCBwbHVnaW5JbnRlcmZhY2UsIGVkaXRvcik7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9LFxyXG5cdFx0fSk7XHJcblxyXG5cdFx0cGx1Z2luLmFkZENvbW1hbmQoe1xyXG5cdFx0XHRpZDogXCJjb252ZXJ0LXdpa2lsaW5rcy1hc3Ryb1wiLFxyXG5cdFx0XHRuYW1lOiBcIkNvbnZlcnQgaW50ZXJuYWwgbGlua3MgZm9yIGFzdHJvXCIsXHJcblx0XHRcdGljb246IFwibGluay0yXCIsXHJcblx0XHRcdGVkaXRvckNhbGxiYWNrOiAoZWRpdG9yOiBFZGl0b3IsIGN0eDogTWFya2Rvd25WaWV3IHwgTWFya2Rvd25GaWxlSW5mbykgPT4ge1xyXG5cdFx0XHRcdGNvbnN0IGZpbGUgPSBjdHggaW5zdGFuY2VvZiBNYXJrZG93blZpZXcgPyBjdHguZmlsZSA6IGN0eC5maWxlO1xyXG5cdFx0XHRcdGlmIChmaWxlIGluc3RhbmNlb2YgVEZpbGUpIHtcclxuXHRcdFx0XHRcdGxpbmtDb252ZXJ0ZXIuY29udmVydFdpa2lsaW5rc0ZvckFzdHJvKGVkaXRvciwgZmlsZSk7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9LFxyXG5cdFx0fSk7XHJcblxyXG5cdFx0Ly8gSGVscGVyIGZ1bmN0aW9uIGZvciByZW5hbWUgY29tbWFuZCAobW9iaWxlIHZlcnNpb24pXHJcblx0XHQvLyBVc2VzIHRoZSBzYW1lIGxvZ2ljIGFzIEZpbGVPcGVyYXRpb25zLmRldGVybWluZVR5cGUoKSB0byBlbnN1cmUgY29uc2lzdGVuY3lcclxuXHRcdGZ1bmN0aW9uIGhhc01hdGNoaW5nQ29udGVudFR5cGUoZmlsZTogVEZpbGUsIHNldHRpbmdzOiBBc3Ryb0NvbXBvc2VyU2V0dGluZ3MpOiBib29sZWFuIHtcclxuXHRcdFx0Y29uc3QgdHlwZSA9IGZpbGVPcHMuZGV0ZXJtaW5lVHlwZShmaWxlKTtcclxuXHRcdFx0Ly8gSWYgZGV0ZXJtaW5lVHlwZSByZXR1cm5zIFwibm90ZVwiLCBpdCBtZWFucyBubyBjb250ZW50IHR5cGUgbWF0Y2hlZFxyXG5cdFx0XHRpZiAodHlwZSA9PT0gXCJub3RlXCIpIHtcclxuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XHJcblx0XHRcdH1cclxuXHRcdFx0Ly8gQ2hlY2sgaWYgdGhlIG1hdGNoZWQgY29udGVudCB0eXBlIGlzIGVuYWJsZWRcclxuXHRcdFx0Y29uc3QgY29udGVudFR5cGUgPSBmaWxlT3BzLmdldENvbnRlbnRUeXBlKHR5cGUpO1xyXG5cdFx0XHRyZXR1cm4gY29udGVudFR5cGUgIT09IG51bGwgJiYgY29udGVudFR5cGUuZW5hYmxlZDtcclxuXHRcdH1cclxuXHJcblx0XHRwbHVnaW4uYWRkQ29tbWFuZCh7XHJcblx0XHRcdGlkOiBcInJlbmFtZS1jb250ZW50XCIsXHJcblx0XHRcdG5hbWU6IFwiUmVuYW1lIGN1cnJlbnQgY29udGVudFwiLFxyXG5cdFx0XHRpY29uOiBcInBlbmNpbFwiLFxyXG5cdFx0XHRlZGl0b3JDYWxsYmFjazogKGVkaXRvcjogRWRpdG9yLCBjdHg6IE1hcmtkb3duVmlldyB8IE1hcmtkb3duRmlsZUluZm8pID0+IHtcclxuXHRcdFx0XHRjb25zdCBmaWxlID0gY3R4IGluc3RhbmNlb2YgTWFya2Rvd25WaWV3ID8gY3R4LmZpbGUgOiBjdHguZmlsZTtcclxuXHRcdFx0XHRpZiAoZmlsZSBpbnN0YW5jZW9mIFRGaWxlKSB7XHJcblx0XHRcdFx0XHRpZiAoIWhhc01hdGNoaW5nQ29udGVudFR5cGUoZmlsZSwgc2V0dGluZ3MpKSB7XHJcblx0XHRcdFx0XHRcdG5ldyBOb3RpY2UoXCJDYW5ub3QgcmVuYW1lOiB0aGlzIGZpbGUgaXMgbm90IHBhcnQgb2YgYSBjb25maWd1cmVkIGNvbnRlbnQgdHlwZSBmb2xkZXIuXCIpO1xyXG5cdFx0XHRcdFx0XHRyZXR1cm47XHJcblx0XHRcdFx0XHR9XHJcblxyXG5cdFx0XHRcdFx0Y29uc3QgdHlwZSA9IGZpbGVPcHMuZGV0ZXJtaW5lVHlwZShmaWxlKTtcclxuXHRcdFx0XHRcdGNvbnN0IGNhY2hlID0gcGx1Z2luLmFwcC5tZXRhZGF0YUNhY2hlLmdldEZpbGVDYWNoZShmaWxlKTtcclxuXHRcdFx0XHRcdGNvbnN0IHRpdGxlS2V5ID0gZmlsZU9wcy5nZXRUaXRsZUtleSh0eXBlKTtcclxuXHJcblx0XHRcdFx0XHRpZiAoIWNhY2hlPy5mcm9udG1hdHRlciB8fCAhKHRpdGxlS2V5IGluIGNhY2hlLmZyb250bWF0dGVyKSkge1xyXG5cdFx0XHRcdFx0XHRuZXcgTm90aWNlKGBDYW5ub3QgcmVuYW1lOiBObyAke3RpdGxlS2V5fSBmb3VuZCBpbiBwcm9wZXJ0aWVzYCk7XHJcblx0XHRcdFx0XHRcdHJldHVybjtcclxuXHRcdFx0XHRcdH1cclxuXHJcblx0XHRcdFx0XHRuZXcgVGl0bGVNb2RhbChwbHVnaW4uYXBwLCBmaWxlLCBwbHVnaW4gYXMgdW5rbm93biBhcyBBc3Ryb0NvbXBvc2VyUGx1Z2luSW50ZXJmYWNlLCB0eXBlLCB0cnVlKS5vcGVuKCk7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9LFxyXG5cdFx0fSk7XHJcblxyXG5cdFx0Ly8gRE8gTk9UIHJlZ2lzdGVyIHRlcm1pbmFsIG9yIGNvbmZpZyBjb21tYW5kcyBvbiBtb2JpbGUgLSByZXR1cm4gZWFybHlcclxuXHRcdHJldHVybjtcclxuXHR9XHJcblxyXG5cdC8vIERlc2t0b3A6IHJlZ2lzdGVyIGFsbCBjb21tYW5kcyBpbmNsdWRpbmcgdGVybWluYWwgYW5kIGNvbmZpZ1xyXG5cdGNvbnN0IHBsdWdpbkludGVyZmFjZSA9IHBsdWdpbiBhcyB1bmtub3duIGFzIEFzdHJvQ29tcG9zZXJQbHVnaW5JbnRlcmZhY2U7XHJcblxyXG5cclxuXHQvLyBIZWxwZXIgZnVuY3Rpb24gdG8gY2hlY2sgaWYgYSBmaWxlIG1hdGNoZXMgYW55IGNvbmZpZ3VyZWQgY29udGVudCB0eXBlXHJcblx0Ly8gVXNlcyB0aGUgc2FtZSBsb2dpYyBhcyBGaWxlT3BlcmF0aW9ucy5kZXRlcm1pbmVUeXBlKCkgdG8gZW5zdXJlIGNvbnNpc3RlbmN5XHJcblx0Ly8gR2V0cyBmcmVzaCBzZXR0aW5ncyBmcm9tIHBsdWdpbiB0byBlbnN1cmUgd2UgY2hlY2sgYWdhaW5zdCBjdXJyZW50IGNvbnRlbnQgdHlwZXNcclxuXHRmdW5jdGlvbiBoYXNNYXRjaGluZ0NvbnRlbnRUeXBlKGZpbGU6IFRGaWxlLCBzZXR0aW5nczogQXN0cm9Db21wb3NlclNldHRpbmdzKTogYm9vbGVhbiB7XHJcblx0XHQvLyBHZXQgZnJlc2ggc2V0dGluZ3MgZnJvbSBwbHVnaW4gaWYgYXZhaWxhYmxlXHJcblx0XHRjb25zdCBjdXJyZW50U2V0dGluZ3MgPSAocGx1Z2luIGFzIHVua25vd24gYXMgQXN0cm9Db21wb3NlclBsdWdpbkludGVyZmFjZSk/LnNldHRpbmdzIHx8IHNldHRpbmdzO1xyXG5cdFx0Ly8gQ3JlYXRlIGEgdGVtcG9yYXJ5IEZpbGVPcGVyYXRpb25zIHdpdGggZnJlc2ggc2V0dGluZ3NcclxuXHRcdGNvbnN0IHRlbXBGaWxlT3BzID0gbmV3IEZpbGVPcGVyYXRpb25zKHBsdWdpbi5hcHAsIGN1cnJlbnRTZXR0aW5ncywgcGx1Z2luIGFzIHVua25vd24gYXMgQXN0cm9Db21wb3NlclBsdWdpbkludGVyZmFjZSk7XHJcblx0XHRjb25zdCB0eXBlID0gdGVtcEZpbGVPcHMuZGV0ZXJtaW5lVHlwZShmaWxlKTtcclxuXHRcdC8vIElmIGRldGVybWluZVR5cGUgcmV0dXJucyBcIm5vdGVcIiwgaXQgbWVhbnMgbm8gY29udGVudCB0eXBlIG1hdGNoZWRcclxuXHRcdGlmICh0eXBlID09PSBcIm5vdGVcIikge1xyXG5cdFx0XHRyZXR1cm4gZmFsc2U7XHJcblx0XHR9XHJcblx0XHQvLyBDaGVjayBpZiB0aGUgbWF0Y2hlZCBjb250ZW50IHR5cGUgaXMgZW5hYmxlZFxyXG5cdFx0Y29uc3QgY29udGVudFR5cGUgPSB0ZW1wRmlsZU9wcy5nZXRDb250ZW50VHlwZSh0eXBlKTtcclxuXHRcdHJldHVybiBjb250ZW50VHlwZSAhPT0gbnVsbCAmJiBjb250ZW50VHlwZS5lbmFibGVkO1xyXG5cdH1cclxuXHJcblx0Ly8gU3RhbmRhcmRpemUgUHJvcGVydGllcyBjb21tYW5kXHJcblx0cGx1Z2luLmFkZENvbW1hbmQoe1xyXG5cdFx0aWQ6IFwic3RhbmRhcmRpemUtcHJvcGVydGllc1wiLFxyXG5cdFx0bmFtZTogXCJTdGFuZGFyZGl6ZSBwcm9wZXJ0aWVzXCIsXHJcblx0XHRpY29uOiBcImZpbGUtY2hlY2tcIixcclxuXHRcdGVkaXRvckNhbGxiYWNrOiAoZWRpdG9yOiBFZGl0b3IsIGN0eDogTWFya2Rvd25WaWV3IHwgTWFya2Rvd25GaWxlSW5mbykgPT4ge1xyXG5cdFx0XHRjb25zdCBmaWxlID0gY3R4IGluc3RhbmNlb2YgTWFya2Rvd25WaWV3ID8gY3R4LmZpbGUgOiBjdHguZmlsZTtcclxuXHRcdFx0aWYgKGZpbGUgaW5zdGFuY2VvZiBURmlsZSkge1xyXG5cdFx0XHRcdHZvaWQgc3RhbmRhcmRpemVQcm9wZXJ0aWVzKHBsdWdpbi5hcHAsIHNldHRpbmdzLCBmaWxlLCBwbHVnaW4gYXMgdW5rbm93biBhcyBBc3Ryb0NvbXBvc2VyUGx1Z2luSW50ZXJmYWNlLCBlZGl0b3IpO1xyXG5cdFx0XHR9XHJcblx0XHR9LFxyXG5cdH0pO1xyXG5cclxuXHQvLyBDb252ZXJ0IFdpa2lsaW5rcyBjb21tYW5kXHJcblx0cGx1Z2luLmFkZENvbW1hbmQoe1xyXG5cdFx0aWQ6IFwiY29udmVydC13aWtpbGlua3MtYXN0cm9cIixcclxuXHRcdG5hbWU6IFwiQ29udmVydCBpbnRlcm5hbCBsaW5rcyBmb3IgYXN0cm9cIixcclxuXHRcdGljb246IFwibGluay0yXCIsXHJcblx0XHRlZGl0b3JDYWxsYmFjazogKGVkaXRvcjogRWRpdG9yLCBjdHg6IE1hcmtkb3duVmlldyB8IE1hcmtkb3duRmlsZUluZm8pID0+IHtcclxuXHRcdFx0Y29uc3QgZmlsZSA9IGN0eCBpbnN0YW5jZW9mIE1hcmtkb3duVmlldyA/IGN0eC5maWxlIDogY3R4LmZpbGU7XHJcblx0XHRcdGlmIChmaWxlIGluc3RhbmNlb2YgVEZpbGUpIHtcclxuXHRcdFx0XHQvLyBHZXQgZnJlc2ggc2V0dGluZ3MgZnJvbSBwbHVnaW4gYW5kIGNyZWF0ZSBMaW5rQ29udmVydGVyIHdpdGggaXRcclxuXHRcdFx0XHRjb25zdCBjdXJyZW50U2V0dGluZ3MgPSBwbHVnaW5JbnRlcmZhY2Uuc2V0dGluZ3MgfHwgc2V0dGluZ3M7XHJcblx0XHRcdFx0Y29uc3QgY3VycmVudExpbmtDb252ZXJ0ZXIgPSBuZXcgTGlua0NvbnZlcnRlcihjdXJyZW50U2V0dGluZ3MsIHBsdWdpbkludGVyZmFjZSk7XHJcblx0XHRcdFx0Y3VycmVudExpbmtDb252ZXJ0ZXIuY29udmVydFdpa2lsaW5rc0ZvckFzdHJvKGVkaXRvciwgZmlsZSk7XHJcblx0XHRcdH1cclxuXHRcdH0sXHJcblx0fSk7XHJcblxyXG5cdC8vIFJlbmFtZSBDb250ZW50IGNvbW1hbmRcclxuXHRwbHVnaW4uYWRkQ29tbWFuZCh7XHJcblx0XHRpZDogXCJyZW5hbWUtY29udGVudFwiLFxyXG5cdFx0bmFtZTogXCJSZW5hbWUgY3VycmVudCBjb250ZW50XCIsXHJcblx0XHRpY29uOiBcInBlbmNpbFwiLFxyXG5cdFx0ZWRpdG9yQ2FsbGJhY2s6IChlZGl0b3I6IEVkaXRvciwgY3R4OiBNYXJrZG93blZpZXcgfCBNYXJrZG93bkZpbGVJbmZvKSA9PiB7XHJcblx0XHRcdGNvbnN0IGZpbGUgPSBjdHggaW5zdGFuY2VvZiBNYXJrZG93blZpZXcgPyBjdHguZmlsZSA6IGN0eC5maWxlO1xyXG5cdFx0XHRpZiAoZmlsZSBpbnN0YW5jZW9mIFRGaWxlKSB7XHJcblx0XHRcdFx0Ly8gR2V0IGZyZXNoIHNldHRpbmdzIGZyb20gcGx1Z2luXHJcblx0XHRcdFx0Y29uc3QgY3VycmVudFNldHRpbmdzID0gcGx1Z2luSW50ZXJmYWNlLnNldHRpbmdzIHx8IHNldHRpbmdzO1xyXG5cdFx0XHRcdC8vIENyZWF0ZSBGaWxlT3BlcmF0aW9ucyB3aXRoIGZyZXNoIHNldHRpbmdzXHJcblx0XHRcdFx0Y29uc3QgY3VycmVudEZpbGVPcHMgPSBuZXcgRmlsZU9wZXJhdGlvbnMocGx1Z2luLmFwcCwgY3VycmVudFNldHRpbmdzLCBwbHVnaW5JbnRlcmZhY2UpO1xyXG5cclxuXHRcdFx0XHQvLyBDaGVjayBpZiB0aGlzIGZpbGUgbWF0Y2hlcyBhbnkgY29uZmlndXJlZCBjb250ZW50IHR5cGVcclxuXHRcdFx0XHRpZiAoIWhhc01hdGNoaW5nQ29udGVudFR5cGUoZmlsZSwgY3VycmVudFNldHRpbmdzKSkge1xyXG5cdFx0XHRcdFx0bmV3IE5vdGljZShcIkNhbm5vdCByZW5hbWU6IHRoaXMgZmlsZSBpcyBub3QgcGFydCBvZiBhIGNvbmZpZ3VyZWQgY29udGVudCB0eXBlIGZvbGRlci5cIik7XHJcblx0XHRcdFx0XHRyZXR1cm47XHJcblx0XHRcdFx0fVxyXG5cclxuXHRcdFx0XHQvLyBEZXRlcm1pbmUgY29udGVudCB0eXBlIGZyb20gZm9sZGVyIHN0cnVjdHVyZVxyXG5cdFx0XHRcdGNvbnN0IHR5cGUgPSBjdXJyZW50RmlsZU9wcy5kZXRlcm1pbmVUeXBlKGZpbGUpO1xyXG5cclxuXHRcdFx0XHQvLyBBbHdheXMgb3BlbiB0aGUgbW9kYWwgLSBpdCB3aWxsIGhhbmRsZSBmaWxlcyB3aXRob3V0IGZyb250bWF0dGVyIG9yIHRpdGxlIGtleVxyXG5cdFx0XHRcdC8vIElmIHRoZXJlJ3Mgbm8gdGl0bGUgaW4gZnJvbnRtYXR0ZXIsIHRoZSBtb2RhbCB3aWxsIHVzZSB0aGUgZmlsZW5hbWUgYXMgZmFsbGJhY2tcclxuXHRcdFx0XHQvLyBhbmQgdGhlIHJlbmFtZSB3aWxsIHByb2NlZWQgd2l0aCBrZWJhYi1jYXNlIHZlcnNpb24gb2Ygd2hhdCB1c2VyIHR5cGVzXHJcblx0XHRcdFx0bmV3IFRpdGxlTW9kYWwocGx1Z2luLmFwcCwgZmlsZSwgcGx1Z2luSW50ZXJmYWNlLCB0eXBlLCB0cnVlKS5vcGVuKCk7XHJcblx0XHRcdH1cclxuXHRcdH0sXHJcblx0fSk7XHJcblxyXG5cdC8vIE9wZW4gVGVybWluYWwgY29tbWFuZCAoZGVza3RvcCBvbmx5IC0gbm90IGF2YWlsYWJsZSBvbiBtb2JpbGUpXHJcblx0aWYgKCFpc01vYmlsZSkge1xyXG5cdFx0cGx1Z2luLmFkZENvbW1hbmQoe1xyXG5cdFx0XHRpZDogXCJvcGVuLXByb2plY3QtdGVybWluYWxcIixcclxuXHRcdFx0bmFtZTogXCJPcGVuIHByb2plY3QgdGVybWluYWxcIixcclxuXHRcdFx0aWNvbjogXCJ0ZXJtaW5hbC1zcXVhcmVcIixcclxuXHRcdFx0Y2FsbGJhY2s6ICgpID0+IHtcclxuXHRcdFx0XHRjb25zdCBjdXJyZW50U2V0dGluZ3MgPSAocGx1Z2luIGFzIHVua25vd24gYXMgQXN0cm9Db21wb3NlclBsdWdpbkludGVyZmFjZSkuc2V0dGluZ3M7XHJcblx0XHRcdFx0aWYgKCFjdXJyZW50U2V0dGluZ3MuZW5hYmxlT3BlblRlcm1pbmFsQ29tbWFuZCkge1xyXG5cdFx0XHRcdFx0bmV3IE5vdGljZShcIk9wZW4gdGVybWluYWwgY29tbWFuZCBpcyBkaXNhYmxlZC4gRW5hYmxlIGl0IGluIHNldHRpbmdzIHRvIHVzZSB0aGlzIGNvbW1hbmQuXCIpO1xyXG5cdFx0XHRcdFx0cmV0dXJuO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0XHRvcGVuVGVybWluYWxJblByb2plY3RSb290KHBsdWdpbi5hcHAsIGN1cnJlbnRTZXR0aW5ncyk7XHJcblx0XHRcdH0sXHJcblx0XHR9KTtcclxuXHR9XHJcblxyXG5cdC8vIEVkaXQgQ29uZmlnIEZpbGUgY29tbWFuZCAoZGVza3RvcCBvbmx5IC0gbm90IGF2YWlsYWJsZSBvbiBtb2JpbGUpXHJcblx0aWYgKCFpc01vYmlsZSkge1xyXG5cdFx0cGx1Z2luLmFkZENvbW1hbmQoe1xyXG5cdFx0XHRpZDogXCJlZGl0LWFzdHJvLWNvbmZpZ1wiLFxyXG5cdFx0XHRuYW1lOiBcIkVkaXQgYXN0cm8gY29uZmlnXCIsXHJcblx0XHRcdGljb246IFwicm9ja2V0XCIsXHJcblx0XHRcdGNhbGxiYWNrOiBhc3luYyAoKSA9PiB7XHJcblx0XHRcdFx0Y29uc3QgY3VycmVudFNldHRpbmdzID0gKHBsdWdpbiBhcyB1bmtub3duIGFzIEFzdHJvQ29tcG9zZXJQbHVnaW5JbnRlcmZhY2UpLnNldHRpbmdzO1xyXG5cdFx0XHRcdGlmICghY3VycmVudFNldHRpbmdzLmVuYWJsZU9wZW5Db25maWdGaWxlQ29tbWFuZCkge1xyXG5cdFx0XHRcdFx0bmV3IE5vdGljZShcIkVkaXQgY29uZmlnIGZpbGUgY29tbWFuZCBpcyBkaXNhYmxlZC4gRW5hYmxlIGl0IGluIHNldHRpbmdzIHRvIHVzZSB0aGlzIGNvbW1hbmQuXCIpO1xyXG5cdFx0XHRcdFx0cmV0dXJuO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0XHRhd2FpdCBvcGVuQ29uZmlnRmlsZShwbHVnaW4uYXBwLCBjdXJyZW50U2V0dGluZ3MpO1xyXG5cdFx0XHR9LFxyXG5cdFx0fSk7XHJcblx0fVxyXG59XHJcblxyXG5hc3luYyBmdW5jdGlvbiBzdGFuZGFyZGl6ZVByb3BlcnRpZXMoYXBwOiBBcHAsIHNldHRpbmdzOiBBc3Ryb0NvbXBvc2VyU2V0dGluZ3MsIGZpbGU6IFRGaWxlLCBwbHVnaW4/OiBBc3Ryb0NvbXBvc2VyUGx1Z2luSW50ZXJmYWNlLCBlZGl0b3I/OiBFZGl0b3IpOiBQcm9taXNlPHZvaWQ+IHtcclxuXHQvLyBHZXQgZnJlc2ggc2V0dGluZ3MgZnJvbSBwbHVnaW4gaWYgYXZhaWxhYmxlXHJcblx0Y29uc3QgY3VycmVudFNldHRpbmdzID0gcGx1Z2luPy5zZXR0aW5ncyB8fCBzZXR0aW5ncztcclxuXHRjb25zdCB0ZW1wbGF0ZVBhcnNlciA9IG5ldyBUZW1wbGF0ZVBhcnNlcihhcHAsIGN1cnJlbnRTZXR0aW5ncyk7XHJcblx0Y29uc3QgZmlsZU9wcyA9IG5ldyBGaWxlT3BlcmF0aW9ucyhhcHAsIGN1cnJlbnRTZXR0aW5ncywgcGx1Z2luKTtcclxuXHJcblx0Ly8gUHJlc2VydmUgY3Vyc29yIHBvc2l0aW9uIGlmIGVkaXRvciBpcyBwcm92aWRlZFxyXG5cdGxldCBjdXJzb3JQb3NpdGlvbjogeyBsaW5lOiBudW1iZXI7IGNoOiBudW1iZXIgfSB8IG51bGwgPSBudWxsO1xyXG5cdGxldCBvcmlnaW5hbENvbnRlbnQgPSBcIlwiO1xyXG5cdGlmIChlZGl0b3IpIHtcclxuXHRcdGNvbnN0IGN1cnNvciA9IGVkaXRvci5nZXRDdXJzb3IoKTtcclxuXHRcdGN1cnNvclBvc2l0aW9uID0geyBsaW5lOiBjdXJzb3IubGluZSwgY2g6IGN1cnNvci5jaCB9O1xyXG5cdFx0b3JpZ2luYWxDb250ZW50ID0gZWRpdG9yLmdldFZhbHVlKCk7XHJcblx0fVxyXG5cclxuXHQvLyBEZXRlcm1pbmUgY29udGVudCB0eXBlIHVzaW5nIHRoZSBleGlzdGluZyBsb2dpY1xyXG5cdGNvbnN0IHR5cGUgPSBmaWxlT3BzLmRldGVybWluZVR5cGUoZmlsZSk7XHJcblxyXG5cdC8vIENoZWNrIGlmIHRoaXMgZmlsZSBoYXMgYSB2YWxpZCBjb250ZW50IHR5cGUgKG5vdCBqdXN0IFwibm90ZVwiKVxyXG5cdGlmICh0eXBlID09PSBcIm5vdGVcIikge1xyXG5cdFx0bmV3IE5vdGljZShcIk5vIHByb3BlcnRpZXMgdGVtcGxhdGUgc3BlY2lmaWVkIGZvciB0aGlzIGNvbnRlbnQuIFRoaXMgZmlsZSBkb2Vzbid0IG1hdGNoIGFueSBjb25maWd1cmVkIGNvbnRlbnQgdHlwZSBmb2xkZXJzLlwiKTtcclxuXHRcdHJldHVybjtcclxuXHR9XHJcblxyXG5cdGxldCB0ZW1wbGF0ZVN0cmluZzogc3RyaW5nO1xyXG5cclxuXHQvLyBEZXRlcm1pbmUgdGVtcGxhdGUgYmFzZWQgb24gY29udGVudCB0eXBlXHJcblx0aWYgKHR5cGUgPT09IFwibm90ZVwiKSB7XHJcblx0XHRuZXcgTm90aWNlKFwiTm8gcHJvcGVydGllcyB0ZW1wbGF0ZSBzcGVjaWZpZWQgZm9yIHRoaXMgY29udGVudC4gVGhpcyBmaWxlIGRvZXNuJ3QgbWF0Y2ggYW55IGNvbmZpZ3VyZWQgY29udGVudCB0eXBlIGZvbGRlcnMuXCIpO1xyXG5cdFx0cmV0dXJuO1xyXG5cdH1cclxuXHJcblx0Y29uc3QgY29udGVudFR5cGUgPSBmaWxlT3BzLmdldENvbnRlbnRUeXBlKHR5cGUpO1xyXG5cdGlmICghY29udGVudFR5cGUpIHtcclxuXHRcdG5ldyBOb3RpY2UoXCJDb250ZW50IHR5cGUgbm90IGZvdW5kLlwiKTtcclxuXHRcdHJldHVybjtcclxuXHR9XHJcblxyXG5cdHRlbXBsYXRlU3RyaW5nID0gY29udGVudFR5cGUudGVtcGxhdGU7XHJcblxyXG5cdC8vIFdhaXQgYnJpZWZseSB0byBhbGxvdyBlZGl0b3Igc3RhdGUgdG8gc3RhYmlsaXplXHJcblx0YXdhaXQgbmV3IFByb21pc2UocmVzb2x2ZSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIDEwMCkpO1xyXG5cclxuXHQvLyBSZS1yZWFkIGNvbnRlbnQgdG8gZW5zdXJlIGxhdGVzdCBzdGF0ZSBhZnRlciBlZGl0b3IgY2hhbmdlc1xyXG5cdGNvbnN0IGNvbnRlbnQgPSBhd2FpdCBhcHAudmF1bHQucmVhZChmaWxlKTtcclxuXHRjb25zdCB0aXRsZSA9IGZpbGUuYmFzZW5hbWUucmVwbGFjZSgvXl8vLCBcIlwiKTtcclxuXHJcblx0Y29uc3QgcGFyc2VkID0gdGVtcGxhdGVQYXJzZXIucGFyc2VGcm9udG1hdHRlcihjb250ZW50KTtcclxuXHRjb25zdCB7IHRlbXBsYXRlUHJvcHMsIHRlbXBsYXRlVmFsdWVzIH0gPSB0ZW1wbGF0ZVBhcnNlci5wYXJzZVRlbXBsYXRlKHRlbXBsYXRlU3RyaW5nLCB0aXRsZSk7XHJcblxyXG5cdC8vIE1lcmdlIHRlbXBsYXRlIHByb3BlcnRpZXMgd2l0aCBleGlzdGluZyBvbmVzLCBwcmVzZXJ2aW5nIGFsbCBleGlzdGluZ1xyXG5cdGNvbnN0IGZpbmFsUHJvcHM6IFJlY29yZDxzdHJpbmcsIHN0cmluZ1tdPiA9IHsgLi4ucGFyc2VkLnByb3BlcnRpZXMgfTtcclxuXHRjb25zdCBhcnJheUtleXMgPSBuZXcgU2V0PHN0cmluZz4oKTsgLy8gVHJhY2sgd2hpY2gga2V5cyBhcmUgYXJyYXlzXHJcblxyXG5cdC8vIEdlbmVyYXRlIHNsdWcgZnJvbSB0aXRsZSBmb3Igc2x1ZyBwcm9wZXJ0eSBhdXRvLXBvcHVsYXRpb25cclxuXHRjb25zdCBzbHVnID0gdG9LZWJhYkNhc2UodGl0bGUpO1xyXG5cclxuXHRmb3IgKGNvbnN0IGtleSBvZiB0ZW1wbGF0ZVByb3BzKSB7XHJcblx0XHRpZiAoIShrZXkgaW4gcGFyc2VkLnByb3BlcnRpZXMpKSB7XHJcblx0XHRcdC8vIFByb3BlcnR5IGRvZXNuJ3QgZXhpc3QsIGFkZCBpdCBmcm9tIHRlbXBsYXRlXHJcblx0XHRcdGNvbnN0IHRlbXBsYXRlVmFsdWUgPSB0ZW1wbGF0ZVZhbHVlc1trZXldO1xyXG5cdFx0XHRpZiAoQXJyYXkuaXNBcnJheSh0ZW1wbGF0ZVZhbHVlKSkge1xyXG5cdFx0XHRcdGZpbmFsUHJvcHNba2V5XSA9IHRlbXBsYXRlVmFsdWU7XHJcblx0XHRcdFx0YXJyYXlLZXlzLmFkZChrZXkpOyAvLyBNYXJrIGFzIGFycmF5XHJcblx0XHRcdH0gZWxzZSB7XHJcblx0XHRcdFx0ZmluYWxQcm9wc1trZXldID0gW3RlbXBsYXRlVmFsdWUgfHwgXCJcIl07XHJcblx0XHRcdH1cclxuXHRcdH0gZWxzZSB7XHJcblx0XHRcdC8vIFByb3BlcnR5IGV4aXN0cywgY2hlY2sgaWYgaXQncyBhbiBhcnJheSB0eXBlXHJcblx0XHRcdGNvbnN0IHRlbXBsYXRlVmFsdWUgPSB0ZW1wbGF0ZVZhbHVlc1trZXldO1xyXG5cdFx0XHRjb25zdCBpc0FycmF5VmFsdWUgPSBBcnJheS5pc0FycmF5KHRlbXBsYXRlVmFsdWUpO1xyXG5cclxuXHRcdFx0aWYgKGlzQXJyYXlWYWx1ZSkge1xyXG5cdFx0XHRcdC8vIFRoaXMgaXMgYW4gYXJyYXkgcHJvcGVydHkgLSBwcmVzZXJ2ZSBleGlzdGluZyB2YWx1ZXMgYW5kIG1lcmdlIHdpdGggdGVtcGxhdGVcclxuXHRcdFx0XHRjb25zdCBleGlzdGluZ0l0ZW1zID0gcGFyc2VkLnByb3BlcnRpZXNba2V5XSB8fCBbXTtcclxuXHRcdFx0XHRjb25zdCBuZXdJdGVtcyA9IHRlbXBsYXRlVmFsdWUuZmlsdGVyKGl0ZW0gPT4gIWV4aXN0aW5nSXRlbXMuaW5jbHVkZXMoaXRlbSkpO1xyXG5cdFx0XHRcdGZpbmFsUHJvcHNba2V5XSA9IFsuLi5leGlzdGluZ0l0ZW1zLCAuLi5uZXdJdGVtc107XHJcblx0XHRcdFx0YXJyYXlLZXlzLmFkZChrZXkpOyAvLyBNYXJrIGFzIGFycmF5XHJcblx0XHRcdH0gZWxzZSB7XHJcblx0XHRcdFx0Ly8gRm9yIG5vbi1hcnJheSB2YWx1ZXMsIGNoZWNrIGlmIGl0J3Mgc2x1ZyBhbmQgbmVlZHMgYXV0by1wb3B1bGF0aW9uXHJcblx0XHRcdFx0aWYgKGtleSA9PT0gXCJzbHVnXCIpIHtcclxuXHRcdFx0XHRcdGNvbnN0IGV4aXN0aW5nU2x1ZyA9IHBhcnNlZC5wcm9wZXJ0aWVzW2tleV1bMF0gfHwgXCJcIjtcclxuXHRcdFx0XHRcdC8vIE9ubHkgYXV0by1wb3B1bGF0ZSBpZiBzbHVnIGlzIGVtcHR5IG9yIG1pc3NpbmdcclxuXHRcdFx0XHRcdGlmICghZXhpc3RpbmdTbHVnIHx8IGV4aXN0aW5nU2x1Zy50cmltKCkgPT09IFwiXCIpIHtcclxuXHRcdFx0XHRcdFx0ZmluYWxQcm9wc1trZXldID0gW3NsdWddO1xyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0Ly8gSWYgc2x1ZyBoYXMgYSB2YWx1ZSwgcHJlc2VydmUgaXQgKGRvbid0IG92ZXJ3cml0ZSlcclxuXHRcdFx0XHR9XHJcblx0XHRcdFx0Ly8gRm9yIG90aGVyIG5vbi1hcnJheSB2YWx1ZXMsIGtlZXAgZXhpc3RpbmcgdmFsdWUgKGRvbid0IG92ZXJ3cml0ZSlcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cdH1cclxuXHJcblx0Ly8gQWxzbyBjaGVjayBpZiBzbHVnIHByb3BlcnR5IGV4aXN0cyBpbiBmcm9udG1hdHRlciBidXQgaXMgZW1wdHkgKGV2ZW4gaWYgbm90IGluIHRlbXBsYXRlKVxyXG5cdC8vIE9ubHkgYXV0by1wb3B1bGF0ZSBpZiB0ZW1wbGF0ZSBoYXMge3tzbHVnfX0gcGxhY2Vob2xkZXJcclxuXHRpZiAoXCJzbHVnXCIgaW4gcGFyc2VkLnByb3BlcnRpZXMgJiYgdGVtcGxhdGVTdHJpbmcuaW5jbHVkZXMoXCJ7e3NsdWd9fVwiKSkge1xyXG5cdFx0Y29uc3QgZXhpc3RpbmdTbHVnID0gcGFyc2VkLnByb3BlcnRpZXNbXCJzbHVnXCJdWzBdIHx8IFwiXCI7XHJcblx0XHRpZiAoIWV4aXN0aW5nU2x1ZyB8fCBleGlzdGluZ1NsdWcudHJpbSgpID09PSBcIlwiKSB7XHJcblx0XHRcdC8vIFNsdWcgZXhpc3RzIGJ1dCBpcyBlbXB0eSwgYW5kIHRlbXBsYXRlIGhhcyB7e3NsdWd9fSAtIGF1dG8tcG9wdWxhdGUgaXRcclxuXHRcdFx0ZmluYWxQcm9wc1tcInNsdWdcIl0gPSBbc2x1Z107XHJcblx0XHR9XHJcblx0fVxyXG5cclxuXHQvLyBBbHNvIGFkZCBhbnkgZXhpc3RpbmcgYXJyYXkga2V5cyB0aGF0IHdlcmVuJ3QgaW4gdGhlIHRlbXBsYXRlXHJcblx0Zm9yIChjb25zdCBrZXkgaW4gcGFyc2VkLnByb3BlcnRpZXMpIHtcclxuXHRcdGlmIChwYXJzZWQucHJvcGVydGllc1trZXldLmxlbmd0aCA+IDEpIHtcclxuXHRcdFx0YXJyYXlLZXlzLmFkZChrZXkpO1xyXG5cdFx0fVxyXG5cdH1cclxuXHJcblx0Y29uc3QgbmV3Q29udGVudCA9IHRlbXBsYXRlUGFyc2VyLmJ1aWxkRnJvbnRtYXR0ZXJDb250ZW50KGZpbmFsUHJvcHMsIGFycmF5S2V5cykgKyBwYXJzZWQuYm9keUNvbnRlbnQ7XHJcblxyXG5cdGF3YWl0IGFwcC52YXVsdC5tb2RpZnkoZmlsZSwgbmV3Q29udGVudCk7XHJcblxyXG5cdC8vIFJlc3RvcmUgY3Vyc29yIHBvc2l0aW9uIGlmIGVkaXRvciB3YXMgcHJvdmlkZWQgYW5kIGZpbGUgaXMgc3RpbGwgb3BlblxyXG5cdGlmIChlZGl0b3IgJiYgY3Vyc29yUG9zaXRpb24pIHtcclxuXHRcdC8vIFdhaXQgZm9yIE9ic2lkaWFuIHRvIHJlbG9hZCB0aGUgZmlsZSBpbiB0aGUgZWRpdG9yXHJcblx0XHRhd2FpdCBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHNldFRpbWVvdXQocmVzb2x2ZSwgNTApKTtcclxuXHJcblx0XHQvLyBUcnkgdG8gZ2V0IHRoZSBhY3RpdmUgZWRpdG9yIGZvciB0aGlzIGZpbGVcclxuXHRcdGNvbnN0IGFjdGl2ZVZpZXcgPSBhcHAud29ya3NwYWNlLmdldEFjdGl2ZVZpZXdPZlR5cGUoTWFya2Rvd25WaWV3KTtcclxuXHRcdGlmIChhY3RpdmVWaWV3ICYmIGFjdGl2ZVZpZXcuZmlsZSA9PT0gZmlsZSAmJiBhY3RpdmVWaWV3LmVkaXRvcikge1xyXG5cdFx0XHRjb25zdCBhY3RpdmVFZGl0b3IgPSBhY3RpdmVWaWV3LmVkaXRvcjtcclxuXHRcdFx0Y29uc3QgbmV3TGluZUNvdW50ID0gbmV3Q29udGVudC5zcGxpdCgnXFxuJykubGVuZ3RoO1xyXG5cdFx0XHRjb25zdCBvcmlnaW5hbExpbmVDb3VudCA9IG9yaWdpbmFsQ29udGVudC5zcGxpdCgnXFxuJykubGVuZ3RoO1xyXG5cclxuXHRcdFx0Ly8gQ2FsY3VsYXRlIG5ldyBjdXJzb3IgcG9zaXRpb25cclxuXHRcdFx0bGV0IG5ld0xpbmUgPSBjdXJzb3JQb3NpdGlvbi5saW5lO1xyXG5cdFx0XHRsZXQgbmV3Q2ggPSBjdXJzb3JQb3NpdGlvbi5jaDtcclxuXHJcblx0XHRcdC8vIEFkanVzdCBmb3IgY29udGVudCBjaGFuZ2VzXHJcblx0XHRcdGlmIChuZXdMaW5lQ291bnQgIT09IG9yaWdpbmFsTGluZUNvdW50KSB7XHJcblx0XHRcdFx0Ly8gSWYgbGluZXMgd2VyZSBhZGRlZC9yZW1vdmVkLCBhZGp1c3QgbGluZSBudW1iZXJcclxuXHRcdFx0XHRpZiAobmV3TGluZSA+PSBuZXdMaW5lQ291bnQpIHtcclxuXHRcdFx0XHRcdG5ld0xpbmUgPSBNYXRoLm1heCgwLCBuZXdMaW5lQ291bnQgLSAxKTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdH1cclxuXHJcblx0XHRcdC8vIEFkanVzdCBjb2x1bW4gcG9zaXRpb24gaWYgbGluZSBsZW5ndGggY2hhbmdlZFxyXG5cdFx0XHRjb25zdCBuZXdMaW5lTGVuZ3RoID0gbmV3Q29udGVudC5zcGxpdCgnXFxuJylbbmV3TGluZV0/Lmxlbmd0aCB8fCAwO1xyXG5cdFx0XHRpZiAobmV3Q2ggPiBuZXdMaW5lTGVuZ3RoKSB7XHJcblx0XHRcdFx0bmV3Q2ggPSBNYXRoLm1heCgwLCBuZXdMaW5lTGVuZ3RoKTtcclxuXHRcdFx0fVxyXG5cclxuXHRcdFx0Ly8gUmVzdG9yZSBjdXJzb3IgcG9zaXRpb25cclxuXHRcdFx0YWN0aXZlRWRpdG9yLnNldEN1cnNvcih7IGxpbmU6IG5ld0xpbmUsIGNoOiBuZXdDaCB9KTtcclxuXHRcdH1cclxuXHR9XHJcblxyXG5cdG5ldyBOb3RpY2UoXCJQcm9wZXJ0aWVzIHN0YW5kYXJkaXplZCB1c2luZyB0ZW1wbGF0ZS5cIik7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBSZW5hbWUgYSBmaWxlIGJ5IHBhdGggKGZvciBwcm9ncmFtbWF0aWMgdXNlLCBlLmcuLCBmcm9tIG90aGVyIHBsdWdpbnMpXHJcbiAqIFRoaXMgYWxsb3dzIHRoZSByZW5hbWUgbW9kYWwgdG8gYXBwZWFyIHdpdGhvdXQgb3BlbmluZyB0aGUgZmlsZSBmaXJzdFxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIHJlbmFtZUNvbnRlbnRCeVBhdGgoXHJcblx0YXBwOiBBcHAsXHJcblx0ZmlsZVBhdGg6IHN0cmluZyxcclxuXHRzZXR0aW5nczogQXN0cm9Db21wb3NlclNldHRpbmdzLFxyXG5cdHBsdWdpbjogQXN0cm9Db21wb3NlclBsdWdpbkludGVyZmFjZVxyXG4pOiB2b2lkIHtcclxuXHRjb25zdCBmaWxlID0gYXBwLnZhdWx0LmdldEFic3RyYWN0RmlsZUJ5UGF0aChmaWxlUGF0aCk7XHJcblx0aWYgKCEoZmlsZSBpbnN0YW5jZW9mIFRGaWxlKSkge1xyXG5cdFx0bmV3IE5vdGljZShgRmlsZSBub3QgZm91bmQ6ICR7ZmlsZVBhdGh9YCk7XHJcblx0XHRyZXR1cm47XHJcblx0fVxyXG5cclxuXHRjb25zdCBmaWxlT3BzID0gbmV3IEZpbGVPcGVyYXRpb25zKGFwcCwgc2V0dGluZ3MsIHBsdWdpbik7XHJcblxyXG5cdC8vIEhlbHBlciBmdW5jdGlvbiB0byBjaGVjayBpZiBmaWxlIG1hdGNoZXMgY29udGVudCB0eXBlXHJcblx0Ly8gVXNlcyB0aGUgc2FtZSBsb2dpYyBhcyBGaWxlT3BlcmF0aW9ucy5kZXRlcm1pbmVUeXBlKCkgdG8gZW5zdXJlIGNvbnNpc3RlbmN5XHJcblx0ZnVuY3Rpb24gaGFzTWF0Y2hpbmdDb250ZW50VHlwZShmaWxlOiBURmlsZSwgc2V0dGluZ3M6IEFzdHJvQ29tcG9zZXJTZXR0aW5ncyk6IGJvb2xlYW4ge1xyXG5cdFx0Y29uc3QgdHlwZSA9IGZpbGVPcHMuZGV0ZXJtaW5lVHlwZShmaWxlKTtcclxuXHRcdC8vIElmIGRldGVybWluZVR5cGUgcmV0dXJucyBcIm5vdGVcIiwgaXQgbWVhbnMgbm8gY29udGVudCB0eXBlIG1hdGNoZWRcclxuXHRcdGlmICh0eXBlID09PSBcIm5vdGVcIikge1xyXG5cdFx0XHRyZXR1cm4gZmFsc2U7XHJcblx0XHR9XHJcblx0XHQvLyBDaGVjayBpZiB0aGUgbWF0Y2hlZCBjb250ZW50IHR5cGUgaXMgZW5hYmxlZFxyXG5cdFx0Y29uc3QgY29udGVudFR5cGUgPSBmaWxlT3BzLmdldENvbnRlbnRUeXBlKHR5cGUpO1xyXG5cdFx0cmV0dXJuIGNvbnRlbnRUeXBlICE9PSBudWxsICYmIGNvbnRlbnRUeXBlLmVuYWJsZWQ7XHJcblx0fVxyXG5cclxuXHRpZiAoIWhhc01hdGNoaW5nQ29udGVudFR5cGUoZmlsZSwgc2V0dGluZ3MpKSB7XHJcblx0XHRuZXcgTm90aWNlKFwiQ2Fubm90IHJlbmFtZTogdGhpcyBmaWxlIGlzIG5vdCBwYXJ0IG9mIGEgY29uZmlndXJlZCBjb250ZW50IHR5cGUgZm9sZGVyLlwiKTtcclxuXHRcdHJldHVybjtcclxuXHR9XHJcblxyXG5cdGNvbnN0IHR5cGUgPSBmaWxlT3BzLmRldGVybWluZVR5cGUoZmlsZSk7XHJcblxyXG5cdC8vIEFsd2F5cyBvcGVuIHRoZSBtb2RhbCAtIGl0IHdpbGwgaGFuZGxlIGZpbGVzIHdpdGhvdXQgZnJvbnRtYXR0ZXIgb3IgdGl0bGUga2V5XHJcblx0Ly8gSWYgdGhlcmUncyBubyB0aXRsZSBpbiBmcm9udG1hdHRlciwgdGhlIG1vZGFsIHdpbGwgdXNlIHRoZSBmaWxlbmFtZSBhcyBmYWxsYmFja1xyXG5cdC8vIGFuZCB0aGUgcmVuYW1lIHdpbGwgcHJvY2VlZCB3aXRoIGtlYmFiLWNhc2UgdmVyc2lvbiBvZiB3aGF0IHVzZXIgdHlwZXNcclxuXHRuZXcgVGl0bGVNb2RhbChhcHAsIGZpbGUsIHBsdWdpbiwgdHlwZSwgdHJ1ZSkub3BlbigpO1xyXG59XHJcblxyXG4vKipcclxuICogUmVnaXN0ZXIgY29tbWFuZHMgZm9yIGVhY2ggZW5hYmxlZCBjb250ZW50IHR5cGVcclxuICogRWFjaCBjb21tYW5kIGNyZWF0ZXMgYSBuZXcgZmlsZSBpbiB0aGUgY29udGVudCB0eXBlJ3MgZm9sZGVyIGFuZCBvcGVucyB0aGUgVGl0bGVNb2RhbFxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIHJlZ2lzdGVyQ29udGVudFR5cGVDb21tYW5kcyhwbHVnaW46IFBsdWdpbiwgc2V0dGluZ3M6IEFzdHJvQ29tcG9zZXJTZXR0aW5ncyk6IHZvaWQge1xyXG5cdGNvbnN0IHBsdWdpbkludGVyZmFjZSA9IHBsdWdpbiBhcyB1bmtub3duIGFzIEFzdHJvQ29tcG9zZXJQbHVnaW5JbnRlcmZhY2U7XHJcblx0Y29uc3QgY29udGVudFR5cGVzID0gc2V0dGluZ3MuY29udGVudFR5cGVzIHx8IFtdO1xyXG5cclxuXHQvLyBSZWdpc3RlciBhIGNvbW1hbmQgZm9yIGVhY2ggZW5hYmxlZCBjb250ZW50IHR5cGVcclxuXHRmb3IgKGNvbnN0IGNvbnRlbnRUeXBlIG9mIGNvbnRlbnRUeXBlcykge1xyXG5cdFx0aWYgKCFjb250ZW50VHlwZS5lbmFibGVkKSB7XHJcblx0XHRcdGNvbnRpbnVlOyAvLyBTa2lwIGRpc2FibGVkIGNvbnRlbnQgdHlwZXNcclxuXHRcdH1cclxuXHJcblx0XHRjb25zdCBjb21tYW5kSWQgPSBgY3JlYXRlLWNvbnRlbnQtdHlwZS0ke2NvbnRlbnRUeXBlLmlkfWA7XHJcblx0XHRjb25zdCBjb21tYW5kTmFtZSA9IGBDcmVhdGUgbmV3IGNvbnRlbnQgdHlwZTogJHtjb250ZW50VHlwZS5uYW1lfWA7XHJcblxyXG5cdFx0cGx1Z2luLmFkZENvbW1hbmQoe1xyXG5cdFx0XHRpZDogY29tbWFuZElkLFxyXG5cdFx0XHRuYW1lOiBjb21tYW5kTmFtZSxcclxuXHRcdFx0Y2FsbGJhY2s6IGFzeW5jICgpID0+IHtcclxuXHRcdFx0XHQvLyBEZXRlcm1pbmUgdGFyZ2V0IGZvbGRlciBmcm9tIGNvbnRlbnQgdHlwZSAob3IgdmF1bHQgcm9vdCBpZiBibGFuaylcclxuXHRcdFx0XHRsZXQgdGFyZ2V0Rm9sZGVyID0gY29udGVudFR5cGUuZm9sZGVyIHx8IFwiXCI7XHJcblxyXG5cdFx0XHRcdC8vIENyZWF0ZSBmb2xkZXIgaWYgaXQgZG9lc24ndCBleGlzdCBhbmQgaXMgc3BlY2lmaWVkXHJcblx0XHRcdFx0aWYgKHRhcmdldEZvbGRlciAmJiB0YXJnZXRGb2xkZXIudHJpbSgpICE9PSBcIlwiKSB7XHJcblx0XHRcdFx0XHRjb25zdCBmb2xkZXIgPSBwbHVnaW4uYXBwLnZhdWx0LmdldEFic3RyYWN0RmlsZUJ5UGF0aCh0YXJnZXRGb2xkZXIpO1xyXG5cdFx0XHRcdFx0aWYgKCEoZm9sZGVyIGluc3RhbmNlb2YgVEZvbGRlcikpIHtcclxuXHRcdFx0XHRcdFx0dHJ5IHtcclxuXHRcdFx0XHRcdFx0XHRhd2FpdCBwbHVnaW4uYXBwLnZhdWx0LmNyZWF0ZUZvbGRlcih0YXJnZXRGb2xkZXIpO1xyXG5cdFx0XHRcdFx0XHR9IGNhdGNoIChlcnJvcikge1xyXG5cdFx0XHRcdFx0XHRcdGNvbnN0IGVycm9yTWVzc2FnZSA9IGVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvci5tZXNzYWdlIDogU3RyaW5nKGVycm9yKTtcclxuXHRcdFx0XHRcdFx0XHRuZXcgTm90aWNlKGBGYWlsZWQgdG8gY3JlYXRlIGZvbGRlcjogJHtlcnJvck1lc3NhZ2V9YCk7XHJcblx0XHRcdFx0XHRcdFx0cmV0dXJuO1xyXG5cdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHR9XHJcblx0XHRcdFx0fVxyXG5cclxuXHRcdFx0XHQvLyBDcmVhdGUgYSB0ZW1wb3JhcnkgZmlsZSBpbiB0aGUgdGFyZ2V0IGZvbGRlclxyXG5cdFx0XHRcdGNvbnN0IHRlbXBGaWxlTmFtZSA9IFwiVW50aXRsZWQubWRcIjtcclxuXHRcdFx0XHRjb25zdCBmaWxlUGF0aCA9IHRhcmdldEZvbGRlciA/IGAke3RhcmdldEZvbGRlcn0vJHt0ZW1wRmlsZU5hbWV9YCA6IHRlbXBGaWxlTmFtZTtcclxuXHJcblx0XHRcdFx0Ly8gQ2hlY2sgaWYgZmlsZSBhbHJlYWR5IGV4aXN0cyAodW5saWtlbHkgYnV0IHBvc3NpYmxlKVxyXG5cdFx0XHRcdGNvbnN0IGV4aXN0aW5nRmlsZSA9IHBsdWdpbi5hcHAudmF1bHQuZ2V0QWJzdHJhY3RGaWxlQnlQYXRoKGZpbGVQYXRoKTtcclxuXHRcdFx0XHRpZiAoZXhpc3RpbmdGaWxlIGluc3RhbmNlb2YgVEZpbGUpIHtcclxuXHRcdFx0XHRcdC8vIElmIGZpbGUgZXhpc3RzLCB1c2UgaXQgZGlyZWN0bHlcclxuXHRcdFx0XHRcdG5ldyBUaXRsZU1vZGFsKHBsdWdpbi5hcHAsIGV4aXN0aW5nRmlsZSwgcGx1Z2luSW50ZXJmYWNlLCBjb250ZW50VHlwZS5pZCwgZmFsc2UsIHRydWUpLm9wZW4oKTtcclxuXHRcdFx0XHRcdHJldHVybjtcclxuXHRcdFx0XHR9XHJcblxyXG5cdFx0XHRcdC8vIE1hcmsgdGhhdCB0aGlzIGZpbGUgd2lsbCBiZSBjcmVhdGVkIGJ5IHRoZSBwbHVnaW5cclxuXHRcdFx0XHQvLyBUaGlzIHByZXZlbnRzIHRoZSBjcmVhdGUgZXZlbnQgZnJvbSB0cmlnZ2VyaW5nIGFub3RoZXIgbW9kYWxcclxuXHRcdFx0XHRpZiAocGx1Z2luSW50ZXJmYWNlICYmICdwbHVnaW5DcmVhdGVkRmlsZXMnIGluIHBsdWdpbkludGVyZmFjZSkge1xyXG5cdFx0XHRcdFx0cGx1Z2luSW50ZXJmYWNlLnBsdWdpbkNyZWF0ZWRGaWxlcy5zZXQoZmlsZVBhdGgsIERhdGUubm93KCkpO1xyXG5cdFx0XHRcdH1cclxuXHJcblx0XHRcdFx0dHJ5IHtcclxuXHRcdFx0XHRcdC8vIENyZWF0ZSB0aGUgdGVtcG9yYXJ5IGZpbGVcclxuXHRcdFx0XHRcdGNvbnN0IHRlbXBGaWxlID0gYXdhaXQgcGx1Z2luLmFwcC52YXVsdC5jcmVhdGUoZmlsZVBhdGgsIFwiXCIpO1xyXG5cclxuXHRcdFx0XHRcdC8vIE9wZW4gdGhlIFRpdGxlTW9kYWwgd2l0aCB0aGUgZmlsZSwgY29udGVudCB0eXBlIElELCBhbmQgaXNOZXdOb3RlIGZsYWdcclxuXHRcdFx0XHRcdG5ldyBUaXRsZU1vZGFsKHBsdWdpbi5hcHAsIHRlbXBGaWxlLCBwbHVnaW5JbnRlcmZhY2UsIGNvbnRlbnRUeXBlLmlkLCBmYWxzZSwgdHJ1ZSkub3BlbigpO1xyXG5cdFx0XHRcdH0gY2F0Y2ggKGVycm9yKSB7XHJcblx0XHRcdFx0XHRjb25zdCBlcnJvck1lc3NhZ2UgPSBlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IubWVzc2FnZSA6IFN0cmluZyhlcnJvcik7XHJcblx0XHRcdFx0XHRuZXcgTm90aWNlKGBGYWlsZWQgdG8gY3JlYXRlIGZpbGU6ICR7ZXJyb3JNZXNzYWdlfWApO1xyXG5cclxuXHRcdFx0XHRcdC8vIENsZWFuIHVwIHRoZSB0cmFja2luZyBpZiBmaWxlIGNyZWF0aW9uIGZhaWxlZFxyXG5cdFx0XHRcdFx0aWYgKHBsdWdpbkludGVyZmFjZSAmJiAncGx1Z2luQ3JlYXRlZEZpbGVzJyBpbiBwbHVnaW5JbnRlcmZhY2UpIHtcclxuXHRcdFx0XHRcdFx0cGx1Z2luSW50ZXJmYWNlLnBsdWdpbkNyZWF0ZWRGaWxlcy5kZWxldGUoZmlsZVBhdGgpO1xyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdH1cclxuXHRcdFx0fSxcclxuXHRcdH0pO1xyXG5cdH1cclxufVxyXG5cclxuLyoqXHJcbiAqIERlYnVnIGxvZ2dlciBmb3IgdGVybWluYWwgY29tbWFuZHNcclxuICovXHJcbmNvbnN0IHRlcm1pbmFsTG9nZ2VyID0ge1xyXG5cdGVuYWJsZWQ6IGZhbHNlLFxyXG5cdHNldEVuYWJsZWQodmFsdWU6IGJvb2xlYW4pIHtcclxuXHRcdHRoaXMuZW5hYmxlZCA9IHZhbHVlO1xyXG5cdH0sXHJcblx0bG9nKC4uLmFyZ3M6IHVua25vd25bXSkge1xyXG5cdFx0aWYgKHRoaXMuZW5hYmxlZCkge1xyXG5cdFx0XHRjb25zb2xlLmRlYnVnKFwiW2FzdHJvLWNvbXBvc2VyOnRlcm1pbmFsXVwiLCAuLi5hcmdzKTtcclxuXHRcdH1cclxuXHR9XHJcbn07XHJcblxyXG4vKipcclxuICogR2V0IGRlZmF1bHQgdGVybWluYWwgYXBwbGljYXRpb24gbmFtZSBiYXNlZCBvbiBwbGF0Zm9ybVxyXG4gKi9cclxuZnVuY3Rpb24gZ2V0RGVmYXVsdFRlcm1pbmFsQXBwKCk6IHN0cmluZyB7XHJcblx0aWYgKCFQbGF0Zm9ybS5pc0Rlc2t0b3BBcHApIHtcclxuXHRcdHJldHVybiBcIlwiO1xyXG5cdH1cclxuXHRpZiAoUGxhdGZvcm0uaXNNYWNPUykge1xyXG5cdFx0cmV0dXJuIFwiVGVybWluYWxcIjtcclxuXHR9XHJcblx0aWYgKFBsYXRmb3JtLmlzV2luKSB7XHJcblx0XHR0cnkge1xyXG5cdFx0XHQvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgaW1wb3J0L25vLW5vZGVqcy1tb2R1bGVzLCBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tcmVxdWlyZS1pbXBvcnRzLCBuby11bmRlZiAtLSBSZXF1aXJlZCBmb3IgT1MgcmVsZWFzZSBkZXRlY3Rpb24gb24gZGVza3RvcFxyXG5cdFx0XHRjb25zdCBvcyA9IHJlcXVpcmUoJ29zJykgYXMgeyByZWxlYXNlOiAoKSA9PiBzdHJpbmcgfTtcclxuXHRcdFx0Y29uc3QgcmVsZWFzZSA9IG9zLnJlbGVhc2UoKTtcclxuXHRcdFx0Ly8gV2luZG93cyAxMSBidWlsZCBudW1iZXJzIHN0YXJ0IGF0IDIyMDAwXHJcblx0XHRcdGNvbnN0IG1ham9yVmVyc2lvbiA9IHBhcnNlSW50KHJlbGVhc2Uuc3BsaXQoJy4nKVswXSk7XHJcblx0XHRcdGNvbnN0IGJ1aWxkTnVtYmVyID0gcGFyc2VJbnQocmVsZWFzZS5zcGxpdCgnLicpWzJdKTtcclxuXHJcblx0XHRcdGlmIChtYWpvclZlcnNpb24gPiAxMCB8fCAobWFqb3JWZXJzaW9uID09PSAxMCAmJiBidWlsZE51bWJlciA+PSAyMjAwMCkpIHtcclxuXHRcdFx0XHRyZXR1cm4gXCJ3dC5leGVcIjtcclxuXHRcdFx0fVxyXG5cdFx0fSBjYXRjaCB7XHJcblx0XHRcdC8vIEZhbGxiYWNrIHRvIGNtZC5leGUgaWYgT1MgZGV0ZWN0aW9uIGZhaWxzXHJcblx0XHR9XHJcblx0XHRyZXR1cm4gXCJjbWQuZXhlXCI7XHJcblx0fVxyXG5cdGlmIChQbGF0Zm9ybS5pc0xpbnV4KSB7XHJcblx0XHRyZXR1cm4gXCJnbm9tZS10ZXJtaW5hbFwiO1xyXG5cdH1cclxuXHRyZXR1cm4gXCJcIjtcclxufVxyXG5cclxuLyoqXHJcbiAqIFNhbml0aXplIHRlcm1pbmFsIGFwcGxpY2F0aW9uIG5hbWUgKHRyaW0gd2hpdGVzcGFjZSlcclxuICovXHJcbmZ1bmN0aW9uIHNhbml0aXplVGVybWluYWxBcHAodmFsdWU6IHN0cmluZyk6IHN0cmluZyB7XHJcblx0cmV0dXJuIHZhbHVlLnRyaW0oKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIEVzY2FwZSBkb3VibGUgcXVvdGVzIGluIGEgc3RyaW5nXHJcbiAqL1xyXG5mdW5jdGlvbiBlc2NhcGVEb3VibGVRdW90ZXModmFsdWU6IHN0cmluZyk6IHN0cmluZyB7XHJcblx0cmV0dXJuIHZhbHVlLnJlcGxhY2UoL1wiL2csICdcXFxcXCInKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIE9wZW4gdGVybWluYWwgaW4gcHJvamVjdCByb290IGRpcmVjdG9yeVxyXG4gKiBFeHBvcnRlZCBmb3IgdXNlIGJ5IHJpYmJvbiBpY29uc1xyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIG9wZW5UZXJtaW5hbEluUHJvamVjdFJvb3QoYXBwOiBBcHAsIHNldHRpbmdzOiBBc3Ryb0NvbXBvc2VyU2V0dGluZ3MpOiB2b2lkIHtcclxuXHQvLyBVcGRhdGUgbG9nZ2VyIHN0YXRlXHJcblx0dGVybWluYWxMb2dnZXIuc2V0RW5hYmxlZChzZXR0aW5ncy5lbmFibGVUZXJtaW5hbERlYnVnTG9nZ2luZyk7XHJcblxyXG5cdHRyeSB7XHJcblx0XHQvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgaW1wb3J0L25vLW5vZGVqcy1tb2R1bGVzLCBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tcmVxdWlyZS1pbXBvcnRzLCBuby11bmRlZiAtLSBjaGlsZF9wcm9jZXNzIGlzIHJlcXVpcmVkIGZvciB0ZXJtaW5hbCBjb21tYW5kcyBvbiBkZXNrdG9wXHJcblx0XHRjb25zdCB7IGV4ZWMgfSA9IHJlcXVpcmUoJ2NoaWxkX3Byb2Nlc3MnKSBhcyB7IGV4ZWM6IChjb21tYW5kOiBzdHJpbmcsIGNhbGxiYWNrOiAoZXJyb3I6IHsgbWVzc2FnZT86IHN0cmluZyB9IHwgbnVsbCkgPT4gdm9pZCkgPT4gdm9pZCB9O1xyXG5cdFx0Ly8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1ub2RlanMtbW9kdWxlcywgQHR5cGVzY3JpcHQtZXNsaW50L25vLXJlcXVpcmUtaW1wb3J0cywgbm8tdW5kZWYgLS0gcGF0aCBpcyByZXF1aXJlZCBmb3IgcmVzb2x2aW5nIHBhdGhzIG9uIGRlc2t0b3BcclxuXHRcdGNvbnN0IHBhdGggPSByZXF1aXJlKCdwYXRoJykgYXMgeyByZXNvbHZlOiAoLi4uYXJnczogc3RyaW5nW10pID0+IHN0cmluZyB9O1xyXG5cdFx0Ly8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1ub2RlanMtbW9kdWxlcywgQHR5cGVzY3JpcHQtZXNsaW50L25vLXJlcXVpcmUtaW1wb3J0cywgbm8tdW5kZWYgLS0gZnMgaXMgcmVxdWlyZWQgZm9yIHZlcmlmeWluZyBwYXRocyBvbiBkZXNrdG9wXHJcblx0XHRjb25zdCBmcyA9IHJlcXVpcmUoJ2ZzJykgYXMgeyBleGlzdHNTeW5jOiAocGF0aDogc3RyaW5nKSA9PiBib29sZWFuIH07XHJcblxyXG5cdFx0Ly8gR2V0IHRoZSBhY3R1YWwgdmF1bHQgcGF0aCBzdHJpbmcgZnJvbSB0aGUgYWRhcHRlclxyXG5cdFx0Y29uc3QgYWRhcHRlciA9IGFwcC52YXVsdC5hZGFwdGVyIGFzIHVua25vd24gYXMgeyBiYXNlUGF0aD86IHN0cmluZzsgcGF0aD86IHN0cmluZyB9O1xyXG5cdFx0Y29uc3QgdmF1bHRQYXRoID0gYWRhcHRlci5iYXNlUGF0aCB8fCBhZGFwdGVyLnBhdGg7XHJcblx0XHRjb25zdCB2YXVsdFBhdGhTdHJpbmcgPSB0eXBlb2YgdmF1bHRQYXRoID09PSAnc3RyaW5nJyA/IHZhdWx0UGF0aCA6IFN0cmluZyh2YXVsdFBhdGgpO1xyXG5cclxuXHRcdC8vIFJlc29sdmUgcHJvamVjdCByb290IHBhdGhcclxuXHRcdGxldCBwcm9qZWN0UGF0aDogc3RyaW5nO1xyXG5cdFx0aWYgKHNldHRpbmdzLnRlcm1pbmFsUHJvamVjdFJvb3RQYXRoICYmIHNldHRpbmdzLnRlcm1pbmFsUHJvamVjdFJvb3RQYXRoLnRyaW0oKSkge1xyXG5cdFx0XHQvLyBVc2UgY3VzdG9tIHBhdGggcmVsYXRpdmUgdG8gdmF1bHRcclxuXHRcdFx0cHJvamVjdFBhdGggPSBwYXRoLnJlc29sdmUodmF1bHRQYXRoU3RyaW5nLCBzZXR0aW5ncy50ZXJtaW5hbFByb2plY3RSb290UGF0aCk7XHJcblx0XHR9IGVsc2Uge1xyXG5cdFx0XHQvLyBEZWZhdWx0OiB2YXVsdCBmb2xkZXIgaXRzZWxmXHJcblx0XHRcdHByb2plY3RQYXRoID0gdmF1bHRQYXRoU3RyaW5nO1xyXG5cdFx0fVxyXG5cclxuXHRcdC8vIFZlcmlmeSB0aGUgcGF0aCBleGlzdHNcclxuXHRcdGlmICghZnMuZXhpc3RzU3luYyhwcm9qZWN0UGF0aCkpIHtcclxuXHRcdFx0bmV3IE5vdGljZShgUHJvamVjdCByb290IGRpcmVjdG9yeSBub3QgZm91bmQgYXQ6ICR7cHJvamVjdFBhdGh9YCk7XHJcblx0XHRcdHJldHVybjtcclxuXHRcdH1cclxuXHJcblx0XHQvLyBHZXQgdGVybWluYWwgYXBwbGljYXRpb24gbmFtZSAodXNlIGNvbmZpZ3VyZWQgb3IgZGVmYXVsdClcclxuXHRcdGNvbnN0IGNvbmZpZ3VyZWRBcHAgPSBzYW5pdGl6ZVRlcm1pbmFsQXBwKHNldHRpbmdzLnRlcm1pbmFsQXBwbGljYXRpb25OYW1lIHx8IFwiXCIpO1xyXG5cdFx0Y29uc3QgdGVybWluYWxBcHAgPSBjb25maWd1cmVkQXBwIHx8IGdldERlZmF1bHRUZXJtaW5hbEFwcCgpO1xyXG5cclxuXHRcdC8vIFdhcm4gaWYgdGVybWluYWwgYXBwIG5hbWUgaXMgZW1wdHkgKGJ1dCBzdGlsbCB0cnkgdG8gdXNlIGRlZmF1bHRzKVxyXG5cdFx0aWYgKCFjb25maWd1cmVkQXBwICYmICF0ZXJtaW5hbEFwcCkge1xyXG5cdFx0XHRuZXcgTm90aWNlKFwiVGVybWluYWwgYXBwbGljYXRpb24gbmFtZSBpcyBlbXB0eS4gUGxlYXNlIGNvbmZpZ3VyZSBpdCBpbiBzZXR0aW5ncy5cIik7XHJcblx0XHRcdHJldHVybjtcclxuXHRcdH1cclxuXHJcblx0XHQvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tdW5kZWYgLS0gcHJvY2VzcyBpcyBhIGdsb2JhbCBpbiB0aGUgRWxlY3Ryb24gcmVuZGVyZXIgcHJvY2Vzc1xyXG5cdFx0Y29uc3QgcGxhdGZvcm0gPSBwcm9jZXNzLnBsYXRmb3JtO1xyXG5cdFx0dGVybWluYWxMb2dnZXIubG9nKFwiT3BlbmluZyB0ZXJtaW5hbFwiLCB7IHBsYXRmb3JtLCB0ZXJtaW5hbEFwcCwgcHJvamVjdFBhdGggfSk7XHJcblxyXG5cdFx0aWYgKHBsYXRmb3JtID09PSAnd2luMzInKSB7XHJcblx0XHRcdC8vIFdpbmRvd3M6IFVzZSBzdGFydCBjb21tYW5kIHdpdGggY29uZmlndXJhYmxlIHRlcm1pbmFsXHJcblx0XHRcdGNvbnN0IGVzY2FwZWRQYXRoID0gcHJvamVjdFBhdGgucmVwbGFjZSgvXCIvZywgJ1wiJyk7XHJcblx0XHRcdGNvbnN0IGxvd2VyQXBwID0gdGVybWluYWxBcHAudG9Mb3dlckNhc2UoKTtcclxuXHJcblx0XHRcdGlmIChsb3dlckFwcCA9PT0gXCJ3dC5leGVcIiB8fCBsb3dlckFwcCA9PT0gXCJ3dFwiIHx8IGxvd2VyQXBwID09PSBcIndpbmRvd3MgdGVybWluYWxcIikge1xyXG5cdFx0XHRcdC8vIFdpbmRvd3MgVGVybWluYWxcclxuXHRcdFx0XHRleGVjKCd3aGVyZSB3dCcsIChlcnJvcjogeyBtZXNzYWdlPzogc3RyaW5nIH0gfCBudWxsKSA9PiB7XHJcblx0XHRcdFx0XHRpZiAoIWVycm9yKSB7XHJcblx0XHRcdFx0XHRcdGNvbnN0IGNvbW1hbmQgPSBgc3RhcnQgXCJcIiB3dC5leGUgLWQgXCIke2VzY2FwZWRQYXRofVwiYDtcclxuXHRcdFx0XHRcdFx0dGVybWluYWxMb2dnZXIubG9nKFwiV2luZG93cyBsYXVuY2ggKHd0KVwiLCB7IGNvbW1hbmQsIHByb2plY3RQYXRoIH0pO1xyXG5cdFx0XHRcdFx0XHRleGVjKGNvbW1hbmQsIChleGVjRXJyb3I6IHsgbWVzc2FnZT86IHN0cmluZyB9IHwgbnVsbCkgPT4ge1xyXG5cdFx0XHRcdFx0XHRcdGlmIChleGVjRXJyb3IpIHtcclxuXHRcdFx0XHRcdFx0XHRcdHRlcm1pbmFsTG9nZ2VyLmxvZyhcIldpbmRvd3MgVGVybWluYWwgZmFpbGVkLCBmYWxsaW5nIGJhY2sgdG8gY21kXCIsIHsgZXJyb3I6IGV4ZWNFcnJvci5tZXNzYWdlIH0pO1xyXG5cdFx0XHRcdFx0XHRcdFx0Ly8gRmFsbGJhY2sgdG8gY21kXHJcblx0XHRcdFx0XHRcdFx0XHRjb25zdCBmYWxsYmFja0NvbW1hbmQgPSBgc3RhcnQgXCJcIiBjbWQuZXhlIC9LIFwiY2QgL2QgXCIke2VzY2FwZWRQYXRofVwiXCJgO1xyXG5cdFx0XHRcdFx0XHRcdFx0ZXhlYyhmYWxsYmFja0NvbW1hbmQsIChjbWRFcnJvcjogeyBtZXNzYWdlPzogc3RyaW5nIH0gfCBudWxsKSA9PiB7XHJcblx0XHRcdFx0XHRcdFx0XHRcdGlmIChjbWRFcnJvcikge1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdG5ldyBOb3RpY2UoYEVycm9yIG9wZW5pbmcgdGVybWluYWw6ICR7Y21kRXJyb3IubWVzc2FnZSB8fCAnVW5rbm93biBlcnJvcid9YCk7XHJcblx0XHRcdFx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0XHRcdH0pO1xyXG5cdFx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0fSk7XHJcblx0XHRcdFx0XHR9IGVsc2Uge1xyXG5cdFx0XHRcdFx0XHQvLyBXaW5kb3dzIFRlcm1pbmFsIG5vdCBmb3VuZCwgZmFsbGJhY2sgdG8gY21kXHJcblx0XHRcdFx0XHRcdHRlcm1pbmFsTG9nZ2VyLmxvZyhcIldpbmRvd3MgVGVybWluYWwgbm90IGZvdW5kLCB1c2luZyBjbWRcIiwge30pO1xyXG5cdFx0XHRcdFx0XHRjb25zdCBmYWxsYmFja0NvbW1hbmQgPSBgc3RhcnQgXCJcIiBjbWQuZXhlIC9LIFwiY2QgL2QgXCIke2VzY2FwZWRQYXRofVwiXCJgO1xyXG5cdFx0XHRcdFx0XHRleGVjKGZhbGxiYWNrQ29tbWFuZCwgKGNtZEVycm9yOiB7IG1lc3NhZ2U/OiBzdHJpbmcgfSB8IG51bGwpID0+IHtcclxuXHRcdFx0XHRcdFx0XHRpZiAoY21kRXJyb3IpIHtcclxuXHRcdFx0XHRcdFx0XHRcdG5ldyBOb3RpY2UoYEVycm9yIG9wZW5pbmcgdGVybWluYWw6ICR7Y21kRXJyb3IubWVzc2FnZSB8fCAnVW5rbm93biBlcnJvcid9YCk7XHJcblx0XHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHR9KTtcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHR9KTtcclxuXHRcdFx0fSBlbHNlIGlmIChsb3dlckFwcCA9PT0gXCJwb3dlcnNoZWxsXCIgfHwgbG93ZXJBcHAgPT09IFwicG93ZXJzaGVsbC5leGVcIikge1xyXG5cdFx0XHRcdC8vIFBvd2VyU2hlbGxcclxuXHRcdFx0XHRjb25zdCBlc2NhcGVkUGF0aEZvclBTID0gcHJvamVjdFBhdGgucmVwbGFjZSgvJy9nLCBcIicnXCIpO1xyXG5cdFx0XHRcdGNvbnN0IGNvbW1hbmQgPSBgc3RhcnQgXCJcIiBwb3dlcnNoZWxsIC1Ob0V4aXQgLUNvbW1hbmQgXCJTZXQtTG9jYXRpb24gJyR7ZXNjYXBlZFBhdGhGb3JQU30nO1wiYDtcclxuXHRcdFx0XHR0ZXJtaW5hbExvZ2dlci5sb2coXCJXaW5kb3dzIGxhdW5jaCAocG93ZXJzaGVsbClcIiwgeyBjb21tYW5kLCBwcm9qZWN0UGF0aCB9KTtcclxuXHRcdFx0XHRleGVjKGNvbW1hbmQsIChlcnJvcjogeyBtZXNzYWdlPzogc3RyaW5nIH0gfCBudWxsKSA9PiB7XHJcblx0XHRcdFx0XHRpZiAoZXJyb3IpIHtcclxuXHRcdFx0XHRcdFx0bmV3IE5vdGljZShgRXJyb3Igb3BlbmluZyB0ZXJtaW5hbDogJHtlcnJvci5tZXNzYWdlIHx8ICdVbmtub3duIGVycm9yJ31gKTtcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHR9KTtcclxuXHRcdFx0fSBlbHNlIGlmIChsb3dlckFwcCA9PT0gXCJjbWQuZXhlXCIgfHwgbG93ZXJBcHAgPT09IFwiY21kXCIpIHtcclxuXHRcdFx0XHQvLyBDb21tYW5kIFByb21wdFxyXG5cdFx0XHRcdGNvbnN0IGNvbW1hbmQgPSBgc3RhcnQgXCJcIiBjbWQuZXhlIC9LIFwiY2QgL2QgXCIke2VzY2FwZWRQYXRofVwiXCJgO1xyXG5cdFx0XHRcdHRlcm1pbmFsTG9nZ2VyLmxvZyhcIldpbmRvd3MgbGF1bmNoIChjbWQpXCIsIHsgY29tbWFuZCwgcHJvamVjdFBhdGggfSk7XHJcblx0XHRcdFx0ZXhlYyhjb21tYW5kLCAoZXJyb3I6IHsgbWVzc2FnZT86IHN0cmluZyB9IHwgbnVsbCkgPT4ge1xyXG5cdFx0XHRcdFx0aWYgKGVycm9yKSB7XHJcblx0XHRcdFx0XHRcdG5ldyBOb3RpY2UoYEVycm9yIG9wZW5pbmcgdGVybWluYWw6ICR7ZXJyb3IubWVzc2FnZSB8fCAnVW5rbm93biBlcnJvcid9YCk7XHJcblx0XHRcdFx0XHR9XHJcblx0XHRcdFx0fSk7XHJcblx0XHRcdH0gZWxzZSB7XHJcblx0XHRcdFx0Ly8gR2VuZXJpYyB0ZXJtaW5hbCAtIHRyeSB0byBsYXVuY2ggaXQgZGlyZWN0bHlcclxuXHRcdFx0XHRjb25zdCBjb21tYW5kID0gYHN0YXJ0IFwiXCIgXCIke3Rlcm1pbmFsQXBwfVwiYDtcclxuXHRcdFx0XHR0ZXJtaW5hbExvZ2dlci5sb2coXCJXaW5kb3dzIGxhdW5jaCAoZ2VuZXJpYylcIiwgeyBjb21tYW5kLCB0ZXJtaW5hbEFwcCwgcHJvamVjdFBhdGggfSk7XHJcblx0XHRcdFx0ZXhlYyhjb21tYW5kLCAoZXJyb3I6IHsgbWVzc2FnZT86IHN0cmluZyB9IHwgbnVsbCkgPT4ge1xyXG5cdFx0XHRcdFx0aWYgKGVycm9yKSB7XHJcblx0XHRcdFx0XHRcdC8vIEZhbGxiYWNrIHRvIGNtZCBpZiBnZW5lcmljIGxhdW5jaCBmYWlsc1xyXG5cdFx0XHRcdFx0XHR0ZXJtaW5hbExvZ2dlci5sb2coXCJHZW5lcmljIHRlcm1pbmFsIGZhaWxlZCwgZmFsbGluZyBiYWNrIHRvIGNtZFwiLCB7IGVycm9yOiBlcnJvci5tZXNzYWdlIH0pO1xyXG5cdFx0XHRcdFx0XHRjb25zdCBmYWxsYmFja0NvbW1hbmQgPSBgc3RhcnQgXCJcIiBjbWQuZXhlIC9LIFwiY2QgL2QgXCIke2VzY2FwZWRQYXRofVwiXCJgO1xyXG5cdFx0XHRcdFx0XHRleGVjKGZhbGxiYWNrQ29tbWFuZCwgKGNtZEVycm9yOiB7IG1lc3NhZ2U/OiBzdHJpbmcgfSB8IG51bGwpID0+IHtcclxuXHRcdFx0XHRcdFx0XHRpZiAoY21kRXJyb3IpIHtcclxuXHRcdFx0XHRcdFx0XHRcdG5ldyBOb3RpY2UoYEVycm9yIG9wZW5pbmcgdGVybWluYWw6ICR7Y21kRXJyb3IubWVzc2FnZSB8fCAnVW5rbm93biBlcnJvcid9YCk7XHJcblx0XHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHR9KTtcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHR9KTtcclxuXHRcdFx0fVxyXG5cdFx0fSBlbHNlIGlmIChwbGF0Zm9ybSA9PT0gJ2RhcndpbicpIHtcclxuXHRcdFx0Ly8gbWFjT1M6IFVzZSBvcGVuIC1hIChzaW1wbGVyIHRoYW4gb3Nhc2NyaXB0KVxyXG5cdFx0XHRjb25zdCBlc2NhcGVkQXBwID0gZXNjYXBlRG91YmxlUXVvdGVzKHRlcm1pbmFsQXBwKTtcclxuXHRcdFx0Y29uc3QgZXNjYXBlZFBhdGggPSBlc2NhcGVEb3VibGVRdW90ZXMocHJvamVjdFBhdGgpO1xyXG5cdFx0XHRjb25zdCBjb21tYW5kID0gYG9wZW4gLW5hIFwiJHtlc2NhcGVkQXBwfVwiIFwiJHtlc2NhcGVkUGF0aH1cImA7XHJcblx0XHRcdHRlcm1pbmFsTG9nZ2VyLmxvZyhcIm1hY09TIGxhdW5jaFwiLCB7IGNvbW1hbmQsIHRlcm1pbmFsQXBwLCBwcm9qZWN0UGF0aCB9KTtcclxuXHRcdFx0ZXhlYyhjb21tYW5kLCAoZXJyb3I6IHsgbWVzc2FnZT86IHN0cmluZyB9IHwgbnVsbCkgPT4ge1xyXG5cdFx0XHRcdGlmIChlcnJvcikge1xyXG5cdFx0XHRcdFx0bmV3IE5vdGljZShgRXJyb3Igb3BlbmluZyB0ZXJtaW5hbDogJHtlcnJvci5tZXNzYWdlIHx8ICdVbmtub3duIGVycm9yJ31gKTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdH0pO1xyXG5cdFx0fSBlbHNlIHtcclxuXHRcdFx0Ly8gTGludXg6IFRyeSBjb25maWd1cmFibGUgdGVybWluYWwgd2l0aCBmYWxsYmFjayBjaGFpblxyXG5cdFx0XHRjb25zdCB0ZXJtaW5hbHMgPSB0ZXJtaW5hbEFwcCA/IFt0ZXJtaW5hbEFwcF0gOiBbXCJnbm9tZS10ZXJtaW5hbFwiLCBcImtvbnNvbGVcIiwgXCJ4dGVybVwiXTtcclxuXHRcdFx0Y29uc3QgcHJvamVjdFBhdGhFc2NhcGVkID0gcHJvamVjdFBhdGgucmVwbGFjZSgvXCIvZywgJ1xcXFxcIicpO1xyXG5cclxuXHRcdFx0Ly8gVHJ5IGVhY2ggdGVybWluYWwgdW50aWwgb25lIHdvcmtzXHJcblx0XHRcdGNvbnN0IHRyeVRlcm1pbmFsID0gKGluZGV4OiBudW1iZXIpID0+IHtcclxuXHRcdFx0XHRpZiAoaW5kZXggPj0gdGVybWluYWxzLmxlbmd0aCkge1xyXG5cdFx0XHRcdFx0bmV3IE5vdGljZSgnTm8gc3VwcG9ydGVkIHRlcm1pbmFsIGZvdW5kLiBQbGVhc2UgaW5zdGFsbCBhIHRlcm1pbmFsIGFwcGxpY2F0aW9uIG9yIGNvbmZpZ3VyZSBvbmUgaW4gc2V0dGluZ3MuJyk7XHJcblx0XHRcdFx0XHRyZXR1cm47XHJcblx0XHRcdFx0fVxyXG5cclxuXHRcdFx0XHRjb25zdCBjdXJyZW50VGVybWluYWwgPSB0ZXJtaW5hbHNbaW5kZXhdO1xyXG5cdFx0XHRcdGNvbnN0IHRlcm1pbmFsTmFtZSA9IGN1cnJlbnRUZXJtaW5hbC5zcGxpdCgnICcpWzBdO1xyXG5cclxuXHRcdFx0XHQvLyBDaGVjayBpZiB0ZXJtaW5hbCBleGlzdHNcclxuXHRcdFx0XHRleGVjKGB3aGljaCAke3Rlcm1pbmFsTmFtZX1gLCAoZXJyb3I6IHsgbWVzc2FnZT86IHN0cmluZyB9IHwgbnVsbCkgPT4ge1xyXG5cdFx0XHRcdFx0aWYgKCFlcnJvcikge1xyXG5cdFx0XHRcdFx0XHQvLyBUZXJtaW5hbCBmb3VuZCwgdHJ5IHRvIGxhdW5jaCBpdFxyXG5cdFx0XHRcdFx0XHRsZXQgY29tbWFuZDogc3RyaW5nO1xyXG5cdFx0XHRcdFx0XHRpZiAoY3VycmVudFRlcm1pbmFsLmluY2x1ZGVzKFwiZ25vbWUtdGVybWluYWxcIikpIHtcclxuXHRcdFx0XHRcdFx0XHRjb21tYW5kID0gYGdub21lLXRlcm1pbmFsIC0td29ya2luZy1kaXJlY3Rvcnk9XCIke3Byb2plY3RQYXRoRXNjYXBlZH1cImA7XHJcblx0XHRcdFx0XHRcdH0gZWxzZSBpZiAoY3VycmVudFRlcm1pbmFsLmluY2x1ZGVzKFwia29uc29sZVwiKSkge1xyXG5cdFx0XHRcdFx0XHRcdGNvbW1hbmQgPSBga29uc29sZSAtLXdvcmtkaXIgXCIke3Byb2plY3RQYXRoRXNjYXBlZH1cImA7XHJcblx0XHRcdFx0XHRcdH0gZWxzZSB7XHJcblx0XHRcdFx0XHRcdFx0Ly8gR2VuZXJpYyB0ZXJtaW5hbFxyXG5cdFx0XHRcdFx0XHRcdGNvbW1hbmQgPSBgJHtjdXJyZW50VGVybWluYWx9IC1lIFwiY2QgXFxcXFwiJHtwcm9qZWN0UGF0aEVzY2FwZWR9XFxcXFwiICYmIGJhc2hcImA7XHJcblx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0dGVybWluYWxMb2dnZXIubG9nKFwiTGludXggbGF1bmNoXCIsIHsgY29tbWFuZCwgdGVybWluYWw6IGN1cnJlbnRUZXJtaW5hbCwgcHJvamVjdFBhdGggfSk7XHJcblx0XHRcdFx0XHRcdGV4ZWMoY29tbWFuZCwgKGV4ZWNFcnJvcjogeyBtZXNzYWdlPzogc3RyaW5nIH0gfCBudWxsKSA9PiB7XHJcblx0XHRcdFx0XHRcdFx0aWYgKGV4ZWNFcnJvciAmJiBpbmRleCA8IHRlcm1pbmFscy5sZW5ndGggLSAxKSB7XHJcblx0XHRcdFx0XHRcdFx0XHR0ZXJtaW5hbExvZ2dlci5sb2coXCJUZXJtaW5hbCBsYXVuY2ggZmFpbGVkLCB0cnlpbmcgbmV4dFwiLCB7IHRlcm1pbmFsOiBjdXJyZW50VGVybWluYWwsIGVycm9yOiBleGVjRXJyb3IubWVzc2FnZSB9KTtcclxuXHRcdFx0XHRcdFx0XHRcdHRyeVRlcm1pbmFsKGluZGV4ICsgMSk7XHJcblx0XHRcdFx0XHRcdFx0fSBlbHNlIGlmIChleGVjRXJyb3IpIHtcclxuXHRcdFx0XHRcdFx0XHRcdG5ldyBOb3RpY2UoYEVycm9yIG9wZW5pbmcgdGVybWluYWw6ICR7ZXhlY0Vycm9yLm1lc3NhZ2UgfHwgJ1Vua25vd24gZXJyb3InfWApO1xyXG5cdFx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0fSk7XHJcblx0XHRcdFx0XHR9IGVsc2Uge1xyXG5cdFx0XHRcdFx0XHQvLyBUZXJtaW5hbCBub3QgZm91bmQsIHRyeSBuZXh0XHJcblx0XHRcdFx0XHRcdHRlcm1pbmFsTG9nZ2VyLmxvZyhcIlRlcm1pbmFsIG5vdCBmb3VuZCwgdHJ5aW5nIG5leHRcIiwgeyB0ZXJtaW5hbDogY3VycmVudFRlcm1pbmFsIH0pO1xyXG5cdFx0XHRcdFx0XHR0cnlUZXJtaW5hbChpbmRleCArIDEpO1xyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdH0pO1xyXG5cdFx0XHR9O1xyXG5cclxuXHRcdFx0dHJ5VGVybWluYWwoMCk7XHJcblx0XHR9XHJcblx0fSBjYXRjaCAoZXJyb3IpIHtcclxuXHRcdHRlcm1pbmFsTG9nZ2VyLmxvZyhcIlVuZXhwZWN0ZWQgZXJyb3JcIiwgeyBlcnJvciB9KTtcclxuXHRcdG5ldyBOb3RpY2UoYEVycm9yIG9wZW5pbmcgdGVybWluYWw6ICR7ZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yLm1lc3NhZ2UgOiBTdHJpbmcoZXJyb3IpfWApO1xyXG5cdH1cclxufVxyXG5cclxuLyoqXHJcbiAqIE9wZW4gY29uZmlnIGZpbGUgaW4gZGVmYXVsdCBlZGl0b3JcclxuICogRXhwb3J0ZWQgZm9yIHVzZSBieSByaWJib24gaWNvbnNcclxuICovXHJcbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBvcGVuQ29uZmlnRmlsZShhcHA6IEFwcCwgc2V0dGluZ3M6IEFzdHJvQ29tcG9zZXJTZXR0aW5ncyk6IFByb21pc2U8dm9pZD4ge1xyXG5cdHRyeSB7XHJcblx0XHQvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgaW1wb3J0L25vLW5vZGVqcy1tb2R1bGVzLCBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tcmVxdWlyZS1pbXBvcnRzLCBuby11bmRlZiAtLSBmcyBpcyByZXF1aXJlZCBmb3IgdmVyaWZ5aW5nIGNvbmZpZyBmaWxlIGV4aXN0cyBvbiBkZXNrdG9wXHJcblx0XHRjb25zdCBmcyA9IHJlcXVpcmUoJ2ZzJykgYXMgeyBleGlzdHNTeW5jOiAocGF0aDogc3RyaW5nKSA9PiBib29sZWFuIH07XHJcblx0XHQvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgaW1wb3J0L25vLW5vZGVqcy1tb2R1bGVzLCBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tcmVxdWlyZS1pbXBvcnRzLCBuby11bmRlZiAtLSBwYXRoIGlzIHJlcXVpcmVkIGZvciByZXNvbHZpbmcgcGF0aHMgb24gZGVza3RvcFxyXG5cdFx0Y29uc3QgcGF0aCA9IHJlcXVpcmUoJ3BhdGgnKSBhcyB7IHJlc29sdmU6ICguLi5hcmdzOiBzdHJpbmdbXSkgPT4gc3RyaW5nIH07XHJcblx0XHQvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXJlcXVpcmUtaW1wb3J0cywgbm8tdW5kZWYgLS0gZWxlY3Ryb24gc2hlbGwgaXMgcmVxdWlyZWQgdG8gb3BlbiBmaWxlcyBpbiBkZWZhdWx0IGVkaXRvclxyXG5cdFx0Y29uc3QgeyBzaGVsbCB9ID0gcmVxdWlyZSgnZWxlY3Ryb24nKSBhcyB7IHNoZWxsOiB7IG9wZW5QYXRoOiAocGF0aDogc3RyaW5nKSA9PiBQcm9taXNlPHN0cmluZz4gfSB9O1xyXG5cclxuXHRcdC8vIEdldCB0aGUgYWN0dWFsIHZhdWx0IHBhdGggc3RyaW5nIGZyb20gdGhlIGFkYXB0ZXJcclxuXHRcdGNvbnN0IGFkYXB0ZXIgPSBhcHAudmF1bHQuYWRhcHRlciBhcyB1bmtub3duIGFzIHsgYmFzZVBhdGg/OiBzdHJpbmc7IHBhdGg/OiBzdHJpbmcgfTtcclxuXHRcdGNvbnN0IHZhdWx0UGF0aCA9IGFkYXB0ZXIuYmFzZVBhdGggfHwgYWRhcHRlci5wYXRoO1xyXG5cdFx0Y29uc3QgdmF1bHRQYXRoU3RyaW5nID0gdHlwZW9mIHZhdWx0UGF0aCA9PT0gJ3N0cmluZycgPyB2YXVsdFBhdGggOiBTdHJpbmcodmF1bHRQYXRoKTtcclxuXHJcblx0XHQvLyBSZXNvbHZlIGNvbmZpZyBmaWxlIHBhdGhcclxuXHRcdGlmICghc2V0dGluZ3MuY29uZmlnRmlsZVBhdGggfHwgIXNldHRpbmdzLmNvbmZpZ0ZpbGVQYXRoLnRyaW0oKSkge1xyXG5cdFx0XHRuZXcgTm90aWNlKFwiUGxlYXNlIHNwZWNpZnkgYSBjb25maWcgZmlsZSBwYXRoIGluIHNldHRpbmdzLlwiKTtcclxuXHRcdFx0cmV0dXJuO1xyXG5cdFx0fVxyXG5cclxuXHRcdC8vIFVzZSBjdXN0b20gcGF0aCByZWxhdGl2ZSB0byB2YXVsdFxyXG5cdFx0Y29uc3QgY29uZmlnUGF0aCA9IHBhdGgucmVzb2x2ZSh2YXVsdFBhdGhTdHJpbmcsIHNldHRpbmdzLmNvbmZpZ0ZpbGVQYXRoKTtcclxuXHJcblx0XHQvLyBDaGVjayBpZiBmaWxlIGV4aXN0c1xyXG5cdFx0aWYgKCFmcy5leGlzdHNTeW5jKGNvbmZpZ1BhdGgpKSB7XHJcblx0XHRcdG5ldyBOb3RpY2UoYENvbmZpZyBmaWxlIG5vdCBmb3VuZCBhdDogJHtjb25maWdQYXRofWApO1xyXG5cdFx0XHRyZXR1cm47XHJcblx0XHR9XHJcblxyXG5cdFx0Ly8gVXNlIEVsZWN0cm9uJ3Mgc2hlbGwgdG8gb3BlbiB0aGUgZmlsZSB3aXRoIHRoZSBkZWZhdWx0IGVkaXRvclxyXG5cdFx0YXdhaXQgc2hlbGwub3BlblBhdGgoY29uZmlnUGF0aCk7XHJcblx0fSBjYXRjaCAoZXJyb3IpIHtcclxuXHRcdG5ldyBOb3RpY2UoYEVycm9yIG9wZW5pbmcgY29uZmlnIGZpbGU6ICR7ZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yLm1lc3NhZ2UgOiBTdHJpbmcoZXJyb3IpfWApO1xyXG5cdH1cclxufSIsICJpbXBvcnQgeyBBcHAsIFRGaWxlLCBURm9sZGVyLCBOb3RpY2UgfSBmcm9tIFwib2JzaWRpYW5cIjtcbmltcG9ydCB7IEFzdHJvQ29tcG9zZXJTZXR0aW5ncywgRmlsZUNyZWF0aW9uT3B0aW9ucywgUmVuYW1lT3B0aW9ucywgQ29udGVudFR5cGUsIENvbnRlbnRUeXBlSWQsIEFzdHJvQ29tcG9zZXJQbHVnaW5JbnRlcmZhY2UgfSBmcm9tIFwiLi4vdHlwZXNcIjtcbmltcG9ydCB7IG1hdGNoZXNGb2xkZXJQYXR0ZXJuLCBzb3J0QnlQYXR0ZXJuU3BlY2lmaWNpdHkgfSBmcm9tIFwiLi9wYXRoLW1hdGNoaW5nXCI7XG5pbXBvcnQgeyB0b0tlYmFiQ2FzZSB9IGZyb20gXCIuL3N0cmluZy11dGlsc1wiO1xuXG5leHBvcnQgY2xhc3MgRmlsZU9wZXJhdGlvbnMge1xuXHRjb25zdHJ1Y3Rvcihwcml2YXRlIGFwcDogQXBwLCBwcml2YXRlIHNldHRpbmdzOiBBc3Ryb0NvbXBvc2VyU2V0dGluZ3MsIHByaXZhdGUgcGx1Z2luPzogQXN0cm9Db21wb3NlclBsdWdpbkludGVyZmFjZSkgeyB9XG5cblx0Ly8gR2V0IGZyZXNoIHNldHRpbmdzIGZyb20gcGx1Z2luIGlmIGF2YWlsYWJsZSwgb3RoZXJ3aXNlIHVzZSBzdG9yZWQgc2V0dGluZ3Ncblx0cHJpdmF0ZSBnZXRTZXR0aW5ncygpOiBBc3Ryb0NvbXBvc2VyU2V0dGluZ3Mge1xuXHRcdC8vIEFsd2F5cyBwcmVmZXIgcGx1Z2luIHNldHRpbmdzICh0aGV5J3JlIGtlcHQgdXAgdG8gZGF0ZSlcblx0XHRpZiAodGhpcy5wbHVnaW4/LnNldHRpbmdzKSB7XG5cdFx0XHRyZXR1cm4gdGhpcy5wbHVnaW4uc2V0dGluZ3M7XG5cdFx0fVxuXHRcdHJldHVybiB0aGlzLnNldHRpbmdzO1xuXHR9XG5cblx0Z2VuZXJhdGVGaWxlbmFtZSh0aXRsZTogc3RyaW5nLCBlbmFibGVVbmRlcnNjb3JlUHJlZml4OiBib29sZWFuID0gZmFsc2UpOiBzdHJpbmcge1xuXHRcdGNvbnN0IGtlYmFiVGl0bGUgPSB0b0tlYmFiQ2FzZSh0aXRsZSk7XG5cdFx0Ly8gSWYga2ViYWIgY2FzZSByZXN1bHRzIGluIGVtcHR5IHN0cmluZywgdXNlIGEgZmFsbGJhY2tcblx0XHRjb25zdCBzYWZlS2ViYWJUaXRsZSA9IGtlYmFiVGl0bGUgfHwgXCJ1bnRpdGxlZFwiO1xuXHRcdGNvbnN0IHByZWZpeCA9IGVuYWJsZVVuZGVyc2NvcmVQcmVmaXggPyBcIl9cIiA6IFwiXCI7XG5cdFx0cmV0dXJuIGAke3ByZWZpeH0ke3NhZmVLZWJhYlRpdGxlfWA7XG5cdH1cblxuXHRkZXRlcm1pbmVUeXBlKGZpbGU6IFRGaWxlKTogQ29udGVudFR5cGVJZCB7XG5cdFx0Y29uc3QgZmlsZVBhdGggPSBmaWxlLnBhdGg7XG5cdFx0Y29uc3Qgc2V0dGluZ3MgPSB0aGlzLmdldFNldHRpbmdzKCk7XG5cblx0XHQvLyBDaGVjayBhbGwgY29udGVudCB0eXBlcywgc29ydGVkIGJ5IHBhdHRlcm4gc3BlY2lmaWNpdHkgKG1vcmUgc3BlY2lmaWMgZmlyc3QpXG5cdFx0Y29uc3QgY29udGVudFR5cGVzID0gc2V0dGluZ3MuY29udGVudFR5cGVzIHx8IFtdO1xuXHRcdGNvbnN0IHNvcnRlZFR5cGVzID0gc29ydEJ5UGF0dGVyblNwZWNpZmljaXR5KGNvbnRlbnRUeXBlcyk7XG5cblx0XHRmb3IgKGNvbnN0IGNvbnRlbnRUeXBlIG9mIHNvcnRlZFR5cGVzKSB7XG5cdFx0XHRpZiAoIWNvbnRlbnRUeXBlLmVuYWJsZWQpIGNvbnRpbnVlO1xuXG5cdFx0XHQvLyBIYW5kbGUgYmxhbmsgZm9sZGVyIChyb290KSAtIG1hdGNoZXMgZmlsZXMgaW4gdmF1bHQgcm9vdCBvbmx5XG5cdFx0XHRpZiAoIWNvbnRlbnRUeXBlLmZvbGRlciB8fCBjb250ZW50VHlwZS5mb2xkZXIudHJpbSgpID09PSBcIlwiKSB7XG5cdFx0XHRcdGlmICghZmlsZVBhdGguaW5jbHVkZXMoXCIvXCIpIHx8IGZpbGVQYXRoLnNwbGl0KFwiL1wiKS5sZW5ndGggPT09IDEpIHtcblx0XHRcdFx0XHRyZXR1cm4gY29udGVudFR5cGUuaWQ7XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSBpZiAobWF0Y2hlc0ZvbGRlclBhdHRlcm4oZmlsZVBhdGgsIGNvbnRlbnRUeXBlLmZvbGRlcikpIHtcblx0XHRcdFx0Ly8gQ2hlY2sgaWdub3JlU3ViZm9sZGVycyBpZiBmb2xkZXIgaXMgc3BlY2lmaWVkXG5cdFx0XHRcdGlmIChjb250ZW50VHlwZS5pZ25vcmVTdWJmb2xkZXJzKSB7XG5cdFx0XHRcdFx0Y29uc3QgcGF0aFNlZ21lbnRzID0gZmlsZVBhdGguc3BsaXQoXCIvXCIpO1xuXHRcdFx0XHRcdGNvbnN0IHBhdGhEZXB0aCA9IHBhdGhTZWdtZW50cy5sZW5ndGg7XG5cdFx0XHRcdFx0Y29uc3QgcGF0dGVyblNlZ21lbnRzID0gY29udGVudFR5cGUuZm9sZGVyLnNwbGl0KFwiL1wiKTtcblx0XHRcdFx0XHRjb25zdCBleHBlY3RlZERlcHRoID0gcGF0dGVyblNlZ21lbnRzLmxlbmd0aDtcblxuXHRcdFx0XHRcdGlmIChjb250ZW50VHlwZS5jcmVhdGlvbk1vZGUgPT09IFwiZm9sZGVyXCIpIHtcblx0XHRcdFx0XHRcdC8vIEZvciBmb2xkZXItYmFzZWQgY3JlYXRpb24sIGZpbGVzIGFyZSBvbmUgbGV2ZWwgZGVlcGVyIChlLmcuLCB0ZXN0L215LWZpbGUvaW5kZXgubWQpXG5cdFx0XHRcdFx0XHQvLyBTbyB3ZSBuZWVkIHRvIGFsbG93IG9uZSBleHRyYSBsZXZlbCBiZXlvbmQgdGhlIHBhdHRlcm4gZGVwdGhcblx0XHRcdFx0XHRcdGNvbnN0IGZvbGRlckRlcHRoID0gcGF0aERlcHRoIC0gMTsgLy8gU3VidHJhY3QgMSBmb3IgdGhlIGluZGV4Lm1kIGZpbGVcblx0XHRcdFx0XHRcdGlmIChmb2xkZXJEZXB0aCA9PT0gZXhwZWN0ZWREZXB0aCB8fCBmb2xkZXJEZXB0aCA9PT0gZXhwZWN0ZWREZXB0aCArIDEpIHtcblx0XHRcdFx0XHRcdFx0cmV0dXJuIGNvbnRlbnRUeXBlLmlkO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHQvLyBGb3IgZmlsZS1iYXNlZCBjcmVhdGlvbiwgZmlsZXMgYXJlIGF0IHRoZSBzYW1lIGRlcHRoIGFzIHRoZSBwYXR0ZXJuXG5cdFx0XHRcdFx0XHRpZiAocGF0aERlcHRoID09PSBleHBlY3RlZERlcHRoKSB7XG5cdFx0XHRcdFx0XHRcdHJldHVybiBjb250ZW50VHlwZS5pZDtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0cmV0dXJuIGNvbnRlbnRUeXBlLmlkO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gSWYgbm8gY29udGVudCB0eXBlIG1hdGNoZXMsIHJldHVybiBcIm5vdGVcIiBhcyBmYWxsYmFja1xuXHRcdHJldHVybiBcIm5vdGVcIjtcblx0fVxuXG5cdGdldENvbnRlbnRUeXBlKHR5cGVJZDogQ29udGVudFR5cGVJZCk6IENvbnRlbnRUeXBlIHwgbnVsbCB7XG5cdFx0Y29uc3Qgc2V0dGluZ3MgPSB0aGlzLmdldFNldHRpbmdzKCk7XG5cdFx0Y29uc3QgY29udGVudFR5cGVzID0gc2V0dGluZ3MuY29udGVudFR5cGVzIHx8IFtdO1xuXHRcdHJldHVybiBjb250ZW50VHlwZXMuZmluZChjdCA9PiBjdC5pZCA9PT0gdHlwZUlkKSB8fCBudWxsO1xuXHR9XG5cblx0LyoqXG5cdCAqIEhlbHBlciB0byBnZXQgY29udGVudCB0eXBlIGZvciBhIGdpdmVuIGZpbGUgcGF0aFxuXHQgKi9cblx0Z2V0Q29udGVudFR5cGVCeVBhdGgoZmlsZVBhdGg6IHN0cmluZyk6IENvbnRlbnRUeXBlIHwgbnVsbCB7XG5cdFx0Ly8gQ3JlYXRlIGEgZHVtbXkgVEZpbGUgZm9yIGRldGVybWluZVR5cGVcblx0XHRjb25zdCBkdW1teUZpbGUgPSB7IHBhdGg6IGZpbGVQYXRoIH0gYXMgVEZpbGU7XG5cdFx0Y29uc3QgdHlwZUlkID0gdGhpcy5kZXRlcm1pbmVUeXBlKGR1bW15RmlsZSk7XG5cdFx0aWYgKHR5cGVJZCA9PT0gXCJub3RlXCIpIHJldHVybiBudWxsO1xuXHRcdHJldHVybiB0aGlzLmdldENvbnRlbnRUeXBlKHR5cGVJZCk7XG5cdH1cblxuXHRnZXRUaXRsZUtleSh0eXBlOiBDb250ZW50VHlwZUlkKTogc3RyaW5nIHtcblx0XHQvLyBGb3IgZ2VuZXJpYyBub3RlcywgYWx3YXlzIHVzZSBcInRpdGxlXCJcblx0XHRpZiAodHlwZSA9PT0gXCJub3RlXCIpIHJldHVybiBcInRpdGxlXCI7XG5cblx0XHRjb25zdCBjb250ZW50VHlwZSA9IHRoaXMuZ2V0Q29udGVudFR5cGUodHlwZSk7XG5cdFx0aWYgKCFjb250ZW50VHlwZSkgcmV0dXJuIFwidGl0bGVcIjtcblxuXHRcdGNvbnN0IHRlbXBsYXRlID0gY29udGVudFR5cGUudGVtcGxhdGU7XG5cdFx0Y29uc3QgbGluZXMgPSB0ZW1wbGF0ZS5zcGxpdChcIlxcblwiKTtcblx0XHRsZXQgaW5Qcm9wZXJ0aWVzID0gZmFsc2U7XG5cdFx0Zm9yIChjb25zdCBsaW5lIG9mIGxpbmVzKSB7XG5cdFx0XHRjb25zdCB0cmltbWVkID0gbGluZS50cmltKCk7XG5cdFx0XHRpZiAodHJpbW1lZCA9PT0gXCItLS1cIikge1xuXHRcdFx0XHRpblByb3BlcnRpZXMgPSAhaW5Qcm9wZXJ0aWVzO1xuXHRcdFx0XHRjb250aW51ZTtcblx0XHRcdH1cblx0XHRcdGlmIChpblByb3BlcnRpZXMpIHtcblx0XHRcdFx0Y29uc3QgbWF0Y2ggPSB0cmltbWVkLm1hdGNoKC9eKFxcdyspOlxccyooLispJC8pO1xuXHRcdFx0XHRpZiAobWF0Y2gpIHtcblx0XHRcdFx0XHRjb25zdCBrZXkgPSBtYXRjaFsxXTtcblx0XHRcdFx0XHRjb25zdCB2YWx1ZSA9IG1hdGNoWzJdO1xuXHRcdFx0XHRcdGlmICh2YWx1ZS5pbmNsdWRlcyhcInt7dGl0bGV9fVwiKSkge1xuXHRcdFx0XHRcdFx0cmV0dXJuIGtleTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdFx0cmV0dXJuIFwidGl0bGVcIjtcblx0fVxuXG5cdGFzeW5jIGNyZWF0ZUZpbGUob3B0aW9uczogRmlsZUNyZWF0aW9uT3B0aW9ucyk6IFByb21pc2U8VEZpbGUgfCBudWxsPiB7XG5cdFx0Y29uc3QgeyBmaWxlLCB0aXRsZSwgdHlwZSB9ID0gb3B0aW9ucztcblxuXHRcdGlmICghdGl0bGUpIHtcblx0XHRcdG5ldyBOb3RpY2UoYFRpdGxlIGlzIHJlcXVpcmVkIHRvIGNyZWF0ZSBhICR7dHlwZX0uYCk7XG5cdFx0XHRyZXR1cm4gbnVsbDtcblx0XHR9XG5cblx0XHQvLyBHZXQgY29udGVudCB0eXBlIHNldHRpbmdzXG5cdFx0Y29uc3QgY29udGVudFR5cGUgPSB0aGlzLmdldENvbnRlbnRUeXBlKHR5cGUpO1xuXHRcdGlmICghY29udGVudFR5cGUgJiYgdHlwZSAhPT0gXCJub3RlXCIpIHtcblx0XHRcdG5ldyBOb3RpY2UoYENvbnRlbnQgdHlwZSAke3R5cGV9IG5vdCBmb3VuZC5gKTtcblx0XHRcdHJldHVybiBudWxsO1xuXHRcdH1cblxuXHRcdGNvbnN0IGtlYmFiVGl0bGUgPSB0b0tlYmFiQ2FzZSh0aXRsZSk7XG5cdFx0Y29uc3QgZW5hYmxlVW5kZXJzY29yZVByZWZpeCA9IGNvbnRlbnRUeXBlPy5lbmFibGVVbmRlcnNjb3JlUHJlZml4IHx8IGZhbHNlO1xuXHRcdGNvbnN0IHByZWZpeCA9IGVuYWJsZVVuZGVyc2NvcmVQcmVmaXggPyBcIl9cIiA6IFwiXCI7XG5cblx0XHRsZXQgdGFyZ2V0Rm9sZGVyID0gXCJcIjtcblx0XHRpZiAodHlwZSA9PT0gXCJub3RlXCIpIHtcblx0XHRcdC8vIEZvciBnZW5lcmljIG5vdGVzLCBrZWVwIHRoZW0gaW4gdGhlaXIgY3VycmVudCBsb2NhdGlvblxuXHRcdFx0dGFyZ2V0Rm9sZGVyID0gXCJcIjtcblx0XHR9IGVsc2UgaWYgKGNvbnRlbnRUeXBlKSB7XG5cdFx0XHQvLyBHZXQgdGhlIGRpcmVjdG9yeSB3aGVyZSB0aGUgdXNlciBjcmVhdGVkIHRoZSBmaWxlXG5cdFx0XHRjb25zdCBvcmlnaW5hbERpciA9IGZpbGUucGFyZW50Py5wYXRoIHx8IFwiXCI7XG5cblx0XHRcdC8vIFJlc3BlY3QgdGhlIHVzZXIncyBjaG9zZW4gbG9jYXRpb24gKHN1YmZvbGRlcilcblx0XHRcdC8vIE9ubHkgdXNlIHRoZSBjb25maWd1cmVkIGZvbGRlciBpZiB0aGUgdXNlciBjcmVhdGVkIHRoZSBmaWxlIGluIHRoZSB2YXVsdCByb290XG5cdFx0XHRpZiAob3JpZ2luYWxEaXIgPT09IFwiXCIgfHwgb3JpZ2luYWxEaXIgPT09IFwiL1wiKSB7XG5cdFx0XHRcdHRhcmdldEZvbGRlciA9IGNvbnRlbnRUeXBlLmZvbGRlciB8fCBcIlwiO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dGFyZ2V0Rm9sZGVyID0gb3JpZ2luYWxEaXI7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0aWYgKHRhcmdldEZvbGRlcikge1xuXHRcdFx0Y29uc3QgZm9sZGVyID0gdGhpcy5hcHAudmF1bHQuZ2V0QWJzdHJhY3RGaWxlQnlQYXRoKHRhcmdldEZvbGRlcik7XG5cdFx0XHRpZiAoIShmb2xkZXIgaW5zdGFuY2VvZiBURm9sZGVyKSkge1xuXHRcdFx0XHRhd2FpdCB0aGlzLmFwcC52YXVsdC5jcmVhdGVGb2xkZXIodGFyZ2V0Rm9sZGVyKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRjb25zdCBjcmVhdGlvbk1vZGUgPSBjb250ZW50VHlwZT8uY3JlYXRpb25Nb2RlIHx8IFwiZmlsZVwiO1xuXHRcdGlmIChjcmVhdGlvbk1vZGUgPT09IFwiZm9sZGVyXCIpIHtcblx0XHRcdHJldHVybiB0aGlzLmNyZWF0ZUZvbGRlclN0cnVjdHVyZShmaWxlLCBrZWJhYlRpdGxlLCBwcmVmaXgsIHRhcmdldEZvbGRlciwgdHlwZSwgY29udGVudFR5cGUpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRyZXR1cm4gdGhpcy5jcmVhdGVGaWxlU3RydWN0dXJlKGZpbGUsIGtlYmFiVGl0bGUsIHByZWZpeCwgdGFyZ2V0Rm9sZGVyLCBjb250ZW50VHlwZSk7XG5cdFx0fVxuXHR9XG5cblx0cHJpdmF0ZSBhc3luYyBjcmVhdGVGb2xkZXJTdHJ1Y3R1cmUoZmlsZTogVEZpbGUsIGtlYmFiVGl0bGU6IHN0cmluZywgcHJlZml4OiBzdHJpbmcsIHRhcmdldEZvbGRlcjogc3RyaW5nLCB0eXBlOiBDb250ZW50VHlwZUlkLCBjb250ZW50VHlwZTogQ29udGVudFR5cGUgfCBudWxsKTogUHJvbWlzZTxURmlsZSB8IG51bGw+IHtcblx0XHRjb25zdCBmb2xkZXJOYW1lID0gYCR7cHJlZml4fSR7a2ViYWJUaXRsZX1gO1xuXHRcdGxldCBmb2xkZXJQYXRoOiBzdHJpbmc7XG5cblx0XHRpZiAodGFyZ2V0Rm9sZGVyKSB7XG5cdFx0XHQvLyBNb3ZlIHRvIHRhcmdldCBmb2xkZXJcblx0XHRcdGZvbGRlclBhdGggPSBgJHt0YXJnZXRGb2xkZXJ9LyR7Zm9sZGVyTmFtZX1gO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHQvLyBLZWVwIGluIGN1cnJlbnQgbG9jYXRpb25cblx0XHRcdGNvbnN0IGN1cnJlbnREaXIgPSBmaWxlLnBhcmVudCA/IGZpbGUucGFyZW50LnBhdGggOiBcIlwiO1xuXHRcdFx0aWYgKGN1cnJlbnREaXIgJiYgY3VycmVudERpciAhPT0gXCIvXCIpIHtcblx0XHRcdFx0Zm9sZGVyUGF0aCA9IGAke2N1cnJlbnREaXJ9LyR7Zm9sZGVyTmFtZX1gO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0Ly8gRmlsZSBpcyBpbiB2YXVsdCByb290LCBqdXN0IHVzZSBmb2xkZXIgbmFtZVxuXHRcdFx0XHRmb2xkZXJQYXRoID0gZm9sZGVyTmFtZTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHR0cnkge1xuXHRcdFx0Y29uc3QgZm9sZGVyID0gdGhpcy5hcHAudmF1bHQuZ2V0QWJzdHJhY3RGaWxlQnlQYXRoKGZvbGRlclBhdGgpO1xuXHRcdFx0aWYgKCEoZm9sZGVyIGluc3RhbmNlb2YgVEZvbGRlcikpIHtcblx0XHRcdFx0YXdhaXQgdGhpcy5hcHAudmF1bHQuY3JlYXRlRm9sZGVyKGZvbGRlclBhdGgpO1xuXHRcdFx0fVxuXHRcdH0gY2F0Y2gge1xuXHRcdFx0Ly8gRm9sZGVyIG1pZ2h0IGFscmVhZHkgZXhpc3QsIHByb2NlZWRcblx0XHR9XG5cblx0XHRjb25zdCBpbmRleEZpbGVOYW1lID0gY29udGVudFR5cGU/LmluZGV4RmlsZU5hbWUgfHwgXCJpbmRleFwiO1xuXHRcdGNvbnN0IGV4dGVuc2lvbiA9IGNvbnRlbnRUeXBlPy51c2VNZHhFeHRlbnNpb24gPyBcIi5tZHhcIiA6IFwiLm1kXCI7XG5cdFx0Y29uc3QgZmlsZU5hbWUgPSBgJHtpbmRleEZpbGVOYW1lfSR7ZXh0ZW5zaW9ufWA7XG5cdFx0Y29uc3QgbmV3UGF0aCA9IGAke2ZvbGRlclBhdGh9LyR7ZmlsZU5hbWV9YDtcblxuXHRcdGNvbnN0IGV4aXN0aW5nRmlsZSA9IHRoaXMuYXBwLnZhdWx0LmdldEFic3RyYWN0RmlsZUJ5UGF0aChuZXdQYXRoKTtcblx0XHRpZiAoZXhpc3RpbmdGaWxlIGluc3RhbmNlb2YgVEZpbGUpIHtcblx0XHRcdG5ldyBOb3RpY2UoYEZpbGUgYWxyZWFkeSBleGlzdHMgYXQgJHtuZXdQYXRofS5gKTtcblx0XHRcdHJldHVybiBudWxsO1xuXHRcdH1cblxuXHRcdC8vIFRyYWNrIHRoYXQgdGhpcyBmaWxlIHdpbGwgYmUgY3JlYXRlZCBieSB0aGUgcGx1Z2luIEJFRk9SRSByZW5hbWluZ1xuXHRcdC8vIFRoaXMgcHJldmVudHMgdGhlIGNyZWF0ZSBldmVudCBmcm9tIHRyaWdnZXJpbmcgYW5vdGhlciBtb2RhbFxuXHRcdGlmICh0aGlzLnBsdWdpbikge1xuXHRcdFx0dGhpcy5wbHVnaW4ucGx1Z2luQ3JlYXRlZEZpbGVzLnNldChuZXdQYXRoLCBEYXRlLm5vdygpKTtcblx0XHR9XG5cblx0XHR0cnkge1xuXHRcdFx0YXdhaXQgdGhpcy5hcHAuZmlsZU1hbmFnZXIucmVuYW1lRmlsZShmaWxlLCBuZXdQYXRoKTtcblx0XHRcdGNvbnN0IG5ld0ZpbGUgPSB0aGlzLmFwcC52YXVsdC5nZXRBYnN0cmFjdEZpbGVCeVBhdGgobmV3UGF0aCk7XG5cdFx0XHRpZiAoIShuZXdGaWxlIGluc3RhbmNlb2YgVEZpbGUpKSB7XG5cdFx0XHRcdHJldHVybiBudWxsO1xuXHRcdFx0fVxuXG5cdFx0XHRzZXRUaW1lb3V0KCgpID0+IHtcblx0XHRcdFx0Y29uc3QgZmlsZUV4cGxvcmVyID0gdGhpcy5hcHAud29ya3NwYWNlLmdldExlYXZlc09mVHlwZShcImZpbGUtZXhwbG9yZXJcIilbMF07XG5cdFx0XHRcdGlmIChmaWxlRXhwbG9yZXIgJiYgZmlsZUV4cGxvcmVyLnZpZXcpIHtcblx0XHRcdFx0XHRjb25zdCB2aWV3ID0gZmlsZUV4cGxvcmVyLnZpZXc7XG5cdFx0XHRcdFx0aWYgKHZpZXcgJiYgdHlwZW9mIHZpZXcgPT09ICdvYmplY3QnICYmICd0cmVlJyBpbiB2aWV3KSB7XG5cdFx0XHRcdFx0XHRjb25zdCBmaWxlVHJlZSA9ICh2aWV3IGFzIHsgdHJlZT86IHsgcmV2ZWFsRmlsZT86IChmaWxlOiBURmlsZSkgPT4gdm9pZCB9IH0pLnRyZWU7XG5cdFx0XHRcdFx0XHRpZiAoZmlsZVRyZWUgJiYgbmV3RmlsZSBpbnN0YW5jZW9mIFRGaWxlICYmIHR5cGVvZiBmaWxlVHJlZS5yZXZlYWxGaWxlID09PSAnZnVuY3Rpb24nKSB7XG5cdFx0XHRcdFx0XHRcdGZpbGVUcmVlLnJldmVhbEZpbGUobmV3RmlsZSk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9LCAyMDApO1xuXG5cdFx0XHRjb25zdCBsZWFmID0gdGhpcy5hcHAud29ya3NwYWNlLmdldExlYWYoZmFsc2UpO1xuXHRcdFx0YXdhaXQgbGVhZi5vcGVuRmlsZShuZXdGaWxlKTtcblxuXHRcdFx0Ly8gUG9zaXRpb24gY3Vyc29yIGF0IHRoZSBlbmQgb2YgY29udGVudCBhZnRlciBlZGl0b3IgaXMgcmVhZHlcblx0XHRcdGNvbnN0IHBvc2l0aW9uQ3Vyc29yID0gKCkgPT4ge1xuXHRcdFx0XHRjb25zdCB2aWV3ID0gbGVhZi52aWV3O1xuXHRcdFx0XHRpZiAodmlldyAmJiAnZWRpdG9yJyBpbiB2aWV3KSB7XG5cdFx0XHRcdFx0Y29uc3QgZWRpdG9yID0gKHZpZXcgYXMgeyBlZGl0b3I/OiB7IHNldEN1cnNvcjogKHBvczogeyBsaW5lOiBudW1iZXI7IGNoOiBudW1iZXIgfSkgPT4gdm9pZDsgZ2V0VmFsdWU6ICgpID0+IHN0cmluZzsgZm9jdXM6ICgpID0+IHZvaWQgfSB9KS5lZGl0b3I7XG5cdFx0XHRcdFx0aWYgKGVkaXRvcikge1xuXHRcdFx0XHRcdFx0Y29uc3QgY29udGVudCA9IGVkaXRvci5nZXRWYWx1ZSgpO1xuXHRcdFx0XHRcdFx0aWYgKGNvbnRlbnQpIHtcblx0XHRcdFx0XHRcdFx0Y29uc3QgbGluZXMgPSBjb250ZW50LnNwbGl0KCdcXG4nKTtcblx0XHRcdFx0XHRcdFx0Y29uc3QgbGFzdExpbmUgPSBsaW5lcy5sZW5ndGggLSAxO1xuXHRcdFx0XHRcdFx0XHRjb25zdCBsYXN0TGluZUxlbmd0aCA9IGxpbmVzW2xhc3RMaW5lXT8ubGVuZ3RoIHx8IDA7XG5cdFx0XHRcdFx0XHRcdGVkaXRvci5zZXRDdXJzb3IoeyBsaW5lOiBsYXN0TGluZSwgY2g6IGxhc3RMaW5lTGVuZ3RoIH0pO1xuXHRcdFx0XHRcdFx0XHRlZGl0b3IuZm9jdXMoKTtcblx0XHRcdFx0XHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdH07XG5cblx0XHRcdHNldFRpbWVvdXQoKCkgPT4ge1xuXHRcdFx0XHRpZiAoIXBvc2l0aW9uQ3Vyc29yKCkpIHtcblx0XHRcdFx0XHRzZXRUaW1lb3V0KCgpID0+IHtcblx0XHRcdFx0XHRcdHBvc2l0aW9uQ3Vyc29yKCk7XG5cdFx0XHRcdFx0fSwgMjAwKTtcblx0XHRcdFx0fVxuXHRcdFx0fSwgMTAwKTtcblxuXHRcdFx0cmV0dXJuIG5ld0ZpbGU7XG5cdFx0fSBjYXRjaCAoZXJyb3IpIHtcblx0XHRcdGNvbnN0IGVycm9yTWVzc2FnZSA9IGVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvci5tZXNzYWdlIDogU3RyaW5nKGVycm9yKTtcblx0XHRcdG5ldyBOb3RpY2UoYEZhaWxlZCB0byBjcmVhdGUgZm9sZGVyIHN0cnVjdHVyZTogJHtlcnJvck1lc3NhZ2V9LmApO1xuXHRcdFx0cmV0dXJuIG51bGw7XG5cdFx0fVxuXHR9XG5cblx0cHJpdmF0ZSBhc3luYyBjcmVhdGVGaWxlU3RydWN0dXJlKGZpbGU6IFRGaWxlLCBrZWJhYlRpdGxlOiBzdHJpbmcsIHByZWZpeDogc3RyaW5nLCB0YXJnZXRGb2xkZXI6IHN0cmluZywgY29udGVudFR5cGU6IENvbnRlbnRUeXBlIHwgbnVsbCk6IFByb21pc2U8VEZpbGUgfCBudWxsPiB7XG5cdFx0Y29uc3QgZXh0ZW5zaW9uID0gY29udGVudFR5cGU/LnVzZU1keEV4dGVuc2lvbiA/IFwiLm1keFwiIDogXCIubWRcIjtcblx0XHRjb25zdCBuZXdOYW1lID0gYCR7cHJlZml4fSR7a2ViYWJUaXRsZX0ke2V4dGVuc2lvbn1gO1xuXHRcdGxldCBuZXdQYXRoOiBzdHJpbmc7XG5cblx0XHRpZiAodGFyZ2V0Rm9sZGVyKSB7XG5cdFx0XHQvLyBNb3ZlIHRvIHRhcmdldCBmb2xkZXJcblx0XHRcdG5ld1BhdGggPSBgJHt0YXJnZXRGb2xkZXJ9LyR7bmV3TmFtZX1gO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHQvLyBLZWVwIGluIGN1cnJlbnQgbG9jYXRpb24sIGp1c3QgcmVuYW1lIHRoZSBmaWxlXG5cdFx0XHRjb25zdCBjdXJyZW50RGlyID0gZmlsZS5wYXJlbnQgPyBmaWxlLnBhcmVudC5wYXRoIDogXCJcIjtcblx0XHRcdGlmIChjdXJyZW50RGlyICYmIGN1cnJlbnREaXIgIT09IFwiL1wiKSB7XG5cdFx0XHRcdG5ld1BhdGggPSBgJHtjdXJyZW50RGlyfS8ke25ld05hbWV9YDtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdC8vIEZpbGUgaXMgaW4gdmF1bHQgcm9vdCwganVzdCB1c2UgbmV3IG5hbWVcblx0XHRcdFx0bmV3UGF0aCA9IG5ld05hbWU7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Y29uc3QgZXhpc3RpbmdGaWxlID0gdGhpcy5hcHAudmF1bHQuZ2V0QWJzdHJhY3RGaWxlQnlQYXRoKG5ld1BhdGgpO1xuXHRcdGlmIChleGlzdGluZ0ZpbGUgaW5zdGFuY2VvZiBURmlsZSAmJiBleGlzdGluZ0ZpbGUgIT09IGZpbGUpIHtcblx0XHRcdG5ldyBOb3RpY2UoYEZpbGUgd2l0aCBuYW1lIFwiJHtuZXdOYW1lfVwiIGFscmVhZHkgZXhpc3RzLmApO1xuXHRcdFx0cmV0dXJuIG51bGw7XG5cdFx0fVxuXG5cdFx0Ly8gVHJhY2sgdGhhdCB0aGlzIGZpbGUgd2lsbCBiZSBjcmVhdGVkIGJ5IHRoZSBwbHVnaW4gQkVGT1JFIHJlbmFtaW5nXG5cdFx0Ly8gVGhpcyBwcmV2ZW50cyB0aGUgY3JlYXRlIGV2ZW50IGZyb20gdHJpZ2dlcmluZyBhbm90aGVyIG1vZGFsXG5cdFx0aWYgKHRoaXMucGx1Z2luKSB7XG5cdFx0XHR0aGlzLnBsdWdpbi5wbHVnaW5DcmVhdGVkRmlsZXMuc2V0KG5ld1BhdGgsIERhdGUubm93KCkpO1xuXHRcdH1cblxuXHRcdHRyeSB7XG5cdFx0XHQvLyBVc2UgZmlsZU1hbmFnZXIucmVuYW1lRmlsZSgpIHdoaWNoIHJlc3BlY3RzIHVzZXIgc2V0dGluZ3MgYW5kIGhhbmRsZXMgYWxsIGxpbmsgZm9ybWF0c1xuXHRcdFx0YXdhaXQgdGhpcy5hcHAuZmlsZU1hbmFnZXIucmVuYW1lRmlsZShmaWxlLCBuZXdQYXRoKTtcblxuXHRcdFx0Y29uc3QgbmV3RmlsZSA9IHRoaXMuYXBwLnZhdWx0LmdldEFic3RyYWN0RmlsZUJ5UGF0aChuZXdQYXRoKTtcblx0XHRcdGlmICghKG5ld0ZpbGUgaW5zdGFuY2VvZiBURmlsZSkpIHtcblx0XHRcdFx0bmV3IE5vdGljZShcIkZhaWxlZCB0byBsb2NhdGUgcmVuYW1lZCBmaWxlLlwiKTtcblx0XHRcdFx0cmV0dXJuIG51bGw7XG5cdFx0XHR9XG5cblx0XHRcdGNvbnN0IGxlYWYgPSB0aGlzLmFwcC53b3Jrc3BhY2UuZ2V0TGVhZihmYWxzZSk7XG5cdFx0XHRhd2FpdCBsZWFmLm9wZW5GaWxlKG5ld0ZpbGUpO1xuXG5cdFx0XHQvLyBQb3NpdGlvbiBjdXJzb3IgYXQgdGhlIGVuZCBvZiBjb250ZW50IGFmdGVyIGVkaXRvciBpcyByZWFkeVxuXHRcdFx0Y29uc3QgcG9zaXRpb25DdXJzb3IgPSAoKSA9PiB7XG5cdFx0XHRcdGNvbnN0IHZpZXcgPSBsZWFmLnZpZXc7XG5cdFx0XHRcdGlmICh2aWV3ICYmICdlZGl0b3InIGluIHZpZXcpIHtcblx0XHRcdFx0XHRjb25zdCBlZGl0b3IgPSAodmlldyBhcyB7IGVkaXRvcj86IHsgc2V0Q3Vyc29yOiAocG9zOiB7IGxpbmU6IG51bWJlcjsgY2g6IG51bWJlciB9KSA9PiB2b2lkOyBnZXRWYWx1ZTogKCkgPT4gc3RyaW5nOyBmb2N1czogKCkgPT4gdm9pZCB9IH0pLmVkaXRvcjtcblx0XHRcdFx0XHRpZiAoZWRpdG9yKSB7XG5cdFx0XHRcdFx0XHRjb25zdCBjb250ZW50ID0gZWRpdG9yLmdldFZhbHVlKCk7XG5cdFx0XHRcdFx0XHRpZiAoY29udGVudCkge1xuXHRcdFx0XHRcdFx0XHRjb25zdCBsaW5lcyA9IGNvbnRlbnQuc3BsaXQoJ1xcbicpO1xuXHRcdFx0XHRcdFx0XHRjb25zdCBsYXN0TGluZSA9IGxpbmVzLmxlbmd0aCAtIDE7XG5cdFx0XHRcdFx0XHRcdGNvbnN0IGxhc3RMaW5lTGVuZ3RoID0gbGluZXNbbGFzdExpbmVdPy5sZW5ndGggfHwgMDtcblx0XHRcdFx0XHRcdFx0ZWRpdG9yLnNldEN1cnNvcih7IGxpbmU6IGxhc3RMaW5lLCBjaDogbGFzdExpbmVMZW5ndGggfSk7XG5cdFx0XHRcdFx0XHRcdGVkaXRvci5mb2N1cygpO1xuXHRcdFx0XHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0fTtcblxuXHRcdFx0c2V0VGltZW91dCgoKSA9PiB7XG5cdFx0XHRcdGlmICghcG9zaXRpb25DdXJzb3IoKSkge1xuXHRcdFx0XHRcdHNldFRpbWVvdXQoKCkgPT4ge1xuXHRcdFx0XHRcdFx0cG9zaXRpb25DdXJzb3IoKTtcblx0XHRcdFx0XHR9LCAyMDApO1xuXHRcdFx0XHR9XG5cdFx0XHR9LCAxMDApO1xuXG5cdFx0XHRyZXR1cm4gbmV3RmlsZTtcblx0XHR9IGNhdGNoIChlcnJvcikge1xuXHRcdFx0Y29uc3QgZXJyb3JNZXNzYWdlID0gZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yLm1lc3NhZ2UgOiBTdHJpbmcoZXJyb3IpO1xuXHRcdFx0bmV3IE5vdGljZShgRmFpbGVkIHRvIHJlbmFtZSBmaWxlOiAke2Vycm9yTWVzc2FnZX0uYCk7XG5cdFx0XHRyZXR1cm4gbnVsbDtcblx0XHR9XG5cdH1cblxuXG5cdGFzeW5jIHJlbmFtZUZpbGUob3B0aW9uczogUmVuYW1lT3B0aW9ucyk6IFByb21pc2U8VEZpbGUgfCBudWxsPiB7XG5cdFx0Y29uc3QgeyBmaWxlLCB0aXRsZSwgdHlwZSB9ID0gb3B0aW9ucztcblxuXHRcdGlmICghdGl0bGUpIHtcblx0XHRcdG5ldyBOb3RpY2UoYFRpdGxlIGlzIHJlcXVpcmVkIHRvIHJlbmFtZSB0aGUgY29udGVudC5gKTtcblx0XHRcdHJldHVybiBudWxsO1xuXHRcdH1cblxuXHRcdGNvbnN0IGNvbnRlbnRUeXBlID0gdGhpcy5nZXRDb250ZW50VHlwZSh0eXBlKTtcblx0XHRpZiAoIWNvbnRlbnRUeXBlICYmIHR5cGUgIT09IFwibm90ZVwiKSB7XG5cdFx0XHRuZXcgTm90aWNlKGBDb250ZW50IHR5cGUgJHt0eXBlfSBub3QgZm91bmQuYCk7XG5cdFx0XHRyZXR1cm4gbnVsbDtcblx0XHR9XG5cblx0XHRjb25zdCBrZWJhYlRpdGxlID0gdG9LZWJhYkNhc2UodGl0bGUpO1xuXHRcdGNvbnN0IHByZWZpeCA9IFwiXCI7XG5cblx0XHRjb25zdCBjcmVhdGlvbk1vZGUgPSBjb250ZW50VHlwZT8uY3JlYXRpb25Nb2RlIHx8IFwiZmlsZVwiO1xuXHRcdGlmIChjcmVhdGlvbk1vZGUgPT09IFwiZm9sZGVyXCIpIHtcblx0XHRcdHJldHVybiB0aGlzLnJlbmFtZUZvbGRlclN0cnVjdHVyZShmaWxlLCBrZWJhYlRpdGxlLCBwcmVmaXgsIHR5cGUsIGNvbnRlbnRUeXBlKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0cmV0dXJuIHRoaXMucmVuYW1lRmlsZVN0cnVjdHVyZShmaWxlLCBrZWJhYlRpdGxlLCBwcmVmaXgsIGNvbnRlbnRUeXBlKTtcblx0XHR9XG5cdH1cblxuXHRwcml2YXRlIGFzeW5jIHJlbmFtZUZvbGRlclN0cnVjdHVyZShmaWxlOiBURmlsZSwga2ViYWJUaXRsZTogc3RyaW5nLCBwcmVmaXg6IHN0cmluZywgdHlwZTogQ29udGVudFR5cGVJZCwgY29udGVudFR5cGU6IENvbnRlbnRUeXBlIHwgbnVsbCk6IFByb21pc2U8VEZpbGUgfCBudWxsPiB7XG5cdFx0Ly8gU21hcnQgZGV0ZWN0aW9uOiB0cmVhdCBhcyBpbmRleCBpZiBmaWxlbmFtZSBtYXRjaGVzIHRoZSBpbmRleCBmaWxlIG5hbWVcblx0XHQvLyBEZWZhdWx0IHRvIFwiaW5kZXhcIiB3aGVuIGluZGV4RmlsZU5hbWUgaXMgYmxhbmtcblx0XHRjb25zdCBpbmRleEZpbGVOYW1lID0gY29udGVudFR5cGU/LmluZGV4RmlsZU5hbWUgfHwgXCJpbmRleFwiO1xuXHRcdGNvbnN0IGlzSW5kZXggPSBmaWxlLmJhc2VuYW1lID09PSBpbmRleEZpbGVOYW1lO1xuXHRcdGlmIChpc0luZGV4KSB7XG5cdFx0XHRpZiAoIWZpbGUucGFyZW50KSB7XG5cdFx0XHRcdG5ldyBOb3RpY2UoXCJDYW5ub3QgcmVuYW1lOiBmaWxlIGhhcyBubyBwYXJlbnQgZm9sZGVyLlwiKTtcblx0XHRcdFx0cmV0dXJuIG51bGw7XG5cdFx0XHR9XG5cdFx0XHRwcmVmaXggPSBmaWxlLnBhcmVudC5uYW1lLnN0YXJ0c1dpdGgoXCJfXCIpID8gXCJfXCIgOiBcIlwiO1xuXHRcdFx0Y29uc3QgbmV3Rm9sZGVyTmFtZSA9IGAke3ByZWZpeH0ke2tlYmFiVGl0bGV9YDtcblx0XHRcdGNvbnN0IHBhcmVudEZvbGRlciA9IGZpbGUucGFyZW50LnBhcmVudDtcblx0XHRcdGlmICghcGFyZW50Rm9sZGVyKSB7XG5cdFx0XHRcdG5ldyBOb3RpY2UoXCJDYW5ub3QgcmVuYW1lOiBwYXJlbnQgZm9sZGVyIGhhcyBubyBwYXJlbnQuXCIpO1xuXHRcdFx0XHRyZXR1cm4gbnVsbDtcblx0XHRcdH1cblx0XHRcdC8vIEZpeCBwYXRoIGNvbnN0cnVjdGlvbiB0byBhdm9pZCBkb3VibGUgc2xhc2hlc1xuXHRcdFx0bGV0IG5ld0ZvbGRlclBhdGg6IHN0cmluZztcblx0XHRcdGlmIChwYXJlbnRGb2xkZXIucGF0aCA9PT0gXCJcIiB8fCBwYXJlbnRGb2xkZXIucGF0aCA9PT0gXCIvXCIpIHtcblx0XHRcdFx0Ly8gUGFyZW50IGlzIHZhdWx0IHJvb3Rcblx0XHRcdFx0bmV3Rm9sZGVyUGF0aCA9IG5ld0ZvbGRlck5hbWU7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHQvLyBQYXJlbnQgaXMgaW4gYSBzdWJmb2xkZXJcblx0XHRcdFx0bmV3Rm9sZGVyUGF0aCA9IGAke3BhcmVudEZvbGRlci5wYXRofS8ke25ld0ZvbGRlck5hbWV9YDtcblx0XHRcdH1cblxuXHRcdFx0Y29uc3QgZXhpc3RpbmdGb2xkZXIgPSB0aGlzLmFwcC52YXVsdC5nZXRBYnN0cmFjdEZpbGVCeVBhdGgobmV3Rm9sZGVyUGF0aCk7XG5cdFx0XHRpZiAoZXhpc3RpbmdGb2xkZXIgaW5zdGFuY2VvZiBURm9sZGVyKSB7XG5cdFx0XHRcdG5ldyBOb3RpY2UoYEZvbGRlciBhbHJlYWR5IGV4aXN0cyBhdCAke25ld0ZvbGRlclBhdGh9LmApO1xuXHRcdFx0XHRyZXR1cm4gbnVsbDtcblx0XHRcdH1cblxuXHRcdFx0dHJ5IHtcblx0XHRcdFx0YXdhaXQgdGhpcy5hcHAuZmlsZU1hbmFnZXIucmVuYW1lRmlsZShmaWxlLnBhcmVudCwgbmV3Rm9sZGVyUGF0aCk7XG5cdFx0XHR9IGNhdGNoIChlcnJvcikge1xuXHRcdFx0XHRjb25zdCBlcnJvck1lc3NhZ2UgPSBlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IubWVzc2FnZSA6IFN0cmluZyhlcnJvcik7XG5cdFx0XHRcdG5ldyBOb3RpY2UoYEZhaWxlZCB0byByZW5hbWUgZm9sZGVyOiAke2Vycm9yTWVzc2FnZX0uYCk7XG5cdFx0XHRcdHJldHVybiBudWxsO1xuXHRcdFx0fVxuXG5cdFx0XHRjb25zdCBuZXdGaWxlUGF0aCA9IGAke25ld0ZvbGRlclBhdGh9LyR7ZmlsZS5uYW1lfWA7XG5cdFx0XHRjb25zdCBuZXdGaWxlID0gdGhpcy5hcHAudmF1bHQuZ2V0QWJzdHJhY3RGaWxlQnlQYXRoKG5ld0ZpbGVQYXRoKTtcblx0XHRcdGlmICghKG5ld0ZpbGUgaW5zdGFuY2VvZiBURmlsZSkpIHtcblx0XHRcdFx0bmV3IE5vdGljZShcIkZhaWxlZCB0byBsb2NhdGUgcmVuYW1lZCBmaWxlLlwiKTtcblx0XHRcdFx0cmV0dXJuIG51bGw7XG5cdFx0XHR9XG5cblxuXHRcdFx0cmV0dXJuIG5ld0ZpbGU7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGlmICghZmlsZS5wYXJlbnQpIHtcblx0XHRcdFx0bmV3IE5vdGljZShcIkNhbm5vdCByZW5hbWU6IGZpbGUgaGFzIG5vIHBhcmVudCBmb2xkZXIuXCIpO1xuXHRcdFx0XHRyZXR1cm4gbnVsbDtcblx0XHRcdH1cblx0XHRcdHByZWZpeCA9IGZpbGUuYmFzZW5hbWUuc3RhcnRzV2l0aChcIl9cIikgPyBcIl9cIiA6IFwiXCI7XG5cdFx0XHQvLyBQcmVzZXJ2ZSB0aGUgb3JpZ2luYWwgZmlsZSBleHRlbnNpb25cblx0XHRcdGNvbnN0IGV4dGVuc2lvbiA9IGZpbGUuZXh0ZW5zaW9uO1xuXHRcdFx0Y29uc3QgbmV3TmFtZSA9IGAke3ByZWZpeH0ke2tlYmFiVGl0bGV9LiR7ZXh0ZW5zaW9ufWA7XG5cdFx0XHRjb25zdCBuZXdQYXRoID0gYCR7ZmlsZS5wYXJlbnQucGF0aH0vJHtuZXdOYW1lfWA7XG5cblx0XHRcdGNvbnN0IGV4aXN0aW5nRmlsZSA9IHRoaXMuYXBwLnZhdWx0LmdldEFic3RyYWN0RmlsZUJ5UGF0aChuZXdQYXRoKTtcblx0XHRcdGlmIChleGlzdGluZ0ZpbGUgaW5zdGFuY2VvZiBURmlsZSAmJiBleGlzdGluZ0ZpbGUgIT09IGZpbGUpIHtcblx0XHRcdFx0bmV3IE5vdGljZShgRmlsZSBhbHJlYWR5IGV4aXN0cyBhdCAke25ld1BhdGh9LmApO1xuXHRcdFx0XHRyZXR1cm4gbnVsbDtcblx0XHRcdH1cblxuXHRcdFx0Ly8gVXNlIGZpbGVNYW5hZ2VyLnJlbmFtZUZpbGUoKSB3aGljaCBhdXRvbWF0aWNhbGx5IHVwZGF0ZXMgbGlua3Ncblx0XHRcdGF3YWl0IHRoaXMuYXBwLmZpbGVNYW5hZ2VyLnJlbmFtZUZpbGUoZmlsZSwgbmV3UGF0aCk7XG5cdFx0XHRjb25zdCBuZXdGaWxlID0gdGhpcy5hcHAudmF1bHQuZ2V0QWJzdHJhY3RGaWxlQnlQYXRoKG5ld1BhdGgpO1xuXHRcdFx0aWYgKCEobmV3RmlsZSBpbnN0YW5jZW9mIFRGaWxlKSkge1xuXHRcdFx0XHRuZXcgTm90aWNlKFwiRmFpbGVkIHRvIGxvY2F0ZSByZW5hbWVkIGZpbGUuXCIpO1xuXHRcdFx0XHRyZXR1cm4gbnVsbDtcblx0XHRcdH1cblxuXG5cdFx0XHRyZXR1cm4gbmV3RmlsZTtcblx0XHR9XG5cdH1cblxuXHRwcml2YXRlIGFzeW5jIHJlbmFtZUZpbGVTdHJ1Y3R1cmUoZmlsZTogVEZpbGUsIGtlYmFiVGl0bGU6IHN0cmluZywgcHJlZml4OiBzdHJpbmcsIGNvbnRlbnRUeXBlOiBDb250ZW50VHlwZSB8IG51bGwpOiBQcm9taXNlPFRGaWxlIHwgbnVsbD4ge1xuXHRcdGlmICghZmlsZS5wYXJlbnQpIHtcblx0XHRcdG5ldyBOb3RpY2UoXCJDYW5ub3QgcmVuYW1lOiBmaWxlIGhhcyBubyBwYXJlbnQgZm9sZGVyLlwiKTtcblx0XHRcdHJldHVybiBudWxsO1xuXHRcdH1cblxuXHRcdC8vIENoZWNrIGlmIHRoaXMgaXMgYW4gaW5kZXggZmlsZSAtIGlmIHNvLCByZW5hbWUgdGhlIHBhcmVudCBmb2xkZXIgaW5zdGVhZFxuXHRcdC8vIFNtYXJ0IGRldGVjdGlvbjogb25seSB0cmVhdCBhcyBpbmRleCBpZiBpbmRleEZpbGVOYW1lIGlzIHNwZWNpZmllZCBhbmQgbWF0Y2hlc1xuXHRcdGNvbnN0IGluZGV4RmlsZU5hbWUgPSBjb250ZW50VHlwZT8uaW5kZXhGaWxlTmFtZSB8fCBcIlwiO1xuXHRcdGNvbnN0IGlzSW5kZXggPSBpbmRleEZpbGVOYW1lICYmXG5cdFx0XHRpbmRleEZpbGVOYW1lLnRyaW0oKSAhPT0gXCJcIiAmJlxuXHRcdFx0ZmlsZS5iYXNlbmFtZSA9PT0gaW5kZXhGaWxlTmFtZTtcblxuXHRcdGlmIChpc0luZGV4KSB7XG5cdFx0XHRwcmVmaXggPSBmaWxlLnBhcmVudC5uYW1lLnN0YXJ0c1dpdGgoXCJfXCIpID8gXCJfXCIgOiBcIlwiO1xuXHRcdFx0Y29uc3QgbmV3Rm9sZGVyTmFtZSA9IGAke3ByZWZpeH0ke2tlYmFiVGl0bGV9YDtcblx0XHRcdGNvbnN0IHBhcmVudEZvbGRlciA9IGZpbGUucGFyZW50LnBhcmVudDtcblx0XHRcdGlmICghcGFyZW50Rm9sZGVyKSB7XG5cdFx0XHRcdG5ldyBOb3RpY2UoXCJDYW5ub3QgcmVuYW1lOiBwYXJlbnQgZm9sZGVyIGhhcyBubyBwYXJlbnQuXCIpO1xuXHRcdFx0XHRyZXR1cm4gbnVsbDtcblx0XHRcdH1cblx0XHRcdC8vIEZpeCBwYXRoIGNvbnN0cnVjdGlvbiB0byBhdm9pZCBkb3VibGUgc2xhc2hlc1xuXHRcdFx0bGV0IG5ld0ZvbGRlclBhdGg6IHN0cmluZztcblx0XHRcdGlmIChwYXJlbnRGb2xkZXIucGF0aCA9PT0gXCJcIiB8fCBwYXJlbnRGb2xkZXIucGF0aCA9PT0gXCIvXCIpIHtcblx0XHRcdFx0Ly8gUGFyZW50IGlzIHZhdWx0IHJvb3Rcblx0XHRcdFx0bmV3Rm9sZGVyUGF0aCA9IG5ld0ZvbGRlck5hbWU7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHQvLyBQYXJlbnQgaXMgaW4gYSBzdWJmb2xkZXJcblx0XHRcdFx0bmV3Rm9sZGVyUGF0aCA9IGAke3BhcmVudEZvbGRlci5wYXRofS8ke25ld0ZvbGRlck5hbWV9YDtcblx0XHRcdH1cblxuXHRcdFx0Y29uc3QgZXhpc3RpbmdGb2xkZXIgPSB0aGlzLmFwcC52YXVsdC5nZXRBYnN0cmFjdEZpbGVCeVBhdGgobmV3Rm9sZGVyUGF0aCk7XG5cdFx0XHRpZiAoZXhpc3RpbmdGb2xkZXIgaW5zdGFuY2VvZiBURm9sZGVyKSB7XG5cdFx0XHRcdG5ldyBOb3RpY2UoYEZvbGRlciBhbHJlYWR5IGV4aXN0cyBhdCAke25ld0ZvbGRlclBhdGh9LmApO1xuXHRcdFx0XHRyZXR1cm4gbnVsbDtcblx0XHRcdH1cblxuXHRcdFx0Ly8gQ2FsY3VsYXRlIHRoZSBuZXcgZmlsZSBwYXRoIGJlZm9yZSByZW5hbWluZ1xuXHRcdFx0Y29uc3QgbmV3RmlsZVBhdGggPSBgJHtuZXdGb2xkZXJQYXRofS8ke2ZpbGUubmFtZX1gO1xuXG5cdFx0XHQvLyBUcmFjayB0aGF0IHRoaXMgZmlsZSB3aWxsIGJlIGNyZWF0ZWQgYnkgdGhlIHBsdWdpbiBCRUZPUkUgcmVuYW1pbmdcblx0XHRcdC8vIFRoaXMgcHJldmVudHMgdGhlIGNyZWF0ZSBldmVudCBmcm9tIHRyaWdnZXJpbmcgYW5vdGhlciBtb2RhbFxuXHRcdFx0aWYgKHRoaXMucGx1Z2luKSB7XG5cdFx0XHRcdHRoaXMucGx1Z2luLnBsdWdpbkNyZWF0ZWRGaWxlcy5zZXQobmV3RmlsZVBhdGgsIERhdGUubm93KCkpO1xuXHRcdFx0fVxuXG5cdFx0XHR0cnkge1xuXHRcdFx0XHRhd2FpdCB0aGlzLmFwcC5maWxlTWFuYWdlci5yZW5hbWVGaWxlKGZpbGUucGFyZW50LCBuZXdGb2xkZXJQYXRoKTtcblx0XHRcdH0gY2F0Y2ggKGVycm9yKSB7XG5cdFx0XHRcdGNvbnNvbGUuZXJyb3IoJ0ZpbGVPcGVyYXRpb25zOiBGb2xkZXIgcmVuYW1lIGZhaWxlZDonLCBlcnJvcik7XG5cdFx0XHRcdGNvbnN0IGVycm9yTWVzc2FnZSA9IGVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvci5tZXNzYWdlIDogU3RyaW5nKGVycm9yKTtcblx0XHRcdFx0bmV3IE5vdGljZShgRmFpbGVkIHRvIHJlbmFtZSBmb2xkZXI6ICR7ZXJyb3JNZXNzYWdlfS5gKTtcblx0XHRcdFx0cmV0dXJuIG51bGw7XG5cdFx0XHR9XG5cblx0XHRcdGNvbnN0IG5ld0ZpbGUgPSB0aGlzLmFwcC52YXVsdC5nZXRBYnN0cmFjdEZpbGVCeVBhdGgobmV3RmlsZVBhdGgpO1xuXHRcdFx0aWYgKCEobmV3RmlsZSBpbnN0YW5jZW9mIFRGaWxlKSkge1xuXHRcdFx0XHRuZXcgTm90aWNlKFwiRmFpbGVkIHRvIGxvY2F0ZSByZW5hbWVkIGZpbGUuXCIpO1xuXHRcdFx0XHRyZXR1cm4gbnVsbDtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIG5ld0ZpbGU7XG5cdFx0fVxuXG5cdFx0Ly8gRm9yIG5vbi1pbmRleCBmaWxlcywgcmVuYW1lIHRoZSBmaWxlIGl0c2VsZlxuXHRcdHByZWZpeCA9IGZpbGUuYmFzZW5hbWUuc3RhcnRzV2l0aChcIl9cIikgPyBcIl9cIiA6IFwiXCI7XG5cdFx0Ly8gUHJlc2VydmUgdGhlIG9yaWdpbmFsIGZpbGUgZXh0ZW5zaW9uXG5cdFx0Y29uc3QgZXh0ZW5zaW9uID0gZmlsZS5leHRlbnNpb247XG5cdFx0Y29uc3QgbmV3TmFtZSA9IGAke3ByZWZpeH0ke2tlYmFiVGl0bGV9LiR7ZXh0ZW5zaW9ufWA7XG5cblx0XHQvLyBGaXggcGF0aCBjb25zdHJ1Y3Rpb24gdG8gYXZvaWQgZG91YmxlIHNsYXNoZXNcblx0XHRsZXQgbmV3UGF0aDogc3RyaW5nO1xuXHRcdGlmIChmaWxlLnBhcmVudC5wYXRoID09PSBcIlwiIHx8IGZpbGUucGFyZW50LnBhdGggPT09IFwiL1wiKSB7XG5cdFx0XHQvLyBGaWxlIGlzIGluIHZhdWx0IHJvb3Rcblx0XHRcdG5ld1BhdGggPSBuZXdOYW1lO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHQvLyBGaWxlIGlzIGluIGEgc3ViZm9sZGVyXG5cdFx0XHRuZXdQYXRoID0gYCR7ZmlsZS5wYXJlbnQucGF0aH0vJHtuZXdOYW1lfWA7XG5cdFx0fVxuXG5cdFx0Y29uc3QgZXhpc3RpbmdGaWxlID0gdGhpcy5hcHAudmF1bHQuZ2V0QWJzdHJhY3RGaWxlQnlQYXRoKG5ld1BhdGgpO1xuXHRcdGlmIChleGlzdGluZ0ZpbGUgaW5zdGFuY2VvZiBURmlsZSAmJiBleGlzdGluZ0ZpbGUgIT09IGZpbGUpIHtcblx0XHRcdG5ldyBOb3RpY2UoYEZpbGUgYWxyZWFkeSBleGlzdHMgYXQgJHtuZXdQYXRofS5gKTtcblx0XHRcdHJldHVybiBudWxsO1xuXHRcdH1cblxuXHRcdC8vIFRyYWNrIHRoYXQgdGhpcyBmaWxlIHdpbGwgYmUgY3JlYXRlZCBieSB0aGUgcGx1Z2luIEJFRk9SRSByZW5hbWluZ1xuXHRcdC8vIFRoaXMgcHJldmVudHMgdGhlIGNyZWF0ZSBldmVudCBmcm9tIHRyaWdnZXJpbmcgYW5vdGhlciBtb2RhbFxuXHRcdGlmICh0aGlzLnBsdWdpbikge1xuXHRcdFx0dGhpcy5wbHVnaW4ucGx1Z2luQ3JlYXRlZEZpbGVzLnNldChuZXdQYXRoLCBEYXRlLm5vdygpKTtcblx0XHR9XG5cblx0XHR0cnkge1xuXHRcdFx0YXdhaXQgdGhpcy5hcHAuZmlsZU1hbmFnZXIucmVuYW1lRmlsZShmaWxlLCBuZXdQYXRoKTtcblx0XHR9IGNhdGNoIChlcnJvcikge1xuXHRcdFx0Y29uc29sZS5lcnJvcignRmlsZU9wZXJhdGlvbnM6IEZpbGUgcmVuYW1lIGZhaWxlZDonLCBlcnJvcik7XG5cdFx0XHRjb25zdCBlcnJvck1lc3NhZ2UgPSBlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IubWVzc2FnZSA6IFN0cmluZyhlcnJvcik7XG5cdFx0XHRuZXcgTm90aWNlKGBGYWlsZWQgdG8gcmVuYW1lIGZpbGU6ICR7ZXJyb3JNZXNzYWdlfS5gKTtcblx0XHRcdHJldHVybiBudWxsO1xuXHRcdH1cblxuXHRcdGNvbnN0IG5ld0ZpbGUgPSB0aGlzLmFwcC52YXVsdC5nZXRBYnN0cmFjdEZpbGVCeVBhdGgobmV3UGF0aCk7XG5cdFx0aWYgKCEobmV3RmlsZSBpbnN0YW5jZW9mIFRGaWxlKSkge1xuXHRcdFx0bmV3IE5vdGljZShcIkZhaWxlZCB0byBsb2NhdGUgcmVuYW1lZCBmaWxlLlwiKTtcblx0XHRcdHJldHVybiBudWxsO1xuXHRcdH1cblxuXHRcdHJldHVybiBuZXdGaWxlO1xuXHR9XG59XG4iLCAiLyoqXHJcbiAqIFV0aWxpdHkgZnVuY3Rpb25zIGZvciBtYXRjaGluZyBmaWxlIHBhdGhzIGFnYWluc3QgZm9sZGVyIHBhdHRlcm5zIHdpdGggd2lsZGNhcmQgc3VwcG9ydC5cclxuICogXHJcbiAqIFdpbGRjYXJkIHBhdHRlcm5zOlxyXG4gKiAtIGBkb2NzYCBtYXRjaGVzIGBkb2NzL2AgYW5kIGFueXRoaW5nIHVuZGVyIGl0XHJcbiAqIC0gYGRvY3Mve2FzdGVyaXNrfWAgbWF0Y2hlcyBgZG9jcy9hbnl0aGluZy9gIGFuZCBhbnl0aGluZyB1bmRlciBpdCAob25lIGxldmVsIGRlZXApXHJcbiAqIC0gYGRvY3Mve2FzdGVyaXNrfS97YXN0ZXJpc2t9YCBtYXRjaGVzIGBkb2NzL2FueXRoaW5nL2FueXRoaW5nL2AgYW5kIGFueXRoaW5nIHVuZGVyIGl0ICh0d28gbGV2ZWxzIGRlZXApXHJcbiAqIC0gZXRjLlxyXG4gKiBcclxuICogTm90ZToge2FzdGVyaXNrfSByZXByZXNlbnRzIHRoZSB3aWxkY2FyZCBjaGFyYWN0ZXIgKlxyXG4gKi9cclxuXHJcbi8qKlxyXG4gKiBDaGVja3MgaWYgYSBmaWxlIHBhdGggbWF0Y2hlcyBhIGZvbGRlciBwYXR0ZXJuIChzdXBwb3J0cyB3aWxkY2FyZHMpXHJcbiAqIEBwYXJhbSBmaWxlUGF0aCBUaGUgZmlsZSBwYXRoIHRvIGNoZWNrIChlLmcuLCBcImRvY3MvZXhhbXBsZS1hL2dldHRpbmctc3RhcnRlZC5tZFwiKVxyXG4gKiBAcGFyYW0gZm9sZGVyUGF0dGVybiBUaGUgZm9sZGVyIHBhdHRlcm4gLSB1c2UgYXN0ZXJpc2sgZm9yIHdpbGRjYXJkcyAoZS5nLiwgXCJkb2NzXCIsIFwiZG9jcy9hc3Rlcmlza1wiLCBcImRvY3MvYXN0ZXJpc2svYXN0ZXJpc2tcIilcclxuICogQHJldHVybnMgdHJ1ZSBpZiB0aGUgZmlsZSBwYXRoIG1hdGNoZXMgdGhlIHBhdHRlcm5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBtYXRjaGVzRm9sZGVyUGF0dGVybihmaWxlUGF0aDogc3RyaW5nLCBmb2xkZXJQYXR0ZXJuOiBzdHJpbmcpOiBib29sZWFuIHtcclxuXHQvLyBOb3JtYWxpemUgZm9yIGNhc2UtaW5zZW5zaXRpdmUgbWF0Y2hpbmdcclxuXHRjb25zdCBub3JtYWxpemVkRmlsZVBhdGggPSBmaWxlUGF0aC50b0xvd2VyQ2FzZSgpO1xyXG5cdGNvbnN0IG5vcm1hbGl6ZWRQYXR0ZXJuID0gZm9sZGVyUGF0dGVybi50b0xvd2VyQ2FzZSgpLnJlcGxhY2UoL15cXC98XFwvJC9nLCBcIlwiKTtcclxuXHJcblx0Ly8gSGFuZGxlIGVtcHR5IGZvbGRlciBwYXR0ZXJuIChyb290IGZvbGRlcikgLSBtYXRjaGVzIGZpbGVzIGluIHZhdWx0IHJvb3Qgb25seVxyXG5cdGlmICghbm9ybWFsaXplZFBhdHRlcm4gfHwgbm9ybWFsaXplZFBhdHRlcm4udHJpbSgpID09PSBcIlwiKSB7XHJcblx0XHRyZXR1cm4gIW5vcm1hbGl6ZWRGaWxlUGF0aC5pbmNsdWRlcyhcIi9cIikgfHwgKG5vcm1hbGl6ZWRGaWxlUGF0aC5zcGxpdChcIi9cIikubGVuZ3RoID09PSAxKTtcclxuXHR9XHJcblxyXG5cdC8vIElmIHBhdHRlcm4gZG9lc24ndCBjb250YWluIHdpbGRjYXJkcywgdXNlIHNpbXBsZSBwcmVmaXggbWF0Y2hpbmdcclxuXHRpZiAoIW5vcm1hbGl6ZWRQYXR0ZXJuLmluY2x1ZGVzKFwiKlwiKSkge1xyXG5cdFx0cmV0dXJuIG5vcm1hbGl6ZWRGaWxlUGF0aCA9PT0gbm9ybWFsaXplZFBhdHRlcm4gfHwgbm9ybWFsaXplZEZpbGVQYXRoLnN0YXJ0c1dpdGgobm9ybWFsaXplZFBhdHRlcm4gKyBcIi9cIik7XHJcblx0fVxyXG5cclxuXHQvLyBDb252ZXJ0IHdpbGRjYXJkIHBhdHRlcm4gdG8gcmVnZXhcclxuXHQvLyBFc2NhcGUgc3BlY2lhbCByZWdleCBjaGFyYWN0ZXJzIGV4Y2VwdCAqXHJcblx0Y29uc3QgZXNjYXBlZFBhdHRlcm4gPSBub3JtYWxpemVkUGF0dGVyblxyXG5cdFx0LnJlcGxhY2UoL1suKz9eJHt9KCl8W1xcXVxcXFxdL2csIFwiXFxcXCQmXCIpXHJcblx0XHQucmVwbGFjZSgvXFwqL2csIFwiW14vXStcIik7IC8vIFdpbGRjYXJkIG1hdGNoZXMgYW55IHBhdGggc2VnbWVudCAobm9uLXNsYXNoIGNoYXJhY3RlcnMpXHJcblxyXG5cdC8vIENyZWF0ZSByZWdleCB0aGF0IG1hdGNoZXMgdGhlIHBhdHRlcm4gYW5kIGFueXRoaW5nIGFmdGVyIGl0XHJcblx0Y29uc3QgcmVnZXhQYXR0ZXJuID0gYF4ke2VzY2FwZWRQYXR0ZXJufSg/Oi98JClgO1xyXG5cdGNvbnN0IHJlZ2V4ID0gbmV3IFJlZ0V4cChyZWdleFBhdHRlcm4pO1xyXG5cdHJldHVybiByZWdleC50ZXN0KG5vcm1hbGl6ZWRGaWxlUGF0aCk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBHZXRzIHRoZSBkZXB0aCBvZiBhIGZvbGRlciBwYXR0ZXJuIChudW1iZXIgb2Ygc2VnbWVudHMpXHJcbiAqIFVzZWQgZm9yIHByaW9yaXRpemluZyBtb3JlIHNwZWNpZmljIHBhdHRlcm5zXHJcbiAqIEJsYW5rL3Jvb3QgZm9sZGVyIGhhcyBkZXB0aCAwIChsZWFzdCBzcGVjaWZpYylcclxuICogQHBhcmFtIGZvbGRlclBhdHRlcm4gVGhlIGZvbGRlciBwYXR0ZXJuXHJcbiAqIEByZXR1cm5zIFRoZSBudW1iZXIgb2YgcGF0aCBzZWdtZW50cyBpbiB0aGUgcGF0dGVybiAoMCBmb3Igcm9vdC9ibGFuaylcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBnZXRQYXR0ZXJuRGVwdGgoZm9sZGVyUGF0dGVybjogc3RyaW5nKTogbnVtYmVyIHtcclxuXHRpZiAoIWZvbGRlclBhdHRlcm4gfHwgZm9sZGVyUGF0dGVybi50cmltKCkgPT09IFwiXCIpIHJldHVybiAwO1xyXG5cdHJldHVybiBmb2xkZXJQYXR0ZXJuLnNwbGl0KFwiL1wiKS5sZW5ndGg7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBTb3J0cyBjb250ZW50IHR5cGVzIGJ5IHBhdHRlcm4gc3BlY2lmaWNpdHkgKG1vcmUgc3BlY2lmaWMgcGF0dGVybnMgZmlyc3QpXHJcbiAqIFRoaXMgZW5zdXJlcyB0aGF0IG1vcmUgc3BlY2lmaWMgcGF0dGVybnMgYXJlIGNoZWNrZWQgYmVmb3JlIGxlc3Mgc3BlY2lmaWMgb25lc1xyXG4gKiBCbGFuay9yb290IGZvbGRlciBwYXR0ZXJucyAoZGVwdGggMCkgYXJlIHNvcnRlZCBsYXN0IChsZWFzdCBzcGVjaWZpYylcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBzb3J0QnlQYXR0ZXJuU3BlY2lmaWNpdHk8VCBleHRlbmRzIHsgZm9sZGVyOiBzdHJpbmcgfT4odHlwZXM6IFRbXSk6IFRbXSB7XHJcblx0cmV0dXJuIFsuLi50eXBlc10uc29ydCgoYSwgYikgPT4ge1xyXG5cdFx0Y29uc3QgZGVwdGhBID0gZ2V0UGF0dGVybkRlcHRoKGEuZm9sZGVyKTtcclxuXHRcdGNvbnN0IGRlcHRoQiA9IGdldFBhdHRlcm5EZXB0aChiLmZvbGRlcik7XHJcblx0XHQvLyBNb3JlIHNwZWNpZmljIChkZWVwZXIpIHBhdHRlcm5zIGZpcnN0XHJcblx0XHQvLyBCbGFuayBwYXR0ZXJucyAoZGVwdGggMCkgd2lsbCBiZSBzb3J0ZWQgbGFzdFxyXG5cdFx0cmV0dXJuIGRlcHRoQiAtIGRlcHRoQTtcclxuXHR9KTtcclxufVxyXG5cclxuIiwgIi8qKlxyXG4gKiBDb252ZXJ0cyBhIHN0cmluZyB0byBrZWJhYi1jYXNlLlxyXG4gKiBAcGFyYW0gc3RyIFRoZSBzdHJpbmcgdG8gY29udmVydFxyXG4gKiBAcmV0dXJucyBLZWJhYi1jYXNlIHN0cmluZ1xyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIHRvS2ViYWJDYXNlKHN0cjogc3RyaW5nKTogc3RyaW5nIHtcclxuICAgIHJldHVybiBzdHJcclxuICAgICAgICAucmVwbGFjZSgvKFthLXowLTldKShbQS1aXSkvZywgJyQxLSQyJylcclxuICAgICAgICAucmVwbGFjZSgvKFtBLVpdKShbQS1aXVthLXpdKS9nLCAnJDEtJDIkMycpXHJcbiAgICAgICAgLnRvTG93ZXJDYXNlKClcclxuICAgICAgICAucmVwbGFjZSgvW15hLXowLTlcXHMtXS9nLCBcIlwiKVxyXG4gICAgICAgIC50cmltKClcclxuICAgICAgICAucmVwbGFjZSgvXFxzKy9nLCBcIi1cIilcclxuICAgICAgICAucmVwbGFjZSgvLSsvZywgXCItXCIpXHJcbiAgICAgICAgLnJlcGxhY2UoL14tfC0kL2csIFwiXCIpO1xyXG59XHJcbiIsICJpbXBvcnQgeyBBcHAsIFRGaWxlLCBOb3RpY2UgfSBmcm9tIFwib2JzaWRpYW5cIjtcclxuaW1wb3J0IHsgQXN0cm9Db21wb3NlclNldHRpbmdzLCBQYXJzZWRGcm9udG1hdHRlciwgVGVtcGxhdGVWYWx1ZXMsIEtOT1dOX0FSUkFZX0tFWVMsIENvbnRlbnRUeXBlSWQsIEFzdHJvQ29tcG9zZXJQbHVnaW5JbnRlcmZhY2UgfSBmcm9tIFwiLi4vdHlwZXNcIjtcclxuXHJcbmV4cG9ydCBjbGFzcyBUZW1wbGF0ZVBhcnNlciB7XHJcblx0Y29uc3RydWN0b3IocHJpdmF0ZSBhcHA6IEFwcCwgcHJpdmF0ZSBzZXR0aW5nczogQXN0cm9Db21wb3NlclNldHRpbmdzLCBwcml2YXRlIHBsdWdpbj86IEFzdHJvQ29tcG9zZXJQbHVnaW5JbnRlcmZhY2UpIHsgfVxyXG5cclxuXHQvLyBHZXQgZnJlc2ggc2V0dGluZ3MgZnJvbSBwbHVnaW4gaWYgYXZhaWxhYmxlLCBvdGhlcndpc2UgdXNlIHN0b3JlZCBzZXR0aW5nc1xyXG5cdHByaXZhdGUgZ2V0U2V0dGluZ3MoKTogQXN0cm9Db21wb3NlclNldHRpbmdzIHtcclxuXHRcdC8vIEFsd2F5cyBwcmVmZXIgcGx1Z2luIHNldHRpbmdzICh0aGV5J3JlIGtlcHQgdXAgdG8gZGF0ZSlcclxuXHRcdGlmICh0aGlzLnBsdWdpbj8uc2V0dGluZ3MpIHtcclxuXHRcdFx0cmV0dXJuIHRoaXMucGx1Z2luLnNldHRpbmdzO1xyXG5cdFx0fVxyXG5cdFx0cmV0dXJuIHRoaXMuc2V0dGluZ3M7XHJcblx0fVxyXG5cclxuXHQvKipcclxuXHQgKiBDb252ZXJ0IGEgc3RyaW5nIHRvIGtlYmFiLWNhc2UgZm9yIHNsdWcgZ2VuZXJhdGlvblxyXG5cdCAqL1xyXG5cdHByaXZhdGUgdG9LZWJhYkNhc2Uoc3RyOiBzdHJpbmcpOiBzdHJpbmcge1xyXG5cdFx0cmV0dXJuIHN0clxyXG5cdFx0XHQudG9Mb3dlckNhc2UoKVxyXG5cdFx0XHQucmVwbGFjZSgvW15hLXowLTlcXHMtXS9nLCBcIlwiKVxyXG5cdFx0XHQudHJpbSgpXHJcblx0XHRcdC5yZXBsYWNlKC9cXHMrL2csIFwiLVwiKVxyXG5cdFx0XHQucmVwbGFjZSgvLSsvZywgXCItXCIpXHJcblx0XHRcdC5yZXBsYWNlKC9eLXwtJC9nLCBcIlwiKTtcclxuXHR9XHJcblxyXG5cdHBhcnNlRnJvbnRtYXR0ZXIoY29udGVudDogc3RyaW5nKTogUGFyc2VkRnJvbnRtYXR0ZXIge1xyXG5cdFx0bGV0IHByb3BlcnRpZXNFbmQgPSAwO1xyXG5cdFx0bGV0IHByb3BlcnRpZXNUZXh0ID0gXCJcIjtcclxuXHRcdGNvbnN0IGV4aXN0aW5nUHJvcGVydGllczogUmVjb3JkPHN0cmluZywgc3RyaW5nW10+ID0ge307XHJcblxyXG5cdFx0Ly8gUGFyc2UgZXhpc3RpbmcgcHJvcGVydGllcyB3aXRoIGZhbGxiYWNrIGZvciBtaXNzaW5nIHNlY29uZCAtLS1cclxuXHRcdGlmIChjb250ZW50LnN0YXJ0c1dpdGgoXCItLS1cIikpIHtcclxuXHRcdFx0cHJvcGVydGllc0VuZCA9IGNvbnRlbnQuaW5kZXhPZihcIlxcbi0tLVwiLCAzKTtcclxuXHRcdFx0aWYgKHByb3BlcnRpZXNFbmQgPT09IC0xKSB7XHJcblx0XHRcdFx0cHJvcGVydGllc0VuZCA9IGNvbnRlbnQubGVuZ3RoOyAvLyBUcmVhdCBlbnRpcmUgY29udGVudCBhcyBwcm9wZXJ0aWVzIGlmIG5vIHNlY29uZCAtLS1cclxuXHRcdFx0fSBlbHNlIHtcclxuXHRcdFx0XHRwcm9wZXJ0aWVzRW5kICs9IDQ7IC8vIE1vdmUgcGFzdCB0aGUgc2Vjb25kIC0tLVxyXG5cdFx0XHR9XHJcblx0XHRcdHByb3BlcnRpZXNUZXh0ID0gY29udGVudC5zbGljZSg0LCBwcm9wZXJ0aWVzRW5kIC0gNCkudHJpbSgpO1xyXG5cclxuXHRcdFx0dHJ5IHtcclxuXHRcdFx0XHRsZXQgY3VycmVudEtleTogc3RyaW5nIHwgbnVsbCA9IG51bGw7XHJcblx0XHRcdFx0Y29uc3QgYXJyYXlLZXlzID0gbmV3IFNldDxzdHJpbmc+KCk7IC8vIFRyYWNrIHdoaWNoIGtleXMgYXJlIGFycmF5c1xyXG5cclxuXHRcdFx0XHRwcm9wZXJ0aWVzVGV4dC5zcGxpdChcIlxcblwiKS5mb3JFYWNoKChsaW5lKSA9PiB7XHJcblx0XHRcdFx0XHRjb25zdCB0cmltbWVkTGluZSA9IGxpbmUudHJpbSgpO1xyXG5cclxuXHRcdFx0XHRcdC8vIE1hdGNoIHByb3BlcnR5IGxpbmVzIC0gbW9yZSBmbGV4aWJsZSByZWdleCB0byBoYW5kbGUgdmFyaW91cyBwcm9wZXJ0eSBuYW1lc1xyXG5cdFx0XHRcdFx0Y29uc3QgbWF0Y2ggPSB0cmltbWVkTGluZS5tYXRjaCgvXihbYS16QS1aX11bYS16QS1aMC05Xy1dKik6XFxzKiguKikkLyk7XHJcblx0XHRcdFx0XHRpZiAobWF0Y2gpIHtcclxuXHRcdFx0XHRcdFx0Y29uc3QgWywga2V5LCB2YWx1ZV0gPSBtYXRjaDtcclxuXHRcdFx0XHRcdFx0Y3VycmVudEtleSA9IGtleTtcclxuXHRcdFx0XHRcdFx0Y29uc3QgdHJpbW1lZFZhbHVlID0gdmFsdWUgPyB2YWx1ZS50cmltKCkgOiBcIlwiO1xyXG5cclxuXHRcdFx0XHRcdFx0Ly8gQ2hlY2sgZm9yIGJyYWNrZXQtc3ludGF4IGFycmF5czogW2l0ZW1dIG9yIFtcIml0ZW0xXCIsIFwiaXRlbTJcIl0gb3IgW2l0ZW0xLCBpdGVtMl1cclxuXHRcdFx0XHRcdFx0Y29uc3QgYnJhY2tldEFycmF5TWF0Y2ggPSB0cmltbWVkVmFsdWUubWF0Y2goL15cXFsoLiopXFxdJC8pO1xyXG5cdFx0XHRcdFx0XHRpZiAoYnJhY2tldEFycmF5TWF0Y2gpIHtcclxuXHRcdFx0XHRcdFx0XHQvLyBUaGlzIGlzIGEgYnJhY2tldC1mb3JtYXQgYXJyYXlcclxuXHRcdFx0XHRcdFx0XHRjb25zdCBhcnJheUNvbnRlbnQgPSBicmFja2V0QXJyYXlNYXRjaFsxXS50cmltKCk7XHJcblx0XHRcdFx0XHRcdFx0ZXhpc3RpbmdQcm9wZXJ0aWVzW2tleV0gPSBbXTtcclxuXHRcdFx0XHRcdFx0XHRhcnJheUtleXMuYWRkKGtleSk7IC8vIE1hcmsgdGhpcyBrZXkgYXMgYW4gYXJyYXlcclxuXHJcblx0XHRcdFx0XHRcdFx0aWYgKGFycmF5Q29udGVudCkge1xyXG5cdFx0XHRcdFx0XHRcdFx0Ly8gUGFyc2UgYXJyYXkgaXRlbXMgLSBoYW5kbGUgYm90aCBxdW90ZWQgYW5kIHVucXVvdGVkIHZhbHVlc1xyXG5cdFx0XHRcdFx0XHRcdFx0Ly8gU3BsaXQgYnkgY29tbWEsIGJ1dCByZXNwZWN0IHF1b3Rlc1xyXG5cdFx0XHRcdFx0XHRcdFx0Y29uc3QgaXRlbXM6IHN0cmluZ1tdID0gW107XHJcblx0XHRcdFx0XHRcdFx0XHRsZXQgY3VycmVudEl0ZW0gPSBcIlwiO1xyXG5cdFx0XHRcdFx0XHRcdFx0bGV0IGluUXVvdGVzID0gZmFsc2U7XHJcblx0XHRcdFx0XHRcdFx0XHRsZXQgcXVvdGVDaGFyID0gJyc7XHJcblxyXG5cdFx0XHRcdFx0XHRcdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBhcnJheUNvbnRlbnQubGVuZ3RoOyBpKyspIHtcclxuXHRcdFx0XHRcdFx0XHRcdFx0Y29uc3QgY2hhciA9IGFycmF5Q29udGVudFtpXTtcclxuXHJcblx0XHRcdFx0XHRcdFx0XHRcdGlmICghaW5RdW90ZXMgJiYgKGNoYXIgPT09ICdcIicgfHwgY2hhciA9PT0gXCInXCIpKSB7XHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0aW5RdW90ZXMgPSB0cnVlO1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdHF1b3RlQ2hhciA9IGNoYXI7XHJcblx0XHRcdFx0XHRcdFx0XHRcdH0gZWxzZSBpZiAoaW5RdW90ZXMgJiYgY2hhciA9PT0gcXVvdGVDaGFyKSB7XHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0Ly8gQ2hlY2sgaWYgaXQncyBlc2NhcGVkXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0aWYgKGkgPiAwICYmIGFycmF5Q29udGVudFtpIC0gMV0gPT09ICdcXFxcJykge1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0Y3VycmVudEl0ZW0gKz0gY2hhcjtcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHR9IGVsc2Uge1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0aW5RdW90ZXMgPSBmYWxzZTtcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdHF1b3RlQ2hhciA9ICcnO1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0XHRcdFx0fSBlbHNlIGlmICghaW5RdW90ZXMgJiYgY2hhciA9PT0gJywnKSB7XHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0Ly8gRW5kIG9mIGN1cnJlbnQgaXRlbVxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdGNvbnN0IHRyaW1tZWRJdGVtID0gY3VycmVudEl0ZW0udHJpbSgpO1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdGlmICh0cmltbWVkSXRlbSkge1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0Ly8gUmVtb3ZlIHN1cnJvdW5kaW5nIHF1b3RlcyBpZiBwcmVzZW50XHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRjb25zdCB1bnF1b3RlZCA9IHRyaW1tZWRJdGVtLnJlcGxhY2UoL15bXCInXXxbXCInXSQvZywgJycpO1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0aXRlbXMucHVzaCh1bnF1b3RlZCk7XHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdGN1cnJlbnRJdGVtID0gXCJcIjtcclxuXHRcdFx0XHRcdFx0XHRcdFx0fSBlbHNlIHtcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRjdXJyZW50SXRlbSArPSBjaGFyO1xyXG5cdFx0XHRcdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdFx0XHR9XHJcblxyXG5cdFx0XHRcdFx0XHRcdFx0Ly8gQWRkIHRoZSBsYXN0IGl0ZW1cclxuXHRcdFx0XHRcdFx0XHRcdGlmIChjdXJyZW50SXRlbS50cmltKCkpIHtcclxuXHRcdFx0XHRcdFx0XHRcdFx0Y29uc3QgdHJpbW1lZEl0ZW0gPSBjdXJyZW50SXRlbS50cmltKCk7XHJcblx0XHRcdFx0XHRcdFx0XHRcdGNvbnN0IHVucXVvdGVkID0gdHJpbW1lZEl0ZW0ucmVwbGFjZSgvXltcIiddfFtcIiddJC9nLCAnJyk7XHJcblx0XHRcdFx0XHRcdFx0XHRcdGl0ZW1zLnB1c2godW5xdW90ZWQpO1xyXG5cdFx0XHRcdFx0XHRcdFx0fVxyXG5cclxuXHRcdFx0XHRcdFx0XHRcdGV4aXN0aW5nUHJvcGVydGllc1trZXldID0gaXRlbXM7XHJcblx0XHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHR9IGVsc2Uge1xyXG5cdFx0XHRcdFx0XHRcdC8vIE5vdCBhIGJyYWNrZXQgYXJyYXksIGNoZWNrIGZvciBvdGhlciBhcnJheSBmb3JtYXRzXHJcblx0XHRcdFx0XHRcdFx0Y29uc3QgaXNLbm93bkFycmF5S2V5ID0gS05PV05fQVJSQVlfS0VZUy5pbmNsdWRlcyhrZXkgYXMgdHlwZW9mIEtOT1dOX0FSUkFZX0tFWVNbbnVtYmVyXSk7XHJcblx0XHRcdFx0XHRcdFx0Y29uc3QgaXNFbXB0eUFycmF5ID0gIXRyaW1tZWRWYWx1ZSB8fCB0cmltbWVkVmFsdWUgPT09IFwiXCI7XHJcblx0XHRcdFx0XHRcdFx0Y29uc3QgaXNBcnJheVByb3BlcnR5ID0gaXNLbm93bkFycmF5S2V5IHx8IGlzRW1wdHlBcnJheTtcclxuXHJcblx0XHRcdFx0XHRcdFx0aWYgKGlzQXJyYXlQcm9wZXJ0eSkge1xyXG5cdFx0XHRcdFx0XHRcdFx0ZXhpc3RpbmdQcm9wZXJ0aWVzW2tleV0gPSBbXTtcclxuXHRcdFx0XHRcdFx0XHRcdGFycmF5S2V5cy5hZGQoa2V5KTsgLy8gTWFyayB0aGlzIGtleSBhcyBhbiBhcnJheVxyXG5cdFx0XHRcdFx0XHRcdH0gZWxzZSB7XHJcblx0XHRcdFx0XHRcdFx0XHQvLyBTdHJpcCBzdXJyb3VuZGluZyBxdW90ZXMgZnJvbSBzdHJpbmcgdmFsdWVzXHJcblx0XHRcdFx0XHRcdFx0XHRjb25zdCB1bnF1b3RlZFZhbHVlID0gdHJpbW1lZFZhbHVlLnJlcGxhY2UoL15bXCInXXxbXCInXSQvZywgJycpO1xyXG5cdFx0XHRcdFx0XHRcdFx0ZXhpc3RpbmdQcm9wZXJ0aWVzW2tleV0gPSBbdW5xdW90ZWRWYWx1ZV07XHJcblx0XHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHR9IGVsc2UgaWYgKGN1cnJlbnRLZXkgJiYgdHJpbW1lZExpbmUuc3RhcnRzV2l0aChcIi0gXCIpKSB7XHJcblx0XHRcdFx0XHRcdC8vIENoZWNrIGlmIGN1cnJlbnQga2V5IGlzIGFuIGFycmF5IHByb3BlcnR5XHJcblx0XHRcdFx0XHRcdGNvbnN0IGlzQXJyYXlQcm9wZXJ0eSA9IGFycmF5S2V5cy5oYXMoY3VycmVudEtleSk7XHJcblxyXG5cdFx0XHRcdFx0XHRpZiAoaXNBcnJheVByb3BlcnR5KSB7XHJcblx0XHRcdFx0XHRcdFx0Y29uc3QgaXRlbSA9IHRyaW1tZWRMaW5lLnJlcGxhY2UoL14tXFxzKi8sIFwiXCIpO1xyXG5cdFx0XHRcdFx0XHRcdGlmIChpdGVtKSBleGlzdGluZ1Byb3BlcnRpZXNbY3VycmVudEtleV0ucHVzaChpdGVtKTtcclxuXHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0fSBlbHNlIGlmICh0cmltbWVkTGluZSAmJiAhdHJpbW1lZExpbmUuc3RhcnRzV2l0aChcIi0gXCIpICYmICF0cmltbWVkTGluZS5zdGFydHNXaXRoKFwiI1wiKSkge1xyXG5cdFx0XHRcdFx0XHQvLyBIYW5kbGUgdW5yZWNvZ25pemVkIHByb3BlcnRpZXMgdGhhdCBkb24ndCBtYXRjaCB0aGUgc3RhbmRhcmQgZm9ybWF0XHJcblx0XHRcdFx0XHRcdC8vIFRoaXMgaXMgYSBmYWxsYmFjayB0byBwcmVzZXJ2ZSBwcm9wZXJ0aWVzIHRoYXQgbWlnaHQgaGF2ZSBzcGVjaWFsIGZvcm1hdHRpbmdcclxuXHRcdFx0XHRcdFx0Y29uc3Qga2V5TWF0Y2ggPSB0cmltbWVkTGluZS5tYXRjaCgvXihbXjpdKyk6XFxzKiguKikkLyk7XHJcblx0XHRcdFx0XHRcdGlmIChrZXlNYXRjaCkge1xyXG5cdFx0XHRcdFx0XHRcdGNvbnN0IFssIGtleSwgdmFsdWVdID0ga2V5TWF0Y2g7XHJcblx0XHRcdFx0XHRcdFx0aWYgKCFleGlzdGluZ1Byb3BlcnRpZXNba2V5XSkge1xyXG5cdFx0XHRcdFx0XHRcdFx0ZXhpc3RpbmdQcm9wZXJ0aWVzW2tleV0gPSBbdmFsdWUgPyB2YWx1ZS50cmltKCkgOiBcIlwiXTtcclxuXHRcdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHR9KTtcclxuXHRcdFx0XHQvLyBQcmVzZXJ2ZSBhcnJheSBrZXlzIGlmIHRoZXkgZXhpc3Qgd2l0aG91dCB2YWx1ZXNcclxuXHRcdFx0XHRLTk9XTl9BUlJBWV9LRVlTLmZvckVhY2goa2V5ID0+IHtcclxuXHRcdFx0XHRcdGlmIChwcm9wZXJ0aWVzVGV4dC5pbmNsdWRlcyhrZXkgKyAnOicpICYmICFleGlzdGluZ1Byb3BlcnRpZXNba2V5XSkge1xyXG5cdFx0XHRcdFx0XHRleGlzdGluZ1Byb3BlcnRpZXNba2V5XSA9IFtdO1xyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdH0pO1xyXG5cdFx0XHR9IGNhdGNoIHtcclxuXHRcdFx0XHQvLyBGYWxsYmFjayB0byB0ZW1wbGF0ZSBpZiBwYXJzaW5nIGZhaWxzXHJcblx0XHRcdFx0bmV3IE5vdGljZShcIkZhbGxpbmcgYmFjayB0byB0ZW1wbGF0ZSBkdWUgdG8gcGFyc2luZyBlcnJvci5cIik7XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHJcblx0XHRjb25zdCBib2R5Q29udGVudCA9IGNvbnRlbnQuc2xpY2UocHJvcGVydGllc0VuZCk7XHJcblx0XHRyZXR1cm4ge1xyXG5cdFx0XHRwcm9wZXJ0aWVzOiBleGlzdGluZ1Byb3BlcnRpZXMsXHJcblx0XHRcdHByb3BlcnRpZXNUZXh0LFxyXG5cdFx0XHRwcm9wZXJ0aWVzRW5kLFxyXG5cdFx0XHRib2R5Q29udGVudFxyXG5cdFx0fTtcclxuXHR9XHJcblxyXG5cdHBhcnNlVGVtcGxhdGUodGVtcGxhdGVTdHJpbmc6IHN0cmluZywgdGl0bGU6IHN0cmluZyk6IHsgdGVtcGxhdGVQcm9wczogc3RyaW5nW107IHRlbXBsYXRlVmFsdWVzOiBUZW1wbGF0ZVZhbHVlcyB9IHtcclxuXHRcdGNvbnN0IHRlbXBsYXRlTGluZXMgPSB0ZW1wbGF0ZVN0cmluZy5zcGxpdChcIlxcblwiKTtcclxuXHRcdGNvbnN0IHRlbXBsYXRlUHJvcHM6IHN0cmluZ1tdID0gW107XHJcblx0XHRjb25zdCB0ZW1wbGF0ZVZhbHVlczogVGVtcGxhdGVWYWx1ZXMgPSB7fTtcclxuXHRcdGxldCBpblByb3BlcnRpZXMgPSBmYWxzZTtcclxuXHJcblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IHRlbXBsYXRlTGluZXMubGVuZ3RoOyBpKyspIHtcclxuXHRcdFx0Y29uc3QgbGluZSA9IHRlbXBsYXRlTGluZXNbaV0udHJpbSgpO1xyXG5cdFx0XHRpZiAobGluZSA9PT0gXCItLS1cIikge1xyXG5cdFx0XHRcdGluUHJvcGVydGllcyA9ICFpblByb3BlcnRpZXM7XHJcblx0XHRcdFx0aWYgKCFpblByb3BlcnRpZXMpIHtcclxuXHRcdFx0XHRcdGJyZWFrOyAvLyBTdG9wIGF0IHNlY29uZCAtLS0gdG8gZXhjbHVkZSBwb3N0LXByb3BlcnR5IGNvbnRlbnRcclxuXHRcdFx0XHR9XHJcblx0XHRcdFx0Y29udGludWU7XHJcblx0XHRcdH1cclxuXHRcdFx0aWYgKGluUHJvcGVydGllcykge1xyXG5cdFx0XHRcdGNvbnN0IG1hdGNoID0gbGluZS5tYXRjaCgvXihcXHcrKTpcXHMqKC4qKSQvKTtcclxuXHRcdFx0XHRpZiAobWF0Y2gpIHtcclxuXHRcdFx0XHRcdGNvbnN0IFssIGtleSwgdmFsdWVdID0gbWF0Y2g7XHJcblx0XHRcdFx0XHR0ZW1wbGF0ZVByb3BzLnB1c2goa2V5KTtcclxuXHJcblx0XHRcdFx0XHQvLyBDaGVjayBpZiB0aGlzIGlzIGFuIGFycmF5IHByb3BlcnR5IChrbm93biBhcnJheSBrZXlzIG9yIFlBTUwgbGlzdCBmb3JtYXQpXHJcblx0XHRcdFx0XHRjb25zdCBpc0tub3duQXJyYXlLZXkgPSBLTk9XTl9BUlJBWV9LRVlTLmluY2x1ZGVzKGtleSBhcyB0eXBlb2YgS05PV05fQVJSQVlfS0VZU1tudW1iZXJdKTtcclxuXHRcdFx0XHRcdC8vIENoZWNrIGlmIGl0J3MgYSBZQU1MIGxpc3QgZm9ybWF0IChubyB2YWx1ZSBhZnRlciBjb2xvbiwgZW1wdHkgYnJhY2tldHMsIG9yIGVtcHR5IHZhbHVlIG1lYW5zIGl0J3MgYW4gYXJyYXkpXHJcblx0XHRcdFx0XHRjb25zdCBpc0VtcHR5QXJyYXkgPSAhdmFsdWUgfHwgdmFsdWUudHJpbSgpID09PSBcIlwiIHx8IHZhbHVlLnRyaW0oKSA9PT0gXCJbXVwiO1xyXG5cdFx0XHRcdFx0Y29uc3QgaXNBcnJheVByb3BlcnR5ID0gaXNLbm93bkFycmF5S2V5IHx8IGlzRW1wdHlBcnJheTtcclxuXHJcblx0XHRcdFx0XHRpZiAoaXNBcnJheVByb3BlcnR5KSB7XHJcblx0XHRcdFx0XHRcdC8vIEhhbmRsZSBhcnJheSBwcm9wZXJ0aWVzXHJcblx0XHRcdFx0XHRcdGlmICh2YWx1ZSAmJiB2YWx1ZS5zdGFydHNXaXRoKFwiW1wiKSkge1xyXG5cdFx0XHRcdFx0XHRcdC8vIEhhbmRsZSBicmFja2V0IGZvcm1hdDogW1wiaXRlbTFcIiwgXCJpdGVtMlwiXVxyXG5cdFx0XHRcdFx0XHRcdGNvbnN0IGl0ZW1zID0gdmFsdWVcclxuXHRcdFx0XHRcdFx0XHRcdC5yZXBsYWNlKC9bW1xcXV0vZywgXCJcIilcclxuXHRcdFx0XHRcdFx0XHRcdC5zcGxpdChcIixcIilcclxuXHRcdFx0XHRcdFx0XHRcdC5tYXAodCA9PiB0LnRyaW0oKSlcclxuXHRcdFx0XHRcdFx0XHRcdC5maWx0ZXIodCA9PiB0KTtcclxuXHRcdFx0XHRcdFx0XHR0ZW1wbGF0ZVZhbHVlc1trZXldID0gaXRlbXM7XHJcblx0XHRcdFx0XHRcdH0gZWxzZSB7XHJcblx0XHRcdFx0XHRcdFx0Ly8gSGFuZGxlIFlBTUwgbGlzdCBmb3JtYXQ6IGVtcHR5IG9yIHdpdGggLSBpdGVtc1xyXG5cdFx0XHRcdFx0XHRcdHRlbXBsYXRlVmFsdWVzW2tleV0gPSBbXTtcclxuXHRcdFx0XHRcdFx0XHQvLyBMb29rIGFoZWFkIGZvciBpdGVtIGxpc3RcclxuXHRcdFx0XHRcdFx0XHRmb3IgKGxldCBqID0gaSArIDE7IGogPCB0ZW1wbGF0ZUxpbmVzLmxlbmd0aDsgaisrKSB7XHJcblx0XHRcdFx0XHRcdFx0XHRjb25zdCBuZXh0TGluZSA9IHRlbXBsYXRlTGluZXNbal0udHJpbSgpO1xyXG5cdFx0XHRcdFx0XHRcdFx0aWYgKG5leHRMaW5lLnN0YXJ0c1dpdGgoXCItIFwiKSkge1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRjb25zdCBpdGVtID0gbmV4dExpbmUucmVwbGFjZSgvXi1cXHMqLywgXCJcIikudHJpbSgpO1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRpZiAoaXRlbSkge1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdGNvbnN0IGFycmF5VmFsdWUgPSB0ZW1wbGF0ZVZhbHVlc1trZXldO1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdGlmIChBcnJheS5pc0FycmF5KGFycmF5VmFsdWUpKSB7XHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRhcnJheVZhbHVlLnB1c2goaXRlbSk7XHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdFx0XHR9IGVsc2UgaWYgKG5leHRMaW5lID09PSBcIi0tLVwiIHx8IChuZXh0TGluZSAmJiAhbmV4dExpbmUuc3RhcnRzV2l0aChcIi0gXCIpICYmIG5leHRMaW5lLmluY2x1ZGVzKFwiOlwiKSkpIHtcclxuXHRcdFx0XHRcdFx0XHRcdFx0Ly8gU3RvcCBhdCBuZXh0IHByb3BlcnR5IG9yIGVuZCBvZiBwcm9wZXJ0aWVzIHNlY3Rpb25cclxuXHRcdFx0XHRcdFx0XHRcdFx0YnJlYWs7XHJcblx0XHRcdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHR9IGVsc2Uge1xyXG5cdFx0XHRcdFx0XHQvLyBUaGlzIGlzIGEgc3RyaW5nIHByb3BlcnR5LCBub3QgYW4gYXJyYXlcclxuXHRcdFx0XHRcdFx0Y29uc3Qgc2x1ZyA9IHRoaXMudG9LZWJhYkNhc2UodGl0bGUpO1xyXG5cdFx0XHRcdFx0XHRjb25zdCBzZXR0aW5ncyA9IHRoaXMuZ2V0U2V0dGluZ3MoKTtcclxuXHRcdFx0XHRcdFx0Y29uc3Qgc3RyaW5nVmFsdWUgPSAodmFsdWUgfHwgXCJcIilcclxuXHRcdFx0XHRcdFx0XHQucmVwbGFjZSgvXFx7XFx7dGl0bGVcXH1cXH0vZywgdGl0bGUpXHJcblx0XHRcdFx0XHRcdFx0LnJlcGxhY2UoL1xce1xce2RhdGVcXH1cXH0vZywgd2luZG93Lm1vbWVudChuZXcgRGF0ZSgpKS5mb3JtYXQoc2V0dGluZ3MuZGF0ZUZvcm1hdCkpXHJcblx0XHRcdFx0XHRcdFx0LnJlcGxhY2UoL1xce1xce3NsdWdcXH1cXH0vZywgc2x1Zyk7XHJcblx0XHRcdFx0XHRcdC8vIFN0b3JlIGFzIGEgc2luZ2xlIHN0cmluZyB2YWx1ZSwgbm90IGluIGFuIGFycmF5XHJcblx0XHRcdFx0XHRcdHRlbXBsYXRlVmFsdWVzW2tleV0gPSBzdHJpbmdWYWx1ZTtcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHR9XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHJcblx0XHRyZXR1cm4geyB0ZW1wbGF0ZVByb3BzLCB0ZW1wbGF0ZVZhbHVlcyB9O1xyXG5cdH1cclxuXHJcblx0YnVpbGRGcm9udG1hdHRlckNvbnRlbnQoZmluYWxQcm9wczogUmVjb3JkPHN0cmluZywgc3RyaW5nW10+LCBhcnJheUtleXM/OiBTZXQ8c3RyaW5nPik6IHN0cmluZyB7XHJcblx0XHRsZXQgbmV3Q29udGVudCA9IFwiLS0tXFxuXCI7XHJcblx0XHRmb3IgKGNvbnN0IGtleSBpbiBmaW5hbFByb3BzKSB7XHJcblx0XHRcdC8vIENoZWNrIGlmIHRoaXMgaXMgYW4gYXJyYXkgcHJvcGVydHlcclxuXHRcdFx0Y29uc3QgaXNBcnJheVByb3BlcnR5ID0gS05PV05fQVJSQVlfS0VZUy5pbmNsdWRlcyhrZXkgYXMgdHlwZW9mIEtOT1dOX0FSUkFZX0tFWVNbbnVtYmVyXSkgfHxcclxuXHRcdFx0XHQoYXJyYXlLZXlzICYmIGFycmF5S2V5cy5oYXMoa2V5KSk7XHJcblxyXG5cdFx0XHRpZiAoaXNBcnJheVByb3BlcnR5KSB7XHJcblx0XHRcdFx0bmV3Q29udGVudCArPSBgJHtrZXl9OlxcbmA7XHJcblx0XHRcdFx0aWYgKGZpbmFsUHJvcHNba2V5XS5sZW5ndGggPiAwKSB7XHJcblx0XHRcdFx0XHRmaW5hbFByb3BzW2tleV0uZm9yRWFjaChpdGVtID0+IHtcclxuXHRcdFx0XHRcdFx0bmV3Q29udGVudCArPSBgICAtICR7aXRlbX1cXG5gO1xyXG5cdFx0XHRcdFx0fSk7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9IGVsc2Uge1xyXG5cdFx0XHRcdG5ld0NvbnRlbnQgKz0gYCR7a2V5fTogJHtmaW5hbFByb3BzW2tleV1bMF0gfHwgXCJcIn1cXG5gO1xyXG5cdFx0XHR9XHJcblx0XHR9XHJcblx0XHRuZXdDb250ZW50ICs9IFwiLS0tXCI7XHJcblx0XHRyZXR1cm4gbmV3Q29udGVudDtcclxuXHR9XHJcblxyXG5cdGFzeW5jIHVwZGF0ZVRpdGxlSW5Gcm9udG1hdHRlcihmaWxlOiBURmlsZSwgbmV3VGl0bGU6IHN0cmluZywgdHlwZTogQ29udGVudFR5cGVJZCk6IFByb21pc2U8dm9pZD4ge1xyXG5cdFx0Ly8gQ2hlY2sgaWYgdGVtcGxhdGUgaGFzIHt7dGl0bGV9fSAtIGlmIG5vdCwgZG9uJ3QgdXBkYXRlIGZyb250bWF0dGVyIGF0IGFsbFxyXG5cdFx0Y29uc3QgdGl0bGVLZXkgPSB0aGlzLmdldFRpdGxlS2V5KHR5cGUpO1xyXG5cdFx0Y29uc3QgaGFzVGl0bGVJblRlbXBsYXRlID0gdGhpcy50ZW1wbGF0ZUhhc1RpdGxlKHR5cGUpO1xyXG5cclxuXHRcdC8vIElmIHRlbXBsYXRlIGRvZXNuJ3QgaGF2ZSB7e3RpdGxlfX0sIGRvbid0IG1vZGlmeSBmcm9udG1hdHRlclxyXG5cdFx0aWYgKCFoYXNUaXRsZUluVGVtcGxhdGUpIHtcclxuXHRcdFx0cmV0dXJuO1xyXG5cdFx0fVxyXG5cclxuXHRcdGNvbnN0IGNvbnRlbnQgPSBhd2FpdCB0aGlzLmFwcC52YXVsdC5yZWFkKGZpbGUpO1xyXG5cdFx0bGV0IHByb3BlcnRpZXNFbmQgPSAwO1xyXG5cdFx0bGV0IHByb3BlcnRpZXNUZXh0ID0gXCJcIjtcclxuXHRcdGxldCBoYXNGcm9udG1hdHRlciA9IGZhbHNlO1xyXG5cclxuXHRcdGlmIChjb250ZW50LnN0YXJ0c1dpdGgoXCItLS1cIikpIHtcclxuXHRcdFx0aGFzRnJvbnRtYXR0ZXIgPSB0cnVlO1xyXG5cdFx0XHRwcm9wZXJ0aWVzRW5kID0gY29udGVudC5pbmRleE9mKFwiXFxuLS0tXCIsIDMpO1xyXG5cdFx0XHRpZiAocHJvcGVydGllc0VuZCA9PT0gLTEpIHtcclxuXHRcdFx0XHRwcm9wZXJ0aWVzRW5kID0gY29udGVudC5sZW5ndGg7XHJcblx0XHRcdH0gZWxzZSB7XHJcblx0XHRcdFx0cHJvcGVydGllc0VuZCArPSA0O1xyXG5cdFx0XHR9XHJcblx0XHRcdHByb3BlcnRpZXNUZXh0ID0gY29udGVudC5zbGljZSg0LCBwcm9wZXJ0aWVzRW5kIC0gNCkudHJpbSgpO1xyXG5cdFx0fVxyXG5cclxuXHRcdGNvbnN0IHByb3BPcmRlcjogc3RyaW5nW10gPSBbXTtcclxuXHRcdGNvbnN0IGV4aXN0aW5nOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmcgfCBzdHJpbmdbXT4gPSB7fTtcclxuXHRcdGxldCBjdXJyZW50S2V5OiBzdHJpbmcgfCBudWxsID0gbnVsbDtcclxuXHRcdGxldCB0aXRsZUtleVBvc2l0aW9uID0gLTE7IC8vIFRyYWNrIHRoZSBvcmlnaW5hbCBwb3NpdGlvbiBvZiB0aGUgdGl0bGUga2V5XHJcblxyXG5cdFx0Y29uc3QgYXJyYXlLZXlzID0gbmV3IFNldDxzdHJpbmc+KCk7IC8vIFRyYWNrIHdoaWNoIGtleXMgYXJlIGFycmF5c1xyXG5cclxuXHRcdHByb3BlcnRpZXNUZXh0LnNwbGl0KFwiXFxuXCIpLmZvckVhY2goKGxpbmUsIGluZGV4KSA9PiB7XHJcblx0XHRcdGNvbnN0IHRyaW1tZWRMaW5lID0gbGluZS50cmltKCk7XHJcblxyXG5cdFx0XHQvLyBNYXRjaCBwcm9wZXJ0eSBsaW5lcyAtIG1vcmUgZmxleGlibGUgcmVnZXggdG8gaGFuZGxlIHZhcmlvdXMgcHJvcGVydHkgbmFtZXNcclxuXHRcdFx0Y29uc3QgbWF0Y2ggPSB0cmltbWVkTGluZS5tYXRjaCgvXihbYS16QS1aX11bYS16QS1aMC05Xy1dKik6XFxzKiguKikkLyk7XHJcblx0XHRcdGlmIChtYXRjaCkge1xyXG5cdFx0XHRcdGNvbnN0IFssIGtleSwgdmFsdWVdID0gbWF0Y2g7XHJcblx0XHRcdFx0cHJvcE9yZGVyLnB1c2goa2V5KTtcclxuXHRcdFx0XHRjdXJyZW50S2V5ID0ga2V5O1xyXG5cclxuXHRcdFx0XHQvLyBUcmFjayB0aGUgb3JpZ2luYWwgcG9zaXRpb24gb2YgdGhlIHRpdGxlIGtleVxyXG5cdFx0XHRcdGlmIChrZXkgPT09IHRpdGxlS2V5KSB7XHJcblx0XHRcdFx0XHR0aXRsZUtleVBvc2l0aW9uID0gaW5kZXg7XHJcblx0XHRcdFx0fVxyXG5cclxuXHRcdFx0XHRjb25zdCBpc0tub3duQXJyYXlLZXkgPSBLTk9XTl9BUlJBWV9LRVlTLmluY2x1ZGVzKGtleSBhcyB0eXBlb2YgS05PV05fQVJSQVlfS0VZU1tudW1iZXJdKTtcclxuXHRcdFx0XHRjb25zdCBpc0VtcHR5QXJyYXkgPSAhdmFsdWUgfHwgdmFsdWUudHJpbSgpID09PSBcIlwiIHx8IHZhbHVlLnRyaW0oKSA9PT0gXCJbXVwiO1xyXG5cdFx0XHRcdGNvbnN0IGlzQXJyYXlQcm9wZXJ0eSA9IGlzS25vd25BcnJheUtleSB8fCBpc0VtcHR5QXJyYXk7XHJcblxyXG5cdFx0XHRcdGlmIChpc0FycmF5UHJvcGVydHkpIHtcclxuXHRcdFx0XHRcdGV4aXN0aW5nW2tleV0gPSBbXTtcclxuXHRcdFx0XHRcdGFycmF5S2V5cy5hZGQoa2V5KTsgLy8gTWFyayB0aGlzIGtleSBhcyBhbiBhcnJheVxyXG5cdFx0XHRcdH0gZWxzZSB7XHJcblx0XHRcdFx0XHRleGlzdGluZ1trZXldID0gdmFsdWUgPyB2YWx1ZS50cmltKCkgOiBcIlwiO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0fSBlbHNlIGlmIChjdXJyZW50S2V5ICYmIGFycmF5S2V5cy5oYXMoY3VycmVudEtleSkgJiYgdHJpbW1lZExpbmUuc3RhcnRzV2l0aChcIi0gXCIpKSB7XHJcblx0XHRcdFx0Ly8gSGFuZGxlIGFycmF5IGl0ZW1zXHJcblx0XHRcdFx0Y29uc3QgaXRlbSA9IHRyaW1tZWRMaW5lLnJlcGxhY2UoL14tXFxzKi8sIFwiXCIpO1xyXG5cdFx0XHRcdGlmIChpdGVtKSAoZXhpc3RpbmdbY3VycmVudEtleV0gYXMgc3RyaW5nW10pLnB1c2goaXRlbSk7XHJcblx0XHRcdH0gZWxzZSBpZiAodHJpbW1lZExpbmUgJiYgIXRyaW1tZWRMaW5lLnN0YXJ0c1dpdGgoXCItIFwiKSAmJiAhdHJpbW1lZExpbmUuc3RhcnRzV2l0aChcIiNcIikpIHtcclxuXHRcdFx0XHQvLyBIYW5kbGUgdW5yZWNvZ25pemVkIHByb3BlcnRpZXMgdGhhdCBkb24ndCBtYXRjaCB0aGUgc3RhbmRhcmQgZm9ybWF0XHJcblx0XHRcdFx0Ly8gVGhpcyBpcyBhIGZhbGxiYWNrIHRvIHByZXNlcnZlIHByb3BlcnRpZXMgdGhhdCBtaWdodCBoYXZlIHNwZWNpYWwgZm9ybWF0dGluZ1xyXG5cdFx0XHRcdGNvbnN0IGtleU1hdGNoID0gdHJpbW1lZExpbmUubWF0Y2goL14oW146XSspOlxccyooLiopJC8pO1xyXG5cdFx0XHRcdGlmIChrZXlNYXRjaCkge1xyXG5cdFx0XHRcdFx0Y29uc3QgWywga2V5LCB2YWx1ZV0gPSBrZXlNYXRjaDtcclxuXHRcdFx0XHRcdGlmICghcHJvcE9yZGVyLmluY2x1ZGVzKGtleSkpIHtcclxuXHRcdFx0XHRcdFx0cHJvcE9yZGVyLnB1c2goa2V5KTtcclxuXHRcdFx0XHRcdFx0ZXhpc3Rpbmdba2V5XSA9IHZhbHVlID8gdmFsdWUudHJpbSgpIDogXCJcIjtcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHR9XHJcblx0XHRcdH1cclxuXHRcdH0pO1xyXG5cclxuXHRcdC8vIFByb3Blcmx5IGVzY2FwZSBZQU1MIHN0cmluZyB2YWx1ZXNcclxuXHRcdC8vIFlBTUwgc3RyaW5ncyB3aXRoIHF1b3RlcyBuZWVkIHRvIGJlIHdyYXBwZWQgaW4gc2luZ2xlIHF1b3RlcyBvciBlc2NhcGVkIHByb3Blcmx5XHJcblx0XHRsZXQgdGl0bGVWYWw6IHN0cmluZztcclxuXHRcdGlmIChuZXdUaXRsZS5pbmNsdWRlcygnXCInKSB8fCBuZXdUaXRsZS5pbmNsdWRlcyhcIidcIikgfHwgbmV3VGl0bGUuaW5jbHVkZXMoJ1xcbicpIHx8IG5ld1RpdGxlLmluY2x1ZGVzKCdcXFxcJykpIHtcclxuXHRcdFx0Ly8gRm9yIHN0cmluZ3Mgd2l0aCBxdW90ZXMsIG5ld2xpbmVzLCBvciBiYWNrc2xhc2hlcywgdXNlIHNpbmdsZSBxdW90ZXMgYW5kIGVzY2FwZSBzaW5nbGUgcXVvdGVzXHJcblx0XHRcdHRpdGxlVmFsID0gYCcke25ld1RpdGxlLnJlcGxhY2UoLycvZywgXCInJ1wiKX0nYDtcclxuXHRcdH0gZWxzZSBpZiAobmV3VGl0bGUuaW5jbHVkZXMoXCIgXCIpIHx8IG5ld1RpdGxlLmluY2x1ZGVzKFwiOlwiKSB8fCBuZXdUaXRsZS5pbmNsdWRlcyhcIiNcIikgfHwgbmV3VGl0bGUuaW5jbHVkZXMoXCJAXCIpKSB7XHJcblx0XHRcdC8vIEZvciBzdHJpbmdzIHdpdGggc3BhY2VzIG9yIHNwZWNpYWwgWUFNTCBjaGFyYWN0ZXJzLCB3cmFwIGluIGRvdWJsZSBxdW90ZXMgYW5kIGVzY2FwZSBkb3VibGUgcXVvdGVzXHJcblx0XHRcdHRpdGxlVmFsID0gYFwiJHtuZXdUaXRsZS5yZXBsYWNlKC9cIi9nLCAnXFxcXFwiJyl9XCJgO1xyXG5cdFx0fSBlbHNlIHtcclxuXHRcdFx0Ly8gRm9yIHNpbXBsZSBzdHJpbmdzLCBubyBxdW90ZXMgbmVlZGVkXHJcblx0XHRcdHRpdGxlVmFsID0gbmV3VGl0bGU7XHJcblx0XHR9XHJcblx0XHRleGlzdGluZ1t0aXRsZUtleV0gPSB0aXRsZVZhbDtcclxuXHJcblx0XHQvLyBBbHNvIHVwZGF0ZSBzbHVnIGlmIGl0IGV4aXN0cyBpbiBmcm9udG1hdHRlclxyXG5cdFx0aWYgKFwic2x1Z1wiIGluIGV4aXN0aW5nKSB7XHJcblx0XHRcdGNvbnN0IG5ld1NsdWcgPSB0aGlzLnRvS2ViYWJDYXNlKG5ld1RpdGxlKTtcclxuXHRcdFx0ZXhpc3RpbmdbXCJzbHVnXCJdID0gbmV3U2x1ZztcclxuXHRcdH1cclxuXHJcblx0XHQvLyBJZiB0aXRsZSBrZXkgd2FzIGZvdW5kIGluIG9yaWdpbmFsIHByb3BlcnRpZXMsIHByZXNlcnZlIGl0cyBwb3NpdGlvblxyXG5cdFx0Ly8gT3RoZXJ3aXNlLCBhZGQgaXQgYXQgdGhlIGVuZFxyXG5cdFx0aWYgKHRpdGxlS2V5UG9zaXRpb24gPT09IC0xKSB7XHJcblx0XHRcdC8vIFRpdGxlIGtleSBub3QgZm91bmQgaW4gb3JpZ2luYWwgcHJvcGVydGllcywgYWRkIGl0IGF0IHRoZSBlbmRcclxuXHRcdFx0cHJvcE9yZGVyLnB1c2godGl0bGVLZXkpO1xyXG5cdFx0fVxyXG5cdFx0Ly8gSWYgdGl0bGVLZXlQb3NpdGlvbiA+PSAwLCB0aGUgdGl0bGUga2V5IGlzIGFscmVhZHkgaW4gcHJvcE9yZGVyIGF0IHRoZSBjb3JyZWN0IHBvc2l0aW9uXHJcblxyXG5cdFx0Ly8gT25seSBjcmVhdGUvdXBkYXRlIGZyb250bWF0dGVyIGlmIGl0IGFscmVhZHkgZXhpc3RzXHJcblx0XHQvLyBEb24ndCBjcmVhdGUgZnJvbnRtYXR0ZXIgZnJvbSBzY3JhdGNoIGlmIGZpbGUgaGFkIG5vbmVcclxuXHRcdGlmICghaGFzRnJvbnRtYXR0ZXIpIHtcclxuXHRcdFx0Ly8gRmlsZSBoYWQgbm8gZnJvbnRtYXR0ZXIgLSBkb24ndCBjcmVhdGUgaXQsIGp1c3QgcmV0dXJuXHJcblx0XHRcdC8vIFRoZSByZW5hbWUgYWxyZWFkeSBoYXBwZW5lZCwgd2UganVzdCBkb24ndCB1cGRhdGUgZnJvbnRtYXR0ZXJcclxuXHRcdFx0cmV0dXJuO1xyXG5cdFx0fVxyXG5cclxuXHRcdC8vIEJ1aWxkIG5ldyBjb250ZW50IHdpdGggZnJvbnRtYXR0ZXJcclxuXHRcdGxldCBuZXdDb250ZW50ID0gXCItLS1cXG5cIjtcclxuXHRcdGZvciAoY29uc3Qga2V5IG9mIHByb3BPcmRlcikge1xyXG5cdFx0XHRjb25zdCB2YWwgPSBleGlzdGluZ1trZXldO1xyXG5cdFx0XHRpZiAoQXJyYXkuaXNBcnJheSh2YWwpKSB7XHJcblx0XHRcdFx0bmV3Q29udGVudCArPSBgJHtrZXl9OlxcbmA7XHJcblx0XHRcdFx0aWYgKHZhbC5sZW5ndGggPiAwKSB7XHJcblx0XHRcdFx0XHR2YWwuZm9yRWFjaCgoaXRlbTogc3RyaW5nKSA9PiB7XHJcblx0XHRcdFx0XHRcdG5ld0NvbnRlbnQgKz0gYCAgLSAke2l0ZW19XFxuYDtcclxuXHRcdFx0XHRcdH0pO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0fSBlbHNlIHtcclxuXHRcdFx0XHRuZXdDb250ZW50ICs9IGAke2tleX06ICR7dmFsIHx8IFwiXCJ9XFxuYDtcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cdFx0bmV3Q29udGVudCArPSBcIi0tLVxcblwiO1xyXG5cclxuXHRcdC8vIEdldCBib2R5IGNvbnRlbnQgKGZyb250bWF0dGVyIGFscmVhZHkgZXhpc3RlZCwgc28gd2Uga25vdyBwcm9wZXJ0aWVzRW5kIGlzIHNldClcclxuXHRcdGNvbnN0IGJvZHlDb250ZW50ID0gY29udGVudC5zbGljZShwcm9wZXJ0aWVzRW5kKTtcclxuXHRcdG5ld0NvbnRlbnQgKz0gYm9keUNvbnRlbnQ7XHJcblxyXG5cdFx0YXdhaXQgdGhpcy5hcHAudmF1bHQubW9kaWZ5KGZpbGUsIG5ld0NvbnRlbnQpO1xyXG5cdH1cclxuXHJcblx0cHJpdmF0ZSBnZXRUaXRsZUtleSh0eXBlOiBDb250ZW50VHlwZUlkKTogc3RyaW5nIHtcclxuXHRcdGlmICh0eXBlID09PSBcIm5vdGVcIikgcmV0dXJuIFwidGl0bGVcIjtcclxuXHJcblx0XHRjb25zdCBzZXR0aW5ncyA9IHRoaXMuZ2V0U2V0dGluZ3MoKTtcclxuXHRcdGNvbnN0IGNvbnRlbnRUeXBlcyA9IHNldHRpbmdzLmNvbnRlbnRUeXBlcyB8fCBbXTtcclxuXHRcdGNvbnN0IGNvbnRlbnRUeXBlID0gY29udGVudFR5cGVzLmZpbmQoY3QgPT4gY3QuaWQgPT09IHR5cGUpO1xyXG5cdFx0aWYgKCFjb250ZW50VHlwZSkgcmV0dXJuIFwidGl0bGVcIjtcclxuXHJcblx0XHRjb25zdCB0ZW1wbGF0ZSA9IGNvbnRlbnRUeXBlLnRlbXBsYXRlO1xyXG5cdFx0Y29uc3QgbGluZXMgPSB0ZW1wbGF0ZS5zcGxpdChcIlxcblwiKTtcclxuXHRcdGxldCBpblByb3BlcnRpZXMgPSBmYWxzZTtcclxuXHRcdGZvciAoY29uc3QgbGluZSBvZiBsaW5lcykge1xyXG5cdFx0XHRjb25zdCB0cmltbWVkID0gbGluZS50cmltKCk7XHJcblx0XHRcdGlmICh0cmltbWVkID09PSBcIi0tLVwiKSB7XHJcblx0XHRcdFx0aW5Qcm9wZXJ0aWVzID0gIWluUHJvcGVydGllcztcclxuXHRcdFx0XHRjb250aW51ZTtcclxuXHRcdFx0fVxyXG5cdFx0XHRpZiAoaW5Qcm9wZXJ0aWVzKSB7XHJcblx0XHRcdFx0Y29uc3QgbWF0Y2ggPSB0cmltbWVkLm1hdGNoKC9eKFxcdyspOlxccyooLispJC8pO1xyXG5cdFx0XHRcdGlmIChtYXRjaCkge1xyXG5cdFx0XHRcdFx0Y29uc3Qga2V5ID0gbWF0Y2hbMV07XHJcblx0XHRcdFx0XHRjb25zdCB2YWx1ZSA9IG1hdGNoWzJdO1xyXG5cdFx0XHRcdFx0aWYgKHZhbHVlLmluY2x1ZGVzKFwie3t0aXRsZX19XCIpKSB7XHJcblx0XHRcdFx0XHRcdHJldHVybiBrZXk7XHJcblx0XHRcdFx0XHR9XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblx0XHR9XHJcblx0XHRyZXR1cm4gXCJ0aXRsZVwiO1xyXG5cdH1cclxuXHJcblx0Ly8gQ2hlY2sgaWYgdGhlIHRlbXBsYXRlIGZvciB0aGlzIGNvbnRlbnQgdHlwZSBoYXMge3t0aXRsZX19XHJcblx0cHJpdmF0ZSB0ZW1wbGF0ZUhhc1RpdGxlKHR5cGU6IENvbnRlbnRUeXBlSWQpOiBib29sZWFuIHtcclxuXHRcdGlmICh0eXBlID09PSBcIm5vdGVcIikgcmV0dXJuIHRydWU7IC8vIE5vdGVzIGFsd2F5cyBoYXZlIHRpdGxlXHJcblxyXG5cdFx0Y29uc3Qgc2V0dGluZ3MgPSB0aGlzLmdldFNldHRpbmdzKCk7XHJcblx0XHRjb25zdCBjb250ZW50VHlwZXMgPSBzZXR0aW5ncy5jb250ZW50VHlwZXMgfHwgW107XHJcblx0XHRjb25zdCBjb250ZW50VHlwZSA9IGNvbnRlbnRUeXBlcy5maW5kKGN0ID0+IGN0LmlkID09PSB0eXBlKTtcclxuXHRcdGlmICghY29udGVudFR5cGUpIHJldHVybiB0cnVlOyAvLyBEZWZhdWx0IHRvIHRydWUgZm9yIHNhZmV0eVxyXG5cclxuXHRcdGNvbnN0IHRlbXBsYXRlID0gY29udGVudFR5cGUudGVtcGxhdGU7XHJcblx0XHRyZXR1cm4gdGVtcGxhdGUuaW5jbHVkZXMoXCJ7e3RpdGxlfX1cIik7XHJcblx0fVxyXG59XHJcbiIsICJpbXBvcnQgeyBFZGl0b3IsIFRGaWxlLCBOb3RpY2UgfSBmcm9tIFwib2JzaWRpYW5cIjtcbmltcG9ydCB7IEFzdHJvQ29tcG9zZXJTZXR0aW5ncyB9IGZyb20gXCIuLi90eXBlc1wiO1xuXG5pbXBvcnQgeyBtYXRjaGVzRm9sZGVyUGF0dGVybiwgc29ydEJ5UGF0dGVyblNwZWNpZmljaXR5IH0gZnJvbSBcIi4vcGF0aC1tYXRjaGluZ1wiO1xuaW1wb3J0IHsgdG9LZWJhYkNhc2UgfSBmcm9tIFwiLi9zdHJpbmctdXRpbHNcIjtcblxuZXhwb3J0IGNsYXNzIExpbmtDb252ZXJ0ZXIge1xuXHRjb25zdHJ1Y3Rvcihwcml2YXRlIHNldHRpbmdzOiBBc3Ryb0NvbXBvc2VyU2V0dGluZ3MsIHByaXZhdGUgcGx1Z2luPzogeyBzZXR0aW5ncz86IEFzdHJvQ29tcG9zZXJTZXR0aW5ncyB9KSB7IH1cblxuXHQvLyBHZXQgZnJlc2ggc2V0dGluZ3MgZnJvbSBwbHVnaW4gaWYgYXZhaWxhYmxlLCBvdGhlcndpc2UgdXNlIHN0b3JlZCBzZXR0aW5nc1xuXHRwcml2YXRlIGdldFNldHRpbmdzKCk6IEFzdHJvQ29tcG9zZXJTZXR0aW5ncyB7XG5cdFx0Ly8gQWx3YXlzIHByZWZlciBwbHVnaW4gc2V0dGluZ3MgKHRoZXkncmUga2VwdCB1cCB0byBkYXRlKVxuXHRcdGlmICh0aGlzLnBsdWdpbj8uc2V0dGluZ3MpIHtcblx0XHRcdHJldHVybiB0aGlzLnBsdWdpbi5zZXR0aW5ncztcblx0XHR9XG5cdFx0cmV0dXJuIHRoaXMuc2V0dGluZ3M7XG5cdH1cblxuXHQvLyBMb2NhbCB0b0tlYmFiQ2FzZSByZW1vdmVkLCB1c2luZyBpbXBvcnRlZCBvbmUgaW5zdGVhZFxuXG5cdGdldEFzdHJvVXJsRnJvbUludGVybmFsTGluayhsaW5rOiBzdHJpbmcpOiBzdHJpbmcge1xuXHRcdGNvbnN0IGhhc2hJbmRleCA9IGxpbmsuaW5kZXhPZignIycpO1xuXHRcdGxldCBwYXRoID0gaGFzaEluZGV4ID49IDAgPyBsaW5rLnNsaWNlKDAsIGhhc2hJbmRleCkgOiBsaW5rO1xuXHRcdGNvbnN0IGFuY2hvciA9IGhhc2hJbmRleCA+PSAwID8gbGluay5zbGljZShoYXNoSW5kZXgpIDogJyc7XG5cblx0XHQvLyBVUkwgZGVjb2RlIHRoZSBwYXRoIHRvIGhhbmRsZSBlbmNvZGVkIGNoYXJhY3RlcnMgbGlrZSAlMjBcblx0XHRwYXRoID0gZGVjb2RlVVJJQ29tcG9uZW50KHBhdGgpO1xuXHRcdHBhdGggPSBwYXRoLnJlcGxhY2UoL1xcLihtZHxtZHgpJC8sIFwiXCIpO1xuXG5cdFx0Ly8gRGV0ZXJtaW5lIGNvbnRlbnQgdHlwZSBhbmQgYXBwcm9wcmlhdGUgYmFzZSBwYXRoIHVzaW5nIHBhdHRlcm4gc3BlY2lmaWNpdHlcblx0XHQvLyBTdXBwb3J0IGJvdGggLm1kIGFuZCAubWR4IGV4dGVuc2lvbnNcblx0XHRjb25zdCBmaWxlRXh0ZW5zaW9uID0gbGluay5lbmRzV2l0aCgnLm1keCcpID8gJy5tZHgnIDogJy5tZCc7XG5cdFx0Y29uc3QgY29udGVudFR5cGVJbmZvID0gdGhpcy5nZXRDb250ZW50VHlwZUZvclBhdGgocGF0aCArIGZpbGVFeHRlbnNpb24pO1xuXHRcdGxldCBiYXNlUGF0aCA9IGNvbnRlbnRUeXBlSW5mby5iYXNlUGF0aCB8fCBcIlwiO1xuXHRcdGxldCBjb250ZW50Rm9sZGVyID0gY29udGVudFR5cGVJbmZvLmNvbnRlbnRGb2xkZXIgfHwgXCJcIjtcblx0XHRsZXQgaW5kZXhGaWxlTmFtZSA9IGNvbnRlbnRUeXBlSW5mby5pbmRleEZpbGVOYW1lIHx8IFwiXCI7XG5cblxuXHRcdC8vIFN0cmlwIGNvbnRlbnQgZm9sZGVyIGlmIHByZXNlbnRcblx0XHRpZiAoY29udGVudEZvbGRlcikge1xuXHRcdFx0cGF0aCA9IHBhdGguc2xpY2UoY29udGVudEZvbGRlci5sZW5ndGggKyAxKTtcblx0XHR9XG5cblx0XHRsZXQgYWRkVHJhaWxpbmdTbGFzaCA9IGZhbHNlO1xuXG5cdFx0Ly8gU21hcnQgZGV0ZWN0aW9uOiBpZiB0aGUgZmlsZW5hbWUgbWF0Y2hlcyB0aGUgaW5kZXggZmlsZSBuYW1lIChyZWdhcmRsZXNzIG9mIGNyZWF0aW9uIG1vZGUpLFxuXHRcdC8vIHRyZWF0IGl0IGFzIGZvbGRlci1iYXNlZCBsb2dpY1xuXHRcdC8vIE5vdGU6IFdlIG9ubHkgc2V0IGFkZFRyYWlsaW5nU2xhc2ggaGVyZTsgdGhlIGZpbmFsIGNoZWNrIHdpbGwgcHJldmVudCBpdCBpZiB0aGVyZSdzIGFuIGFuY2hvclxuXHRcdGNvbnN0IHBhcnRzID0gcGF0aC5zcGxpdCgnLycpO1xuXHRcdGNvbnN0IGxhc3RQYXJ0ID0gcGFydHNbcGFydHMubGVuZ3RoIC0gMV07XG5cblx0XHQvLyBDaGVjayBpZiB0aGUgbGFzdCBwYXJ0IG1hdGNoZXMgdGhlIHNwZWNpZmllZCBpbmRleCBmaWxlIG5hbWVcblx0XHRpZiAoaW5kZXhGaWxlTmFtZSAmJiBpbmRleEZpbGVOYW1lLnRyaW0oKSAhPT0gXCJcIiAmJiBsYXN0UGFydCA9PT0gaW5kZXhGaWxlTmFtZSkge1xuXHRcdFx0cGFydHMucG9wKCk7XG5cdFx0XHRwYXRoID0gcGFydHMuam9pbignLycpO1xuXHRcdFx0YWRkVHJhaWxpbmdTbGFzaCA9IHRydWU7XG5cdFx0fVxuXHRcdC8vIENoZWNrIGlmIHRoZSBsYXN0IHBhcnQgbWF0Y2hlcyB0aGUgZGVmYXVsdCBcImluZGV4XCIgKHdoZW4gbm8gaW5kZXhGaWxlTmFtZSBpcyBzcGVjaWZpZWQpXG5cdFx0ZWxzZSBpZiAoKCFpbmRleEZpbGVOYW1lIHx8IGluZGV4RmlsZU5hbWUudHJpbSgpID09PSBcIlwiKSAmJiBsYXN0UGFydCA9PT0gXCJpbmRleFwiKSB7XG5cdFx0XHRwYXJ0cy5wb3AoKTtcblx0XHRcdHBhdGggPSBwYXJ0cy5qb2luKCcvJyk7XG5cdFx0XHRhZGRUcmFpbGluZ1NsYXNoID0gdHJ1ZTtcblx0XHR9XG5cblx0XHRjb25zdCBzbHVnUGFydHMgPSBwYXRoLnNwbGl0KCcvJykubWFwKHBhcnQgPT4gdG9LZWJhYkNhc2UocGFydCkpO1xuXHRcdGNvbnN0IHNsdWcgPSBzbHVnUGFydHMuam9pbignLycpO1xuXG5cdFx0Ly8gRm9ybWF0IGJhc2UgcGF0aFxuXHRcdGlmIChiYXNlUGF0aCkge1xuXHRcdFx0Ly8gQWRkIGxlYWRpbmcgc2xhc2ggaWYgbm90IHByZXNlbnQgdG8gbWFrZSBpdCBhYnNvbHV0ZSBmcm9tIHJvb3Rcblx0XHRcdGlmICghYmFzZVBhdGguc3RhcnRzV2l0aChcIi9cIikpIHtcblx0XHRcdFx0YmFzZVBhdGggPSBcIi9cIiArIGJhc2VQYXRoO1xuXHRcdFx0fVxuXHRcdFx0Ly8gQWRkIHRyYWlsaW5nIHNsYXNoIGlmIG5vdCBwcmVzZW50XG5cdFx0XHRpZiAoIWJhc2VQYXRoLmVuZHNXaXRoKFwiL1wiKSkge1xuXHRcdFx0XHRiYXNlUGF0aCArPSBcIi9cIjtcblx0XHRcdH1cblx0XHR9IGVsc2Uge1xuXHRcdFx0Ly8gV2hlbiBubyBiYXNlIHBhdGggaXMgc3BlY2lmaWVkLCBhZGQgbGVhZGluZyBzbGFzaCB0byBtYWtlIGl0IGFic29sdXRlIGZyb20gcm9vdFxuXHRcdFx0YmFzZVBhdGggPSBcIi9cIjtcblx0XHR9XG5cblx0XHQvLyBEZXRlcm1pbmUgaWYgd2Ugc2hvdWxkIGFkZCB0cmFpbGluZyBzbGFzaFxuXHRcdC8vIENSSVRJQ0FMOiBOZXZlciBhZGQgdHJhaWxpbmcgc2xhc2ggYmVmb3JlIGFuIGFuY2hvciAoZS5nLiwgL2Fib3V0I2hlYWRpbmcgbm90IC9hYm91dC8jaGVhZGluZylcblx0XHQvLyBUaGlzIGlzIGVzcGVjaWFsbHkgaW1wb3J0YW50IGZvciBhbmNob3IgbGlua3MgZnJvbSBjb3B5IGhlYWRpbmcgVVJMIGZ1bmN0aW9uYWxpdHlcblx0XHQvLyBBbmNob3IgbGlua3Mgc2hvdWxkIE5FVkVSIGhhdmUgdHJhaWxpbmcgc2xhc2hlcywgcmVnYXJkbGVzcyBvZiBzZXR0aW5nc1xuXHRcdGNvbnN0IHNldHRpbmdzID0gdGhpcy5nZXRTZXR0aW5ncygpO1xuXHRcdGNvbnN0IHNob3VsZEFkZFRyYWlsaW5nU2xhc2ggPSAoc2V0dGluZ3MuYWRkVHJhaWxpbmdTbGFzaFRvTGlua3MgfHwgYWRkVHJhaWxpbmdTbGFzaCkgJiYgIWFuY2hvcjtcblxuXHRcdHJldHVybiBgJHtiYXNlUGF0aH0ke3NsdWd9JHtzaG91bGRBZGRUcmFpbGluZ1NsYXNoID8gJy8nIDogJyd9JHthbmNob3J9YDtcblx0fVxuXG5cdHByaXZhdGUgZ2V0QXN0cm9VcmxGcm9tSW50ZXJuYWxMaW5rV2l0aENvbnRleHQobGluazogc3RyaW5nLCBjdXJyZW50RmlsZVBhdGg6IHN0cmluZywgY3VycmVudEZpbGVDb250ZW50VHlwZTogeyBiYXNlUGF0aDogc3RyaW5nOyBjcmVhdGlvbk1vZGU6IFwiZmlsZVwiIHwgXCJmb2xkZXJcIjsgaW5kZXhGaWxlTmFtZTogc3RyaW5nOyBjb250ZW50Rm9sZGVyOiBzdHJpbmcgfSk6IHN0cmluZyB7XG5cblx0XHRjb25zdCBoYXNoSW5kZXggPSBsaW5rLmluZGV4T2YoJyMnKTtcblx0XHRsZXQgcGF0aCA9IGhhc2hJbmRleCA+PSAwID8gbGluay5zbGljZSgwLCBoYXNoSW5kZXgpIDogbGluaztcblx0XHRjb25zdCBhbmNob3IgPSBoYXNoSW5kZXggPj0gMCA/IGxpbmsuc2xpY2UoaGFzaEluZGV4KSA6ICcnO1xuXG5cdFx0Ly8gVVJMIGRlY29kZSB0aGUgcGF0aCB0byBoYW5kbGUgZW5jb2RlZCBjaGFyYWN0ZXJzIGxpa2UgJTIwXG5cdFx0cGF0aCA9IGRlY29kZVVSSUNvbXBvbmVudChwYXRoKTtcblx0XHRwYXRoID0gcGF0aC5yZXBsYWNlKC9cXC4obWR8bWR4KSQvLCBcIlwiKTtcblxuXG5cdFx0Ly8gRGV0ZXJtaW5lIGNvbnRlbnQgdHlwZSBhbmQgYXBwcm9wcmlhdGUgYmFzZSBwYXRoXG5cdFx0bGV0IGJhc2VQYXRoID0gXCJcIjtcblx0XHRsZXQgY29udGVudEZvbGRlciA9IFwiXCI7XG5cdFx0bGV0IGluZGV4RmlsZU5hbWUgPSBcIlwiO1xuXG5cdFx0Ly8gVXNlIHRoZSBzYW1lIGxvZ2ljIGFzIGdldENvbnRlbnRUeXBlRm9yUGF0aCBidXQgZm9yIHRoZSB0YXJnZXQgbGlua1xuXHRcdC8vIFN1cHBvcnQgYm90aCAubWQgYW5kIC5tZHggZXh0ZW5zaW9ucyAtIHRyeSAubWR4IGZpcnN0IGlmIGxpbmsgc3VnZ2VzdHMgaXRcblx0XHRjb25zdCBmaWxlRXh0ZW5zaW9uID0gbGluay5lbmRzV2l0aCgnLm1keCcpID8gJy5tZHgnIDogJy5tZCc7XG5cdFx0Y29uc3QgdGFyZ2V0Q29udGVudFR5cGUgPSB0aGlzLmdldENvbnRlbnRUeXBlRm9yUGF0aChwYXRoICsgZmlsZUV4dGVuc2lvbik7XG5cblx0XHQvLyBJZiB0YXJnZXQgbGluayBkb2Vzbid0IGhhdmUgYSBjbGVhciBjb250ZW50IHR5cGUgKG5vIGZvbGRlciBwYXRoKSwgdXNlIGN1cnJlbnQgZmlsZSdzIGNvbnRlbnQgdHlwZVxuXHRcdGlmICghdGFyZ2V0Q29udGVudFR5cGUuYmFzZVBhdGggJiYgY3VycmVudEZpbGVDb250ZW50VHlwZS5iYXNlUGF0aCkge1xuXHRcdFx0YmFzZVBhdGggPSBjdXJyZW50RmlsZUNvbnRlbnRUeXBlLmJhc2VQYXRoO1xuXHRcdFx0aW5kZXhGaWxlTmFtZSA9IGN1cnJlbnRGaWxlQ29udGVudFR5cGUuaW5kZXhGaWxlTmFtZTtcblx0XHRcdGNvbnRlbnRGb2xkZXIgPSBjdXJyZW50RmlsZUNvbnRlbnRUeXBlLmNvbnRlbnRGb2xkZXI7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGJhc2VQYXRoID0gdGFyZ2V0Q29udGVudFR5cGUuYmFzZVBhdGg7XG5cdFx0XHRpbmRleEZpbGVOYW1lID0gdGFyZ2V0Q29udGVudFR5cGUuaW5kZXhGaWxlTmFtZTtcblx0XHRcdGNvbnRlbnRGb2xkZXIgPSB0YXJnZXRDb250ZW50VHlwZS5jb250ZW50Rm9sZGVyO1xuXHRcdH1cblxuXHRcdC8vIFN0cmlwIGNvbnRlbnQgZm9sZGVyIGlmIHByZXNlbnRcblx0XHRpZiAoY29udGVudEZvbGRlcikge1xuXHRcdFx0cGF0aCA9IHBhdGguc2xpY2UoY29udGVudEZvbGRlci5sZW5ndGggKyAxKTtcblx0XHR9XG5cblx0XHRsZXQgYWRkVHJhaWxpbmdTbGFzaCA9IGZhbHNlO1xuXG5cdFx0Ly8gU21hcnQgZGV0ZWN0aW9uOiBpZiB0aGUgZmlsZW5hbWUgbWF0Y2hlcyB0aGUgaW5kZXggZmlsZSBuYW1lIChyZWdhcmRsZXNzIG9mIGNyZWF0aW9uIG1vZGUpLFxuXHRcdC8vIHRyZWF0IGl0IGFzIGZvbGRlci1iYXNlZCBsb2dpY1xuXHRcdC8vIE5vdGU6IFdlIG9ubHkgc2V0IGFkZFRyYWlsaW5nU2xhc2ggaGVyZTsgdGhlIGZpbmFsIGNoZWNrIHdpbGwgcHJldmVudCBpdCBpZiB0aGVyZSdzIGFuIGFuY2hvclxuXHRcdGNvbnN0IHBhcnRzID0gcGF0aC5zcGxpdCgnLycpO1xuXHRcdGNvbnN0IGxhc3RQYXJ0ID0gcGFydHNbcGFydHMubGVuZ3RoIC0gMV07XG5cblx0XHQvLyBDaGVjayBpZiB0aGUgbGFzdCBwYXJ0IG1hdGNoZXMgdGhlIHNwZWNpZmllZCBpbmRleCBmaWxlIG5hbWVcblx0XHRpZiAoaW5kZXhGaWxlTmFtZSAmJiBpbmRleEZpbGVOYW1lLnRyaW0oKSAhPT0gXCJcIiAmJiBsYXN0UGFydCA9PT0gaW5kZXhGaWxlTmFtZSkge1xuXHRcdFx0cGFydHMucG9wKCk7XG5cdFx0XHRwYXRoID0gcGFydHMuam9pbignLycpO1xuXHRcdFx0YWRkVHJhaWxpbmdTbGFzaCA9IHRydWU7XG5cdFx0fVxuXHRcdC8vIENoZWNrIGlmIHRoZSBsYXN0IHBhcnQgbWF0Y2hlcyB0aGUgZGVmYXVsdCBcImluZGV4XCIgKHdoZW4gbm8gaW5kZXhGaWxlTmFtZSBpcyBzcGVjaWZpZWQpXG5cdFx0ZWxzZSBpZiAoKCFpbmRleEZpbGVOYW1lIHx8IGluZGV4RmlsZU5hbWUudHJpbSgpID09PSBcIlwiKSAmJiBsYXN0UGFydCA9PT0gXCJpbmRleFwiKSB7XG5cdFx0XHRwYXJ0cy5wb3AoKTtcblx0XHRcdHBhdGggPSBwYXJ0cy5qb2luKCcvJyk7XG5cdFx0XHRhZGRUcmFpbGluZ1NsYXNoID0gdHJ1ZTtcblx0XHR9XG5cblx0XHRjb25zdCBzbHVnUGFydHMgPSBwYXRoLnNwbGl0KCcvJykubWFwKHBhcnQgPT4gdG9LZWJhYkNhc2UocGFydCkpO1xuXHRcdGNvbnN0IHNsdWcgPSBzbHVnUGFydHMuam9pbignLycpO1xuXG5cdFx0Ly8gRm9ybWF0IGJhc2UgcGF0aFxuXHRcdGlmIChiYXNlUGF0aCkge1xuXHRcdFx0Ly8gQWRkIGxlYWRpbmcgc2xhc2ggaWYgbm90IHByZXNlbnQgdG8gbWFrZSBpdCBhYnNvbHV0ZSBmcm9tIHJvb3Rcblx0XHRcdGlmICghYmFzZVBhdGguc3RhcnRzV2l0aChcIi9cIikpIHtcblx0XHRcdFx0YmFzZVBhdGggPSBcIi9cIiArIGJhc2VQYXRoO1xuXHRcdFx0fVxuXHRcdFx0Ly8gQWRkIHRyYWlsaW5nIHNsYXNoIGlmIG5vdCBwcmVzZW50XG5cdFx0XHRpZiAoIWJhc2VQYXRoLmVuZHNXaXRoKFwiL1wiKSkge1xuXHRcdFx0XHRiYXNlUGF0aCArPSBcIi9cIjtcblx0XHRcdH1cblx0XHR9IGVsc2Uge1xuXHRcdFx0Ly8gV2hlbiBubyBiYXNlIHBhdGggaXMgc3BlY2lmaWVkLCBhZGQgbGVhZGluZyBzbGFzaCB0byBtYWtlIGl0IGFic29sdXRlIGZyb20gcm9vdFxuXHRcdFx0YmFzZVBhdGggPSBcIi9cIjtcblx0XHR9XG5cblx0XHQvLyBEZXRlcm1pbmUgaWYgd2Ugc2hvdWxkIGFkZCB0cmFpbGluZyBzbGFzaFxuXHRcdC8vIENSSVRJQ0FMOiBOZXZlciBhZGQgdHJhaWxpbmcgc2xhc2ggYmVmb3JlIGFuIGFuY2hvciAoZS5nLiwgL2Fib3V0I2hlYWRpbmcgbm90IC9hYm91dC8jaGVhZGluZylcblx0XHQvLyBUaGlzIGlzIGVzcGVjaWFsbHkgaW1wb3J0YW50IGZvciBhbmNob3IgbGlua3MgZnJvbSBjb3B5IGhlYWRpbmcgVVJMIGZ1bmN0aW9uYWxpdHlcblx0XHQvLyBBbmNob3IgbGlua3Mgc2hvdWxkIE5FVkVSIGhhdmUgdHJhaWxpbmcgc2xhc2hlcywgcmVnYXJkbGVzcyBvZiBzZXR0aW5nc1xuXHRcdGNvbnN0IHNldHRpbmdzID0gdGhpcy5nZXRTZXR0aW5ncygpO1xuXHRcdGNvbnN0IHNob3VsZEFkZFRyYWlsaW5nU2xhc2ggPSAoc2V0dGluZ3MuYWRkVHJhaWxpbmdTbGFzaFRvTGlua3MgfHwgYWRkVHJhaWxpbmdTbGFzaCkgJiYgIWFuY2hvcjtcblxuXHRcdHJldHVybiBgJHtiYXNlUGF0aH0ke3NsdWd9JHtzaG91bGRBZGRUcmFpbGluZ1NsYXNoID8gJy8nIDogJyd9JHthbmNob3J9YDtcblx0fVxuXG5cdHByaXZhdGUgaXNJbkNvbmZpZ3VyZWRDb250ZW50RGlyZWN0b3J5KGZpbGVQYXRoOiBzdHJpbmcpOiBib29sZWFuIHtcblx0XHQvLyBDaGVjayBhbGwgY29udGVudCB0eXBlcywgc29ydGVkIGJ5IHBhdHRlcm4gc3BlY2lmaWNpdHkgKG1vcmUgc3BlY2lmaWMgZmlyc3QpXG5cdFx0Y29uc3Qgc2V0dGluZ3MgPSB0aGlzLmdldFNldHRpbmdzKCk7XG5cdFx0Y29uc3QgY29udGVudFR5cGVzID0gc2V0dGluZ3MuY29udGVudFR5cGVzIHx8IFtdO1xuXHRcdGNvbnN0IHNvcnRlZFR5cGVzID0gc29ydEJ5UGF0dGVyblNwZWNpZmljaXR5KGNvbnRlbnRUeXBlcyk7XG5cblx0XHRmb3IgKGNvbnN0IGNvbnRlbnRUeXBlIG9mIHNvcnRlZFR5cGVzKSB7XG5cdFx0XHRpZiAoIWNvbnRlbnRUeXBlLmVuYWJsZWQpIGNvbnRpbnVlO1xuXG5cdFx0XHQvLyBIYW5kbGUgYmxhbmsgZm9sZGVyIChyb290KSAtIG1hdGNoZXMgZmlsZXMgaW4gdmF1bHQgcm9vdCBvbmx5XG5cdFx0XHRpZiAoIWNvbnRlbnRUeXBlLmZvbGRlciB8fCBjb250ZW50VHlwZS5mb2xkZXIudHJpbSgpID09PSBcIlwiKSB7XG5cdFx0XHRcdGlmICghZmlsZVBhdGguaW5jbHVkZXMoXCIvXCIpIHx8IGZpbGVQYXRoLnNwbGl0KFwiL1wiKS5sZW5ndGggPT09IDEpIHtcblx0XHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdFx0fVxuXHRcdFx0fSBlbHNlIGlmIChtYXRjaGVzRm9sZGVyUGF0dGVybihmaWxlUGF0aCwgY29udGVudFR5cGUuZm9sZGVyKSkge1xuXHRcdFx0XHQvLyBDaGVjayBpZ25vcmVTdWJmb2xkZXJzIGlmIGZvbGRlciBpcyBzcGVjaWZpZWRcblx0XHRcdFx0aWYgKGNvbnRlbnRUeXBlLmlnbm9yZVN1YmZvbGRlcnMpIHtcblx0XHRcdFx0XHRjb25zdCBwYXRoU2VnbWVudHMgPSBmaWxlUGF0aC5zcGxpdChcIi9cIik7XG5cdFx0XHRcdFx0Y29uc3QgcGF0aERlcHRoID0gcGF0aFNlZ21lbnRzLmxlbmd0aDtcblx0XHRcdFx0XHRjb25zdCBwYXR0ZXJuU2VnbWVudHMgPSBjb250ZW50VHlwZS5mb2xkZXIuc3BsaXQoXCIvXCIpO1xuXHRcdFx0XHRcdGNvbnN0IGV4cGVjdGVkRGVwdGggPSBwYXR0ZXJuU2VnbWVudHMubGVuZ3RoO1xuXG5cdFx0XHRcdFx0aWYgKGNvbnRlbnRUeXBlLmNyZWF0aW9uTW9kZSA9PT0gXCJmb2xkZXJcIikge1xuXHRcdFx0XHRcdFx0Ly8gRm9yIGZvbGRlci1iYXNlZCBjcmVhdGlvbiwgZmlsZXMgYXJlIG9uZSBsZXZlbCBkZWVwZXIgKGUuZy4sIHRlc3QvbXktZmlsZS9pbmRleC5tZClcblx0XHRcdFx0XHRcdC8vIFNvIHdlIG5lZWQgdG8gYWxsb3cgb25lIGV4dHJhIGxldmVsIGJleW9uZCB0aGUgcGF0dGVybiBkZXB0aFxuXHRcdFx0XHRcdFx0Y29uc3QgZm9sZGVyRGVwdGggPSBwYXRoRGVwdGggLSAxOyAvLyBTdWJ0cmFjdCAxIGZvciB0aGUgaW5kZXgubWQgZmlsZVxuXHRcdFx0XHRcdFx0aWYgKGZvbGRlckRlcHRoID09PSBleHBlY3RlZERlcHRoIHx8IGZvbGRlckRlcHRoID09PSBleHBlY3RlZERlcHRoICsgMSkge1xuXHRcdFx0XHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0Ly8gRm9yIGZpbGUtYmFzZWQgY3JlYXRpb24sIGZpbGVzIGFyZSBhdCB0aGUgc2FtZSBkZXB0aCBhcyB0aGUgcGF0dGVyblxuXHRcdFx0XHRcdFx0aWYgKHBhdGhEZXB0aCA9PT0gZXhwZWN0ZWREZXB0aCkge1xuXHRcdFx0XHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cblxuXHRwcml2YXRlIGdldENvbnRlbnRUeXBlRm9yUGF0aChmaWxlUGF0aDogc3RyaW5nKTogeyBiYXNlUGF0aDogc3RyaW5nOyBjcmVhdGlvbk1vZGU6IFwiZmlsZVwiIHwgXCJmb2xkZXJcIjsgaW5kZXhGaWxlTmFtZTogc3RyaW5nOyBjb250ZW50Rm9sZGVyOiBzdHJpbmcgfSB7XG5cdFx0Ly8gQ2hlY2sgYWxsIGNvbnRlbnQgdHlwZXMsIHNvcnRlZCBieSBwYXR0ZXJuIHNwZWNpZmljaXR5IChtb3JlIHNwZWNpZmljIGZpcnN0KVxuXHRcdGNvbnN0IHNldHRpbmdzID0gdGhpcy5nZXRTZXR0aW5ncygpO1xuXHRcdGNvbnN0IGNvbnRlbnRUeXBlcyA9IHNldHRpbmdzLmNvbnRlbnRUeXBlcyB8fCBbXTtcblx0XHRjb25zdCBzb3J0ZWRUeXBlcyA9IHNvcnRCeVBhdHRlcm5TcGVjaWZpY2l0eShjb250ZW50VHlwZXMpO1xuXG5cdFx0Zm9yIChjb25zdCBjb250ZW50VHlwZSBvZiBzb3J0ZWRUeXBlcykge1xuXHRcdFx0aWYgKCFjb250ZW50VHlwZS5lbmFibGVkKSBjb250aW51ZTtcblxuXHRcdFx0Ly8gSGFuZGxlIGJsYW5rIGZvbGRlciAocm9vdCkgLSBtYXRjaGVzIGZpbGVzIGluIHZhdWx0IHJvb3Qgb25seVxuXHRcdFx0aWYgKCFjb250ZW50VHlwZS5mb2xkZXIgfHwgY29udGVudFR5cGUuZm9sZGVyLnRyaW0oKSA9PT0gXCJcIikge1xuXHRcdFx0XHRpZiAoIWZpbGVQYXRoLmluY2x1ZGVzKFwiL1wiKSB8fCBmaWxlUGF0aC5zcGxpdChcIi9cIikubGVuZ3RoID09PSAxKSB7XG5cdFx0XHRcdFx0cmV0dXJuIHtcblx0XHRcdFx0XHRcdGJhc2VQYXRoOiBjb250ZW50VHlwZS5saW5rQmFzZVBhdGggfHwgXCJcIixcblx0XHRcdFx0XHRcdGNyZWF0aW9uTW9kZTogY29udGVudFR5cGUuY3JlYXRpb25Nb2RlLFxuXHRcdFx0XHRcdFx0aW5kZXhGaWxlTmFtZTogY29udGVudFR5cGUuaW5kZXhGaWxlTmFtZSB8fCBcIlwiLFxuXHRcdFx0XHRcdFx0Y29udGVudEZvbGRlcjogXCJcIlxuXHRcdFx0XHRcdH07XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSBpZiAobWF0Y2hlc0ZvbGRlclBhdHRlcm4oZmlsZVBhdGgsIGNvbnRlbnRUeXBlLmZvbGRlcikpIHtcblx0XHRcdFx0Ly8gQ2hlY2sgaWdub3JlU3ViZm9sZGVycyBpZiBmb2xkZXIgaXMgc3BlY2lmaWVkXG5cdFx0XHRcdGlmIChjb250ZW50VHlwZS5pZ25vcmVTdWJmb2xkZXJzKSB7XG5cdFx0XHRcdFx0Y29uc3QgcGF0aFNlZ21lbnRzID0gZmlsZVBhdGguc3BsaXQoXCIvXCIpO1xuXHRcdFx0XHRcdGNvbnN0IHBhdGhEZXB0aCA9IHBhdGhTZWdtZW50cy5sZW5ndGg7XG5cdFx0XHRcdFx0Y29uc3QgcGF0dGVyblNlZ21lbnRzID0gY29udGVudFR5cGUuZm9sZGVyLnNwbGl0KFwiL1wiKTtcblx0XHRcdFx0XHRjb25zdCBleHBlY3RlZERlcHRoID0gcGF0dGVyblNlZ21lbnRzLmxlbmd0aDtcblxuXHRcdFx0XHRcdGlmIChjb250ZW50VHlwZS5jcmVhdGlvbk1vZGUgPT09IFwiZm9sZGVyXCIpIHtcblx0XHRcdFx0XHRcdC8vIEZvciBmb2xkZXItYmFzZWQgY3JlYXRpb24sIGZpbGVzIGFyZSBvbmUgbGV2ZWwgZGVlcGVyIChlLmcuLCB0ZXN0L215LWZpbGUvaW5kZXgubWQpXG5cdFx0XHRcdFx0XHQvLyBTbyB3ZSBuZWVkIHRvIGFsbG93IG9uZSBleHRyYSBsZXZlbCBiZXlvbmQgdGhlIHBhdHRlcm4gZGVwdGhcblx0XHRcdFx0XHRcdGNvbnN0IGZvbGRlckRlcHRoID0gcGF0aERlcHRoIC0gMTsgLy8gU3VidHJhY3QgMSBmb3IgdGhlIGluZGV4Lm1kIGZpbGVcblx0XHRcdFx0XHRcdGlmIChmb2xkZXJEZXB0aCA9PT0gZXhwZWN0ZWREZXB0aCB8fCBmb2xkZXJEZXB0aCA9PT0gZXhwZWN0ZWREZXB0aCArIDEpIHtcblx0XHRcdFx0XHRcdFx0cmV0dXJuIHtcblx0XHRcdFx0XHRcdFx0XHRiYXNlUGF0aDogY29udGVudFR5cGUubGlua0Jhc2VQYXRoIHx8IFwiXCIsXG5cdFx0XHRcdFx0XHRcdFx0Y3JlYXRpb25Nb2RlOiBjb250ZW50VHlwZS5jcmVhdGlvbk1vZGUsXG5cdFx0XHRcdFx0XHRcdFx0aW5kZXhGaWxlTmFtZTogY29udGVudFR5cGUuaW5kZXhGaWxlTmFtZSB8fCBcIlwiLFxuXHRcdFx0XHRcdFx0XHRcdGNvbnRlbnRGb2xkZXI6IGNvbnRlbnRUeXBlLmZvbGRlclxuXHRcdFx0XHRcdFx0XHR9O1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHQvLyBGb3IgZmlsZS1iYXNlZCBjcmVhdGlvbiwgZmlsZXMgYXJlIGF0IHRoZSBzYW1lIGRlcHRoIGFzIHRoZSBwYXR0ZXJuXG5cdFx0XHRcdFx0XHRpZiAocGF0aERlcHRoID09PSBleHBlY3RlZERlcHRoKSB7XG5cdFx0XHRcdFx0XHRcdHJldHVybiB7XG5cdFx0XHRcdFx0XHRcdFx0YmFzZVBhdGg6IGNvbnRlbnRUeXBlLmxpbmtCYXNlUGF0aCB8fCBcIlwiLFxuXHRcdFx0XHRcdFx0XHRcdGNyZWF0aW9uTW9kZTogY29udGVudFR5cGUuY3JlYXRpb25Nb2RlLFxuXHRcdFx0XHRcdFx0XHRcdGluZGV4RmlsZU5hbWU6IGNvbnRlbnRUeXBlLmluZGV4RmlsZU5hbWUgfHwgXCJcIixcblx0XHRcdFx0XHRcdFx0XHRjb250ZW50Rm9sZGVyOiBjb250ZW50VHlwZS5mb2xkZXJcblx0XHRcdFx0XHRcdFx0fTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0cmV0dXJuIHtcblx0XHRcdFx0XHRcdGJhc2VQYXRoOiBjb250ZW50VHlwZS5saW5rQmFzZVBhdGggfHwgXCJcIixcblx0XHRcdFx0XHRcdGNyZWF0aW9uTW9kZTogY29udGVudFR5cGUuY3JlYXRpb25Nb2RlLFxuXHRcdFx0XHRcdFx0aW5kZXhGaWxlTmFtZTogY29udGVudFR5cGUuaW5kZXhGaWxlTmFtZSB8fCBcIlwiLFxuXHRcdFx0XHRcdFx0Y29udGVudEZvbGRlcjogY29udGVudFR5cGUuZm9sZGVyXG5cdFx0XHRcdFx0fTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vIERlZmF1bHQgZmFsbGJhY2tcblx0XHRyZXR1cm4ge1xuXHRcdFx0YmFzZVBhdGg6IFwiXCIsXG5cdFx0XHRjcmVhdGlvbk1vZGU6IFwiZmlsZVwiLFxuXHRcdFx0aW5kZXhGaWxlTmFtZTogXCJcIixcblx0XHRcdGNvbnRlbnRGb2xkZXI6IFwiXCJcblx0XHR9O1xuXHR9XG5cblx0Y29udmVydFdpa2lsaW5rc0ZvckFzdHJvKGVkaXRvcjogRWRpdG9yLCBmaWxlOiBURmlsZSB8IG51bGwpOiB2b2lkIHtcblx0XHRpZiAoIShmaWxlIGluc3RhbmNlb2YgVEZpbGUpKSB7XG5cdFx0XHRuZXcgTm90aWNlKFwiTm8gYWN0aXZlIGZpbGUuXCIpO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdC8vIFByZXNlcnZlIGN1cnNvciBwb3NpdGlvbiBiZWZvcmUgbW9kaWZ5aW5nIGNvbnRlbnRcblx0XHRjb25zdCBjdXJzb3IgPSBlZGl0b3IuZ2V0Q3Vyc29yKCk7XG5cdFx0Y29uc3Qgb3JpZ2luYWxMaW5lID0gY3Vyc29yLmxpbmU7XG5cdFx0Y29uc3Qgb3JpZ2luYWxDaCA9IGN1cnNvci5jaDtcblx0XHRjb25zdCBvcmlnaW5hbENvbnRlbnQgPSBlZGl0b3IuZ2V0VmFsdWUoKTtcblx0XHRjb25zdCBvcmlnaW5hbExpbmVDb3VudCA9IG9yaWdpbmFsQ29udGVudC5zcGxpdCgnXFxuJykubGVuZ3RoO1xuXHRcdGNvbnN0IG9yaWdpbmFsTGluZUxlbmd0aCA9IG9yaWdpbmFsQ29udGVudC5zcGxpdCgnXFxuJylbb3JpZ2luYWxMaW5lXT8ubGVuZ3RoIHx8IDA7XG5cblx0XHRjb25zdCBjb250ZW50ID0gZWRpdG9yLmdldFZhbHVlKCk7XG5cdFx0bGV0IG5ld0NvbnRlbnQgPSBjb250ZW50O1xuXHRcdGxldCBjb252ZXJ0ZWRDb3VudCA9IDA7XG5cdFx0bGV0IHNraXBwZWRDb3VudCA9IDA7XG5cdFx0Y29uc3Qgc2tpcHBlZExpbmtzOiBzdHJpbmdbXSA9IFtdO1xuXG5cdFx0Ly8gRGV0ZXJtaW5lIHRoZSBjdXJyZW50IGZpbGUncyBjb250ZW50IHR5cGUgZm9yIHJlbGF0aXZlIGxpbmtzXG5cdFx0Y29uc3QgY3VycmVudEZpbGVDb250ZW50VHlwZSA9IHRoaXMuZ2V0Q29udGVudFR5cGVGb3JQYXRoKGZpbGUucGF0aCk7XG5cblx0XHQvLyBEZWZpbmUgY29tbW9uIGltYWdlIGV4dGVuc2lvbnNcblx0XHRjb25zdCBpbWFnZUV4dGVuc2lvbnMgPSAvXFwuKHBuZ3xqcGd8anBlZ3xnaWZ8c3ZnKSQvaTtcblxuXHRcdC8vIEhlbHBlciBmdW5jdGlvbiB0byBjaGVjayBpZiBhIGxpbmsgY2FuIGJlIHJlbGlhYmx5IGNvbnZlcnRlZFxuXHRcdGNvbnN0IGNhbkNvbnZlcnRMaW5rID0gKGxpbmtUZXh0OiBzdHJpbmcpOiBib29sZWFuID0+IHtcblx0XHRcdC8vIERvbid0IGNvbnZlcnQgaWYgaXQncyBhbiBpbWFnZVxuXHRcdFx0aWYgKGltYWdlRXh0ZW5zaW9ucy50ZXN0KGxpbmtUZXh0KSkge1xuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHR9XG5cblx0XHRcdC8vIERvbid0IGNvbnZlcnQgZXh0ZXJuYWwgbGlua3Ncblx0XHRcdGlmIChsaW5rVGV4dC5tYXRjaCgvXmh0dHBzPzpcXC9cXC8vKSkge1xuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHR9XG5cblx0XHRcdC8vIERvbid0IGNvbnZlcnQgaWYgaXQncyBub3QgYSAubWQgb3IgLm1keCBmaWxlIGFuZCBkb2Vzbid0IGxvb2sgbGlrZSBhIHZhbGlkIGludGVybmFsIGxpbmtcblx0XHRcdGlmICghbGlua1RleHQuaW5jbHVkZXMoJy5tZCcpICYmICFsaW5rVGV4dC5pbmNsdWRlcygnLm1keCcpICYmICFsaW5rVGV4dC5tYXRjaCgvXlthLXpBLVowLTlfLV0rKFxcL1thLXpBLVowLTlfLV0rKSokLykpIHtcblx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBDaGVjayBpZiB0aGUgdGFyZ2V0IGZpbGUgaXMgaW4gYW55IGNvbmZpZ3VyZWQgY29udGVudCBkaXJlY3Rvcnlcblx0XHRcdC8vIFN1cHBvcnQgYm90aCAubWQgYW5kIC5tZHggZXh0ZW5zaW9uc1xuXHRcdFx0bGV0IHRhcmdldFBhdGg6IHN0cmluZztcblx0XHRcdGlmIChsaW5rVGV4dC5lbmRzV2l0aCgnLm1kJykgfHwgbGlua1RleHQuZW5kc1dpdGgoJy5tZHgnKSkge1xuXHRcdFx0XHR0YXJnZXRQYXRoID0gbGlua1RleHQ7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHQvLyBEZWZhdWx0IHRvIC5tZCBpZiBubyBleHRlbnNpb24gc3BlY2lmaWVkXG5cdFx0XHRcdHRhcmdldFBhdGggPSBsaW5rVGV4dCArICcubWQnO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBDaGVjayBpZiBpdCdzIGluIGEgY29uZmlndXJlZCBjb250ZW50IGRpcmVjdG9yeVxuXHRcdFx0Y29uc3QgaXNJbkNvbmZpZ3VyZWREaXJlY3RvcnkgPSB0aGlzLmlzSW5Db25maWd1cmVkQ29udGVudERpcmVjdG9yeSh0YXJnZXRQYXRoKTtcblxuXHRcdFx0Ly8gQWxzbyBjaGVjayBpZiBpdCdzIGEgc2ltcGxlIGZpbGVuYW1lIChubyBwYXRoKSBhbmQgY3VycmVudCBmaWxlIGhhcyBhIGNvbnRlbnQgdHlwZVxuXHRcdFx0Y29uc3QgaXNTaW1wbGVGaWxlbmFtZSA9ICF0YXJnZXRQYXRoLmluY2x1ZGVzKCcvJyk7XG5cdFx0XHRjb25zdCBoYXNDdXJyZW50Q29udGVudFR5cGUgPSBjdXJyZW50RmlsZUNvbnRlbnRUeXBlLmJhc2VQYXRoICE9PSBcIlwiIHx8IGN1cnJlbnRGaWxlQ29udGVudFR5cGUuY3JlYXRpb25Nb2RlICE9PSBcImZpbGVcIiB8fCBjdXJyZW50RmlsZUNvbnRlbnRUeXBlLmluZGV4RmlsZU5hbWUgIT09IFwiXCI7XG5cblx0XHRcdHJldHVybiBpc0luQ29uZmlndXJlZERpcmVjdG9yeSB8fCAoaXNTaW1wbGVGaWxlbmFtZSAmJiBoYXNDdXJyZW50Q29udGVudFR5cGUpO1xuXHRcdH07XG5cblx0XHQvLyBIYW5kbGUgcmVndWxhciBXaWtpbGlua3MgKG5vbi1pbWFnZSlcblx0XHRuZXdDb250ZW50ID0gbmV3Q29udGVudC5yZXBsYWNlKFxuXHRcdFx0L1xcW1xcWyhbXlxcXXxdKykoXFx8KFteXFxdXSspKT9cXF1cXF0vZyxcblx0XHRcdChtYXRjaDogc3RyaW5nLCBsaW5rVGV4dDogc3RyaW5nLCBfcGlwZTogc3RyaW5nIHwgdW5kZWZpbmVkLCBkaXNwbGF5VGV4dDogc3RyaW5nIHwgdW5kZWZpbmVkKSA9PiB7XG5cdFx0XHRcdC8vIENoZWNrIGlmIGl0J3MgYW4gaW1hZ2UgV2lraWxpbmtcblx0XHRcdFx0aWYgKGltYWdlRXh0ZW5zaW9ucy50ZXN0KGxpbmtUZXh0KSkge1xuXHRcdFx0XHRcdHNraXBwZWRDb3VudCsrO1xuXHRcdFx0XHRcdHNraXBwZWRMaW5rcy5wdXNoKGxpbmtUZXh0KTtcblx0XHRcdFx0XHRyZXR1cm4gbWF0Y2g7IC8vIElnbm9yZSBhbmQgcmV0dXJuIG9yaWdpbmFsIGltYWdlIFdpa2lsaW5rXG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBDaGVjayBpZiB3ZSBjYW4gcmVsaWFibHkgY29udmVydCB0aGlzIGxpbmtcblx0XHRcdFx0aWYgKCFjYW5Db252ZXJ0TGluayhsaW5rVGV4dCkpIHtcblx0XHRcdFx0XHRza2lwcGVkQ291bnQrKztcblx0XHRcdFx0XHRza2lwcGVkTGlua3MucHVzaChsaW5rVGV4dCk7XG5cdFx0XHRcdFx0cmV0dXJuIG1hdGNoOyAvLyBSZXR1cm4gb3JpZ2luYWwgaWYgd2UgY2FuJ3QgY29udmVydCByZWxpYWJseVxuXHRcdFx0XHR9XG5cblx0XHRcdFx0Y29uc3QgZGlzcGxheSA9IGRpc3BsYXlUZXh0IHx8IGxpbmtUZXh0LnJlcGxhY2UoL1xcLihtZHxtZHgpJC8sIFwiXCIpO1xuXG5cdFx0XHRcdC8vIEZvciByZWxhdGl2ZSBsaW5rcyAobm8gZm9sZGVyIHBhdGgpLCB1c2UgY3VycmVudCBmaWxlJ3MgY29udGVudCB0eXBlXG5cdFx0XHRcdGNvbnN0IHVybCA9IHRoaXMuZ2V0QXN0cm9VcmxGcm9tSW50ZXJuYWxMaW5rV2l0aENvbnRleHQobGlua1RleHQsIGZpbGUucGF0aCwgY3VycmVudEZpbGVDb250ZW50VHlwZSk7XG5cblx0XHRcdFx0Y29udmVydGVkQ291bnQrKztcblx0XHRcdFx0cmV0dXJuIGBbJHtkaXNwbGF5fV0oJHt1cmx9KWA7XG5cdFx0XHR9XG5cdFx0KTtcblxuXHRcdC8vIEhhbmRsZSBzdGFuZGFyZCBNYXJrZG93biBsaW5rcyAobm9uLWltYWdlLCBub24tZXh0ZXJuYWwpXG5cdFx0Ly8gT25seSBwcm9jZXNzIGxpbmtzIHRoYXQgY29udGFpbiAubWQgb3IgLm1keCB0byBhdm9pZCBwcm9jZXNzaW5nIGFscmVhZHktY29udmVydGVkIGxpbmtzXG5cdFx0bmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZShcblx0XHRcdC9cXFsoW15cXF1dKylcXF1cXCgoW14pXStcXC4obWR8bWR4KVteKV0qKVxcKS9nLFxuXHRcdFx0KG1hdGNoOiBzdHJpbmcsIGRpc3BsYXlUZXh0OiBzdHJpbmcsIGxpbms6IHN0cmluZykgPT4ge1xuXHRcdFx0XHQvLyBDaGVjayBpZiBpdCdzIGFuIGltYWdlIGxpbmsgb3IgZXh0ZXJuYWwgbGlua1xuXHRcdFx0XHRpZiAobGluay5tYXRjaCgvXmh0dHBzPzpcXC9cXC8vKSB8fCBpbWFnZUV4dGVuc2lvbnMudGVzdChsaW5rKSkge1xuXHRcdFx0XHRcdHNraXBwZWRDb3VudCsrO1xuXHRcdFx0XHRcdHNraXBwZWRMaW5rcy5wdXNoKGxpbmspO1xuXHRcdFx0XHRcdHJldHVybiBtYXRjaDsgLy8gSWdub3JlIGV4dGVybmFsIG9yIGltYWdlIGxpbmtzXG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBDaGVjayBpZiB3ZSBjYW4gcmVsaWFibHkgY29udmVydCB0aGlzIGxpbmtcblx0XHRcdFx0aWYgKCFjYW5Db252ZXJ0TGluayhsaW5rKSkge1xuXHRcdFx0XHRcdHNraXBwZWRDb3VudCsrO1xuXHRcdFx0XHRcdHNraXBwZWRMaW5rcy5wdXNoKGxpbmspO1xuXHRcdFx0XHRcdHJldHVybiBtYXRjaDsgLy8gUmV0dXJuIG9yaWdpbmFsIGlmIHdlIGNhbid0IGNvbnZlcnQgcmVsaWFibHlcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGNvbnN0IHVybCA9IHRoaXMuZ2V0QXN0cm9VcmxGcm9tSW50ZXJuYWxMaW5rV2l0aENvbnRleHQobGluaywgZmlsZS5wYXRoLCBjdXJyZW50RmlsZUNvbnRlbnRUeXBlKTtcblxuXHRcdFx0XHRjb252ZXJ0ZWRDb3VudCsrO1xuXHRcdFx0XHRyZXR1cm4gYFske2Rpc3BsYXlUZXh0fV0oJHt1cmx9KWA7XG5cdFx0XHR9XG5cdFx0KTtcblxuXHRcdC8vIEhhbmRsZSBpbWFnZSBsaW5rcyBpbiBNYXJrZG93biBmb3JtYXQgKGUuZy4sICFbSW1hZ2VdKG1vdW50YWlucy5wbmcpKVxuXHRcdG5ld0NvbnRlbnQgPSBuZXdDb250ZW50LnJlcGxhY2UoXG5cdFx0XHQvIVxcWyguKj8pXFxdXFwoKFteKV0rKVxcKS9nLFxuXHRcdFx0KG1hdGNoOiBzdHJpbmcpID0+IHtcblx0XHRcdFx0c2tpcHBlZENvdW50Kys7XG5cdFx0XHRcdHJldHVybiBtYXRjaDsgLy8gSWdub3JlIGFsbCBpbWFnZSBsaW5rc1xuXHRcdFx0fVxuXHRcdCk7XG5cblx0XHQvLyBIYW5kbGUge3tlbWJlZH19IHN5bnRheFxuXHRcdG5ld0NvbnRlbnQgPSBuZXdDb250ZW50LnJlcGxhY2UoL1xce1xceyhbXn1dKylcXH1cXH0vZywgKG1hdGNoOiBzdHJpbmcsIGZpbGVOYW1lOiBzdHJpbmcpID0+IHtcblx0XHRcdGlmIChpbWFnZUV4dGVuc2lvbnMudGVzdChmaWxlTmFtZSkpIHtcblx0XHRcdFx0c2tpcHBlZENvdW50Kys7XG5cdFx0XHRcdHNraXBwZWRMaW5rcy5wdXNoKGZpbGVOYW1lKTtcblx0XHRcdFx0cmV0dXJuIG1hdGNoOyAvLyBJZ25vcmUgZW1iZWRkZWQgaW1hZ2VzXG5cdFx0XHR9XG5cblx0XHRcdC8vIENoZWNrIGlmIHdlIGNhbiByZWxpYWJseSBjb252ZXJ0IHRoaXMgbGlua1xuXHRcdFx0aWYgKCFjYW5Db252ZXJ0TGluayhmaWxlTmFtZSkpIHtcblx0XHRcdFx0c2tpcHBlZENvdW50Kys7XG5cdFx0XHRcdHNraXBwZWRMaW5rcy5wdXNoKGZpbGVOYW1lKTtcblx0XHRcdFx0cmV0dXJuIG1hdGNoOyAvLyBSZXR1cm4gb3JpZ2luYWwgaWYgd2UgY2FuJ3QgY29udmVydCByZWxpYWJseVxuXHRcdFx0fVxuXG5cdFx0XHRjb25zdCB1cmwgPSB0aGlzLmdldEFzdHJvVXJsRnJvbUludGVybmFsTGlua1dpdGhDb250ZXh0KGZpbGVOYW1lLCBmaWxlLnBhdGgsIGN1cnJlbnRGaWxlQ29udGVudFR5cGUpO1xuXG5cdFx0XHRjb252ZXJ0ZWRDb3VudCsrO1xuXHRcdFx0cmV0dXJuIGBbRW1iZWRkZWQ6ICR7ZmlsZU5hbWV9XSgke3VybH0pYDtcblx0XHR9KTtcblxuXHRcdGVkaXRvci5zZXRWYWx1ZShuZXdDb250ZW50KTtcblxuXHRcdC8vIFJlc3RvcmUgY3Vyc29yIHBvc2l0aW9uLCBhZGp1c3RpbmcgZm9yIGNvbnRlbnQgY2hhbmdlc1xuXHRcdGNvbnN0IG5ld0xpbmVDb3VudCA9IG5ld0NvbnRlbnQuc3BsaXQoJ1xcbicpLmxlbmd0aDtcblx0XHRjb25zdCBuZXdMaW5lTGVuZ3RoID0gbmV3Q29udGVudC5zcGxpdCgnXFxuJylbb3JpZ2luYWxMaW5lXT8ubGVuZ3RoIHx8IDA7XG5cblx0XHQvLyBDYWxjdWxhdGUgbmV3IGN1cnNvciBwb3NpdGlvblxuXHRcdGxldCBuZXdMaW5lID0gb3JpZ2luYWxMaW5lO1xuXHRcdGxldCBuZXdDaCA9IG9yaWdpbmFsQ2g7XG5cblx0XHQvLyBJZiBjb250ZW50IGxlbmd0aCBjaGFuZ2VkLCBhZGp1c3QgY3Vyc29yIHBvc2l0aW9uXG5cdFx0aWYgKG5ld0xpbmVDb3VudCAhPT0gb3JpZ2luYWxMaW5lQ291bnQpIHtcblx0XHRcdC8vIElmIGxpbmVzIHdlcmUgYWRkZWQvcmVtb3ZlZCBiZWZvcmUgY3Vyc29yLCBhZGp1c3QgbGluZSBudW1iZXJcblx0XHRcdC8vIEZvciBzaW1wbGljaXR5LCBrZWVwIHNhbWUgbGluZSBpZiBpdCBzdGlsbCBleGlzdHMsIG90aGVyd2lzZSBjbGFtcCB0byBlbmRcblx0XHRcdGlmIChuZXdMaW5lID49IG5ld0xpbmVDb3VudCkge1xuXHRcdFx0XHRuZXdMaW5lID0gTWF0aC5tYXgoMCwgbmV3TGluZUNvdW50IC0gMSk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gQWRqdXN0IGNvbHVtbiBwb3NpdGlvbiBpZiBsaW5lIGxlbmd0aCBjaGFuZ2VkXG5cdFx0aWYgKG5ld0xpbmVMZW5ndGggIT09IG9yaWdpbmFsTGluZUxlbmd0aCkge1xuXHRcdFx0Ly8gSWYgbGluZSBnb3Qgc2hvcnRlciwgY2xhbXAgdG8gZW5kIG9mIGxpbmVcblx0XHRcdGlmIChuZXdDaCA+IG5ld0xpbmVMZW5ndGgpIHtcblx0XHRcdFx0bmV3Q2ggPSBNYXRoLm1heCgwLCBuZXdMaW5lTGVuZ3RoKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHQvLyBSZXN0b3JlIGN1cnNvciBwb3NpdGlvblxuXHRcdGVkaXRvci5zZXRDdXJzb3IoeyBsaW5lOiBuZXdMaW5lLCBjaDogbmV3Q2ggfSk7XG5cblx0XHQvLyBTaG93IGFwcHJvcHJpYXRlIG5vdGljZSBiYXNlZCBvbiByZXN1bHRzXG5cdFx0aWYgKGNvbnZlcnRlZENvdW50ID4gMCAmJiBza2lwcGVkQ291bnQgPT09IDApIHtcblx0XHRcdG5ldyBOb3RpY2UoYENvbnZlcnRlZCAke2NvbnZlcnRlZENvdW50fSBpbnRlcm5hbCBsaW5rJHtjb252ZXJ0ZWRDb3VudCA+IDEgPyAncycgOiAnJ30gZm9yIEFzdHJvLmApO1xuXHRcdH0gZWxzZSBpZiAoY29udmVydGVkQ291bnQgPiAwICYmIHNraXBwZWRDb3VudCA+IDApIHtcblx0XHRcdG5ldyBOb3RpY2UoYENvbnZlcnRlZCAke2NvbnZlcnRlZENvdW50fSBsaW5rJHtjb252ZXJ0ZWRDb3VudCA+IDEgPyAncycgOiAnJ30gZm9yIEFzdHJvLiBTa2lwcGVkICR7c2tpcHBlZENvdW50fSBsaW5rJHtza2lwcGVkQ291bnQgPiAxID8gJ3MnIDogJyd9IG91dHNpZGUgY29uZmlndXJlZCBjb250ZW50IGRpcmVjdG9yaWVzLmApO1xuXHRcdH0gZWxzZSBpZiAoc2tpcHBlZENvdW50ID4gMCkge1xuXHRcdFx0bmV3IE5vdGljZShgTm8gbGlua3MgY29udmVydGVkLiBBbGwgJHtza2lwcGVkQ291bnR9IGxpbmske3NraXBwZWRDb3VudCA+IDEgPyAncycgOiAnJ30gYXJlIG91dHNpZGUgY29uZmlndXJlZCBjb250ZW50IGRpcmVjdG9yaWVzIG9yIGFyZSBpbWFnZXMvZXh0ZXJuYWwgbGlua3MuYCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdG5ldyBOb3RpY2UoXCJObyBpbnRlcm5hbCBsaW5rcyBmb3VuZCB0byBjb252ZXJ0LlwiKTtcblx0XHR9XG5cdH1cbn1cbiIsICJpbXBvcnQgeyBBcHAsIE1vZGFsLCBURmlsZSwgTm90aWNlLCBQbGF0Zm9ybSwgTWFya2Rvd25WaWV3IH0gZnJvbSBcIm9ic2lkaWFuXCI7XHJcbmltcG9ydCB7IEFzdHJvQ29tcG9zZXJQbHVnaW5JbnRlcmZhY2UsIENvbnRlbnRUeXBlSWQgfSBmcm9tIFwiLi4vdHlwZXNcIjtcclxuaW1wb3J0IHsgRmlsZU9wZXJhdGlvbnMgfSBmcm9tIFwiLi4vdXRpbHMvZmlsZS1vcGVyYXRpb25zXCI7XHJcbmltcG9ydCB7IFRlbXBsYXRlUGFyc2VyIH0gZnJvbSBcIi4uL3V0aWxzL3RlbXBsYXRlLXBhcnNpbmdcIjtcclxuaW1wb3J0IHsgdG9LZWJhYkNhc2UgfSBmcm9tIFwiLi4vdXRpbHMvc3RyaW5nLXV0aWxzXCI7XHJcblxyXG5leHBvcnQgY2xhc3MgVGl0bGVNb2RhbCBleHRlbmRzIE1vZGFsIHtcclxuXHRmaWxlOiBURmlsZSB8IG51bGw7XHJcblx0cGx1Z2luOiBBc3Ryb0NvbXBvc2VyUGx1Z2luSW50ZXJmYWNlO1xyXG5cdHR5cGU6IENvbnRlbnRUeXBlSWQ7XHJcblx0aXNSZW5hbWU6IGJvb2xlYW47XHJcblx0aXNOZXdOb3RlOiBib29sZWFuO1xyXG5cdHRpdGxlSW5wdXQhOiBIVE1MSW5wdXRFbGVtZW50O1xyXG5cdHByaXZhdGUgZmlsZU9wczogRmlsZU9wZXJhdGlvbnM7XHJcblx0cHJpdmF0ZSB0ZW1wbGF0ZVBhcnNlcjogVGVtcGxhdGVQYXJzZXI7XHJcblxyXG5cdGNvbnN0cnVjdG9yKGFwcDogQXBwLCBmaWxlOiBURmlsZSB8IG51bGwsIHBsdWdpbjogQXN0cm9Db21wb3NlclBsdWdpbkludGVyZmFjZSwgdHlwZTogQ29udGVudFR5cGVJZCwgaXNSZW5hbWUgPSBmYWxzZSwgaXNOZXdOb3RlID0gZmFsc2UpIHtcclxuXHRcdHN1cGVyKGFwcCk7XHJcblx0XHR0aGlzLmZpbGUgPSBmaWxlO1xyXG5cdFx0dGhpcy5wbHVnaW4gPSBwbHVnaW47XHJcblx0XHR0aGlzLnR5cGUgPSB0eXBlO1xyXG5cdFx0dGhpcy5pc1JlbmFtZSA9IGlzUmVuYW1lO1xyXG5cdFx0dGhpcy5pc05ld05vdGUgPSBpc05ld05vdGU7XHJcblxyXG5cdFx0Ly8gSW5pdGlhbGl6ZSB1dGlsaXRpZXMgd2l0aCBjdXJyZW50IHNldHRpbmdzXHJcblx0XHQvLyBGaWxlT3BlcmF0aW9ucyB3aWxsIGdldCBmcmVzaCBzZXR0aW5ncyBmcm9tIHBsdWdpbiBkeW5hbWljYWxseVxyXG5cdFx0Y29uc3Qgc2V0dGluZ3MgPSBwbHVnaW4uc2V0dGluZ3M7XHJcblx0XHR0aGlzLmZpbGVPcHMgPSBuZXcgRmlsZU9wZXJhdGlvbnMoYXBwLCBzZXR0aW5ncywgcGx1Z2luKTtcclxuXHRcdHRoaXMudGVtcGxhdGVQYXJzZXIgPSBuZXcgVGVtcGxhdGVQYXJzZXIoYXBwLCBzZXR0aW5ncyk7XHJcblx0fVxyXG5cclxuXHRhc3luYyBnZXRDdXJyZW50VGl0bGVBc3luYygpOiBQcm9taXNlPHN0cmluZz4ge1xyXG5cdFx0aWYgKCF0aGlzLmZpbGUpIHtcclxuXHRcdFx0cmV0dXJuIFwiXCI7XHJcblx0XHR9XHJcblxyXG5cdFx0Ly8gUmVhZCB0aGUgZmlsZSBjb250ZW50IGRpcmVjdGx5IHRvIGVuc3VyZSB3ZSBoYXZlIHRoZSBsYXRlc3QgdGl0bGVcclxuXHRcdHRyeSB7XHJcblx0XHRcdGNvbnN0IGNvbnRlbnQgPSBhd2FpdCB0aGlzLmFwcC52YXVsdC5yZWFkKHRoaXMuZmlsZSk7XHJcblx0XHRcdGNvbnN0IHRpdGxlS2V5ID0gdGhpcy5maWxlT3BzLmdldFRpdGxlS2V5KHRoaXMudHlwZSk7XHJcblx0XHRcdGNvbnN0IHsgcHJvcGVydGllcyB9ID0gdGhpcy50ZW1wbGF0ZVBhcnNlci5wYXJzZUZyb250bWF0dGVyKGNvbnRlbnQpO1xyXG5cclxuXHRcdFx0aWYgKHRpdGxlS2V5IGluIHByb3BlcnRpZXMpIHtcclxuXHRcdFx0XHRjb25zdCB0aXRsZVZhbHVlID0gcHJvcGVydGllc1t0aXRsZUtleV07XHJcblx0XHRcdFx0aWYgKEFycmF5LmlzQXJyYXkodGl0bGVWYWx1ZSkgJiYgdGl0bGVWYWx1ZS5sZW5ndGggPiAwKSB7XHJcblx0XHRcdFx0XHRyZXR1cm4gU3RyaW5nKHRpdGxlVmFsdWVbMF0pO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0XHRpZiAodGl0bGVWYWx1ZSAhPT0gbnVsbCAmJiB0aXRsZVZhbHVlICE9PSB1bmRlZmluZWQpIHtcclxuXHRcdFx0XHRcdHJldHVybiBTdHJpbmcodGl0bGVWYWx1ZSk7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblx0XHR9IGNhdGNoIChlcnJvcikge1xyXG5cdFx0XHRjb25zb2xlLmVycm9yKFwiRXJyb3IgcmVhZGluZyBmaWxlIGZvciB0aXRsZTpcIiwgZXJyb3IpO1xyXG5cdFx0fVxyXG5cclxuXHRcdC8vIEZhbGwgYmFjayB0byBmaWxlbmFtZS1iYXNlZCB0aXRsZVxyXG5cdFx0cmV0dXJuIHRoaXMuZ2V0RmFsbGJhY2tUaXRsZSgpO1xyXG5cdH1cclxuXHJcblx0Z2V0Q3VycmVudFRpdGxlKCk6IHN0cmluZyB7XHJcblx0XHRpZiAoIXRoaXMuZmlsZSkge1xyXG5cdFx0XHRyZXR1cm4gXCJcIjtcclxuXHRcdH1cclxuXHJcblx0XHRjb25zdCB0aXRsZUtleSA9IHRoaXMuZmlsZU9wcy5nZXRUaXRsZUtleSh0aGlzLnR5cGUpO1xyXG5cdFx0Y29uc3QgY2FjaGUgPSB0aGlzLmFwcC5tZXRhZGF0YUNhY2hlLmdldEZpbGVDYWNoZSh0aGlzLmZpbGUpO1xyXG5cclxuXHRcdGlmIChjYWNoZT8uZnJvbnRtYXR0ZXIgJiYgdGl0bGVLZXkgaW4gY2FjaGUuZnJvbnRtYXR0ZXIpIHtcclxuXHRcdFx0Y29uc3QgdGl0bGVWYWx1ZSA9IGNhY2hlLmZyb250bWF0dGVyW3RpdGxlS2V5XSBhcyB1bmtub3duO1xyXG5cdFx0XHRpZiAodHlwZW9mIHRpdGxlVmFsdWUgPT09ICdzdHJpbmcnKSB7XHJcblx0XHRcdFx0cmV0dXJuIHRpdGxlVmFsdWU7XHJcblx0XHRcdH1cclxuXHRcdFx0aWYgKEFycmF5LmlzQXJyYXkodGl0bGVWYWx1ZSkgJiYgdGl0bGVWYWx1ZS5sZW5ndGggPiAwKSB7XHJcblx0XHRcdFx0Y29uc3QgZmlyc3RWYWx1ZSA9IHRpdGxlVmFsdWVbMF0gYXMgdW5rbm93bjtcclxuXHRcdFx0XHRpZiAodHlwZW9mIGZpcnN0VmFsdWUgPT09ICdzdHJpbmcnKSB7XHJcblx0XHRcdFx0XHRyZXR1cm4gZmlyc3RWYWx1ZTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdFx0aWYgKGZpcnN0VmFsdWUgIT0gbnVsbCkge1xyXG5cdFx0XHRcdFx0aWYgKHR5cGVvZiBmaXJzdFZhbHVlID09PSAnbnVtYmVyJyB8fCB0eXBlb2YgZmlyc3RWYWx1ZSA9PT0gJ2Jvb2xlYW4nKSB7XHJcblx0XHRcdFx0XHRcdHJldHVybiBTdHJpbmcoZmlyc3RWYWx1ZSk7XHJcblx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRpZiAodHlwZW9mIGZpcnN0VmFsdWUgPT09ICdzdHJpbmcnKSB7XHJcblx0XHRcdFx0XHRcdHJldHVybiBmaXJzdFZhbHVlO1xyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdH1cclxuXHRcdFx0fVxyXG5cdFx0XHRpZiAodGl0bGVWYWx1ZSA9PSBudWxsKSB7XHJcblx0XHRcdFx0cmV0dXJuICcnO1xyXG5cdFx0XHR9XHJcblx0XHRcdGlmICh0eXBlb2YgdGl0bGVWYWx1ZSA9PT0gJ251bWJlcicgfHwgdHlwZW9mIHRpdGxlVmFsdWUgPT09ICdib29sZWFuJykge1xyXG5cdFx0XHRcdHJldHVybiBTdHJpbmcodGl0bGVWYWx1ZSk7XHJcblx0XHRcdH1cclxuXHRcdFx0aWYgKHR5cGVvZiB0aXRsZVZhbHVlID09PSAnc3RyaW5nJykge1xyXG5cdFx0XHRcdHJldHVybiB0aXRsZVZhbHVlO1xyXG5cdFx0XHR9XHJcblx0XHRcdHJldHVybiAnJztcclxuXHRcdH1cclxuXHRcdHJldHVybiB0aGlzLmdldEZhbGxiYWNrVGl0bGUoKTtcclxuXHR9XHJcblxyXG5cdHByaXZhdGUgZ2V0RmFsbGJhY2tUaXRsZSgpOiBzdHJpbmcge1xyXG5cdFx0aWYgKCF0aGlzLmZpbGUpIHtcclxuXHRcdFx0cmV0dXJuIFwiXCI7XHJcblx0XHR9XHJcblxyXG5cdFx0bGV0IGJhc2VuYW1lID0gdGhpcy5maWxlLmJhc2VuYW1lO1xyXG5cdFx0aWYgKHRoaXMuZmlsZS5wYXJlbnQgJiYgdGhpcy50eXBlICE9PSBcIm5vdGVcIikge1xyXG5cdFx0XHRjb25zdCBjb250ZW50VHlwZSA9IHRoaXMuZmlsZU9wcy5nZXRDb250ZW50VHlwZSh0aGlzLnR5cGUpO1xyXG5cdFx0XHRjb25zdCBpbmRleEZpbGVOYW1lID0gY29udGVudFR5cGU/LmluZGV4RmlsZU5hbWUgfHwgXCJcIjtcclxuXHRcdFx0aWYgKGluZGV4RmlsZU5hbWUudHJpbSgpICE9PSBcIlwiICYmIGJhc2VuYW1lID09PSBpbmRleEZpbGVOYW1lKSB7XHJcblx0XHRcdFx0YmFzZW5hbWUgPSB0aGlzLmZpbGUucGFyZW50Lm5hbWU7XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHRcdGlmIChiYXNlbmFtZS5zdGFydHNXaXRoKFwiX1wiKSkge1xyXG5cdFx0XHRiYXNlbmFtZSA9IGJhc2VuYW1lLnNsaWNlKDEpO1xyXG5cdFx0fVxyXG5cdFx0cmV0dXJuIGJhc2VuYW1lLnJlcGxhY2UoLy0vZywgXCIgXCIpLnNwbGl0KFwiIFwiKS5tYXAod29yZCA9PiB3b3JkLmNoYXJBdCgwKS50b1VwcGVyQ2FzZSgpICsgd29yZC5zbGljZSgxKSkuam9pbihcIiBcIik7XHJcblx0fVxyXG5cclxuXHQvKipcclxuXHQgKiBFeHRyYWN0cyBhIHN1Z2dlc3RlZCB0aXRsZSBmcm9tIHRoZSBmaWxlIGJhc2VuYW1lIGZvciBuZXdseSBjcmVhdGVkIGZpbGVzLlxyXG5cdCAqIFRoaXMgaXMgdXNlZCB3aGVuIGEgZmlsZSBpcyBjcmVhdGVkIGZyb20gYSBsaW5rIChlLmcuLCBbW3NFZnNsZWlmXV0pLlxyXG5cdCAqIFByZXNlcnZlcyB0aGUgb3JpZ2luYWwgdGV4dCBhcyBtdWNoIGFzIHBvc3NpYmxlLlxyXG5cdCAqL1xyXG5cdGdldFN1Z2dlc3RlZFRpdGxlRnJvbUJhc2VuYW1lKCk6IHN0cmluZyB7XHJcblx0XHRpZiAoIXRoaXMuZmlsZSkge1xyXG5cdFx0XHRyZXR1cm4gXCJcIjtcclxuXHRcdH1cclxuXHJcblx0XHRsZXQgYmFzZW5hbWUgPSB0aGlzLmZpbGUuYmFzZW5hbWU7XHJcblxyXG5cdFx0Ly8gSGFuZGxlIGluZGV4IGZpbGUgbmFtZXMgLSB1c2UgcGFyZW50IGZvbGRlciBuYW1lIGluc3RlYWRcclxuXHRcdGlmICh0aGlzLmZpbGUucGFyZW50ICYmIHRoaXMudHlwZSAhPT0gXCJub3RlXCIpIHtcclxuXHRcdFx0Y29uc3QgY29udGVudFR5cGUgPSB0aGlzLmZpbGVPcHMuZ2V0Q29udGVudFR5cGUodGhpcy50eXBlKTtcclxuXHRcdFx0Y29uc3QgaW5kZXhGaWxlTmFtZSA9IGNvbnRlbnRUeXBlPy5pbmRleEZpbGVOYW1lIHx8IFwiXCI7XHJcblx0XHRcdGlmIChpbmRleEZpbGVOYW1lLnRyaW0oKSAhPT0gXCJcIiAmJiBiYXNlbmFtZSA9PT0gaW5kZXhGaWxlTmFtZSkge1xyXG5cdFx0XHRcdGJhc2VuYW1lID0gdGhpcy5maWxlLnBhcmVudC5uYW1lO1xyXG5cdFx0XHR9XHJcblx0XHR9XHJcblxyXG5cdFx0Ly8gUmVtb3ZlIGxlYWRpbmcgdW5kZXJzY29yZSBpZiBwcmVzZW50XHJcblx0XHRpZiAoYmFzZW5hbWUuc3RhcnRzV2l0aChcIl9cIikpIHtcclxuXHRcdFx0YmFzZW5hbWUgPSBiYXNlbmFtZS5zbGljZSgxKTtcclxuXHRcdH1cclxuXHJcblx0XHQvLyBSZXR1cm4gdGhlIGJhc2VuYW1lIGFzLWlzIHRvIHByZXNlcnZlIHVzZXIncyBvcmlnaW5hbCBpbnB1dFxyXG5cdFx0Ly8gKGUuZy4sIFwic0Vmc2xlaWZcIiBzdGF5cyBhcyBcInNFZnNsZWlmXCIpXHJcblx0XHRyZXR1cm4gYmFzZW5hbWU7XHJcblx0fVxyXG5cclxuXHRvbk9wZW4oKSB7XHJcblx0XHRjb25zdCB7IGNvbnRlbnRFbCB9ID0gdGhpcztcclxuXHRcdGNvbnRlbnRFbC5lbXB0eSgpO1xyXG5cclxuXHRcdC8vIEFkZCBtb2JpbGUtZnJpZW5kbHkgcG9zaXRpb25pbmcgY2xhc3MgLSBjaGVjayBib3RoIHdpZHRoIGFuZCBwbGF0Zm9ybVxyXG5cdFx0Y29uc3QgaXNNb2JpbGUgPSB3aW5kb3cuaW5uZXJXaWR0aCA8PSA3NjggfHwgUGxhdGZvcm0uaXNNb2JpbGU7XHJcblx0XHRpZiAoaXNNb2JpbGUpIHtcclxuXHRcdFx0dGhpcy5tb2RhbEVsLmFkZENsYXNzKCdhc3Ryby1jb21wb3Nlci1tb2JpbGUtbW9kYWwnKTtcclxuXHRcdH1cclxuXHJcblx0XHRpZiAodGhpcy5pc1JlbmFtZSkge1xyXG5cdFx0XHRjb25zdCB0eXBlTmFtZSA9IHRoaXMuZ2V0VHlwZURpc3BsYXlOYW1lKCk7XHJcblxyXG5cdFx0XHRpZiAodGhpcy50eXBlID09PSBcIm5vdGVcIikge1xyXG5cdFx0XHRcdC8vIEZvciBnZW5lcmljIG5vdGVzIG91dHNpZGUgb2YgYW55IGtub3duIGNvbnRlbnQgdHlwZVxyXG5cdFx0XHRcdGNvbnRlbnRFbC5jcmVhdGVFbChcImgyXCIsIHsgdGV4dDogXCJSZW5hbWUgY29udGVudFwiIH0pO1xyXG5cdFx0XHRcdGNvbnRlbnRFbC5jcmVhdGVFbChcInBcIiwgeyB0ZXh0OiBcIkVudGVyIGEgdGl0bGUgZm9yIHRoaXMgY29udGVudDpcIiB9KTtcclxuXHRcdFx0fSBlbHNlIHtcclxuXHRcdFx0XHRjb250ZW50RWwuY3JlYXRlRWwoXCJoMlwiLCB7IHRleHQ6IGBSZW5hbWUgJHt0eXBlTmFtZX0gY29udGVudGAgfSk7XHJcblx0XHRcdFx0Y29udGVudEVsLmNyZWF0ZUVsKFwicFwiLCB7IHRleHQ6IGBFbnRlciBuZXcgdGl0bGUgZm9yIHlvdXIgJHt0eXBlTmFtZX0gY29udGVudDpgIH0pO1xyXG5cdFx0XHR9XHJcblxyXG5cdFx0XHR0aGlzLnRpdGxlSW5wdXQgPSBjb250ZW50RWwuY3JlYXRlRWwoXCJpbnB1dFwiLCB7XHJcblx0XHRcdFx0dHlwZTogXCJ0ZXh0XCIsXHJcblx0XHRcdFx0cGxhY2Vob2xkZXI6IFwiTmV3IFRpdGxlXCIsXHJcblx0XHRcdFx0Y2xzOiBcImFzdHJvLWNvbXBvc2VyLXRpdGxlLWlucHV0XCJcclxuXHRcdFx0fSk7XHJcblxyXG5cdFx0XHQvLyBBc3luYyBsb2FkIHRoZSBjdXJyZW50IHRpdGxlIGZyb20gZmlsZVxyXG5cdFx0XHR2b2lkIHRoaXMuZ2V0Q3VycmVudFRpdGxlQXN5bmMoKS50aGVuKHRpdGxlID0+IHtcclxuXHRcdFx0XHR0aGlzLnRpdGxlSW5wdXQudmFsdWUgPSB0aXRsZTtcclxuXHRcdFx0fSk7XHJcblx0XHR9IGVsc2UgaWYgKHRoaXMuaXNOZXdOb3RlKSB7XHJcblx0XHRcdGNvbnN0IHR5cGVOYW1lID0gdGhpcy5nZXRUeXBlRGlzcGxheU5hbWUoKTtcclxuXHJcblx0XHRcdGlmICh0aGlzLnR5cGUgPT09IFwibm90ZVwiKSB7XHJcblx0XHRcdFx0Y29udGVudEVsLmNyZWF0ZUVsKFwiaDJcIiwgeyB0ZXh0OiBcIk5ldyBjb250ZW50XCIgfSk7XHJcblx0XHRcdFx0Y29udGVudEVsLmNyZWF0ZUVsKFwicFwiLCB7IHRleHQ6IFwiRW50ZXIgYSB0aXRsZSBmb3IgdGhpcyBjb250ZW50OlwiIH0pO1xyXG5cdFx0XHR9IGVsc2Uge1xyXG5cdFx0XHRcdGNvbnRlbnRFbC5jcmVhdGVFbChcImgyXCIsIHsgdGV4dDogYENyZWF0ZSBuZXcgJHt0eXBlTmFtZX0gY29udGVudGAgfSk7XHJcblx0XHRcdFx0Y29udGVudEVsLmNyZWF0ZUVsKFwicFwiLCB7IHRleHQ6IGBFbnRlciBhIHRpdGxlIGZvciB5b3VyIG5ldyAke3R5cGVOYW1lfSBjb250ZW50OmAgfSk7XHJcblx0XHRcdH1cclxuXHJcblx0XHRcdHRoaXMudGl0bGVJbnB1dCA9IGNvbnRlbnRFbC5jcmVhdGVFbChcImlucHV0XCIsIHtcclxuXHRcdFx0XHR0eXBlOiBcInRleHRcIixcclxuXHRcdFx0XHRwbGFjZWhvbGRlcjogXCJOZXcgVGl0bGVcIixcclxuXHRcdFx0XHRjbHM6IFwiYXN0cm8tY29tcG9zZXItdGl0bGUtaW5wdXRcIlxyXG5cdFx0XHR9KTtcclxuXHRcdFx0Ly8gTGVhdmUgaW5wdXQgZW1wdHkgZm9yIG5ldyBub3RlcyAtIHVzZXIgY2FuIHR5cGUgZGlyZWN0bHlcclxuXHRcdH0gZWxzZSB7XHJcblx0XHRcdGNvbnN0IHR5cGVOYW1lID0gdGhpcy5nZXRUeXBlRGlzcGxheU5hbWUoKTtcclxuXHJcblx0XHRcdGlmICh0aGlzLnR5cGUgPT09IFwibm90ZVwiKSB7XHJcblx0XHRcdFx0Y29udGVudEVsLmNyZWF0ZUVsKFwiaDJcIiwgeyB0ZXh0OiBcIk5ldyBjb250ZW50XCIgfSk7XHJcblx0XHRcdFx0Y29udGVudEVsLmNyZWF0ZUVsKFwicFwiLCB7IHRleHQ6IFwiRW50ZXIgYSB0aXRsZSBmb3IgdGhpcyBjb250ZW50OlwiIH0pO1xyXG5cdFx0XHR9IGVsc2Uge1xyXG5cdFx0XHRcdGNvbnRlbnRFbC5jcmVhdGVFbChcImgyXCIsIHsgdGV4dDogYENyZWF0ZSBuZXcgJHt0eXBlTmFtZX0gY29udGVudGAgfSk7XHJcblx0XHRcdFx0Y29udGVudEVsLmNyZWF0ZUVsKFwicFwiLCB7IHRleHQ6IGBFbnRlciBhIHRpdGxlIGZvciB5b3VyIG5ldyAke3R5cGVOYW1lfSBjb250ZW50OmAgfSk7XHJcblx0XHRcdH1cclxuXHJcblx0XHRcdHRoaXMudGl0bGVJbnB1dCA9IGNvbnRlbnRFbC5jcmVhdGVFbChcImlucHV0XCIsIHtcclxuXHRcdFx0XHR0eXBlOiBcInRleHRcIixcclxuXHRcdFx0XHRwbGFjZWhvbGRlcjogXCJOZXcgVGl0bGVcIixcclxuXHRcdFx0XHRjbHM6IFwiYXN0cm8tY29tcG9zZXItdGl0bGUtaW5wdXRcIlxyXG5cdFx0XHR9KTtcclxuXHRcdFx0Ly8gUHJlLXBvcHVsYXRlIHdpdGggc3VnZ2VzdGVkIHRpdGxlIGZyb20gYmFzZW5hbWUgaWYgYXZhaWxhYmxlXHJcblx0XHRcdC8vIFRoaXMgaGFuZGxlcyBmaWxlcyBjcmVhdGVkIGZyb20gbGlua3MgKGUuZy4sIFtbc0Vmc2xlaWZdXSlcclxuXHRcdFx0aWYgKHRoaXMuZmlsZSkge1xyXG5cdFx0XHRcdGNvbnN0IHN1Z2dlc3RlZFRpdGxlID0gdGhpcy5nZXRTdWdnZXN0ZWRUaXRsZUZyb21CYXNlbmFtZSgpO1xyXG5cdFx0XHRcdGlmIChzdWdnZXN0ZWRUaXRsZSkge1xyXG5cdFx0XHRcdFx0dGhpcy50aXRsZUlucHV0LnZhbHVlID0gc3VnZ2VzdGVkVGl0bGU7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblx0XHR9XHJcblx0XHR0aGlzLnRpdGxlSW5wdXQuZm9jdXMoKTtcclxuXHRcdC8vIEZvciBuZXcgbm90ZXMsIGVuc3VyZSBjdXJzb3IgaXMgYXQgdGhlIHN0YXJ0IChwb3NpdGlvbiAwKVxyXG5cdFx0aWYgKHRoaXMuaXNOZXdOb3RlKSB7XHJcblx0XHRcdHNldFRpbWVvdXQoKCkgPT4ge1xyXG5cdFx0XHRcdHRoaXMudGl0bGVJbnB1dC5zZXRTZWxlY3Rpb25SYW5nZSgwLCAwKTtcclxuXHRcdFx0fSwgMCk7XHJcblx0XHR9XHJcblxyXG5cdFx0Y29uc3QgYnV0dG9uQ29udGFpbmVyID0gY29udGVudEVsLmNyZWF0ZURpdih7IGNsczogXCJhc3Ryby1jb21wb3Nlci1idXR0b24tY29udGFpbmVyXCIgfSk7XHJcblxyXG5cdFx0Y29uc3QgY2FuY2VsQnV0dG9uID0gYnV0dG9uQ29udGFpbmVyLmNyZWF0ZUVsKFwiYnV0dG9uXCIsIHsgdGV4dDogXCJDYW5jZWxcIiwgY2xzOiBcImFzdHJvLWNvbXBvc2VyLWNhbmNlbC1idXR0b25cIiB9KTtcclxuXHRcdGNhbmNlbEJ1dHRvbi5vbmNsaWNrID0gKCkgPT4gdGhpcy5jbG9zZSgpO1xyXG5cclxuXHRcdGNvbnN0IHN1Ym1pdEJ1dHRvbiA9IGJ1dHRvbkNvbnRhaW5lci5jcmVhdGVFbChcImJ1dHRvblwiLCB7IHRleHQ6IHRoaXMuaXNSZW5hbWUgPyBcIlJlbmFtZVwiIDogXCJDcmVhdGVcIiwgY2xzOiBbXCJhc3Ryby1jb21wb3Nlci1jcmVhdGUtYnV0dG9uXCIsIFwibW9kLWN0YVwiXSB9KTtcclxuXHRcdHN1Ym1pdEJ1dHRvbi5vbmNsaWNrID0gKCkgPT4gdGhpcy5zdWJtaXQoKTtcclxuXHJcblx0XHR0aGlzLnRpdGxlSW5wdXQuYWRkRXZlbnRMaXN0ZW5lcihcImtleXByZXNzXCIsIChlKSA9PiB7XHJcblx0XHRcdGlmIChlLmtleSA9PT0gXCJFbnRlclwiKSB2b2lkIHRoaXMuc3VibWl0KCk7XHJcblx0XHR9KTtcclxuXHR9XHJcblxyXG5cdGFzeW5jIHN1Ym1pdCgpIHtcclxuXHRcdGNvbnN0IHRpdGxlID0gdGhpcy50aXRsZUlucHV0LnZhbHVlLnRyaW0oKTtcclxuXHJcblx0XHRpZiAoIXRpdGxlKSB7XHJcblx0XHRcdG5ldyBOb3RpY2UoXCJQbGVhc2UgZW50ZXIgYSB0aXRsZS5cIik7XHJcblx0XHRcdHJldHVybjtcclxuXHRcdH1cclxuXHJcblx0XHR0cnkge1xyXG5cdFx0XHRsZXQgbmV3RmlsZTogVEZpbGUgfCBudWxsID0gbnVsbDtcclxuXHRcdFx0aWYgKHRoaXMuaXNSZW5hbWUpIHtcclxuXHRcdFx0XHRuZXdGaWxlID0gYXdhaXQgdGhpcy5maWxlT3BzLnJlbmFtZUZpbGUoeyBmaWxlOiB0aGlzLmZpbGUhLCB0aXRsZSwgdHlwZTogdGhpcy50eXBlIH0pO1xyXG5cclxuXHRcdFx0XHRpZiAobmV3RmlsZSkge1xyXG5cdFx0XHRcdFx0YXdhaXQgdGhpcy50ZW1wbGF0ZVBhcnNlci51cGRhdGVUaXRsZUluRnJvbnRtYXR0ZXIobmV3RmlsZSwgdGl0bGUsIHRoaXMudHlwZSk7XHJcblx0XHRcdFx0fSBlbHNlIHtcclxuXHRcdFx0XHRcdC8vIHJlbmFtZUZpbGUgYWxyZWFkeSBzaG93ZWQgYW4gZXJyb3Igbm90aWNlLCBjbG9zZSBtb2RhbCBhbmQgcmV0dXJuXHJcblx0XHRcdFx0XHR0aGlzLmNsb3NlKCk7XHJcblx0XHRcdFx0XHRyZXR1cm47XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9IGVsc2UgaWYgKHRoaXMuaXNOZXdOb3RlKSB7XHJcblx0XHRcdFx0Ly8gUHJvY2VzcyB0aGUgXCJVbnRpdGxlZFwiIGZpbGUgLSByZW5hbWUgaXQgYW5kIGFkZCBwcm9wZXJ0aWVzXHJcblx0XHRcdFx0Ly8gVGhpcyByZXNwZWN0cyBjcmVhdGlvbk1vZGUgKGZvbGRlciB2cyBmaWxlKSBhbmQgZG9lc24ndCByZXF1aXJlIGRlbGV0aW9uXHJcblx0XHRcdFx0aWYgKHRoaXMuZmlsZSkge1xyXG5cdFx0XHRcdFx0bmV3RmlsZSA9IGF3YWl0IHRoaXMuZmlsZU9wcy5jcmVhdGVGaWxlKHsgZmlsZTogdGhpcy5maWxlLCB0aXRsZSwgdHlwZTogdGhpcy50eXBlIH0pO1xyXG5cdFx0XHRcdFx0Ly8gQWx3YXlzIGluc2VydCBwcm9wZXJ0aWVzIHdoZW4gYXV0b0luc2VydFByb3BlcnRpZXMgaXMgZW5hYmxlZFxyXG5cdFx0XHRcdFx0Y29uc3Qgc2hvdWxkSW5zZXJ0UHJvcGVydGllcyA9IHRoaXMucGx1Z2luLnNldHRpbmdzLmF1dG9JbnNlcnRQcm9wZXJ0aWVzO1xyXG5cclxuXHRcdFx0XHRcdGlmIChuZXdGaWxlICYmIHNob3VsZEluc2VydFByb3BlcnRpZXMpIHtcclxuXHRcdFx0XHRcdFx0YXdhaXQgdGhpcy5hZGRQcm9wZXJ0aWVzVG9GaWxlKG5ld0ZpbGUsIHRpdGxlLCB0aGlzLnR5cGUpO1xyXG5cdFx0XHRcdFx0XHQvLyBQb3NpdGlvbiBjdXJzb3IgYXQgZW5kIGFmdGVyIHByb3BlcnRpZXMgYXJlIGFkZGVkXHJcblx0XHRcdFx0XHRcdHRoaXMucG9zaXRpb25DdXJzb3JBdEVuZChuZXdGaWxlKTtcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHR9XHJcblx0XHRcdH0gZWxzZSBpZiAodGhpcy5maWxlKSB7XHJcblx0XHRcdFx0Ly8gV2UgaGF2ZSBhbiBleGlzdGluZyBmaWxlLCBwcm9jZXNzIGl0XHJcblx0XHRcdFx0bmV3RmlsZSA9IGF3YWl0IHRoaXMuZmlsZU9wcy5jcmVhdGVGaWxlKHsgZmlsZTogdGhpcy5maWxlLCB0aXRsZSwgdHlwZTogdGhpcy50eXBlIH0pO1xyXG5cdFx0XHRcdC8vIEFsd2F5cyBpbnNlcnQgcHJvcGVydGllcyB3aGVuIGF1dG9JbnNlcnRQcm9wZXJ0aWVzIGlzIGVuYWJsZWRcclxuXHRcdFx0XHRjb25zdCBzaG91bGRJbnNlcnRQcm9wZXJ0aWVzID0gdGhpcy5wbHVnaW4uc2V0dGluZ3MuYXV0b0luc2VydFByb3BlcnRpZXM7XHJcblxyXG5cdFx0XHRcdGlmIChuZXdGaWxlICYmIHNob3VsZEluc2VydFByb3BlcnRpZXMpIHtcclxuXHRcdFx0XHRcdGF3YWl0IHRoaXMuYWRkUHJvcGVydGllc1RvRmlsZShuZXdGaWxlLCB0aXRsZSwgdGhpcy50eXBlKTtcclxuXHRcdFx0XHRcdC8vIFBvc2l0aW9uIGN1cnNvciBhdCBlbmQgYWZ0ZXIgcHJvcGVydGllcyBhcmUgYWRkZWRcclxuXHRcdFx0XHRcdHRoaXMucG9zaXRpb25DdXJzb3JBdEVuZChuZXdGaWxlKTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdH0gZWxzZSB7XHJcblx0XHRcdFx0Ly8gRmFsbGJhY2sgLSBjcmVhdGUgbmV3IGZpbGVcclxuXHRcdFx0XHRuZXdGaWxlID0gYXdhaXQgdGhpcy5jcmVhdGVOZXdGaWxlKHRpdGxlKTtcclxuXHRcdFx0fVxyXG5cclxuXHRcdFx0aWYgKCFuZXdGaWxlKSB7XHJcblx0XHRcdFx0bmV3IE5vdGljZShgRmFpbGVkIHRvICR7dGhpcy5pc1JlbmFtZSA/IFwicmVuYW1lXCIgOiBcImNyZWF0ZVwifSAke3RoaXMudHlwZX0uYCk7XHJcblx0XHRcdFx0dGhpcy5jbG9zZSgpO1xyXG5cdFx0XHRcdHJldHVybjtcclxuXHRcdFx0fVxyXG5cdFx0fSBjYXRjaCAoZXJyb3IpIHtcclxuXHRcdFx0Y29uc29sZS5lcnJvcignVGl0bGVNb2RhbDogRXJyb3IgZHVyaW5nIHByb2Nlc3M6JywgZXJyb3IpO1xyXG5cdFx0XHRjb25zdCBlcnJvck1lc3NhZ2UgPSBlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IubWVzc2FnZSA6IFN0cmluZyhlcnJvcik7XHJcblx0XHRcdG5ldyBOb3RpY2UoYEVycm9yICR7dGhpcy5pc1JlbmFtZSA/IFwicmVuYW1pbmdcIiA6IFwiY3JlYXRpbmdcIn0gJHt0aGlzLnR5cGV9OiAke2Vycm9yTWVzc2FnZX0uYCk7XHJcblx0XHRcdHRoaXMuY2xvc2UoKTtcclxuXHRcdFx0cmV0dXJuO1xyXG5cdFx0fVxyXG5cclxuXHRcdHRoaXMuY2xvc2UoKTtcclxuXHR9XHJcblxyXG5cdHByaXZhdGUgZ2V0VHlwZURpc3BsYXlOYW1lKCk6IHN0cmluZyB7XHJcblx0XHRpZiAodGhpcy50eXBlID09PSBcIm5vdGVcIikge1xyXG5cdFx0XHRyZXR1cm4gXCJDb250ZW50XCI7XHJcblx0XHR9XHJcblx0XHRjb25zdCBjb250ZW50VHlwZSA9IHRoaXMuZmlsZU9wcy5nZXRDb250ZW50VHlwZSh0aGlzLnR5cGUpO1xyXG5cdFx0cmV0dXJuIGNvbnRlbnRUeXBlID8gY29udGVudFR5cGUubmFtZSA6IFwiQ29udGVudFwiO1xyXG5cdH1cclxuXHJcblx0cHJpdmF0ZSBhc3luYyBjcmVhdGVOZXdGaWxlKHRpdGxlOiBzdHJpbmcpOiBQcm9taXNlPFRGaWxlIHwgbnVsbD4ge1xyXG5cdFx0Ly8gRGV0ZXJtaW5lIHRoZSBhcHByb3ByaWF0ZSBmb2xkZXIgYmFzZWQgb24gd2hlcmUgdGhlIHVzZXIgY3JlYXRlZCB0aGUgZmlsZVxyXG5cdFx0bGV0IHRhcmdldEZvbGRlcjogc3RyaW5nO1xyXG5cclxuXHRcdC8vIEdldCB0aGUgZGlyZWN0b3J5IHdoZXJlIHRoZSB1c2VyIGNyZWF0ZWQgdGhlIGZpbGVcclxuXHRcdGNvbnN0IG9yaWdpbmFsRGlyID0gdGhpcy5maWxlPy5wYXJlbnQ/LnBhdGggfHwgXCJcIjtcclxuXHJcblx0XHRpZiAodGhpcy50eXBlICE9PSBcIm5vdGVcIikge1xyXG5cdFx0XHRjb25zdCBjb250ZW50VHlwZSA9IHRoaXMuZmlsZU9wcy5nZXRDb250ZW50VHlwZSh0aGlzLnR5cGUpO1xyXG5cdFx0XHQvLyBGb3IgY29udGVudCB0eXBlcywgcmVzcGVjdCB0aGUgdXNlcidzIGNob3NlbiBsb2NhdGlvbiAoc3ViZm9sZGVyKVxyXG5cdFx0XHQvLyBPbmx5IHVzZSB0aGUgY29uZmlndXJlZCBmb2xkZXIgaWYgdGhlIHVzZXIgY3JlYXRlZCB0aGUgZmlsZSBpbiB0aGUgdmF1bHQgcm9vdFxyXG5cdFx0XHRpZiAob3JpZ2luYWxEaXIgPT09IFwiXCIgfHwgb3JpZ2luYWxEaXIgPT09IFwiL1wiKSB7XHJcblx0XHRcdFx0dGFyZ2V0Rm9sZGVyID0gY29udGVudFR5cGU/LmZvbGRlciB8fCBcIlwiO1xyXG5cdFx0XHR9IGVsc2Uge1xyXG5cdFx0XHRcdHRhcmdldEZvbGRlciA9IG9yaWdpbmFsRGlyO1xyXG5cdFx0XHR9XHJcblx0XHR9IGVsc2Uge1xyXG5cdFx0XHQvLyBGb3Igbm90ZXMsIHVzZSB0aGUgb3JpZ2luYWwgZGlyZWN0b3J5XHJcblx0XHRcdHRhcmdldEZvbGRlciA9IG9yaWdpbmFsRGlyO1xyXG5cdFx0fVxyXG5cclxuXHRcdC8vIENyZWF0ZSB0aGUgZmlsZW5hbWUgZnJvbSB0aGUgdGl0bGVcclxuXHRcdGNvbnN0IGZpbGVuYW1lID0gdGhpcy5maWxlT3BzLmdlbmVyYXRlRmlsZW5hbWUodGl0bGUpO1xyXG5cdFx0Y29uc3QgY29udGVudFR5cGUgPSB0aGlzLmZpbGVPcHMuZ2V0Q29udGVudFR5cGUodGhpcy50eXBlKTtcclxuXHRcdGNvbnN0IGV4dGVuc2lvbiA9IGNvbnRlbnRUeXBlPy51c2VNZHhFeHRlbnNpb24gPyBcIi5tZHhcIiA6IFwiLm1kXCI7XHJcblx0XHRjb25zdCBmaWxlUGF0aCA9IHRhcmdldEZvbGRlciA/IGAke3RhcmdldEZvbGRlcn0vJHtmaWxlbmFtZX0ke2V4dGVuc2lvbn1gIDogYCR7ZmlsZW5hbWV9JHtleHRlbnNpb259YDtcclxuXHJcblx0XHQvLyBUcmFjayB0aGF0IHRoaXMgZmlsZSB3aWxsIGJlIGNyZWF0ZWQgYnkgdGhlIHBsdWdpbiBCRUZPUkUgY3JlYXRpbmcgaXRcclxuXHRcdC8vIFRoaXMgcHJldmVudHMgdGhlIGNyZWF0ZSBldmVudCBmcm9tIHRyaWdnZXJpbmcgYW5vdGhlciBtb2RhbFxyXG5cdFx0aWYgKHRoaXMucGx1Z2luKSB7XHJcblx0XHRcdHRoaXMucGx1Z2luLnBsdWdpbkNyZWF0ZWRGaWxlcy5zZXQoZmlsZVBhdGgsIERhdGUubm93KCkpO1xyXG5cdFx0fVxyXG5cclxuXHRcdC8vIENyZWF0ZSB0aGUgZmlsZSB3aXRoIGluaXRpYWwgY29udGVudFxyXG5cdFx0bGV0IGluaXRpYWxDb250ZW50ID0gXCJcIjtcclxuXHRcdC8vIEFsd2F5cyBpbnNlcnQgcHJvcGVydGllcyB3aGVuIGF1dG9JbnNlcnRQcm9wZXJ0aWVzIGlzIGVuYWJsZWRcclxuXHRcdGlmICh0aGlzLnBsdWdpbi5zZXR0aW5ncy5hdXRvSW5zZXJ0UHJvcGVydGllcykge1xyXG5cdFx0XHRpbml0aWFsQ29udGVudCA9IHRoaXMuZ2VuZXJhdGVJbml0aWFsQ29udGVudCh0aXRsZSk7XHJcblx0XHR9XHJcblxyXG5cdFx0dHJ5IHtcclxuXHRcdFx0Y29uc3QgbmV3RmlsZSA9IGF3YWl0IHRoaXMuYXBwLnZhdWx0LmNyZWF0ZShmaWxlUGF0aCwgaW5pdGlhbENvbnRlbnQpO1xyXG5cclxuXHRcdFx0Ly8gT3BlbiB0aGUgbmV3IGZpbGVcclxuXHRcdFx0Y29uc3QgbGVhZiA9IHRoaXMuYXBwLndvcmtzcGFjZS5nZXRMZWFmKCk7XHJcblx0XHRcdGF3YWl0IGxlYWYub3BlbkZpbGUobmV3RmlsZSk7XHJcblxyXG5cdFx0XHQvLyBQb3NpdGlvbiBjdXJzb3IgYXQgdGhlIGVuZCBvZiBjb250ZW50IGFmdGVyIGVkaXRvciBpcyByZWFkeVxyXG5cdFx0XHQvLyBVc2UgbXVsdGlwbGUgYXR0ZW1wdHMgdG8gZW5zdXJlIGl0IHdvcmtzIGV2ZW4gaWYgZWRpdG9yIGlzbid0IHJlYWR5IGltbWVkaWF0ZWx5XHJcblx0XHRcdGNvbnN0IHBvc2l0aW9uQ3Vyc29yID0gKCkgPT4ge1xyXG5cdFx0XHRcdGNvbnN0IHZpZXcgPSBsZWFmLnZpZXc7XHJcblx0XHRcdFx0aWYgKHZpZXcgaW5zdGFuY2VvZiBNYXJrZG93blZpZXcgJiYgdmlldy5lZGl0b3IpIHtcclxuXHRcdFx0XHRcdGNvbnN0IGVkaXRvciA9IHZpZXcuZWRpdG9yO1xyXG5cdFx0XHRcdFx0Y29uc3QgY29udGVudCA9IGVkaXRvci5nZXRWYWx1ZSgpO1xyXG5cdFx0XHRcdFx0aWYgKGNvbnRlbnQpIHtcclxuXHRcdFx0XHRcdFx0Y29uc3QgbGluZXMgPSBjb250ZW50LnNwbGl0KCdcXG4nKTtcclxuXHRcdFx0XHRcdFx0Y29uc3QgbGFzdExpbmUgPSBsaW5lcy5sZW5ndGggLSAxO1xyXG5cdFx0XHRcdFx0XHRjb25zdCBsYXN0TGluZUxlbmd0aCA9IGxpbmVzW2xhc3RMaW5lXT8ubGVuZ3RoIHx8IDA7XHJcblx0XHRcdFx0XHRcdGVkaXRvci5zZXRDdXJzb3IoeyBsaW5lOiBsYXN0TGluZSwgY2g6IGxhc3RMaW5lTGVuZ3RoIH0pO1xyXG5cdFx0XHRcdFx0XHQvLyBGb2N1cyB0aGUgZWRpdG9yIHRvIGVuc3VyZSBjdXJzb3IgaXMgdmlzaWJsZSBhbmQgZmlsZW5hbWUgaXNuJ3Qgc2VsZWN0ZWRcclxuXHRcdFx0XHRcdFx0ZWRpdG9yLmZvY3VzKCk7XHJcblx0XHRcdFx0XHRcdHJldHVybiB0cnVlO1xyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdH1cclxuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XHJcblx0XHRcdH07XHJcblxyXG5cdFx0XHQvLyBUcnkgaW1tZWRpYXRlbHlcclxuXHRcdFx0c2V0VGltZW91dCgoKSA9PiB7XHJcblx0XHRcdFx0aWYgKCFwb3NpdGlvbkN1cnNvcigpKSB7XHJcblx0XHRcdFx0XHQvLyBJZiBpdCBkaWRuJ3Qgd29yaywgdHJ5IGFnYWluIGFmdGVyIGEgbG9uZ2VyIGRlbGF5XHJcblx0XHRcdFx0XHRzZXRUaW1lb3V0KCgpID0+IHtcclxuXHRcdFx0XHRcdFx0cG9zaXRpb25DdXJzb3IoKTtcclxuXHRcdFx0XHRcdH0sIDIwMCk7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9LCAxMDApO1xyXG5cclxuXHRcdFx0cmV0dXJuIG5ld0ZpbGU7XHJcblx0XHR9IGNhdGNoIChlcnJvcikge1xyXG5cdFx0XHRjb25zdCBlcnJvck1lc3NhZ2UgPSBlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IubWVzc2FnZSA6IFN0cmluZyhlcnJvcik7XHJcblx0XHRcdHRocm93IG5ldyBFcnJvcihgRmFpbGVkIHRvIGNyZWF0ZSBmaWxlOiAke2Vycm9yTWVzc2FnZX1gKTtcclxuXHRcdH1cclxuXHR9XHJcblxyXG5cdHByaXZhdGUgZ2VuZXJhdGVJbml0aWFsQ29udGVudCh0aXRsZTogc3RyaW5nKTogc3RyaW5nIHtcclxuXHRcdGNvbnN0IG5vdyA9IG5ldyBEYXRlKCk7XHJcblx0XHRjb25zdCBkYXRlU3RyaW5nID0gd2luZG93Lm1vbWVudChub3cpLmZvcm1hdCh0aGlzLnBsdWdpbi5zZXR0aW5ncy5kYXRlRm9ybWF0KTtcclxuXHRcdGNvbnN0IHNsdWcgPSB0b0tlYmFiQ2FzZSh0aXRsZSk7XHJcblxyXG5cdFx0bGV0IHRlbXBsYXRlOiBzdHJpbmc7XHJcblx0XHRpZiAodGhpcy50eXBlID09PSBcIm5vdGVcIikge1xyXG5cdFx0XHQvLyBGb3IgZ2VuZXJpYyBub3RlcywgdXNlIGEgc2ltcGxlIHRlbXBsYXRlXHJcblx0XHRcdC8vIFByb3Blcmx5IGVzY2FwZSB0aGUgdGl0bGUgZm9yIFlBTUxcclxuXHRcdFx0Y29uc3QgZXNjYXBlZFRpdGxlID0gdGhpcy5lc2NhcGVZYW1sU3RyaW5nKHRpdGxlKTtcclxuXHRcdFx0dGVtcGxhdGUgPSBgLS0tXFxudGl0bGU6ICR7ZXNjYXBlZFRpdGxlfVxcbmRhdGU6ICR7ZGF0ZVN0cmluZ31cXG4tLS1cXG5gO1xyXG5cdFx0fSBlbHNlIHtcclxuXHRcdFx0Y29uc3QgY29udGVudFR5cGUgPSB0aGlzLmZpbGVPcHMuZ2V0Q29udGVudFR5cGUodGhpcy50eXBlKTtcclxuXHRcdFx0aWYgKCFjb250ZW50VHlwZSkge1xyXG5cdFx0XHRcdGNvbnN0IGVzY2FwZWRUaXRsZSA9IHRoaXMuZXNjYXBlWWFtbFN0cmluZyh0aXRsZSk7XHJcblx0XHRcdFx0dGVtcGxhdGUgPSBgLS0tXFxudGl0bGU6ICR7ZXNjYXBlZFRpdGxlfVxcbmRhdGU6ICR7ZGF0ZVN0cmluZ31cXG4tLS1cXG5gO1xyXG5cdFx0XHR9IGVsc2Uge1xyXG5cdFx0XHRcdHRlbXBsYXRlID0gY29udGVudFR5cGUudGVtcGxhdGU7XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHJcblx0XHR0ZW1wbGF0ZSA9IHRlbXBsYXRlLnJlcGxhY2UoL1xce1xce3RpdGxlXFx9XFx9L2csIHRpdGxlKTtcclxuXHRcdHRlbXBsYXRlID0gdGVtcGxhdGUucmVwbGFjZSgvXFx7XFx7ZGF0ZVxcfVxcfS9nLCBkYXRlU3RyaW5nKTtcclxuXHRcdHRlbXBsYXRlID0gdGVtcGxhdGUucmVwbGFjZSgvXFx7XFx7c2x1Z1xcfVxcfS9nLCBzbHVnKTtcclxuXHJcblx0XHRyZXR1cm4gdGVtcGxhdGU7XHJcblx0fVxyXG5cclxuXHRwcml2YXRlIGFzeW5jIGFkZFByb3BlcnRpZXNUb0ZpbGUoZmlsZTogVEZpbGUsIHRpdGxlOiBzdHJpbmcsIHR5cGU6IENvbnRlbnRUeXBlSWQpIHtcclxuXHRcdGNvbnN0IG5vdyA9IG5ldyBEYXRlKCk7XHJcblx0XHRjb25zdCBkYXRlU3RyaW5nID0gd2luZG93Lm1vbWVudChub3cpLmZvcm1hdCh0aGlzLnBsdWdpbi5zZXR0aW5ncy5kYXRlRm9ybWF0KTtcclxuXHRcdGNvbnN0IHNsdWcgPSB0b0tlYmFiQ2FzZSh0aXRsZSk7XHJcblxyXG5cdFx0bGV0IHRlbXBsYXRlOiBzdHJpbmc7XHJcblx0XHRpZiAodHlwZSA9PT0gXCJub3RlXCIpIHtcclxuXHRcdFx0Ly8gRm9yIGdlbmVyaWMgbm90ZXMsIHVzZSBhIHNpbXBsZSB0ZW1wbGF0ZVxyXG5cdFx0XHQvLyBQcm9wZXJseSBlc2NhcGUgdGhlIHRpdGxlIGZvciBZQU1MXHJcblx0XHRcdGNvbnN0IGVzY2FwZWRUaXRsZSA9IHRoaXMuZXNjYXBlWWFtbFN0cmluZyh0aXRsZSk7XHJcblx0XHRcdHRlbXBsYXRlID0gYC0tLVxcbnRpdGxlOiAke2VzY2FwZWRUaXRsZX1cXG5kYXRlOiAke2RhdGVTdHJpbmd9XFxuLS0tXFxuYDtcclxuXHRcdH0gZWxzZSB7XHJcblx0XHRcdGNvbnN0IGNvbnRlbnRUeXBlID0gdGhpcy5maWxlT3BzLmdldENvbnRlbnRUeXBlKHR5cGUpO1xyXG5cdFx0XHRpZiAoIWNvbnRlbnRUeXBlKSB7XHJcblx0XHRcdFx0Y29uc3QgZXNjYXBlZFRpdGxlID0gdGhpcy5lc2NhcGVZYW1sU3RyaW5nKHRpdGxlKTtcclxuXHRcdFx0XHR0ZW1wbGF0ZSA9IGAtLS1cXG50aXRsZTogJHtlc2NhcGVkVGl0bGV9XFxuZGF0ZTogJHtkYXRlU3RyaW5nfVxcbi0tLVxcbmA7XHJcblx0XHRcdH0gZWxzZSB7XHJcblx0XHRcdFx0dGVtcGxhdGUgPSBjb250ZW50VHlwZS50ZW1wbGF0ZTtcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cclxuXHRcdHRlbXBsYXRlID0gdGVtcGxhdGUucmVwbGFjZSgvXFx7XFx7dGl0bGVcXH1cXH0vZywgdGl0bGUpO1xyXG5cdFx0dGVtcGxhdGUgPSB0ZW1wbGF0ZS5yZXBsYWNlKC9cXHtcXHtkYXRlXFx9XFx9L2csIGRhdGVTdHJpbmcpO1xyXG5cdFx0dGVtcGxhdGUgPSB0ZW1wbGF0ZS5yZXBsYWNlKC9cXHtcXHtzbHVnXFx9XFx9L2csIHNsdWcpO1xyXG5cclxuXHRcdC8vIEVuc3VyZSBubyBleHRyYSBuZXdsaW5lcyBvciAtLS0gYXJlIGFkZGVkIGJleW9uZCB0aGUgdGVtcGxhdGVcclxuXHRcdGF3YWl0IHRoaXMuYXBwLnZhdWx0Lm1vZGlmeShmaWxlLCB0ZW1wbGF0ZSk7XHJcblx0fVxyXG5cclxuXHRwcml2YXRlIHBvc2l0aW9uQ3Vyc29yQXRFbmQoZmlsZTogVEZpbGUpIHtcclxuXHRcdGNvbnN0IHBvc2l0aW9uQ3Vyc29yID0gKCkgPT4ge1xyXG5cdFx0XHRjb25zdCB2aWV3ID0gdGhpcy5hcHAud29ya3NwYWNlLmdldEFjdGl2ZVZpZXdPZlR5cGUoTWFya2Rvd25WaWV3KTtcclxuXHRcdFx0aWYgKHZpZXcgJiYgdmlldy5maWxlID09PSBmaWxlICYmIHZpZXcuZWRpdG9yKSB7XHJcblx0XHRcdFx0Y29uc3QgZWRpdG9yID0gdmlldy5lZGl0b3I7XHJcblx0XHRcdFx0Y29uc3QgY29udGVudCA9IGVkaXRvci5nZXRWYWx1ZSgpO1xyXG5cdFx0XHRcdGlmIChjb250ZW50KSB7XHJcblx0XHRcdFx0XHRjb25zdCBsaW5lcyA9IGNvbnRlbnQuc3BsaXQoJ1xcbicpO1xyXG5cdFx0XHRcdFx0Y29uc3QgbGFzdExpbmUgPSBsaW5lcy5sZW5ndGggLSAxO1xyXG5cdFx0XHRcdFx0Y29uc3QgbGFzdExpbmVMZW5ndGggPSBsaW5lc1tsYXN0TGluZV0/Lmxlbmd0aCB8fCAwO1xyXG5cdFx0XHRcdFx0ZWRpdG9yLnNldEN1cnNvcih7IGxpbmU6IGxhc3RMaW5lLCBjaDogbGFzdExpbmVMZW5ndGggfSk7XHJcblx0XHRcdFx0XHQvLyBGb2N1cyB0aGUgZWRpdG9yIHRvIGVuc3VyZSBjdXJzb3IgaXMgdmlzaWJsZVxyXG5cdFx0XHRcdFx0ZWRpdG9yLmZvY3VzKCk7XHJcblx0XHRcdFx0XHRyZXR1cm4gdHJ1ZTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdH1cclxuXHRcdFx0cmV0dXJuIGZhbHNlO1xyXG5cdFx0fTtcclxuXHJcblx0XHRzZXRUaW1lb3V0KCgpID0+IHtcclxuXHRcdFx0aWYgKCFwb3NpdGlvbkN1cnNvcigpKSB7XHJcblx0XHRcdFx0Ly8gSWYgaXQgZGlkbid0IHdvcmssIHRyeSBhZ2FpbiBhZnRlciBhIGxvbmdlciBkZWxheVxyXG5cdFx0XHRcdHNldFRpbWVvdXQoKCkgPT4ge1xyXG5cdFx0XHRcdFx0cG9zaXRpb25DdXJzb3IoKTtcclxuXHRcdFx0XHR9LCAyMDApO1xyXG5cdFx0XHR9XHJcblx0XHR9LCAxMDApO1xyXG5cdH1cclxuXHJcblx0cHJpdmF0ZSBlc2NhcGVZYW1sU3RyaW5nKHN0cjogc3RyaW5nKTogc3RyaW5nIHtcclxuXHRcdC8vIFByb3Blcmx5IGVzY2FwZSBZQU1MIHN0cmluZyB2YWx1ZXNcclxuXHRcdC8vIFlBTUwgc3RyaW5ncyB3aXRoIHF1b3RlcyBuZWVkIHRvIGJlIHdyYXBwZWQgaW4gc2luZ2xlIHF1b3RlcyBvciBlc2NhcGVkIHByb3Blcmx5XHJcblx0XHRpZiAoc3RyLmluY2x1ZGVzKCdcIicpIHx8IHN0ci5pbmNsdWRlcyhcIidcIikgfHwgc3RyLmluY2x1ZGVzKCdcXG4nKSB8fCBzdHIuaW5jbHVkZXMoJ1xcXFwnKSkge1xyXG5cdFx0XHQvLyBGb3Igc3RyaW5ncyB3aXRoIHF1b3RlcywgbmV3bGluZXMsIG9yIGJhY2tzbGFzaGVzLCB1c2Ugc2luZ2xlIHF1b3RlcyBhbmQgZXNjYXBlIHNpbmdsZSBxdW90ZXNcclxuXHRcdFx0cmV0dXJuIGAnJHtzdHIucmVwbGFjZSgvJy9nLCBcIicnXCIpfSdgO1xyXG5cdFx0fSBlbHNlIGlmIChzdHIuaW5jbHVkZXMoXCIgXCIpIHx8IHN0ci5pbmNsdWRlcyhcIjpcIikgfHwgc3RyLmluY2x1ZGVzKFwiI1wiKSB8fCBzdHIuaW5jbHVkZXMoXCJAXCIpKSB7XHJcblx0XHRcdC8vIEZvciBzdHJpbmdzIHdpdGggc3BhY2VzIG9yIHNwZWNpYWwgWUFNTCBjaGFyYWN0ZXJzLCB3cmFwIGluIGRvdWJsZSBxdW90ZXMgYW5kIGVzY2FwZSBkb3VibGUgcXVvdGVzXHJcblx0XHRcdHJldHVybiBgXCIke3N0ci5yZXBsYWNlKC9cIi9nLCAnXFxcXFwiJyl9XCJgO1xyXG5cdFx0fSBlbHNlIHtcclxuXHRcdFx0Ly8gRm9yIHNpbXBsZSBzdHJpbmdzLCBubyBxdW90ZXMgbmVlZGVkXHJcblx0XHRcdHJldHVybiBzdHI7XHJcblx0XHR9XHJcblx0fVxyXG5cclxuXHRvbkNsb3NlKCkge1xyXG5cdFx0Y29uc3QgeyBjb250ZW50RWwgfSA9IHRoaXM7XHJcblx0XHRjb250ZW50RWwuZW1wdHkoKTtcclxuXHR9XHJcbn1cclxuIiwgImltcG9ydCB7IEFwcCwgUGx1Z2luU2V0dGluZ1RhYiwgU2V0dGluZywgUGxhdGZvcm0sIHNldEljb24sIFNldHRpbmdHcm91cCB9IGZyb20gXCJvYnNpZGlhblwiO1xuaW1wb3J0IHsgUGx1Z2luIH0gZnJvbSBcIm9ic2lkaWFuXCI7XG5pbXBvcnQgeyBDb250ZW50VHlwZSwgQXN0cm9Db21wb3NlclBsdWdpbkludGVyZmFjZSwgQXN0cm9Db21wb3NlclNldHRpbmdzIH0gZnJvbSBcIi4uL3R5cGVzXCI7XG5pbXBvcnQgeyBDb21tYW5kUGlja2VyTW9kYWwgfSBmcm9tIFwiLi9jb21wb25lbnRzL0NvbW1hbmRQaWNrZXJNb2RhbFwiO1xuaW1wb3J0IHsgSWNvblBpY2tlck1vZGFsIH0gZnJvbSBcIi4vY29tcG9uZW50cy9JY29uUGlja2VyTW9kYWxcIjtcbmltcG9ydCB7IENvbmZpcm1Nb2RhbCB9IGZyb20gXCIuL2NvbXBvbmVudHMvQ29uZmlybU1vZGFsXCI7XG5cbmltcG9ydCB7IHJlZ2lzdGVyQ29udGVudFR5cGVDb21tYW5kcyB9IGZyb20gXCIuLi9jb21tYW5kc1wiO1xuXG5leHBvcnQgY2xhc3MgQXN0cm9Db21wb3NlclNldHRpbmdUYWIgZXh0ZW5kcyBQbHVnaW5TZXR0aW5nVGFiIHtcblx0cGx1Z2luOiBBc3Ryb0NvbXBvc2VyUGx1Z2luSW50ZXJmYWNlO1xuXHRwdWJsaWMgaWNvbiA9ICdsdWNpZGUtcGVuY2lsLWxpbmUnO1xuXHRhdXRvUmVuYW1lQ29udGFpbmVyOiBIVE1MRWxlbWVudCB8IG51bGwgPSBudWxsO1xuXHRwb3N0c0ZvbGRlckNvbnRhaW5lcjogSFRNTEVsZW1lbnQgfCBudWxsID0gbnVsbDtcblx0b25seUF1dG9tYXRlQ29udGFpbmVyOiBIVE1MRWxlbWVudCB8IG51bGwgPSBudWxsO1xuXHRjcmVhdGlvbk1vZGVDb250YWluZXI6IEhUTUxFbGVtZW50IHwgbnVsbCA9IG51bGw7XG5cdGluZGV4RmlsZUNvbnRhaW5lcjogSFRNTEVsZW1lbnQgfCBudWxsID0gbnVsbDtcblx0ZXhjbHVkZWREaXJzQ29udGFpbmVyOiBIVE1MRWxlbWVudCB8IG51bGwgPSBudWxsO1xuXHR1bmRlcnNjb3JlUHJlZml4Q29udGFpbmVyOiBIVE1MRWxlbWVudCB8IG51bGwgPSBudWxsO1xuXHRhdXRvSW5zZXJ0Q29udGFpbmVyOiBIVE1MRWxlbWVudCB8IG51bGwgPSBudWxsO1xuXHRwYWdlc0ZpZWxkc0NvbnRhaW5lcjogSFRNTEVsZW1lbnQgfCBudWxsID0gbnVsbDtcblx0cGFnZXNJbmRleEZpbGVDb250YWluZXI6IEhUTUxFbGVtZW50IHwgbnVsbCA9IG51bGw7XG5cdHBhZ2VzT25seUF1dG9tYXRlQ29udGFpbmVyOiBIVE1MRWxlbWVudCB8IG51bGwgPSBudWxsO1xuXHR0ZXJtaW5hbENvbW1hbmRDb250YWluZXI6IEhUTUxFbGVtZW50IHwgbnVsbCA9IG51bGw7XG5cdGNvbmZpZ0NvbW1hbmRDb250YWluZXI6IEhUTUxFbGVtZW50IHwgbnVsbCA9IG51bGw7XG5cdGN1c3RvbUNvbnRlbnRUeXBlc0NvbnRhaW5lcjogSFRNTEVsZW1lbnQgfCBudWxsID0gbnVsbDtcblx0dGVybWluYWxSaWJib25Ub2dnbGU6IFNldHRpbmcgfCBudWxsID0gbnVsbDtcblx0Y29uZmlnUmliYm9uVG9nZ2xlOiBTZXR0aW5nIHwgbnVsbCA9IG51bGw7XG5cdHByaXZhdGUgdGVybWluYWxSaWJib25Ub2dnbGVDb21wb25lbnQ6IHsgc2V0RGlzYWJsZWQ6IChkaXNhYmxlZDogYm9vbGVhbikgPT4gdm9pZCB9IHwgbnVsbCA9IG51bGw7XG5cdHByaXZhdGUgY29uZmlnUmliYm9uVG9nZ2xlQ29tcG9uZW50OiB7IHNldERpc2FibGVkOiAoZGlzYWJsZWQ6IGJvb2xlYW4pID0+IHZvaWQgfSB8IG51bGwgPSBudWxsO1xuXG5cdGNvbnN0cnVjdG9yKGFwcDogQXBwLCBwbHVnaW46IFBsdWdpbikge1xuXHRcdHN1cGVyKGFwcCwgcGx1Z2luKTtcblx0XHR0aGlzLnBsdWdpbiA9IHBsdWdpbiBhcyB1bmtub3duIGFzIEFzdHJvQ29tcG9zZXJQbHVnaW5JbnRlcmZhY2U7XG5cdH1cblxuXHQvKipcblx0ICogUmVmcmVzaCBqdXN0IHRoZSBjb250ZW50IHR5cGVzIHNlY3Rpb25cblx0ICogTW9yZSBlZmZpY2llbnQgdGhhbiByZWZyZXNoaW5nIHRoZSBlbnRpcmUgc2V0dGluZ3MgdGFiXG5cdCAqL1xuXHRwdWJsaWMgcmVmcmVzaENvbnRlbnRUeXBlcygpOiB2b2lkIHtcblx0XHRpZiAodGhpcy5jdXN0b21Db250ZW50VHlwZXNDb250YWluZXIpIHtcblx0XHRcdHRoaXMucmVuZGVyQ3VzdG9tQ29udGVudFR5cGVzKCk7XG5cdFx0fVxuXHR9XG5cblx0ZGlzcGxheSgpOiB2b2lkIHtcblx0XHRjb25zdCB7IGNvbnRhaW5lckVsIH0gPSB0aGlzO1xuXHRcdGNvbnRhaW5lckVsLmVtcHR5KCk7XG5cblx0XHQvLyBVc2UgY3VycmVudCBwbHVnaW4gc2V0dGluZ3MgKGFscmVhZHkgbG9hZGVkIGFuZCB1cC10by1kYXRlKVxuXHRcdC8vIEFsd2F5cyByZWFkIGZyZXNoIHNldHRpbmdzIHRvIGVuc3VyZSB3ZSBzaG93IG1pZ3JhdGVkIGNvbnRlbnQgdHlwZXMgaW1tZWRpYXRlbHlcblx0XHRjb25zdCBzZXR0aW5ncyA9IHRoaXMucGx1Z2luLnNldHRpbmdzO1xuXG5cdFx0Ly8gUmVuZGVyIHRoZSBzZXR0aW5ncyB0YWIgd2l0aCBjdXJyZW50IHNldHRpbmdzXG5cdFx0Ly8gVGhpcyB3aWxsIHNob3cgYWxsIGNvbnRlbnQgdHlwZXMgaW5jbHVkaW5nIG5ld2x5IG1pZ3JhdGVkIG9uZXNcblx0XHR0aGlzLnJlbmRlclNldHRpbmdzVGFiKGNvbnRhaW5lckVsLCBzZXR0aW5ncyk7XG5cdH1cblxuXHRwcml2YXRlIHJlbmRlclNldHRpbmdzVGFiKGNvbnRhaW5lckVsOiBIVE1MRWxlbWVudCwgc2V0dGluZ3M6IEFzdHJvQ29tcG9zZXJTZXR0aW5ncyk6IHZvaWQge1xuXG5cdFx0Ly8gR2xvYmFsIHNldHRpbmdzIChmaXJzdCBncm91cCAtIG5vIGhlYWRpbmcpXG5cdFx0Y29uc3QgZ2VuZXJhbEdyb3VwID0gbmV3IFNldHRpbmdHcm91cChjb250YWluZXJFbCk7XG5cdFx0Z2VuZXJhbEdyb3VwLmFkZFNldHRpbmcoc2V0dGluZyA9PiB7XG5cdFx0XHRzZXR0aW5nXG5cdFx0XHRcdC5zZXROYW1lKFwiRGF0ZSBmb3JtYXRcIilcblx0XHRcdFx0Ly8gRGF0ZSBmb3JtYXQgY29kZXMgKE1NTU0sIHl5eXksIGV0Yy4pIGFyZSB0ZWNobmljYWwgbm90YXRpb24sIG5vdCBVSSB0ZXh0XG5cdFx0XHRcdC5zZXREZXNjKFwiRm9ybWF0IGZvciB0aGUgZGF0ZSBpbiBwcm9wZXJ0aWVzICh5eXl5LW1tLWRkLCBNTU1NIEQsIHl5eXksIHl5eXktbW0tZGQgSEg6bW0pXCIpXG5cdFx0XHRcdC5hZGRUZXh0KHRleHQgPT5cblx0XHRcdFx0XHR0ZXh0XG5cdFx0XHRcdFx0XHQvLyBcIllZWVktTU0tRERcIiBpcyBhIGRhdGUgZm9ybWF0IHBsYWNlaG9sZGVyLCBub3QgVUkgdGV4dFxuXHRcdFx0XHRcdFx0LnNldFBsYWNlaG9sZGVyKFwiWVlZWS1NTS1ERFwiKVxuXHRcdFx0XHRcdFx0LnNldFZhbHVlKHNldHRpbmdzLmRhdGVGb3JtYXQpXG5cdFx0XHRcdFx0XHQub25DaGFuZ2UoYXN5bmMgKHZhbHVlOiBzdHJpbmcpID0+IHtcblx0XHRcdFx0XHRcdFx0c2V0dGluZ3MuZGF0ZUZvcm1hdCA9IHZhbHVlIHx8IFwiWVlZWS1NTS1ERFwiO1xuXHRcdFx0XHRcdFx0XHRhd2FpdCB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKTtcblx0XHRcdFx0XHRcdH0pXG5cdFx0XHRcdCk7XG5cdFx0fSk7XG5cblx0XHRnZW5lcmFsR3JvdXAuYWRkU2V0dGluZyhzZXR0aW5nID0+IHtcblx0XHRcdHNldHRpbmdcblx0XHRcdFx0LnNldE5hbWUoXCJFbmFibGUgY29weSBoZWFkaW5nIGxpbmtzXCIpXG5cdFx0XHRcdC5zZXREZXNjKFwiQWRkIHJpZ2h0LWNsaWNrIGNvbnRleHQgbWVudSBvcHRpb24gdG8gY29weSBoZWFkaW5nIGxpbmtzIGluIHZhcmlvdXMgZm9ybWF0cy5cIilcblx0XHRcdFx0LmFkZFRvZ2dsZSh0b2dnbGUgPT5cblx0XHRcdFx0XHR0b2dnbGVcblx0XHRcdFx0XHRcdC5zZXRWYWx1ZShzZXR0aW5ncy5lbmFibGVDb3B5SGVhZGluZ0xpbmspXG5cdFx0XHRcdFx0XHQub25DaGFuZ2UoYXN5bmMgKHZhbHVlOiBib29sZWFuKSA9PiB7XG5cdFx0XHRcdFx0XHRcdHNldHRpbmdzLmVuYWJsZUNvcHlIZWFkaW5nTGluayA9IHZhbHVlO1xuXHRcdFx0XHRcdFx0XHRhd2FpdCB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKTtcblx0XHRcdFx0XHRcdFx0dGhpcy51cGRhdGVDb3B5SGVhZGluZ0ZpZWxkcygpO1xuXHRcdFx0XHRcdFx0fSlcblx0XHRcdFx0KTtcblx0XHR9KTtcblxuXHRcdGdlbmVyYWxHcm91cC5hZGRTZXR0aW5nKHNldHRpbmcgPT4ge1xuXHRcdFx0c2V0dGluZ1xuXHRcdFx0XHQuc2V0TmFtZShcIkRlZmF1bHQgaGVhZGluZyBsaW5rIGZvcm1hdFwiKVxuXHRcdFx0XHQvLyBcIkFzdHJvXCIgaXMgYSBwcm9wZXIgbm91biAoZnJhbWV3b3JrIG5hbWUpIGFuZCBzaG91bGQgYmUgY2FwaXRhbGl6ZWRcblx0XHRcdFx0LnNldERlc2MoXCJDaG9vc2UgdGhlIGRlZmF1bHQgZm9ybWF0IGZvciBjb3BpZWQgaGVhZGluZyBsaW5rcy4gT2JzaWRpYW4gZm9ybWF0IHJlc3BlY3RzIHlvdXIgT2JzaWRpYW4gc2V0dGluZ3MgZm9yIHdpa2lsaW5rIHZzIG1hcmtkb3duIHByZWZlcmVuY2UuIEFzdHJvIGxpbmsgdXNlcyB5b3VyIGxpbmsgYmFzZSBwYXRoIGZyb20gYWJvdmUgYW5kIGNvbnZlcnRzIHRoZSBoZWFkaW5nIGludG8ga2ViYWItY2FzZSBmb3JtYXQgYXMgYW4gYW5jaG9yIGxpbmtcIilcblx0XHRcdFx0LmFkZERyb3Bkb3duKGRyb3Bkb3duID0+XG5cdFx0XHRcdFx0ZHJvcGRvd25cblx0XHRcdFx0XHRcdC5hZGRPcHRpb24oXCJvYnNpZGlhblwiLCBcIk9ic2lkaWFuIGxpbmtcIilcblx0XHRcdFx0XHRcdC5hZGRPcHRpb24oXCJhc3Ryb1wiLCBcIkFzdHJvIGxpbmtcIilcblx0XHRcdFx0XHRcdC5zZXRWYWx1ZShzZXR0aW5ncy5jb3B5SGVhZGluZ0xpbmtGb3JtYXQpXG5cdFx0XHRcdFx0XHQub25DaGFuZ2UoYXN5bmMgKHZhbHVlOiBzdHJpbmcpID0+IHtcblx0XHRcdFx0XHRcdFx0c2V0dGluZ3MuY29weUhlYWRpbmdMaW5rRm9ybWF0ID0gdmFsdWUgYXMgXCJvYnNpZGlhblwiIHwgXCJhc3Ryb1wiO1xuXHRcdFx0XHRcdFx0XHRhd2FpdCB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKTtcblx0XHRcdFx0XHRcdH0pXG5cdFx0XHRcdCk7XG5cdFx0XHQvLyBBZGQgY29uZGl0aW9uYWwgdmlzaWJpbGl0eSBjbGFzc2VzIC0ga2VlcCBzZXR0aW5nIGluIGdyb3VwXG5cdFx0XHRzZXR0aW5nLnNldHRpbmdFbC5jbGFzc0xpc3QudG9nZ2xlKFwiYXN0cm8tY29tcG9zZXItc2V0dGluZy1jb250YWluZXItdmlzaWJsZVwiLCBzZXR0aW5ncy5lbmFibGVDb3B5SGVhZGluZ0xpbmspO1xuXHRcdFx0c2V0dGluZy5zZXR0aW5nRWwuY2xhc3NMaXN0LnRvZ2dsZShcImFzdHJvLWNvbXBvc2VyLXNldHRpbmctY29udGFpbmVyLWhpZGRlblwiLCAhc2V0dGluZ3MuZW5hYmxlQ29weUhlYWRpbmdMaW5rKTtcblx0XHR9KTtcblxuXHRcdGdlbmVyYWxHcm91cC5hZGRTZXR0aW5nKHNldHRpbmcgPT4ge1xuXHRcdFx0c2V0dGluZ1xuXHRcdFx0XHQuc2V0TmFtZShcIkFkZCB0cmFpbGluZyBzbGFzaCB0byBsaW5rc1wiKVxuXHRcdFx0XHQuc2V0RGVzYyhcIkFkZCB0cmFpbGluZyBzbGFzaGVzIHRvIGFsbCBjb252ZXJ0ZWQgaW50ZXJuYWwgbGlua3MgKC9hYm91dC8gaW5zdGVhZCBvZiAvYWJvdXQpLlwiKVxuXHRcdFx0XHQuYWRkVG9nZ2xlKHRvZ2dsZSA9PlxuXHRcdFx0XHRcdHRvZ2dsZVxuXHRcdFx0XHRcdFx0LnNldFZhbHVlKHNldHRpbmdzLmFkZFRyYWlsaW5nU2xhc2hUb0xpbmtzKVxuXHRcdFx0XHRcdFx0Lm9uQ2hhbmdlKGFzeW5jICh2YWx1ZTogYm9vbGVhbikgPT4ge1xuXHRcdFx0XHRcdFx0XHRzZXR0aW5ncy5hZGRUcmFpbGluZ1NsYXNoVG9MaW5rcyA9IHZhbHVlO1xuXHRcdFx0XHRcdFx0XHRhd2FpdCB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKTtcblx0XHRcdFx0XHRcdH0pXG5cdFx0XHRcdCk7XG5cdFx0fSk7XG5cblx0XHRnZW5lcmFsR3JvdXAuYWRkU2V0dGluZyhzZXR0aW5nID0+IHtcblx0XHRcdHNldHRpbmdcblx0XHRcdFx0LnNldE5hbWUoXCJQcm9jZXNzIGJhY2tncm91bmQgZmlsZSBjaGFuZ2VzXCIpXG5cdFx0XHRcdC8vIFRlY2huaWNhbCB0ZXJtcyBsaWtlIFwiT2JzaWRpYW5cIiwgXCJnaXRcIiBhcmUgcHJvcGVyIG5vdW5zIGluIHRoaXMgY29udGV4dFxuXHRcdFx0XHQuc2V0RGVzYyhcIkF1dG9tYXRpY2FsbHkgcHJvY2VzcyBuZXcgZmlsZXMgd2hlbiB0aGV5J3JlIGNoYW5nZWQgaW4gdGhlIGJhY2tncm91bmQgKGJ5IEdpdCBvciBvdGhlciBwbHVnaW5zKS4gRGlzYWJsZSB0byBwcmV2ZW50IG1vZGFsIHNwYW0gd2hlbiBmaWxlcyBhcmUgYWxyZWFkeSBwcm9jZXNzZWQgb24gb3RoZXIgZGV2aWNlcyBkdXJpbmcgYSBzeW5jLlwiKVxuXHRcdFx0XHQuYWRkVG9nZ2xlKHRvZ2dsZSA9PlxuXHRcdFx0XHRcdHRvZ2dsZVxuXHRcdFx0XHRcdFx0LnNldFZhbHVlKHNldHRpbmdzLnByb2Nlc3NCYWNrZ3JvdW5kRmlsZUNoYW5nZXMpXG5cdFx0XHRcdFx0XHQub25DaGFuZ2UoYXN5bmMgKHZhbHVlOiBib29sZWFuKSA9PiB7XG5cdFx0XHRcdFx0XHRcdHNldHRpbmdzLnByb2Nlc3NCYWNrZ3JvdW5kRmlsZUNoYW5nZXMgPSB2YWx1ZTtcblx0XHRcdFx0XHRcdFx0YXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XG5cdFx0XHRcdFx0XHR9KVxuXHRcdFx0XHQpO1xuXHRcdH0pO1xuXG5cdFx0Z2VuZXJhbEdyb3VwLmFkZFNldHRpbmcoc2V0dGluZyA9PiB7XG5cdFx0XHRzZXR0aW5nXG5cdFx0XHRcdC8vIFwiTURYXCIgaXMgYSBwcm9wZXIgbm91biAoZmlsZSBmb3JtYXQpIGFuZCBzaG91bGQgYmUgY2FwaXRhbGl6ZWRcblx0XHRcdFx0LnNldE5hbWUoXCJTaG93IE1EWCBmaWxlcyBpbiBmaWxlIGV4cGxvcmVyXCIpXG5cdFx0XHRcdC5zZXREZXNjKFwiTWFrZSAubWR4IGZpbGVzIHZpc2libGUgaW4gT2JzaWRpYW4ncyBmaWxlIGV4cGxvcmVyLiBSZXF1aXJlcyByZWxvYWQgdG8gdGFrZSBlZmZlY3QuXCIpXG5cdFx0XHRcdC5hZGRUb2dnbGUodG9nZ2xlID0+XG5cdFx0XHRcdFx0dG9nZ2xlXG5cdFx0XHRcdFx0XHQuc2V0VmFsdWUoc2V0dGluZ3Muc2hvd01keEZpbGVzSW5FeHBsb3Jlcilcblx0XHRcdFx0XHRcdC5vbkNoYW5nZShhc3luYyAodmFsdWU6IGJvb2xlYW4pID0+IHtcblx0XHRcdFx0XHRcdFx0c2V0dGluZ3Muc2hvd01keEZpbGVzSW5FeHBsb3JlciA9IHZhbHVlO1xuXHRcdFx0XHRcdFx0XHRhd2FpdCB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKTtcblx0XHRcdFx0XHRcdH0pXG5cdFx0XHRcdCk7XG5cdFx0fSk7XG5cblx0XHQvLyBQcm9wZXJ0eSBhdXRvbWF0aW9uXG5cdFx0Y29uc3QgYXV0b21hdGlvbkdyb3VwID0gbmV3IFNldHRpbmdHcm91cChjb250YWluZXJFbCkuc2V0SGVhZGluZyhcIlByb3BlcnR5IGF1dG9tYXRpb25cIik7XG5cblx0XHQvLyBBdXRvLWluc2VydCBwcm9wZXJ0aWVzIChtb3ZlZCBmcm9tIGdlbmVyYWxHcm91cClcblx0XHRhdXRvbWF0aW9uR3JvdXAuYWRkU2V0dGluZyhzZXR0aW5nID0+IHtcblx0XHRcdHNldHRpbmdcblx0XHRcdFx0LnNldE5hbWUoXCJBdXRvLWluc2VydCBwcm9wZXJ0aWVzXCIpXG5cdFx0XHRcdC5zZXREZXNjKFwiQXV0b21hdGljYWxseSBpbnNlcnQgdGhlIHByb3BlcnRpZXMgdGVtcGxhdGUgd2hlbiBjcmVhdGluZyBuZXcgZmlsZXMuXCIpXG5cdFx0XHRcdC5hZGRUb2dnbGUodG9nZ2xlID0+XG5cdFx0XHRcdFx0dG9nZ2xlXG5cdFx0XHRcdFx0XHQuc2V0VmFsdWUoc2V0dGluZ3MuYXV0b0luc2VydFByb3BlcnRpZXMpXG5cdFx0XHRcdFx0XHQub25DaGFuZ2UoYXN5bmMgKHZhbHVlOiBib29sZWFuKSA9PiB7XG5cdFx0XHRcdFx0XHRcdHNldHRpbmdzLmF1dG9JbnNlcnRQcm9wZXJ0aWVzID0gdmFsdWU7XG5cdFx0XHRcdFx0XHRcdGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xuXHRcdFx0XHRcdFx0fSlcblx0XHRcdFx0KTtcblx0XHR9KTtcblxuXHRcdGF1dG9tYXRpb25Hcm91cC5hZGRTZXR0aW5nKHNldHRpbmcgPT4ge1xuXHRcdFx0c2V0dGluZ1xuXHRcdFx0XHQuc2V0TmFtZShcIlJlbmFtZSBmaWxlIG9uIHRpdGxlIHByb3BlcnR5IGNsaWNrXCIpXG5cdFx0XHRcdC5zZXREZXNjKFwiV2hlbiBlbmFibGVkLCBjbGlja2luZyBpbnRvIHRoZSB0aXRsZSBwcm9wZXJ0eSB3aWxsIHRyaWdnZXIgdGhlIHJlbmFtZSBmaWxlIGNvbW1hbmQsIGtlZXBpbmcgdGhlIGZpbGUgc2x1ZyBpbiBzeW5jLlwiKVxuXHRcdFx0XHQuYWRkVG9nZ2xlKHRvZ2dsZSA9PlxuXHRcdFx0XHRcdHRvZ2dsZVxuXHRcdFx0XHRcdFx0LnNldFZhbHVlKHNldHRpbmdzLnJlbmFtZU9uVGl0bGVDbGljaylcblx0XHRcdFx0XHRcdC5vbkNoYW5nZShhc3luYyAodmFsdWU6IGJvb2xlYW4pID0+IHtcblx0XHRcdFx0XHRcdFx0c2V0dGluZ3MucmVuYW1lT25UaXRsZUNsaWNrID0gdmFsdWU7XG5cdFx0XHRcdFx0XHRcdGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xuXHRcdFx0XHRcdFx0fSlcblx0XHRcdFx0KTtcblx0XHR9KTtcblxuXHRcdGF1dG9tYXRpb25Hcm91cC5hZGRTZXR0aW5nKHNldHRpbmcgPT4ge1xuXHRcdFx0c2V0dGluZ1xuXHRcdFx0XHQuc2V0TmFtZShcIlVwZGF0ZSBkYXRlIG9uIHB1Ymxpc2hcIilcblx0XHRcdFx0LnNldERlc2MoXCJVcGRhdGUgJ2RhdGUnIHByb3BlcnR5IHdoZW4gc3dpdGNoaW5nIGZyb20gZHJhZnQgdG8gcHVibGlzaGVkIHN0YXR1cy5cIilcblx0XHRcdFx0LmFkZFRvZ2dsZSh0b2dnbGUgPT5cblx0XHRcdFx0XHR0b2dnbGVcblx0XHRcdFx0XHRcdC5zZXRWYWx1ZShzZXR0aW5ncy5zeW5jRHJhZnREYXRlKVxuXHRcdFx0XHRcdFx0Lm9uQ2hhbmdlKGFzeW5jICh2YWx1ZTogYm9vbGVhbikgPT4ge1xuXHRcdFx0XHRcdFx0XHRzZXR0aW5ncy5zeW5jRHJhZnREYXRlID0gdmFsdWU7XG5cdFx0XHRcdFx0XHRcdGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xuXHRcdFx0XHRcdFx0XHRjb25zdCBzY3JvbGxUb3AgPSB0aGlzLmNvbnRhaW5lckVsLnNjcm9sbFRvcDtcblx0XHRcdFx0XHRcdFx0dGhpcy5kaXNwbGF5KCk7XG5cdFx0XHRcdFx0XHRcdHRoaXMuY29udGFpbmVyRWwuc2Nyb2xsVG9wID0gc2Nyb2xsVG9wO1xuXHRcdFx0XHRcdFx0fSlcblx0XHRcdFx0KTtcblx0XHR9KTtcblxuXHRcdGlmIChzZXR0aW5ncy5zeW5jRHJhZnREYXRlKSB7XG5cdFx0XHRhdXRvbWF0aW9uR3JvdXAuYWRkU2V0dGluZyhzZXR0aW5nID0+IHtcblx0XHRcdFx0c2V0dGluZ1xuXHRcdFx0XHRcdC5zZXROYW1lKFwiRHJhZnQgZGV0ZWN0aW9uIG1vZGVcIilcblx0XHRcdFx0XHQuc2V0RGVzYyhcIkhvdyBkcmFmdCBzdGF0dXMgaXMgZGV0ZXJtaW5lZC4gUHJvcGVydHktYmFzZWQgdXNlcyBhIGJvb2xlYW4gcHJvcGVydHkgKGRyYWZ0OiB0cnVlKS4gVW5kZXJzY29yZSBwcmVmaXggdXNlcyB0aGUgZmlsZSBuYW1lIChfbXktcG9zdC5tZCA9IGRyYWZ0KS5cIilcblx0XHRcdFx0XHQuYWRkRHJvcGRvd24oZHJvcGRvd24gPT5cblx0XHRcdFx0XHRcdGRyb3Bkb3duXG5cdFx0XHRcdFx0XHRcdC5hZGRPcHRpb24oXCJwcm9wZXJ0eVwiLCBcIlByb3BlcnR5LWJhc2VkXCIpXG5cdFx0XHRcdFx0XHRcdC5hZGRPcHRpb24oXCJ1bmRlcnNjb3JlLXByZWZpeFwiLCBcIlVuZGVyc2NvcmUgcHJlZml4XCIpXG5cdFx0XHRcdFx0XHRcdC5zZXRWYWx1ZShzZXR0aW5ncy5kcmFmdERldGVjdGlvbk1vZGUgfHwgXCJwcm9wZXJ0eVwiKVxuXHRcdFx0XHRcdFx0XHQub25DaGFuZ2UoYXN5bmMgdmFsdWUgPT4ge1xuXHRcdFx0XHRcdFx0XHRcdHNldHRpbmdzLmRyYWZ0RGV0ZWN0aW9uTW9kZSA9IHZhbHVlIGFzICdwcm9wZXJ0eScgfCAndW5kZXJzY29yZS1wcmVmaXgnO1xuXHRcdFx0XHRcdFx0XHRcdGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xuXHRcdFx0XHRcdFx0XHRcdHRoaXMucGx1Z2luLmZyb250bWF0dGVyU2VydmljZT8uaW5pdGlhbGl6ZURyYWZ0U3RhdHVzTWFwKCk7XG5cdFx0XHRcdFx0XHRcdFx0Y29uc3Qgc2Nyb2xsVG9wID0gdGhpcy5jb250YWluZXJFbC5zY3JvbGxUb3A7XG5cdFx0XHRcdFx0XHRcdFx0dGhpcy5kaXNwbGF5KCk7XG5cdFx0XHRcdFx0XHRcdFx0dGhpcy5jb250YWluZXJFbC5zY3JvbGxUb3AgPSBzY3JvbGxUb3A7XG5cdFx0XHRcdFx0XHRcdH0pXG5cdFx0XHRcdFx0KTtcblx0XHRcdH0pO1xuXG5cdFx0XHRpZiAoc2V0dGluZ3MuZHJhZnREZXRlY3Rpb25Nb2RlICE9PSAndW5kZXJzY29yZS1wcmVmaXgnKSB7XG5cdFx0XHRcdGF1dG9tYXRpb25Hcm91cC5hZGRTZXR0aW5nKHNldHRpbmcgPT4ge1xuXHRcdFx0XHRcdHNldHRpbmdcblx0XHRcdFx0XHRcdC5zZXROYW1lKFwiRHJhZnQgcHJvcGVydHkgbmFtZVwiKVxuXHRcdFx0XHRcdFx0LnNldERlc2MoXCJUaGUgcHJvcGVydHkgZmllbGQgdG8gdXNlIGZvciBkcmFmdCBzdGF0dXMuXCIpXG5cdFx0XHRcdFx0XHQuYWRkVGV4dCh0ZXh0ID0+XG5cdFx0XHRcdFx0XHRcdHRleHRcblx0XHRcdFx0XHRcdFx0XHQuc2V0UGxhY2Vob2xkZXIoXCJkcmFmdFwiKVxuXHRcdFx0XHRcdFx0XHRcdC5zZXRWYWx1ZShzZXR0aW5ncy5kcmFmdFByb3BlcnR5IHx8IFwiXCIpXG5cdFx0XHRcdFx0XHRcdFx0Lm9uQ2hhbmdlKGFzeW5jICh2YWx1ZTogc3RyaW5nKSA9PiB7XG5cdFx0XHRcdFx0XHRcdFx0XHRzZXR0aW5ncy5kcmFmdFByb3BlcnR5ID0gdmFsdWU7XG5cdFx0XHRcdFx0XHRcdFx0XHRhd2FpdCB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKTtcblx0XHRcdFx0XHRcdFx0XHRcdHRoaXMucGx1Z2luLmZyb250bWF0dGVyU2VydmljZT8uaW5pdGlhbGl6ZURyYWZ0U3RhdHVzTWFwKCk7XG5cdFx0XHRcdFx0XHRcdFx0fSlcblx0XHRcdFx0XHRcdCk7XG5cdFx0XHRcdH0pO1xuXG5cdFx0XHRcdGF1dG9tYXRpb25Hcm91cC5hZGRTZXR0aW5nKHNldHRpbmcgPT4ge1xuXHRcdFx0XHRcdHNldHRpbmdcblx0XHRcdFx0XHRcdC5zZXROYW1lKFwiRHJhZnQgbG9naWNcIilcblx0XHRcdFx0XHRcdC5zZXREZXNjKFwiV2hldGhlciB0aGUgcHJvcGVydHkgdmFsdWUgJ3RydWUnIG1lYW5zIGl0IGlzIGEgZHJhZnQgb3IgcHVibGlzaGVkLlwiKVxuXHRcdFx0XHRcdFx0LmFkZERyb3Bkb3duKGRyb3Bkb3duID0+XG5cdFx0XHRcdFx0XHRcdGRyb3Bkb3duXG5cdFx0XHRcdFx0XHRcdFx0LmFkZE9wdGlvbihcInRydWUtaXMtZHJhZnRcIiwgXCJUcnVlID0gRHJhZnRcIilcblx0XHRcdFx0XHRcdFx0XHQuYWRkT3B0aW9uKFwiZmFsc2UtaXMtZHJhZnRcIiwgXCJUcnVlID0gUHVibGlzaGVkXCIpXG5cdFx0XHRcdFx0XHRcdFx0LnNldFZhbHVlKHNldHRpbmdzLmRyYWZ0TG9naWMgfHwgXCJ0cnVlLWlzLWRyYWZ0XCIpXG5cdFx0XHRcdFx0XHRcdFx0Lm9uQ2hhbmdlKGFzeW5jIHZhbHVlID0+IHtcblx0XHRcdFx0XHRcdFx0XHRcdHNldHRpbmdzLmRyYWZ0TG9naWMgPSB2YWx1ZSBhcyAndHJ1ZS1pcy1kcmFmdCcgfCAnZmFsc2UtaXMtZHJhZnQnO1xuXHRcdFx0XHRcdFx0XHRcdFx0YXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XG5cdFx0XHRcdFx0XHRcdFx0XHR0aGlzLnBsdWdpbi5mcm9udG1hdHRlclNlcnZpY2U/LmluaXRpYWxpemVEcmFmdFN0YXR1c01hcCgpO1xuXHRcdFx0XHRcdFx0XHRcdH0pXG5cdFx0XHRcdFx0XHQpO1xuXHRcdFx0XHR9KTtcblx0XHRcdH1cblxuXHRcdFx0YXV0b21hdGlvbkdyb3VwLmFkZFNldHRpbmcoc2V0dGluZyA9PiB7XG5cdFx0XHRcdHNldHRpbmdcblx0XHRcdFx0XHQuc2V0TmFtZShcIlB1Ymxpc2hlZCBkYXRlIHByb3BlcnR5IG5hbWVcIilcblx0XHRcdFx0XHQuc2V0RGVzYyhcIlRoZSBwcm9wZXJ0eSBmaWVsZCB0byB1cGRhdGUgd2hlbiBwdWJsaXNoZWQgKCdkYXRlJyBvciAncHViRGF0ZScpLlwiKVxuXHRcdFx0XHRcdC5hZGRUZXh0KHRleHQgPT5cblx0XHRcdFx0XHRcdHRleHRcblx0XHRcdFx0XHRcdFx0LnNldFBsYWNlaG9sZGVyKFwiZGF0ZVwiKVxuXHRcdFx0XHRcdFx0XHQuc2V0VmFsdWUoc2V0dGluZ3MucHVibGlzaERhdGVGaWVsZCB8fCBcIlwiKVxuXHRcdFx0XHRcdFx0XHQub25DaGFuZ2UoYXN5bmMgKHZhbHVlOiBzdHJpbmcpID0+IHtcblx0XHRcdFx0XHRcdFx0XHRzZXR0aW5ncy5wdWJsaXNoRGF0ZUZpZWxkID0gdmFsdWU7XG5cdFx0XHRcdFx0XHRcdFx0YXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XG5cdFx0XHRcdFx0XHRcdH0pXG5cdFx0XHRcdFx0KTtcblx0XHRcdH0pO1xuXHRcdH1cblxuXHRcdC8vIENvbnRlbnQgdHlwZXNcblx0XHRjb25zdCBjb250ZW50VHlwZXNHcm91cCA9IG5ldyBTZXR0aW5nR3JvdXAoY29udGFpbmVyRWwpLnNldEhlYWRpbmcoXCJDb250ZW50IHR5cGVzXCIpO1xuXG5cdFx0Ly8gQWRkIGNvbnRhaW5lciBhcyBhIHNldHRpbmcgLSBoaWRlIHRoZSBzZXR0aW5nJ3MgZGVmYXVsdCBVSSwgYWRkIG91ciBjb250YWluZXIgaW5zaWRlXG5cdFx0Y29udGVudFR5cGVzR3JvdXAuYWRkU2V0dGluZyhzZXR0aW5nID0+IHtcblx0XHRcdC8vIEhpZGUgdGhlIHNldHRpbmcncyBkZWZhdWx0IFVJIGVsZW1lbnRzIHVzaW5nIENTUyBjbGFzc2VzXG5cdFx0XHRzZXR0aW5nLnNldHRpbmdFbC5hZGRDbGFzcyhcImFzdHJvLWNvbXBvc2VyLXNldHRpbmctaGlkZGVuLWVsZW1lbnRzXCIpO1xuXHRcdFx0c2V0dGluZy5zZXR0aW5nRWwuYWRkQ2xhc3MoXCJhc3Ryby1jb21wb3Nlci1zZXR0aW5nLWNvbnRhaW5lci1mdWxsLXdpZHRoXCIpO1xuXHRcdFx0Ly8gQWRkIG91ciBjb250YWluZXIgaW5zaWRlIHRoZSBzZXR0aW5nIGVsZW1lbnQgLSBlbnN1cmUgaXQncyB2aXNpYmxlXG5cdFx0XHR0aGlzLmN1c3RvbUNvbnRlbnRUeXBlc0NvbnRhaW5lciA9IHNldHRpbmcuc2V0dGluZ0VsLmNyZWF0ZURpdih7XG5cdFx0XHRcdGNsczogXCJjdXN0b20tY29udGVudC10eXBlcy1jb250YWluZXIgYXN0cm8tY29tcG9zZXItY3VzdG9tLXR5cGVzLWNvbnRhaW5lci12aXNpYmxlXCJcblx0XHRcdH0pO1xuXHRcdH0pO1xuXHRcdC8vIFJlbmRlciBjb250ZW50IHR5cGVzIGFmdGVyIGNvbnRhaW5lciBpcyBjcmVhdGVkXG5cdFx0aWYgKHRoaXMuY3VzdG9tQ29udGVudFR5cGVzQ29udGFpbmVyKSB7XG5cdFx0XHR0aGlzLnJlbmRlckN1c3RvbUNvbnRlbnRUeXBlcygpO1xuXHRcdH1cblxuXHRcdC8vIERldmVsb3BlciBjb21tYW5kcyAoZGVza3RvcCBvbmx5IC0gbm90IGF2YWlsYWJsZSBvbiBtb2JpbGUpXG5cdFx0aWYgKCFQbGF0Zm9ybS5pc01vYmlsZSkge1xuXHRcdFx0Y29uc3QgZGV2ZWxvcGVyR3JvdXAgPSBuZXcgU2V0dGluZ0dyb3VwKGNvbnRhaW5lckVsKS5zZXRIZWFkaW5nKFwiRGV2ZWxvcGVyIGNvbW1hbmRzXCIpO1xuXG5cdFx0XHQvLyBUZXJtaW5hbCBjb21tYW5kIHNldHRpbmdzXG5cdFx0XHRkZXZlbG9wZXJHcm91cC5hZGRTZXR0aW5nKHNldHRpbmcgPT4ge1xuXHRcdFx0XHRzZXR0aW5nXG5cdFx0XHRcdFx0LnNldE5hbWUoXCJFbmFibGUgb3BlbiB0ZXJtaW5hbCBjb21tYW5kXCIpXG5cdFx0XHRcdFx0LnNldERlc2MoXCJFbmFibGUgY29tbWFuZCB0byBvcGVuIHRlcm1pbmFsIGluIHByb2plY3Qgcm9vdCBkaXJlY3RvcnkuXCIpXG5cdFx0XHRcdFx0LmFkZFRvZ2dsZSh0b2dnbGUgPT5cblx0XHRcdFx0XHRcdHRvZ2dsZVxuXHRcdFx0XHRcdFx0XHQuc2V0VmFsdWUoc2V0dGluZ3MuZW5hYmxlT3BlblRlcm1pbmFsQ29tbWFuZClcblx0XHRcdFx0XHRcdFx0Lm9uQ2hhbmdlKGFzeW5jICh2YWx1ZTogYm9vbGVhbikgPT4ge1xuXHRcdFx0XHRcdFx0XHRcdHNldHRpbmdzLmVuYWJsZU9wZW5UZXJtaW5hbENvbW1hbmQgPSB2YWx1ZTtcblx0XHRcdFx0XHRcdFx0XHRhd2FpdCB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKTtcblx0XHRcdFx0XHRcdFx0XHR0aGlzLnVwZGF0ZVRlcm1pbmFsQ29tbWFuZEZpZWxkcygpO1xuXHRcdFx0XHRcdFx0XHRcdC8vIHJlZ2lzdGVyUmliYm9uSWNvbnMgY2hlY2tzIGJvdGggY29tbWFuZCBhbmQgaWNvbiBzZXR0aW5nc1xuXHRcdFx0XHRcdFx0XHRcdC8vIElmIGNvbW1hbmQgaXMgZW5hYmxlZCBBTkQgaWNvbiBpcyBlbmFibGVkLCBpdCB3aWxsIHNob3c7IG90aGVyd2lzZSBpdCB3aWxsIGhpZGVcblx0XHRcdFx0XHRcdFx0XHRpZiAodGhpcy5wbHVnaW4ucmVnaXN0ZXJSaWJib25JY29ucykge1xuXHRcdFx0XHRcdFx0XHRcdFx0dGhpcy5wbHVnaW4ucmVnaXN0ZXJSaWJib25JY29ucygpO1xuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0fSlcblx0XHRcdFx0XHQpO1xuXHRcdFx0fSk7XG5cblx0XHRcdC8vIENyZWF0ZSBjb250YWluZXIgZm9yIHRlcm1pbmFsIGNvbW1hbmQgZmllbGRzIC0ga2VlcCBmb3IgYmFja3dhcmQgY29tcGF0aWJpbGl0eSB3aXRoIHVwZGF0ZSBtZXRob2RzXG5cdFx0XHR0aGlzLnRlcm1pbmFsQ29tbWFuZENvbnRhaW5lciA9IGNvbnRhaW5lckVsLmNyZWF0ZURpdih7IGNsczogXCJ0ZXJtaW5hbC1jb21tYW5kLWZpZWxkc1wiIH0pO1xuXHRcdFx0dGhpcy50ZXJtaW5hbENvbW1hbmRDb250YWluZXIuY2xhc3NMaXN0LnRvZ2dsZShcImFzdHJvLWNvbXBvc2VyLXNldHRpbmctY29udGFpbmVyLXZpc2libGVcIiwgc2V0dGluZ3MuZW5hYmxlT3BlblRlcm1pbmFsQ29tbWFuZCk7XG5cdFx0XHR0aGlzLnRlcm1pbmFsQ29tbWFuZENvbnRhaW5lci5jbGFzc0xpc3QudG9nZ2xlKFwiYXN0cm8tY29tcG9zZXItc2V0dGluZy1jb250YWluZXItaGlkZGVuXCIsICFzZXR0aW5ncy5lbmFibGVPcGVuVGVybWluYWxDb21tYW5kKTtcblxuXHRcdFx0ZGV2ZWxvcGVyR3JvdXAuYWRkU2V0dGluZyhzZXR0aW5nID0+IHtcblx0XHRcdFx0Y29uc3QgZGVzY0ZyYWdtZW50ID0gZG9jdW1lbnQuY3JlYXRlRG9jdW1lbnRGcmFnbWVudCgpO1xuXHRcdFx0XHQvLyBUZXh0IGlzIGFscmVhZHkgaW4gc2VudGVuY2UgY2FzZTsgXCJPYnNpZGlhblwiIGlzIGEgcHJvcGVyIG5vdW5cblx0XHRcdFx0ZGVzY0ZyYWdtZW50LmNyZWF0ZUVsKFwiZGl2XCIsIHsgdGV4dDogXCJQYXRoIHJlbGF0aXZlIHRvIHRoZSBPYnNpZGlhbiB2YXVsdCByb290IGZvbGRlci4gVXNlIC4uLy4uIGZvciB0d28gbGV2ZWxzIHVwLiBMZWF2ZSBibGFuayB0byB1c2UgdGhlIHZhdWx0IGZvbGRlclwiIH0pO1xuXHRcdFx0XHRkZXNjRnJhZ21lbnQuY3JlYXRlRWwoXCJkaXZcIiwgeyB0ZXh0OiBcIlRoaXMgaXMgd2hlcmUgdGhlIHRlcm1pbmFsIHdpbGwgb3Blbi4gQWJzb2x1dGUgcGF0aHMgd29yayBhbHNvLlwiIH0pO1xuXHRcdFx0XHRzZXR0aW5nXG5cdFx0XHRcdFx0LnNldE5hbWUoXCJQcm9qZWN0IHJvb3QgZGlyZWN0b3J5IHBhdGhcIilcblx0XHRcdFx0XHQuc2V0RGVzYyhkZXNjRnJhZ21lbnQpXG5cdFx0XHRcdFx0LmFkZFRleHQodGV4dCA9PlxuXHRcdFx0XHRcdFx0dGV4dFxuXHRcdFx0XHRcdFx0XHQuc2V0UGxhY2Vob2xkZXIoXCIuLi8uLlwiKVxuXHRcdFx0XHRcdFx0XHQuc2V0VmFsdWUoc2V0dGluZ3MudGVybWluYWxQcm9qZWN0Um9vdFBhdGgpXG5cdFx0XHRcdFx0XHRcdC5vbkNoYW5nZShhc3luYyAodmFsdWU6IHN0cmluZykgPT4ge1xuXHRcdFx0XHRcdFx0XHRcdHNldHRpbmdzLnRlcm1pbmFsUHJvamVjdFJvb3RQYXRoID0gdmFsdWU7XG5cdFx0XHRcdFx0XHRcdFx0YXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XG5cdFx0XHRcdFx0XHRcdH0pXG5cdFx0XHRcdFx0KTtcblx0XHRcdFx0Ly8gQWRkIGNsYXNzIGZvciBjb25kaXRpb25hbCB2aXNpYmlsaXR5IC0ga2VlcCBzZXR0aW5nIGluIGdyb3VwXG5cdFx0XHRcdHNldHRpbmcuc2V0dGluZ0VsLmNsYXNzTGlzdC50b2dnbGUoXCJhc3Ryby1jb21wb3Nlci1zZXR0aW5nLWNvbnRhaW5lci12aXNpYmxlXCIsIHNldHRpbmdzLmVuYWJsZU9wZW5UZXJtaW5hbENvbW1hbmQpO1xuXHRcdFx0XHRzZXR0aW5nLnNldHRpbmdFbC5jbGFzc0xpc3QudG9nZ2xlKFwiYXN0cm8tY29tcG9zZXItc2V0dGluZy1jb250YWluZXItaGlkZGVuXCIsICFzZXR0aW5ncy5lbmFibGVPcGVuVGVybWluYWxDb21tYW5kKTtcblx0XHRcdH0pO1xuXG5cdFx0XHRkZXZlbG9wZXJHcm91cC5hZGRTZXR0aW5nKHNldHRpbmcgPT4ge1xuXHRcdFx0XHRjb25zdCBkZXNjRnJhZ21lbnQgPSBkb2N1bWVudC5jcmVhdGVEb2N1bWVudEZyYWdtZW50KCk7XG5cdFx0XHRcdC8vIFRleHQgaXMgYWxyZWFkeSBpbiBzZW50ZW5jZSBjYXNlOyBwcm9wZXIgbm91bnMgb3IgcHJvZHVjdCBuYW1lcyBsaWtlIFwibWFjT1NcIiwgXCJXaW5kb3dzXCIsIFwiTGludXhcIlxuXHRcdFx0XHRkZXNjRnJhZ21lbnQuY3JlYXRlRWwoXCJkaXZcIiwgeyB0ZXh0OiBcIkxlYXZlIGJsYW5rIHRvIHVzZSBwbGF0Zm9ybSBkZWZhdWx0cy4gT24gbWFjT1MsIHRoZSBkZWZhdWx0IGlzIFRlcm1pbmFsLiBPbiBXaW5kb3dzLCBpdCdzIFdpbmRvd3MgVGVybWluYWwgKFdpbiAxMSkgb3IgY21kLmV4ZSAoV2luIDEwKS4gT24gTGludXgsIGl0J3MgZ25vbWUtdGVybWluYWwsIGtvbnNvbGUsIG9yIHh0ZXJtXCIgfSk7XG5cdFx0XHRcdC8vIFRleHQgaXMgYWxyZWFkeSBpbiBzZW50ZW5jZSBjYXNlOyBwcm9wZXIgbm91bnMgbGlrZSBcIlRlcm1pbmFsXCIsIFwiaVRlcm1cIiwgXCJQb3dlclNoZWxsXCJcblx0XHRcdFx0ZGVzY0ZyYWdtZW50LmNyZWF0ZUVsKFwiZGl2XCIsIHsgdGV4dDogXCJFeGFtcGxlcyBpbmNsdWRlIFRlcm1pbmFsLCBpVGVybSwgUG93ZXJTaGVsbCwgYW5kIEFsYWNyaXR0eVwiIH0pO1xuXHRcdFx0XHRzZXR0aW5nXG5cdFx0XHRcdFx0LnNldE5hbWUoXCJUZXJtaW5hbCBhcHBsaWNhdGlvbiBuYW1lXCIpXG5cdFx0XHRcdFx0LnNldERlc2MoZGVzY0ZyYWdtZW50KVxuXHRcdFx0XHRcdC5hZGRUZXh0KHRleHQgPT5cblx0XHRcdFx0XHRcdHRleHRcblx0XHRcdFx0XHRcdFx0LnNldFBsYWNlaG9sZGVyKFwiVGVybWluYWxcIilcblx0XHRcdFx0XHRcdFx0LnNldFZhbHVlKHNldHRpbmdzLnRlcm1pbmFsQXBwbGljYXRpb25OYW1lKVxuXHRcdFx0XHRcdFx0XHQub25DaGFuZ2UoYXN5bmMgKHZhbHVlOiBzdHJpbmcpID0+IHtcblx0XHRcdFx0XHRcdFx0XHRzZXR0aW5ncy50ZXJtaW5hbEFwcGxpY2F0aW9uTmFtZSA9IHZhbHVlO1xuXHRcdFx0XHRcdFx0XHRcdGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xuXHRcdFx0XHRcdFx0XHR9KVxuXHRcdFx0XHRcdCk7XG5cdFx0XHRcdC8vIEFkZCBjbGFzcyBmb3IgY29uZGl0aW9uYWwgdmlzaWJpbGl0eSAtIGtlZXAgc2V0dGluZyBpbiBncm91cFxuXHRcdFx0XHRzZXR0aW5nLnNldHRpbmdFbC5jbGFzc0xpc3QudG9nZ2xlKFwiYXN0cm8tY29tcG9zZXItc2V0dGluZy1jb250YWluZXItdmlzaWJsZVwiLCBzZXR0aW5ncy5lbmFibGVPcGVuVGVybWluYWxDb21tYW5kKTtcblx0XHRcdFx0c2V0dGluZy5zZXR0aW5nRWwuY2xhc3NMaXN0LnRvZ2dsZShcImFzdHJvLWNvbXBvc2VyLXNldHRpbmctY29udGFpbmVyLWhpZGRlblwiLCAhc2V0dGluZ3MuZW5hYmxlT3BlblRlcm1pbmFsQ29tbWFuZCk7XG5cdFx0XHR9KTtcblxuXHRcdFx0ZGV2ZWxvcGVyR3JvdXAuYWRkU2V0dGluZyhzZXR0aW5nID0+IHtcblx0XHRcdFx0c2V0dGluZ1xuXHRcdFx0XHRcdC5zZXROYW1lKFwiRW5hYmxlIGRlYnVnIGxvZ2dpbmdcIilcblx0XHRcdFx0XHQuc2V0RGVzYyhcIkxvZyB0ZXJtaW5hbCBsYXVuY2ggY29tbWFuZHMgYW5kIHBsYXRmb3JtIGRlY2lzaW9ucyB0byB0aGUgZGV2ZWxvcGVyIGNvbnNvbGUgZm9yIHRyb3VibGVzaG9vdGluZy5cIilcblx0XHRcdFx0XHQuYWRkVG9nZ2xlKHRvZ2dsZSA9PlxuXHRcdFx0XHRcdFx0dG9nZ2xlXG5cdFx0XHRcdFx0XHRcdC5zZXRWYWx1ZShzZXR0aW5ncy5lbmFibGVUZXJtaW5hbERlYnVnTG9nZ2luZylcblx0XHRcdFx0XHRcdFx0Lm9uQ2hhbmdlKGFzeW5jICh2YWx1ZTogYm9vbGVhbikgPT4ge1xuXHRcdFx0XHRcdFx0XHRcdHNldHRpbmdzLmVuYWJsZVRlcm1pbmFsRGVidWdMb2dnaW5nID0gdmFsdWU7XG5cdFx0XHRcdFx0XHRcdFx0YXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XG5cdFx0XHRcdFx0XHRcdH0pXG5cdFx0XHRcdFx0KTtcblx0XHRcdFx0Ly8gQWRkIGNsYXNzIGZvciBjb25kaXRpb25hbCB2aXNpYmlsaXR5IC0ga2VlcCBzZXR0aW5nIGluIGdyb3VwXG5cdFx0XHRcdHNldHRpbmcuc2V0dGluZ0VsLmNsYXNzTGlzdC50b2dnbGUoXCJhc3Ryby1jb21wb3Nlci1zZXR0aW5nLWNvbnRhaW5lci12aXNpYmxlXCIsIHNldHRpbmdzLmVuYWJsZU9wZW5UZXJtaW5hbENvbW1hbmQpO1xuXHRcdFx0XHRzZXR0aW5nLnNldHRpbmdFbC5jbGFzc0xpc3QudG9nZ2xlKFwiYXN0cm8tY29tcG9zZXItc2V0dGluZy1jb250YWluZXItaGlkZGVuXCIsICFzZXR0aW5ncy5lbmFibGVPcGVuVGVybWluYWxDb21tYW5kKTtcblx0XHRcdH0pO1xuXG5cdFx0XHRkZXZlbG9wZXJHcm91cC5hZGRTZXR0aW5nKHNldHRpbmcgPT4ge1xuXHRcdFx0XHRzZXR0aW5nXG5cdFx0XHRcdFx0LnNldE5hbWUoXCJTaG93IG9wZW4gdGVybWluYWwgcmliYm9uIGljb25cIilcblx0XHRcdFx0XHQuc2V0RGVzYyhcIkFkZCBhIHJpYmJvbiBpY29uIHRvIGxhdW5jaCB0aGUgdGVybWluYWwgY29tbWFuZC5cIilcblx0XHRcdFx0XHQuYWRkVG9nZ2xlKHRvZ2dsZSA9PiB7XG5cdFx0XHRcdFx0XHR0aGlzLnRlcm1pbmFsUmliYm9uVG9nZ2xlQ29tcG9uZW50ID0gdG9nZ2xlO1xuXHRcdFx0XHRcdFx0dG9nZ2xlXG5cdFx0XHRcdFx0XHRcdC5zZXRWYWx1ZShzZXR0aW5ncy5lbmFibGVUZXJtaW5hbFJpYmJvbkljb24pXG5cdFx0XHRcdFx0XHRcdC5zZXREaXNhYmxlZCghc2V0dGluZ3MuZW5hYmxlT3BlblRlcm1pbmFsQ29tbWFuZClcblx0XHRcdFx0XHRcdFx0Lm9uQ2hhbmdlKGFzeW5jICh2YWx1ZTogYm9vbGVhbikgPT4ge1xuXHRcdFx0XHRcdFx0XHRcdC8vIFVwZGF0ZSBzZXR0aW5ncyBkaXJlY3RseSBvbiBwbHVnaW4gaW5zdGFuY2Vcblx0XHRcdFx0XHRcdFx0XHR0aGlzLnBsdWdpbi5zZXR0aW5ncy5lbmFibGVUZXJtaW5hbFJpYmJvbkljb24gPSB2YWx1ZTtcblx0XHRcdFx0XHRcdFx0XHRzZXR0aW5ncy5lbmFibGVUZXJtaW5hbFJpYmJvbkljb24gPSB2YWx1ZTtcblx0XHRcdFx0XHRcdFx0XHRhd2FpdCB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKTtcblx0XHRcdFx0XHRcdFx0XHQvLyBTbWFsbCBkZWxheSB0byBlbnN1cmUgc2V0dGluZ3MgYXJlIHNhdmVkLCB0aGVuIHJlLXJlZ2lzdGVyXG5cdFx0XHRcdFx0XHRcdFx0c2V0VGltZW91dCgoKSA9PiB7XG5cdFx0XHRcdFx0XHRcdFx0XHRpZiAodGhpcy5wbHVnaW4ucmVnaXN0ZXJSaWJib25JY29ucykge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHR0aGlzLnBsdWdpbi5yZWdpc3RlclJpYmJvbkljb25zKCk7XG5cdFx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdFx0fSwgNTApO1xuXHRcdFx0XHRcdFx0XHR9KTtcblx0XHRcdFx0XHR9KTtcblx0XHRcdFx0Ly8gQWRkIGNsYXNzIGZvciBjb25kaXRpb25hbCB2aXNpYmlsaXR5IC0ga2VlcCBzZXR0aW5nIGluIGdyb3VwXG5cdFx0XHRcdHNldHRpbmcuc2V0dGluZ0VsLmNsYXNzTGlzdC50b2dnbGUoXCJhc3Ryby1jb21wb3Nlci1zZXR0aW5nLWNvbnRhaW5lci12aXNpYmxlXCIsIHNldHRpbmdzLmVuYWJsZU9wZW5UZXJtaW5hbENvbW1hbmQpO1xuXHRcdFx0XHRzZXR0aW5nLnNldHRpbmdFbC5jbGFzc0xpc3QudG9nZ2xlKFwiYXN0cm8tY29tcG9zZXItc2V0dGluZy1jb250YWluZXItaGlkZGVuXCIsICFzZXR0aW5ncy5lbmFibGVPcGVuVGVybWluYWxDb21tYW5kKTtcblx0XHRcdFx0Ly8gU3RvcmUgcmVmZXJlbmNlIGZvciB1cGRhdGluZyBkaXNhYmxlZCBzdGF0ZVxuXHRcdFx0XHR0aGlzLnRlcm1pbmFsUmliYm9uVG9nZ2xlID0gc2V0dGluZztcblx0XHRcdH0pO1xuXG5cdFx0XHQvLyBDb25maWcgZmlsZSBjb21tYW5kIHNldHRpbmdzXG5cdFx0XHRkZXZlbG9wZXJHcm91cC5hZGRTZXR0aW5nKHNldHRpbmcgPT4ge1xuXHRcdFx0XHRzZXR0aW5nXG5cdFx0XHRcdFx0LnNldE5hbWUoXCJFbmFibGUgZWRpdCBjb25maWcgZmlsZSBjb21tYW5kXCIpXG5cdFx0XHRcdFx0LnNldERlc2MoXCJFbmFibGUgY29tbWFuZCB0byBvcGVuIGFzdHJvIGNvbmZpZyBmaWxlIGluIGRlZmF1bHQgZWRpdG9yLlwiKVxuXHRcdFx0XHRcdC5hZGRUb2dnbGUodG9nZ2xlID0+XG5cdFx0XHRcdFx0XHR0b2dnbGVcblx0XHRcdFx0XHRcdFx0LnNldFZhbHVlKHNldHRpbmdzLmVuYWJsZU9wZW5Db25maWdGaWxlQ29tbWFuZClcblx0XHRcdFx0XHRcdFx0Lm9uQ2hhbmdlKGFzeW5jICh2YWx1ZTogYm9vbGVhbikgPT4ge1xuXHRcdFx0XHRcdFx0XHRcdHNldHRpbmdzLmVuYWJsZU9wZW5Db25maWdGaWxlQ29tbWFuZCA9IHZhbHVlO1xuXHRcdFx0XHRcdFx0XHRcdGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xuXHRcdFx0XHRcdFx0XHRcdHRoaXMudXBkYXRlQ29uZmlnQ29tbWFuZEZpZWxkcygpO1xuXHRcdFx0XHRcdFx0XHRcdC8vIHJlZ2lzdGVyUmliYm9uSWNvbnMgY2hlY2tzIGJvdGggY29tbWFuZCBhbmQgaWNvbiBzZXR0aW5nc1xuXHRcdFx0XHRcdFx0XHRcdC8vIElmIGNvbW1hbmQgaXMgZW5hYmxlZCBBTkQgaWNvbiBpcyBlbmFibGVkLCBpdCB3aWxsIHNob3c7IG90aGVyd2lzZSBpdCB3aWxsIGhpZGVcblx0XHRcdFx0XHRcdFx0XHRpZiAodGhpcy5wbHVnaW4ucmVnaXN0ZXJSaWJib25JY29ucykge1xuXHRcdFx0XHRcdFx0XHRcdFx0dGhpcy5wbHVnaW4ucmVnaXN0ZXJSaWJib25JY29ucygpO1xuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0fSlcblx0XHRcdFx0XHQpO1xuXHRcdFx0fSk7XG5cblx0XHRcdC8vIENyZWF0ZSBjb250YWluZXIgZm9yIGNvbmZpZyBjb21tYW5kIGZpZWxkcyAtIGtlZXAgZm9yIGJhY2t3YXJkIGNvbXBhdGliaWxpdHkgd2l0aCB1cGRhdGUgbWV0aG9kc1xuXHRcdFx0dGhpcy5jb25maWdDb21tYW5kQ29udGFpbmVyID0gY29udGFpbmVyRWwuY3JlYXRlRGl2KHsgY2xzOiBcImNvbmZpZy1jb21tYW5kLWZpZWxkc1wiIH0pO1xuXHRcdFx0dGhpcy5jb25maWdDb21tYW5kQ29udGFpbmVyLmNsYXNzTGlzdC50b2dnbGUoXCJhc3Ryby1jb21wb3Nlci1zZXR0aW5nLWNvbnRhaW5lci12aXNpYmxlXCIsIHNldHRpbmdzLmVuYWJsZU9wZW5Db25maWdGaWxlQ29tbWFuZCk7XG5cdFx0XHR0aGlzLmNvbmZpZ0NvbW1hbmRDb250YWluZXIuY2xhc3NMaXN0LnRvZ2dsZShcImFzdHJvLWNvbXBvc2VyLXNldHRpbmctY29udGFpbmVyLWhpZGRlblwiLCAhc2V0dGluZ3MuZW5hYmxlT3BlbkNvbmZpZ0ZpbGVDb21tYW5kKTtcblxuXHRcdFx0ZGV2ZWxvcGVyR3JvdXAuYWRkU2V0dGluZyhzZXR0aW5nID0+IHtcblx0XHRcdFx0Y29uc3QgZGVzY0ZyYWdtZW50ID0gZG9jdW1lbnQuY3JlYXRlRG9jdW1lbnRGcmFnbWVudCgpO1xuXHRcdFx0XHRkZXNjRnJhZ21lbnQuY3JlYXRlRWwoXCJkaXZcIiwgeyB0ZXh0OiBcIlBhdGggdG8gdGhlIGNvbmZpZyBmaWxlIHJlbGF0aXZlIHRvIHRoZSB2YXVsdCByb290LiBVc2UgLi4vY29uZmlnLnRzIG9yIC4uLy4uL2FzdHJvLmNvbmZpZy5tanMuXCIgfSk7XG5cdFx0XHRcdGRlc2NGcmFnbWVudC5jcmVhdGVFbChcImRpdlwiLCB7IHRleHQ6IFwiQWJzb2x1dGUgcGF0aHMgd29yayBhbHNvLlwiIH0pO1xuXHRcdFx0XHRzZXR0aW5nXG5cdFx0XHRcdFx0LnNldE5hbWUoXCJDb25maWcgZmlsZSBwYXRoXCIpXG5cdFx0XHRcdFx0LnNldERlc2MoZGVzY0ZyYWdtZW50KVxuXHRcdFx0XHRcdC5hZGRUZXh0KHRleHQgPT5cblx0XHRcdFx0XHRcdHRleHRcblx0XHRcdFx0XHRcdFx0LnNldFBsYWNlaG9sZGVyKFwiLi4vY29uZmlnLnRzXCIpXG5cdFx0XHRcdFx0XHRcdC5zZXRWYWx1ZShzZXR0aW5ncy5jb25maWdGaWxlUGF0aClcblx0XHRcdFx0XHRcdFx0Lm9uQ2hhbmdlKGFzeW5jICh2YWx1ZTogc3RyaW5nKSA9PiB7XG5cdFx0XHRcdFx0XHRcdFx0c2V0dGluZ3MuY29uZmlnRmlsZVBhdGggPSB2YWx1ZTtcblx0XHRcdFx0XHRcdFx0XHRhd2FpdCB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKTtcblx0XHRcdFx0XHRcdFx0fSlcblx0XHRcdFx0XHQpO1xuXHRcdFx0XHQvLyBBZGQgY2xhc3MgZm9yIGNvbmRpdGlvbmFsIHZpc2liaWxpdHkgLSBrZWVwIHNldHRpbmcgaW4gZ3JvdXBcblx0XHRcdFx0c2V0dGluZy5zZXR0aW5nRWwuY2xhc3NMaXN0LnRvZ2dsZShcImFzdHJvLWNvbXBvc2VyLXNldHRpbmctY29udGFpbmVyLXZpc2libGVcIiwgc2V0dGluZ3MuZW5hYmxlT3BlbkNvbmZpZ0ZpbGVDb21tYW5kKTtcblx0XHRcdFx0c2V0dGluZy5zZXR0aW5nRWwuY2xhc3NMaXN0LnRvZ2dsZShcImFzdHJvLWNvbXBvc2VyLXNldHRpbmctY29udGFpbmVyLWhpZGRlblwiLCAhc2V0dGluZ3MuZW5hYmxlT3BlbkNvbmZpZ0ZpbGVDb21tYW5kKTtcblx0XHRcdH0pO1xuXG5cdFx0XHRkZXZlbG9wZXJHcm91cC5hZGRTZXR0aW5nKHNldHRpbmcgPT4ge1xuXHRcdFx0XHRzZXR0aW5nXG5cdFx0XHRcdFx0LnNldE5hbWUoXCJTaG93IG9wZW4gY29uZmlnIHJpYmJvbiBpY29uXCIpXG5cdFx0XHRcdFx0LnNldERlc2MoXCJBZGQgYSByaWJib24gaWNvbiB0byBsYXVuY2ggdGhlIGNvbmZpZyBmaWxlIGNvbW1hbmQuXCIpXG5cdFx0XHRcdFx0LmFkZFRvZ2dsZSh0b2dnbGUgPT4ge1xuXHRcdFx0XHRcdFx0dGhpcy5jb25maWdSaWJib25Ub2dnbGVDb21wb25lbnQgPSB0b2dnbGU7XG5cdFx0XHRcdFx0XHR0b2dnbGVcblx0XHRcdFx0XHRcdFx0LnNldFZhbHVlKHNldHRpbmdzLmVuYWJsZUNvbmZpZ1JpYmJvbkljb24pXG5cdFx0XHRcdFx0XHRcdC5zZXREaXNhYmxlZCghc2V0dGluZ3MuZW5hYmxlT3BlbkNvbmZpZ0ZpbGVDb21tYW5kKVxuXHRcdFx0XHRcdFx0XHQub25DaGFuZ2UoYXN5bmMgKHZhbHVlOiBib29sZWFuKSA9PiB7XG5cdFx0XHRcdFx0XHRcdFx0Ly8gVXBkYXRlIHNldHRpbmdzIGRpcmVjdGx5IG9uIHBsdWdpbiBpbnN0YW5jZVxuXHRcdFx0XHRcdFx0XHRcdHRoaXMucGx1Z2luLnNldHRpbmdzLmVuYWJsZUNvbmZpZ1JpYmJvbkljb24gPSB2YWx1ZTtcblx0XHRcdFx0XHRcdFx0XHRzZXR0aW5ncy5lbmFibGVDb25maWdSaWJib25JY29uID0gdmFsdWU7XG5cdFx0XHRcdFx0XHRcdFx0YXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XG5cdFx0XHRcdFx0XHRcdFx0Ly8gU21hbGwgZGVsYXkgdG8gZW5zdXJlIHNldHRpbmdzIGFyZSBzYXZlZCwgdGhlbiByZS1yZWdpc3RlclxuXHRcdFx0XHRcdFx0XHRcdHNldFRpbWVvdXQoKCkgPT4ge1xuXHRcdFx0XHRcdFx0XHRcdFx0aWYgKHRoaXMucGx1Z2luLnJlZ2lzdGVyUmliYm9uSWNvbnMpIHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0dGhpcy5wbHVnaW4ucmVnaXN0ZXJSaWJib25JY29ucygpO1xuXHRcdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdH0sIDUwKTtcblx0XHRcdFx0XHRcdFx0fSk7XG5cdFx0XHRcdFx0fSk7XG5cdFx0XHRcdC8vIEFkZCBjbGFzcyBmb3IgY29uZGl0aW9uYWwgdmlzaWJpbGl0eSAtIGtlZXAgc2V0dGluZyBpbiBncm91cFxuXHRcdFx0XHRzZXR0aW5nLnNldHRpbmdFbC5jbGFzc0xpc3QudG9nZ2xlKFwiYXN0cm8tY29tcG9zZXItc2V0dGluZy1jb250YWluZXItdmlzaWJsZVwiLCBzZXR0aW5ncy5lbmFibGVPcGVuQ29uZmlnRmlsZUNvbW1hbmQpO1xuXHRcdFx0XHRzZXR0aW5nLnNldHRpbmdFbC5jbGFzc0xpc3QudG9nZ2xlKFwiYXN0cm8tY29tcG9zZXItc2V0dGluZy1jb250YWluZXItaGlkZGVuXCIsICFzZXR0aW5ncy5lbmFibGVPcGVuQ29uZmlnRmlsZUNvbW1hbmQpO1xuXHRcdFx0XHQvLyBTdG9yZSByZWZlcmVuY2UgZm9yIHVwZGF0aW5nIGRpc2FibGVkIHN0YXRlXG5cdFx0XHRcdHRoaXMuY29uZmlnUmliYm9uVG9nZ2xlID0gc2V0dGluZztcblx0XHRcdH0pO1xuXG5cdFx0XHQvLyBIZWxwIGJ1dHRvbiByZXBsYWNlbWVudCB0b2dnbGUgKHBhcnQgb2YgZGV2ZWxvcGVyIGNvbW1hbmRzIGdyb3VwKVxuXHRcdFx0ZGV2ZWxvcGVyR3JvdXAuYWRkU2V0dGluZyhzZXR0aW5nID0+IHtcblx0XHRcdFx0c2V0dGluZ1xuXHRcdFx0XHRcdC5zZXROYW1lKCdTd2FwIG91dCBoZWxwIGJ1dHRvbiBmb3IgY3VzdG9tIGFjdGlvbicpXG5cdFx0XHRcdFx0LnNldERlc2MoJ1JlcGxhY2UgdGhlIGhlbHAgYnV0dG9uIGluIHRoZSB2YXVsdCBwcm9maWxlIGFyZWEgd2l0aCBhIGN1c3RvbSBhY3Rpb24uJylcblx0XHRcdFx0XHQuYWRkVG9nZ2xlKHRvZ2dsZSA9PiB0b2dnbGVcblx0XHRcdFx0XHRcdC5zZXRWYWx1ZShzZXR0aW5ncy5oZWxwQnV0dG9uUmVwbGFjZW1lbnQ/LmVuYWJsZWQgPz8gZmFsc2UpXG5cdFx0XHRcdFx0XHQub25DaGFuZ2UoYXN5bmMgdmFsdWUgPT4ge1xuXHRcdFx0XHRcdFx0XHRpZiAoIXNldHRpbmdzLmhlbHBCdXR0b25SZXBsYWNlbWVudCkge1xuXHRcdFx0XHRcdFx0XHRcdHNldHRpbmdzLmhlbHBCdXR0b25SZXBsYWNlbWVudCA9IHtcblx0XHRcdFx0XHRcdFx0XHRcdGVuYWJsZWQ6IGZhbHNlLFxuXHRcdFx0XHRcdFx0XHRcdFx0Y29tbWFuZElkOiAnZWRpdC1hc3Ryby1jb25maWcnLFxuXHRcdFx0XHRcdFx0XHRcdFx0aWNvbklkOiAncm9ja2V0Jyxcblx0XHRcdFx0XHRcdFx0XHR9O1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdHNldHRpbmdzLmhlbHBCdXR0b25SZXBsYWNlbWVudC5lbmFibGVkID0gdmFsdWU7XG5cdFx0XHRcdFx0XHRcdGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xuXHRcdFx0XHRcdFx0XHQvLyBUcmlnZ2VyIGhlbHAgYnV0dG9uIHJlcGxhY2VtZW50IHVwZGF0ZSAoaXQgd2lsbCByZWxvYWQgc2V0dGluZ3MpXG5cdFx0XHRcdFx0XHRcdGlmICh0aGlzLnBsdWdpbi51cGRhdGVIZWxwQnV0dG9uKSB7XG5cdFx0XHRcdFx0XHRcdFx0YXdhaXQgdGhpcy5wbHVnaW4udXBkYXRlSGVscEJ1dHRvbigpO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdC8vIFJlLXJlbmRlciB0byBzaG93L2hpZGUgb3B0aW9uc1xuXHRcdFx0XHRcdFx0XHR0aGlzLmRpc3BsYXkoKTtcblx0XHRcdFx0XHRcdH0pKTtcblx0XHRcdH0pO1xuXG5cdFx0XHQvLyBTaG93IGNvbW1hbmQgYW5kIGljb24gcGlja2VycyBvbmx5IGlmIGVuYWJsZWQgKHBhcnQgb2YgZGV2ZWxvcGVyIGNvbW1hbmRzIGdyb3VwKVxuXHRcdFx0aWYgKHNldHRpbmdzLmhlbHBCdXR0b25SZXBsYWNlbWVudD8uZW5hYmxlZCkge1xuXHRcdFx0XHQvLyBDb21tYW5kIHBpY2tlclxuXHRcdFx0XHRjb25zdCBjb21tYW5kTmFtZSA9IHRoaXMuZ2V0Q29tbWFuZE5hbWUoc2V0dGluZ3MuaGVscEJ1dHRvblJlcGxhY2VtZW50LmNvbW1hbmRJZCk7XG5cdFx0XHRcdGRldmVsb3Blckdyb3VwLmFkZFNldHRpbmcoc2V0dGluZyA9PiB7XG5cdFx0XHRcdFx0c2V0dGluZ1xuXHRcdFx0XHRcdFx0LnNldE5hbWUoJ0NvbW1hbmQnKVxuXHRcdFx0XHRcdFx0LnNldERlc2MoJ1NlbGVjdCB0aGUgY29tbWFuZCB0byBleGVjdXRlIHdoZW4gdGhlIGJ1dHRvbiBpcyBjbGlja2VkLicpXG5cdFx0XHRcdFx0XHQuYWRkQnV0dG9uKGJ1dHRvbiA9PiBidXR0b25cblx0XHRcdFx0XHRcdFx0LnNldEJ1dHRvblRleHQoY29tbWFuZE5hbWUgfHwgJ1NlbGVjdCBjb21tYW5kJylcblx0XHRcdFx0XHRcdFx0Lm9uQ2xpY2soKCkgPT4ge1xuXHRcdFx0XHRcdFx0XHRcdGNvbnN0IG1vZGFsID0gbmV3IENvbW1hbmRQaWNrZXJNb2RhbCh0aGlzLmFwcCwgKGNvbW1hbmRJZCkgPT4ge1xuXHRcdFx0XHRcdFx0XHRcdFx0dm9pZCAoYXN5bmMgKCkgPT4ge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRpZiAoIXNldHRpbmdzLmhlbHBCdXR0b25SZXBsYWNlbWVudCkge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdHNldHRpbmdzLmhlbHBCdXR0b25SZXBsYWNlbWVudCA9IHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdGVuYWJsZWQ6IHRydWUsXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRjb21tYW5kSWQ6ICdlZGl0LWFzdHJvLWNvbmZpZycsXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRpY29uSWQ6ICdyb2NrZXQnLFxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdH07XG5cdFx0XHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0XHRcdFx0c2V0dGluZ3MuaGVscEJ1dHRvblJlcGxhY2VtZW50LmNvbW1hbmRJZCA9IGNvbW1hbmRJZDtcblx0XHRcdFx0XHRcdFx0XHRcdFx0YXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdC8vIFRyaWdnZXIgaGVscCBidXR0b24gcmVwbGFjZW1lbnQgdXBkYXRlIGltbWVkaWF0ZWx5IChpdCB3aWxsIHJlbG9hZCBzZXR0aW5ncylcblx0XHRcdFx0XHRcdFx0XHRcdFx0aWYgKHRoaXMucGx1Z2luLnVwZGF0ZUhlbHBCdXR0b24pIHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRhd2FpdCB0aGlzLnBsdWdpbi51cGRhdGVIZWxwQnV0dG9uKCk7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0XHRcdFx0Ly8gUmUtcmVuZGVyIHRvIHNob3cgdXBkYXRlZCBjb21tYW5kIG5hbWVcblx0XHRcdFx0XHRcdFx0XHRcdFx0dGhpcy5kaXNwbGF5KCk7XG5cdFx0XHRcdFx0XHRcdFx0XHR9KSgpO1xuXHRcdFx0XHRcdFx0XHRcdH0pO1xuXHRcdFx0XHRcdFx0XHRcdG1vZGFsLm9wZW4oKTtcblx0XHRcdFx0XHRcdFx0fSkpO1xuXHRcdFx0XHR9KTtcblxuXHRcdFx0XHQvLyBJY29uIHBpY2tlclxuXHRcdFx0XHRjb25zdCBpY29uTmFtZSA9IHRoaXMuZ2V0SWNvbk5hbWUoc2V0dGluZ3MuaGVscEJ1dHRvblJlcGxhY2VtZW50Lmljb25JZCk7XG5cdFx0XHRcdGRldmVsb3Blckdyb3VwLmFkZFNldHRpbmcoc2V0dGluZyA9PiB7XG5cdFx0XHRcdFx0c2V0dGluZ1xuXHRcdFx0XHRcdFx0LnNldE5hbWUoJ0ljb24nKVxuXHRcdFx0XHRcdFx0LnNldERlc2MoJ1NlbGVjdCB0aGUgaWNvbiB0byBkaXNwbGF5IG9uIHRoZSBidXR0b24uJylcblx0XHRcdFx0XHRcdC5hZGRCdXR0b24oYnV0dG9uID0+IGJ1dHRvblxuXHRcdFx0XHRcdFx0XHQuc2V0QnV0dG9uVGV4dChpY29uTmFtZSB8fCAnU2VsZWN0IGljb24uLi4nKVxuXHRcdFx0XHRcdFx0XHQub25DbGljaygoKSA9PiB7XG5cdFx0XHRcdFx0XHRcdFx0Y29uc3QgbW9kYWwgPSBuZXcgSWNvblBpY2tlck1vZGFsKHRoaXMuYXBwLCAoaWNvbklkKSA9PiB7XG5cdFx0XHRcdFx0XHRcdFx0XHR2b2lkIChhc3luYyAoKSA9PiB7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdGlmICghc2V0dGluZ3MuaGVscEJ1dHRvblJlcGxhY2VtZW50KSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0c2V0dGluZ3MuaGVscEJ1dHRvblJlcGxhY2VtZW50ID0ge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0ZW5hYmxlZDogdHJ1ZSxcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdGNvbW1hbmRJZDogJ2VkaXQtYXN0cm8tY29uZmlnJyxcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdGljb25JZDogJ3JvY2tldCcsXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0fTtcblx0XHRcdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdFx0XHRzZXR0aW5ncy5oZWxwQnV0dG9uUmVwbGFjZW1lbnQuaWNvbklkID0gaWNvbklkO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRhd2FpdCB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKTtcblx0XHRcdFx0XHRcdFx0XHRcdFx0Ly8gVHJpZ2dlciBoZWxwIGJ1dHRvbiByZXBsYWNlbWVudCB1cGRhdGUgaW1tZWRpYXRlbHkgKGl0IHdpbGwgcmVsb2FkIHNldHRpbmdzKVxuXHRcdFx0XHRcdFx0XHRcdFx0XHRpZiAodGhpcy5wbHVnaW4udXBkYXRlSGVscEJ1dHRvbikge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdGF3YWl0IHRoaXMucGx1Z2luLnVwZGF0ZUhlbHBCdXR0b24oKTtcblx0XHRcdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBSZS1yZW5kZXIgdG8gc2hvdyB1cGRhdGVkIGljb24gbmFtZVxuXHRcdFx0XHRcdFx0XHRcdFx0XHR0aGlzLmRpc3BsYXkoKTtcblx0XHRcdFx0XHRcdFx0XHRcdH0pKCk7XG5cdFx0XHRcdFx0XHRcdFx0fSk7XG5cdFx0XHRcdFx0XHRcdFx0bW9kYWwub3BlbigpO1xuXHRcdFx0XHRcdFx0XHR9KSk7XG5cdFx0XHRcdH0pO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHRoaXMudXBkYXRlQ29weUhlYWRpbmdGaWVsZHMoKTtcblx0XHQvLyBPbmx5IHVwZGF0ZSB0ZXJtaW5hbC9jb25maWcgZmllbGRzIGlmIG5vdCBvbiBtb2JpbGVcblx0XHRpZiAoIVBsYXRmb3JtLmlzTW9iaWxlKSB7XG5cdFx0XHR0aGlzLnVwZGF0ZVRlcm1pbmFsQ29tbWFuZEZpZWxkcygpO1xuXHRcdFx0dGhpcy51cGRhdGVDb25maWdDb21tYW5kRmllbGRzKCk7XG5cdFx0fVxuXHR9XG5cblxuXHR1cGRhdGVDb3B5SGVhZGluZ0ZpZWxkcygpIHtcblx0XHRjb25zdCBzZXR0aW5ncyA9IHRoaXMucGx1Z2luLnNldHRpbmdzO1xuXHRcdGNvbnN0IGlzVmlzaWJsZSA9IHNldHRpbmdzLmVuYWJsZUNvcHlIZWFkaW5nTGluaztcblxuXHRcdC8vIFVwZGF0ZSB0aGUgXCJEZWZhdWx0IGhlYWRpbmcgbGluayBmb3JtYXRcIiBzZXR0aW5nIGVsZW1lbnQgdmlzaWJpbGl0eVxuXHRcdGNvbnN0IGNvbnRhaW5lckVsID0gdGhpcy5jb250YWluZXJFbDtcblx0XHRjb25zdCBhbGxTZXR0aW5ncyA9IGNvbnRhaW5lckVsLnF1ZXJ5U2VsZWN0b3JBbGwoJy5zZXR0aW5nLWl0ZW0nKTtcblx0XHRhbGxTZXR0aW5ncy5mb3JFYWNoKChzZXR0aW5nRWwpID0+IHtcblx0XHRcdGNvbnN0IG5hbWVFbCA9IHNldHRpbmdFbC5xdWVyeVNlbGVjdG9yKCcuc2V0dGluZy1pdGVtLW5hbWUnKTtcblx0XHRcdGlmIChuYW1lRWwgJiYgbmFtZUVsLnRleHRDb250ZW50Py50cmltKCkgPT09IFwiRGVmYXVsdCBoZWFkaW5nIGxpbmsgZm9ybWF0XCIpIHtcblx0XHRcdFx0c2V0dGluZ0VsLmNsYXNzTGlzdC50b2dnbGUoXCJhc3Ryby1jb21wb3Nlci1zZXR0aW5nLWNvbnRhaW5lci12aXNpYmxlXCIsIGlzVmlzaWJsZSk7XG5cdFx0XHRcdHNldHRpbmdFbC5jbGFzc0xpc3QudG9nZ2xlKFwiYXN0cm8tY29tcG9zZXItc2V0dGluZy1jb250YWluZXItaGlkZGVuXCIsICFpc1Zpc2libGUpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9XG5cblx0dXBkYXRlVGVybWluYWxDb21tYW5kRmllbGRzKCkge1xuXHRcdGNvbnN0IHNldHRpbmdzID0gdGhpcy5wbHVnaW4uc2V0dGluZ3M7XG5cdFx0Y29uc3QgaXNWaXNpYmxlID0gc2V0dGluZ3MuZW5hYmxlT3BlblRlcm1pbmFsQ29tbWFuZDtcblxuXHRcdC8vIFVwZGF0ZSBjb250YWluZXIgZm9yIGJhY2t3YXJkIGNvbXBhdGliaWxpdHlcblx0XHRpZiAodGhpcy50ZXJtaW5hbENvbW1hbmRDb250YWluZXIpIHtcblx0XHRcdHRoaXMudGVybWluYWxDb21tYW5kQ29udGFpbmVyLmNsYXNzTGlzdC50b2dnbGUoXCJhc3Ryby1jb21wb3Nlci1zZXR0aW5nLWNvbnRhaW5lci12aXNpYmxlXCIsIGlzVmlzaWJsZSk7XG5cdFx0XHR0aGlzLnRlcm1pbmFsQ29tbWFuZENvbnRhaW5lci5jbGFzc0xpc3QudG9nZ2xlKFwiYXN0cm8tY29tcG9zZXItc2V0dGluZy1jb250YWluZXItaGlkZGVuXCIsICFpc1Zpc2libGUpO1xuXHRcdH1cblxuXHRcdC8vIFVwZGF0ZSBpbmRpdmlkdWFsIHNldHRpbmcgZWxlbWVudHMgdGhhdCBhcmUgaW4gdGhlIGdyb3VwXG5cdFx0Ly8gRmluZCBzZXR0aW5ncyBieSB0aGVpciBuYW1lIHRleHQgY29udGVudFxuXHRcdGNvbnN0IGNvbnRhaW5lckVsID0gdGhpcy5jb250YWluZXJFbDtcblx0XHRjb25zdCBhbGxTZXR0aW5ncyA9IGNvbnRhaW5lckVsLnF1ZXJ5U2VsZWN0b3JBbGwoJy5zZXR0aW5nLWl0ZW0nKTtcblx0XHRhbGxTZXR0aW5ncy5mb3JFYWNoKChzZXR0aW5nRWwpID0+IHtcblx0XHRcdGNvbnN0IG5hbWVFbCA9IHNldHRpbmdFbC5xdWVyeVNlbGVjdG9yKCcuc2V0dGluZy1pdGVtLW5hbWUnKTtcblx0XHRcdGlmIChuYW1lRWwpIHtcblx0XHRcdFx0Y29uc3QgbmFtZSA9IG5hbWVFbC50ZXh0Q29udGVudD8udHJpbSgpO1xuXHRcdFx0XHRpZiAobmFtZSA9PT0gXCJQcm9qZWN0IHJvb3QgZGlyZWN0b3J5IHBhdGhcIiB8fCBuYW1lID09PSBcIlNob3cgb3BlbiB0ZXJtaW5hbCByaWJib24gaWNvblwiKSB7XG5cdFx0XHRcdFx0c2V0dGluZ0VsLmNsYXNzTGlzdC50b2dnbGUoXCJhc3Ryby1jb21wb3Nlci1zZXR0aW5nLWNvbnRhaW5lci12aXNpYmxlXCIsIGlzVmlzaWJsZSk7XG5cdFx0XHRcdFx0c2V0dGluZ0VsLmNsYXNzTGlzdC50b2dnbGUoXCJhc3Ryby1jb21wb3Nlci1zZXR0aW5nLWNvbnRhaW5lci1oaWRkZW5cIiwgIWlzVmlzaWJsZSk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9KTtcblxuXHRcdC8vIFVwZGF0ZSByaWJib24gdG9nZ2xlIGRpc2FibGVkIHN0YXRlIHVzaW5nIHRoZSB0b2dnbGUgY29tcG9uZW50XG5cdFx0aWYgKHRoaXMudGVybWluYWxSaWJib25Ub2dnbGVDb21wb25lbnQpIHtcblx0XHRcdHRoaXMudGVybWluYWxSaWJib25Ub2dnbGVDb21wb25lbnQuc2V0RGlzYWJsZWQoIXRoaXMucGx1Z2luLnNldHRpbmdzLmVuYWJsZU9wZW5UZXJtaW5hbENvbW1hbmQpO1xuXHRcdH1cblx0fVxuXG5cdHVwZGF0ZUNvbmZpZ0NvbW1hbmRGaWVsZHMoKSB7XG5cdFx0Y29uc3Qgc2V0dGluZ3MgPSB0aGlzLnBsdWdpbi5zZXR0aW5ncztcblx0XHRjb25zdCBpc1Zpc2libGUgPSBzZXR0aW5ncy5lbmFibGVPcGVuQ29uZmlnRmlsZUNvbW1hbmQ7XG5cblx0XHQvLyBVcGRhdGUgY29udGFpbmVyIGZvciBiYWNrd2FyZCBjb21wYXRpYmlsaXR5XG5cdFx0aWYgKHRoaXMuY29uZmlnQ29tbWFuZENvbnRhaW5lcikge1xuXHRcdFx0dGhpcy5jb25maWdDb21tYW5kQ29udGFpbmVyLmNsYXNzTGlzdC50b2dnbGUoXCJhc3Ryby1jb21wb3Nlci1zZXR0aW5nLWNvbnRhaW5lci12aXNpYmxlXCIsIGlzVmlzaWJsZSk7XG5cdFx0XHR0aGlzLmNvbmZpZ0NvbW1hbmRDb250YWluZXIuY2xhc3NMaXN0LnRvZ2dsZShcImFzdHJvLWNvbXBvc2VyLXNldHRpbmctY29udGFpbmVyLWhpZGRlblwiLCAhaXNWaXNpYmxlKTtcblx0XHR9XG5cblx0XHQvLyBVcGRhdGUgaW5kaXZpZHVhbCBzZXR0aW5nIGVsZW1lbnRzIHRoYXQgYXJlIGluIHRoZSBncm91cFxuXHRcdC8vIEZpbmQgc2V0dGluZ3MgYnkgdGhlaXIgbmFtZSB0ZXh0IGNvbnRlbnRcblx0XHRjb25zdCBjb250YWluZXJFbCA9IHRoaXMuY29udGFpbmVyRWw7XG5cdFx0Y29uc3QgYWxsU2V0dGluZ3MgPSBjb250YWluZXJFbC5xdWVyeVNlbGVjdG9yQWxsKCcuc2V0dGluZy1pdGVtJyk7XG5cdFx0YWxsU2V0dGluZ3MuZm9yRWFjaCgoc2V0dGluZ0VsKSA9PiB7XG5cdFx0XHRjb25zdCBuYW1lRWwgPSBzZXR0aW5nRWwucXVlcnlTZWxlY3RvcignLnNldHRpbmctaXRlbS1uYW1lJyk7XG5cdFx0XHRpZiAobmFtZUVsKSB7XG5cdFx0XHRcdGNvbnN0IG5hbWUgPSBuYW1lRWwudGV4dENvbnRlbnQ/LnRyaW0oKTtcblx0XHRcdFx0aWYgKG5hbWUgPT09IFwiQ29uZmlnIGZpbGUgcGF0aFwiIHx8IG5hbWUgPT09IFwiU2hvdyBvcGVuIGNvbmZpZyByaWJib24gaWNvblwiKSB7XG5cdFx0XHRcdFx0c2V0dGluZ0VsLmNsYXNzTGlzdC50b2dnbGUoXCJhc3Ryby1jb21wb3Nlci1zZXR0aW5nLWNvbnRhaW5lci12aXNpYmxlXCIsIGlzVmlzaWJsZSk7XG5cdFx0XHRcdFx0c2V0dGluZ0VsLmNsYXNzTGlzdC50b2dnbGUoXCJhc3Ryby1jb21wb3Nlci1zZXR0aW5nLWNvbnRhaW5lci1oaWRkZW5cIiwgIWlzVmlzaWJsZSk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9KTtcblxuXHRcdC8vIFVwZGF0ZSByaWJib24gdG9nZ2xlIGRpc2FibGVkIHN0YXRlIHVzaW5nIHRoZSB0b2dnbGUgY29tcG9uZW50XG5cdFx0aWYgKHRoaXMuY29uZmlnUmliYm9uVG9nZ2xlQ29tcG9uZW50KSB7XG5cdFx0XHR0aGlzLmNvbmZpZ1JpYmJvblRvZ2dsZUNvbXBvbmVudC5zZXREaXNhYmxlZCghdGhpcy5wbHVnaW4uc2V0dGluZ3MuZW5hYmxlT3BlbkNvbmZpZ0ZpbGVDb21tYW5kKTtcblx0XHR9XG5cdH1cblxuXHRjaGVja0ZvckZvbGRlckNvbmZsaWN0cygpIHtcblx0XHRjb25zdCBzZXR0aW5ncyA9IHRoaXMucGx1Z2luLnNldHRpbmdzO1xuXHRcdGNvbnN0IGJsYW5rRm9sZGVyczogc3RyaW5nW10gPSBbXTtcblx0XHRjb25zdCBmb2xkZXJDb25mbGljdHM6IHsgW2ZvbGRlcjogc3RyaW5nXTogc3RyaW5nW10gfSA9IHt9O1xuXG5cdFx0Ly8gQ2hlY2sgY29udGVudCB0eXBlc1xuXHRcdGNvbnN0IGNvbnRlbnRUeXBlcyA9IHNldHRpbmdzLmNvbnRlbnRUeXBlcyB8fCBbXTtcblx0XHRmb3IgKGNvbnN0IGNvbnRlbnRUeXBlIG9mIGNvbnRlbnRUeXBlcykge1xuXHRcdFx0aWYgKGNvbnRlbnRUeXBlLmVuYWJsZWQpIHtcblx0XHRcdFx0aWYgKCFjb250ZW50VHlwZS5mb2xkZXIgfHwgY29udGVudFR5cGUuZm9sZGVyLnRyaW0oKSA9PT0gXCJcIikge1xuXHRcdFx0XHRcdGJsYW5rRm9sZGVycy5wdXNoKGNvbnRlbnRUeXBlLm5hbWUgfHwgXCJDb250ZW50XCIpO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdGlmICghZm9sZGVyQ29uZmxpY3RzW2NvbnRlbnRUeXBlLmZvbGRlcl0pIHtcblx0XHRcdFx0XHRcdGZvbGRlckNvbmZsaWN0c1tjb250ZW50VHlwZS5mb2xkZXJdID0gW107XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGZvbGRlckNvbmZsaWN0c1tjb250ZW50VHlwZS5mb2xkZXJdLnB1c2goY29udGVudFR5cGUubmFtZSB8fCBcIkNvbnRlbnRcIik7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblx0XHQvLyBDaGVjayBmb3IgY29uZmxpY3RzXG5cdFx0Ly8gV2FybmluZyBib3ggcmVtb3ZlZCAtIGNvbmZsaWN0cyBhcmUgc3RpbGwgZGV0ZWN0ZWQgYXQgcnVudGltZVxuXHR9XG5cblx0cHJpdmF0ZSBhZGRDdXN0b21Db250ZW50VHlwZSgpIHtcblx0XHRjb25zdCBzZXR0aW5ncyA9IHRoaXMucGx1Z2luLnNldHRpbmdzO1xuXHRcdGNvbnN0IGNvbnRlbnRUeXBlcyA9IHNldHRpbmdzLmNvbnRlbnRUeXBlcyB8fCBbXTtcblx0XHRjb25zdCBuZXdUeXBlOiBDb250ZW50VHlwZSA9IHtcblx0XHRcdGlkOiBgY29udGVudC0ke0RhdGUubm93KCl9YCxcblx0XHRcdG5hbWU6IGBDb250ZW50ICR7Y29udGVudFR5cGVzLmxlbmd0aCArIDF9YCxcblx0XHRcdGZvbGRlcjogXCJcIixcblx0XHRcdGxpbmtCYXNlUGF0aDogXCJcIixcblx0XHRcdHRlbXBsYXRlOiAnLS0tXFxudGl0bGU6IFwie3t0aXRsZX19XCJcXG5kYXRlOiB7e2RhdGV9fVxcbi0tLVxcbicsXG5cdFx0XHRlbmFibGVkOiB0cnVlLFxuXHRcdFx0Y3JlYXRpb25Nb2RlOiBcImZpbGVcIixcblx0XHRcdGluZGV4RmlsZU5hbWU6IFwiXCIsXG5cdFx0XHRpZ25vcmVTdWJmb2xkZXJzOiBmYWxzZSxcblx0XHRcdGVuYWJsZVVuZGVyc2NvcmVQcmVmaXg6IGZhbHNlLFxuXHRcdFx0dXNlTWR4RXh0ZW5zaW9uOiBmYWxzZSxcblx0XHRcdG1vZGlmaWVkRGF0ZUZpZWxkOiBcIlwiLFxuXHRcdH07XG5cdFx0Y29udGVudFR5cGVzLnB1c2gobmV3VHlwZSk7XG5cdFx0c2V0dGluZ3MuY29udGVudFR5cGVzID0gY29udGVudFR5cGVzO1xuXHRcdHZvaWQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XG5cdFx0dGhpcy5yZW5kZXJDdXN0b21Db250ZW50VHlwZXMoKTtcblx0XHR0aGlzLnBsdWdpbi5yZWdpc3RlckNyZWF0ZUV2ZW50KCk7XG5cdFx0Ly8gUmUtcmVnaXN0ZXIgY29udGVudCB0eXBlIGNvbW1hbmRzIHRvIGluY2x1ZGUgdGhlIG5ldyB0eXBlXG5cdFx0cmVnaXN0ZXJDb250ZW50VHlwZUNvbW1hbmRzKHRoaXMucGx1Z2luIGFzIHVua25vd24gYXMgUGx1Z2luLCBzZXR0aW5ncyk7XG5cdH1cblxuXHRwcml2YXRlIHJlbmRlckN1c3RvbUNvbnRlbnRUeXBlcygpIHtcblx0XHRpZiAoIXRoaXMuY3VzdG9tQ29udGVudFR5cGVzQ29udGFpbmVyKSByZXR1cm47XG5cblx0XHR0aGlzLmN1c3RvbUNvbnRlbnRUeXBlc0NvbnRhaW5lci5lbXB0eSgpO1xuXG5cdFx0Ly8gQWx3YXlzIHJlYWQgZnJlc2ggc2V0dGluZ3MgZnJvbSBwbHVnaW4gdG8gZW5zdXJlIHdlIGhhdmUgbGF0ZXN0IGRhdGFcblx0XHQvLyBUaGlzIGlzIGNyaXRpY2FsIGFmdGVyIG1pZ3JhdGlvblxuXHRcdGNvbnN0IHNldHRpbmdzID0gdGhpcy5wbHVnaW4uc2V0dGluZ3M7XG5cdFx0Y29uc3QgY29udGVudFR5cGVzID0gc2V0dGluZ3MuY29udGVudFR5cGVzIHx8IFtdO1xuXHRcdGNvbnRlbnRUeXBlcy5mb3JFYWNoKChjdXN0b21UeXBlOiBDb250ZW50VHlwZSwgaW5kZXg6IG51bWJlcikgPT4ge1xuXHRcdFx0aWYgKCF0aGlzLmN1c3RvbUNvbnRlbnRUeXBlc0NvbnRhaW5lcikgcmV0dXJuO1xuXHRcdFx0Y29uc3QgdHlwZUNvbnRhaW5lciA9IHRoaXMuY3VzdG9tQ29udGVudFR5cGVzQ29udGFpbmVyLmNyZWF0ZURpdih7XG5cdFx0XHRcdGNsczogXCJjdXN0b20tY29udGVudC10eXBlLWl0ZW1cIixcblx0XHRcdFx0YXR0cjogeyBcImRhdGEtdHlwZS1pZFwiOiBjdXN0b21UeXBlLmlkIH1cblx0XHRcdH0pO1xuXG5cdFx0XHQvLyBIZWFkZXIgd2l0aCBjb250cm9sc1xuXHRcdFx0Y29uc3QgaGVhZGVyID0gdHlwZUNvbnRhaW5lci5jcmVhdGVEaXYoeyBjbHM6IFwiY3VzdG9tLWNvbnRlbnQtdHlwZS1oZWFkZXJcIiB9KTtcblx0XHRcdGhlYWRlci5jbGFzc0xpc3QuYWRkKFwiYXN0cm8tY29tcG9zZXItY3VzdG9tLXR5cGUtaGVhZGVyXCIpO1xuXG5cdFx0XHQvLyBMZWZ0IHNpZGUgLSBjb2xsYXBzZS9leHBhbmQgYnV0dG9uXG5cdFx0XHRjb25zdCBjb2xsYXBzZUJ1dHRvbiA9IGhlYWRlci5jcmVhdGVFbChcImJ1dHRvblwiLCB7XG5cdFx0XHRcdGNsczogXCJhc3Ryby1jb21wb3Nlci1jb2xsYXBzZS1idXR0b25cIixcblx0XHRcdFx0YXR0cjogeyBcImFyaWEtbGFiZWxcIjogXCJDb2xsYXBzZS9leHBhbmRcIiB9XG5cdFx0XHR9KTtcblx0XHRcdGNvbnN0IGlzQ29sbGFwc2VkID0gY3VzdG9tVHlwZS5jb2xsYXBzZWQgPz8gZmFsc2U7XG5cdFx0XHQvLyBBbHdheXMgdXNlIGNoZXZyb24tZG93biwgcm90YXRlIGl0IHdoZW4gY29sbGFwc2VkIHRvIHBvaW50IHJpZ2h0XG5cdFx0XHRzZXRJY29uKGNvbGxhcHNlQnV0dG9uLCBcImNoZXZyb24tZG93blwiKTtcblx0XHRcdGlmIChpc0NvbGxhcHNlZCkge1xuXHRcdFx0XHRjb2xsYXBzZUJ1dHRvbi5jbGFzc0xpc3QuYWRkKFwiaXMtY29sbGFwc2VkXCIpO1xuXHRcdFx0fVxuXHRcdFx0Y29sbGFwc2VCdXR0b24uYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsICgpID0+IHtcblx0XHRcdFx0dm9pZCB0aGlzLnRvZ2dsZUNvbnRlbnRUeXBlQ29sbGFwc2UoY3VzdG9tVHlwZS5pZCk7XG5cdFx0XHRcdC8vIFVwZGF0ZSBjbGFzcyBhZnRlciB0b2dnbGUgKGljb24gc3RheXMgdGhlIHNhbWUsIGp1c3Qgcm90YXRlcylcblx0XHRcdFx0Y29uc3QgdXBkYXRlZFR5cGUgPSB0aGlzLnBsdWdpbi5zZXR0aW5ncy5jb250ZW50VHlwZXMuZmluZCgoY3Q6IENvbnRlbnRUeXBlKSA9PiBjdC5pZCA9PT0gY3VzdG9tVHlwZS5pZCk7XG5cdFx0XHRcdGlmICh1cGRhdGVkVHlwZSkge1xuXHRcdFx0XHRcdGlmICh1cGRhdGVkVHlwZS5jb2xsYXBzZWQpIHtcblx0XHRcdFx0XHRcdGNvbGxhcHNlQnV0dG9uLmNsYXNzTGlzdC5hZGQoXCJpcy1jb2xsYXBzZWRcIik7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdGNvbGxhcHNlQnV0dG9uLmNsYXNzTGlzdC5yZW1vdmUoXCJpcy1jb2xsYXBzZWRcIik7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblxuXHRcdFx0Ly8gTWlkZGxlIGxlZnQgLSBjb250ZW50IHR5cGUgbmFtZVxuXHRcdFx0Y29uc3QgaGVhZGVyTmFtZSA9IGhlYWRlci5jcmVhdGVEaXYoeyBjbHM6IFwiYXN0cm8tY29tcG9zZXItaGVhZGVyLW5hbWVcIiB9KTtcblx0XHRcdGhlYWRlck5hbWUuY3JlYXRlRWwoXCJkaXZcIiwgeyB0ZXh0OiBjdXN0b21UeXBlLm5hbWUgfHwgYENvbnRlbnQgJHtpbmRleCArIDF9YCwgY2xzOiBcInNldHRpbmctaXRlbS1uYW1lXCIgfSk7XG5cblx0XHRcdC8vIE1pZGRsZSByaWdodCAtIHVwL2Rvd24gYnV0dG9ucyAoc2lkZS1ieS1zaWRlKVxuXHRcdFx0Y29uc3QgcmVvcmRlckNvbnRhaW5lciA9IGhlYWRlci5jcmVhdGVEaXYoeyBjbHM6IFwiYXN0cm8tY29tcG9zZXItcmVvcmRlci1idXR0b25zXCIgfSk7XG5cdFx0XHRjb25zdCB1cEJ1dHRvbiA9IHJlb3JkZXJDb250YWluZXIuY3JlYXRlRWwoXCJidXR0b25cIiwge1xuXHRcdFx0XHRjbHM6IFwiYXN0cm8tY29tcG9zZXItcmVvcmRlci1idXR0b25cIixcblx0XHRcdFx0YXR0cjogeyBcImFyaWEtbGFiZWxcIjogXCJNb3ZlIHVwXCIgfVxuXHRcdFx0fSk7XG5cdFx0XHRzZXRJY29uKHVwQnV0dG9uLCBcImNoZXZyb24tdXBcIik7XG5cdFx0XHR1cEJ1dHRvbi5kaXNhYmxlZCA9IGluZGV4ID09PSAwO1xuXHRcdFx0dXBCdXR0b24uYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsICgpID0+IHtcblx0XHRcdFx0dm9pZCB0aGlzLm1vdmVDb250ZW50VHlwZVVwKGN1c3RvbVR5cGUuaWQpO1xuXHRcdFx0fSk7XG5cblx0XHRcdGNvbnN0IGRvd25CdXR0b24gPSByZW9yZGVyQ29udGFpbmVyLmNyZWF0ZUVsKFwiYnV0dG9uXCIsIHtcblx0XHRcdFx0Y2xzOiBcImFzdHJvLWNvbXBvc2VyLXJlb3JkZXItYnV0dG9uXCIsXG5cdFx0XHRcdGF0dHI6IHsgXCJhcmlhLWxhYmVsXCI6IFwiTW92ZSBkb3duXCIgfVxuXHRcdFx0fSk7XG5cdFx0XHRzZXRJY29uKGRvd25CdXR0b24sIFwiY2hldnJvbi1kb3duXCIpO1xuXHRcdFx0ZG93bkJ1dHRvbi5kaXNhYmxlZCA9IGluZGV4ID09PSBjb250ZW50VHlwZXMubGVuZ3RoIC0gMTtcblx0XHRcdGRvd25CdXR0b24uYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsICgpID0+IHtcblx0XHRcdFx0dm9pZCB0aGlzLm1vdmVDb250ZW50VHlwZURvd24oY3VzdG9tVHlwZS5pZCk7XG5cdFx0XHR9KTtcblxuXHRcdFx0Ly8gUmlnaHQgc2lkZSAtIHRvZ2dsZVxuXHRcdFx0Y29uc3QgdG9nZ2xlQ29udGFpbmVyID0gaGVhZGVyLmNyZWF0ZURpdih7IGNsczogXCJjaGVja2JveC1jb250YWluZXJcIiB9KTtcblx0XHRcdGlmIChjdXN0b21UeXBlLmVuYWJsZWQpIHtcblx0XHRcdFx0dG9nZ2xlQ29udGFpbmVyLmNsYXNzTGlzdC5hZGQoXCJpcy1lbmFibGVkXCIpO1xuXHRcdFx0fVxuXG5cdFx0XHRjb25zdCB0b2dnbGUgPSB0b2dnbGVDb250YWluZXIuY3JlYXRlRWwoXCJpbnB1dFwiLCB7IHR5cGU6IFwiY2hlY2tib3hcIiwgY2xzOiBcImNoZWNrYm94LWlucHV0XCIgfSk7XG5cdFx0XHR0b2dnbGUuY2hlY2tlZCA9IGN1c3RvbVR5cGUuZW5hYmxlZDtcblxuXHRcdFx0Ly8gQWRkIGNsaWNrIGV2ZW50IHRvIHRoZSBjb250YWluZXIgYXMgd2VsbFxuXHRcdFx0dG9nZ2xlQ29udGFpbmVyLmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCAoZSkgPT4ge1xuXHRcdFx0XHR2b2lkIChhc3luYyAoKSA9PiB7XG5cdFx0XHRcdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFx0XHRcdGNvbnN0IG5ld1ZhbHVlID0gIWN1c3RvbVR5cGUuZW5hYmxlZDtcblx0XHRcdFx0XHRjdXN0b21UeXBlLmVuYWJsZWQgPSBuZXdWYWx1ZTtcblx0XHRcdFx0XHR0b2dnbGUuY2hlY2tlZCA9IG5ld1ZhbHVlO1xuXG5cdFx0XHRcdFx0YXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XG5cdFx0XHRcdFx0dGhpcy5wbHVnaW4ucmVnaXN0ZXJDcmVhdGVFdmVudCgpO1xuXG5cdFx0XHRcdFx0Ly8gVXBkYXRlIHRoZSBjb250YWluZXIgY2xhc3MgZm9yIHZpc3VhbCBmZWVkYmFja1xuXHRcdFx0XHRcdGlmIChuZXdWYWx1ZSkge1xuXHRcdFx0XHRcdFx0dG9nZ2xlQ29udGFpbmVyLmNsYXNzTGlzdC5hZGQoXCJpcy1lbmFibGVkXCIpO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHR0b2dnbGVDb250YWluZXIuY2xhc3NMaXN0LnJlbW92ZShcImlzLWVuYWJsZWRcIik7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0Ly8gVXBkYXRlIHZpc2liaWxpdHlcblx0XHRcdFx0XHR0aGlzLnVwZGF0ZUN1c3RvbUNvbnRlbnRUeXBlVmlzaWJpbGl0eShjdXN0b21UeXBlLmlkLCBuZXdWYWx1ZSk7XG5cblx0XHRcdFx0XHQvLyBSZS1yZWdpc3RlciBjb250ZW50IHR5cGUgY29tbWFuZHMgdG8gcmVmbGVjdCBlbmFibGVkL2Rpc2FibGVkIHN0YXRlXG5cdFx0XHRcdFx0cmVnaXN0ZXJDb250ZW50VHlwZUNvbW1hbmRzKHRoaXMucGx1Z2luIGFzIHVua25vd24gYXMgUGx1Z2luLCB0aGlzLnBsdWdpbi5zZXR0aW5ncyk7XG5cblx0XHRcdFx0XHQvLyBDb25mbGljdCBjaGVja2luZyByZW1vdmVkIGZyb20gc2V0dGluZ3MgVUlcblx0XHRcdFx0fSkoKTtcblx0XHRcdH0pO1xuXG5cdFx0XHQvLyBBbHNvIGFkZCBjaGFuZ2UgZXZlbnQgYXMgYmFja3VwXG5cdFx0XHR0b2dnbGUuYWRkRXZlbnRMaXN0ZW5lcihcImNoYW5nZVwiLCAoZSkgPT4ge1xuXHRcdFx0XHR2b2lkIChhc3luYyAoKSA9PiB7XG5cdFx0XHRcdFx0Y29uc3QgdmFsdWUgPSAoZS50YXJnZXQgYXMgSFRNTElucHV0RWxlbWVudCkuY2hlY2tlZDtcblx0XHRcdFx0XHRjdXN0b21UeXBlLmVuYWJsZWQgPSB2YWx1ZTtcblx0XHRcdFx0XHRhd2FpdCB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKTtcblx0XHRcdFx0XHR0aGlzLnBsdWdpbi5yZWdpc3RlckNyZWF0ZUV2ZW50KCk7XG5cblx0XHRcdFx0XHQvLyBVcGRhdGUgdGhlIGNvbnRhaW5lciBjbGFzcyBmb3IgdmlzdWFsIGZlZWRiYWNrXG5cdFx0XHRcdFx0aWYgKHZhbHVlKSB7XG5cdFx0XHRcdFx0XHR0b2dnbGVDb250YWluZXIuY2xhc3NMaXN0LmFkZChcImlzLWVuYWJsZWRcIik7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdHRvZ2dsZUNvbnRhaW5lci5jbGFzc0xpc3QucmVtb3ZlKFwiaXMtZW5hYmxlZFwiKTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHQvLyBVcGRhdGUgdmlzaWJpbGl0eVxuXHRcdFx0XHRcdHRoaXMudXBkYXRlQ3VzdG9tQ29udGVudFR5cGVWaXNpYmlsaXR5KGN1c3RvbVR5cGUuaWQsIHZhbHVlKTtcblxuXHRcdFx0XHRcdC8vIFJlLXJlZ2lzdGVyIGNvbnRlbnQgdHlwZSBjb21tYW5kcyB0byByZWZsZWN0IGVuYWJsZWQvZGlzYWJsZWQgc3RhdGVcblx0XHRcdFx0XHRyZWdpc3RlckNvbnRlbnRUeXBlQ29tbWFuZHModGhpcy5wbHVnaW4gYXMgdW5rbm93biBhcyBQbHVnaW4sIHRoaXMucGx1Z2luLnNldHRpbmdzKTtcblx0XHRcdFx0fSkoKTtcblx0XHRcdH0pO1xuXG5cdFx0XHQvLyBTZXR0aW5ncyBjb250YWluZXIgdGhhdCBjYW4gYmUgY29sbGFwc2VkXG5cdFx0XHRjb25zdCBzZXR0aW5nc0NvbnRhaW5lciA9IHR5cGVDb250YWluZXIuY3JlYXRlRGl2KHtcblx0XHRcdFx0Y2xzOiBcImN1c3RvbS1jb250ZW50LXR5cGUtc2V0dGluZ3NcIixcblx0XHRcdFx0YXR0cjogeyBcImRhdGEtdHlwZS1pZFwiOiBjdXN0b21UeXBlLmlkIH1cblx0XHRcdH0pO1xuXG5cdFx0XHQvLyBTZXQgaW5pdGlhbCB2aXNpYmlsaXR5IHN0YXRlIGJhc2VkIG9uIGVuYWJsZWQgYW5kIGNvbGxhcHNlZCBzdGF0ZVxuXHRcdFx0Y29uc3QgaW5pdGlhbGx5Q29sbGFwc2VkID0gY3VzdG9tVHlwZS5jb2xsYXBzZWQgPz8gZmFsc2U7XG5cdFx0XHRjb25zdCBpbml0aWFsbHlWaXNpYmxlID0gY3VzdG9tVHlwZS5lbmFibGVkICYmICFpbml0aWFsbHlDb2xsYXBzZWQ7XG5cdFx0XHRpZiAoaW5pdGlhbGx5VmlzaWJsZSkge1xuXHRcdFx0XHRzZXR0aW5nc0NvbnRhaW5lci5jbGFzc0xpc3QuYWRkKFwiYXN0cm8tY29tcG9zZXItc2V0dGluZy1jb250YWluZXItdmlzaWJsZVwiKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHNldHRpbmdzQ29udGFpbmVyLmNsYXNzTGlzdC5hZGQoXCJhc3Ryby1jb21wb3Nlci1zZXR0aW5nLWNvbnRhaW5lci1oaWRkZW5cIik7XG5cdFx0XHR9XG5cblx0XHRcdC8vIENvbnRlbnQgdHlwZSBuYW1lXG5cdFx0XHRjb25zdCBuYW1lQ29udGFpbmVyID0gc2V0dGluZ3NDb250YWluZXIuY3JlYXRlRGl2KCk7XG5cdFx0XHRuZXcgU2V0dGluZyhuYW1lQ29udGFpbmVyKVxuXHRcdFx0XHQuc2V0TmFtZShcIkNvbnRlbnQgdHlwZSBuYW1lXCIpXG5cdFx0XHRcdC5zZXREZXNjKFwiRGlzcGxheSBuYW1lIGZvciB0aGlzIGNvbnRlbnQgdHlwZSAoJ3Byb2plY3RzJywgJ25vdGVzJywgJ3R1dG9yaWFscycpXCIpXG5cdFx0XHRcdC5hZGRUZXh0KHRleHQgPT4ge1xuXHRcdFx0XHRcdHRleHRcblx0XHRcdFx0XHRcdC5zZXRQbGFjZWhvbGRlcihcIkVudGVyIGNvbnRlbnQgdHlwZSBuYW1lXCIpXG5cdFx0XHRcdFx0XHQuc2V0VmFsdWUoY3VzdG9tVHlwZS5uYW1lKVxuXHRcdFx0XHRcdFx0Lm9uQ2hhbmdlKGFzeW5jICh2YWx1ZTogc3RyaW5nKSA9PiB7XG5cdFx0XHRcdFx0XHRcdGN1c3RvbVR5cGUubmFtZSA9IHZhbHVlO1xuXHRcdFx0XHRcdFx0XHRhd2FpdCB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKTtcblx0XHRcdFx0XHRcdFx0Ly8gUmUtcmVnaXN0ZXIgY29udGVudCB0eXBlIGNvbW1hbmRzIHRvIHVwZGF0ZSBjb21tYW5kIG5hbWVcblx0XHRcdFx0XHRcdFx0cmVnaXN0ZXJDb250ZW50VHlwZUNvbW1hbmRzKHRoaXMucGx1Z2luIGFzIHVua25vd24gYXMgUGx1Z2luLCB0aGlzLnBsdWdpbi5zZXR0aW5ncyk7XG5cdFx0XHRcdFx0XHR9KTtcblx0XHRcdFx0fSk7XG5cblx0XHRcdC8vIEZvbGRlciBsb2NhdGlvblxuXHRcdFx0Y29uc3QgZm9sZGVyQ29udGFpbmVyID0gc2V0dGluZ3NDb250YWluZXIuY3JlYXRlRGl2KCk7XG5cdFx0XHRjb25zdCBmb2xkZXJTZXR0aW5nID0gbmV3IFNldHRpbmcoZm9sZGVyQ29udGFpbmVyKVxuXHRcdFx0XHQuc2V0TmFtZShcIkZvbGRlciBsb2NhdGlvblwiKVxuXHRcdFx0XHQuc2V0RGVzYyhcIkZvbGRlciBwYXRoIHdoZXJlIHRoaXMgY29udGVudCB0eXBlIHdpbGwgYmUgY3JlYXRlZC4gTGVhdmUgYmxhbmsgdG8gdXNlIHRoZSB2YXVsdCBmb2xkZXIuIFN1cHBvcnRzIHdpbGRjYXJkcyBsaWtlIGRpcmVjdG9yeS8qIG9yIGRpcmVjdG9yeS8qLyogdG8gbWF0Y2ggc3BlY2lmaWMgZm9sZGVyIGRlcHRocy5cIilcblx0XHRcdFx0LmFkZFRleHQodGV4dCA9PiB7XG5cdFx0XHRcdFx0dGV4dFxuXHRcdFx0XHRcdFx0LnNldFBsYWNlaG9sZGVyKFwiRW50ZXIgZm9sZGVyIHBhdGggKCdkb2NzJywgJ2RvY3MvKicsICdkb2NzLyovKicpIG9yIGxlYXZlIGJsYW5rIGZvciB2YXVsdCByb290XCIpXG5cdFx0XHRcdFx0XHQuc2V0VmFsdWUoY3VzdG9tVHlwZS5mb2xkZXIpXG5cdFx0XHRcdFx0XHQub25DaGFuZ2UoYXN5bmMgKHZhbHVlOiBzdHJpbmcpID0+IHtcblx0XHRcdFx0XHRcdFx0Y3VzdG9tVHlwZS5mb2xkZXIgPSB2YWx1ZTtcblx0XHRcdFx0XHRcdFx0YXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XG5cdFx0XHRcdFx0XHRcdHRoaXMucGx1Z2luLnJlZ2lzdGVyQ3JlYXRlRXZlbnQoKTtcblx0XHRcdFx0XHRcdFx0dGhpcy51cGRhdGVDdXN0b21Db250ZW50VHlwZUlnbm9yZVN1YmZvbGRlcnNGaWVsZChjdXN0b21UeXBlLmlkKTtcblx0XHRcdFx0XHRcdFx0Ly8gVXBkYXRlIGNvbmZsaWN0IHdhcm5pbmdzIGZvciBhbGwgY29udGVudCB0eXBlcyAoZm9sZGVyIGNoYW5nZSBtYXkgYWZmZWN0IG90aGVycylcblx0XHRcdFx0XHRcdFx0Y29uc3QgYWxsQ29udGVudFR5cGVzID0gdGhpcy5wbHVnaW4uc2V0dGluZ3MuY29udGVudFR5cGVzIHx8IFtdO1xuXHRcdFx0XHRcdFx0XHRmb3IgKGNvbnN0IGN0IG9mIGFsbENvbnRlbnRUeXBlcykge1xuXHRcdFx0XHRcdFx0XHRcdHRoaXMudXBkYXRlRm9sZGVyQ29uZmxpY3RXYXJuaW5nKGN0LmlkLCBudWxsKTtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fSk7XG5cdFx0XHRcdH0pO1xuXG5cdFx0XHQvLyBBZGQgY29uZmxpY3Qgd2FybmluZyBlbGVtZW50XG5cdFx0XHRmb2xkZXJDb250YWluZXIuY3JlYXRlRGl2KHsgY2xzOiBcImFzdHJvLWNvbXBvc2VyLWNvbmZsaWN0LXdhcm5pbmcgaGlkZGVuXCIsIGF0dHI6IHsgXCJkYXRhLXR5cGUtaWRcIjogY3VzdG9tVHlwZS5pZCB9IH0pO1xuXHRcdFx0dGhpcy51cGRhdGVGb2xkZXJDb25mbGljdFdhcm5pbmcoY3VzdG9tVHlwZS5pZCwgZm9sZGVyU2V0dGluZyk7XG5cblx0XHRcdC8vIElnbm9yZSBzdWJmb2xkZXJzIChvbmx5IHNob3cgd2hlbiBmb2xkZXIgaXMgc2V0KVxuXHRcdFx0Y29uc3QgaWdub3JlU3ViZm9sZGVyc0NvbnRhaW5lciA9IHNldHRpbmdzQ29udGFpbmVyLmNyZWF0ZURpdih7IGNsczogXCJjdXN0b20taWdub3JlLXN1YmZvbGRlcnMtZmllbGRcIiB9KTtcblx0XHRcdGlnbm9yZVN1YmZvbGRlcnNDb250YWluZXIuc2V0QXR0cmlidXRlKFwiZGF0YS10eXBlLWlkXCIsIGN1c3RvbVR5cGUuaWQpO1xuXHRcdFx0aWdub3JlU3ViZm9sZGVyc0NvbnRhaW5lci5jbGFzc0xpc3QudG9nZ2xlKFwiYXN0cm8tY29tcG9zZXItc2V0dGluZy1jb250YWluZXItdmlzaWJsZVwiLCAhIWN1c3RvbVR5cGUuZm9sZGVyKTtcblx0XHRcdGlnbm9yZVN1YmZvbGRlcnNDb250YWluZXIuY2xhc3NMaXN0LnRvZ2dsZShcImFzdHJvLWNvbXBvc2VyLXNldHRpbmctY29udGFpbmVyLWhpZGRlblwiLCAhY3VzdG9tVHlwZS5mb2xkZXIpO1xuXHRcdFx0bmV3IFNldHRpbmcoaWdub3JlU3ViZm9sZGVyc0NvbnRhaW5lcilcblx0XHRcdFx0LnNldE5hbWUoXCJJZ25vcmUgc3ViZm9sZGVyc1wiKVxuXHRcdFx0XHQuc2V0RGVzYyhcIldoZW4gZW5hYmxlZCwgYXV0b21hdGlvbiB3aWxsIG9ubHkgdHJpZ2dlciBmb3IgbmV3IC5tZCBmaWxlcyB3aXRoaW4gdGhpcyBjb250ZW50IHR5cGUncyBmb2xkZXIgYW5kIG9uZSBsZXZlbCBkb3duIChmb3IgZm9sZGVyLWJhc2VkIGNvbnRlbnQpLiBGaWxlcyBpbiBkZWVwZXIgc3ViZm9sZGVycyB3aWxsIGJlIGlnbm9yZWQuXCIpXG5cdFx0XHRcdC5hZGRUb2dnbGUodG9nZ2xlID0+XG5cdFx0XHRcdFx0dG9nZ2xlXG5cdFx0XHRcdFx0XHQuc2V0VmFsdWUoY3VzdG9tVHlwZS5pZ25vcmVTdWJmb2xkZXJzIHx8IGZhbHNlKVxuXHRcdFx0XHRcdFx0Lm9uQ2hhbmdlKGFzeW5jICh2YWx1ZTogYm9vbGVhbikgPT4ge1xuXHRcdFx0XHRcdFx0XHRjdXN0b21UeXBlLmlnbm9yZVN1YmZvbGRlcnMgPSB2YWx1ZTtcblx0XHRcdFx0XHRcdFx0YXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XG5cdFx0XHRcdFx0XHR9KVxuXHRcdFx0XHQpO1xuXG5cdFx0XHQvLyBVbmRlcnNjb3JlIHByZWZpeFxuXHRcdFx0Y29uc3QgdW5kZXJzY29yZVByZWZpeENvbnRhaW5lciA9IHNldHRpbmdzQ29udGFpbmVyLmNyZWF0ZURpdigpO1xuXHRcdFx0bmV3IFNldHRpbmcodW5kZXJzY29yZVByZWZpeENvbnRhaW5lcilcblx0XHRcdFx0LnNldE5hbWUoXCJVc2UgdW5kZXJzY29yZSBwcmVmaXggZm9yIGRyYWZ0c1wiKVxuXHRcdFx0XHQuc2V0RGVzYyhcIkFkZCBhbiB1bmRlcnNjb3JlIHByZWZpeCAoX2NvbnRlbnQtdGl0bGUpIHRvIG5ldyBub3RlcyBieSBkZWZhdWx0IHdoZW4gZW5hYmxlZC4gVGhpcyBoaWRlcyB0aGVtIGZyb20gYXN0cm8sIHdoaWNoIGNhbiBiZSBoZWxwZnVsIGZvciBkcmFmdHNcIilcblx0XHRcdFx0LmFkZFRvZ2dsZSh0b2dnbGUgPT5cblx0XHRcdFx0XHR0b2dnbGVcblx0XHRcdFx0XHRcdC5zZXRWYWx1ZShjdXN0b21UeXBlLmVuYWJsZVVuZGVyc2NvcmVQcmVmaXggfHwgZmFsc2UpXG5cdFx0XHRcdFx0XHQub25DaGFuZ2UoYXN5bmMgKHZhbHVlOiBib29sZWFuKSA9PiB7XG5cdFx0XHRcdFx0XHRcdGN1c3RvbVR5cGUuZW5hYmxlVW5kZXJzY29yZVByZWZpeCA9IHZhbHVlO1xuXHRcdFx0XHRcdFx0XHRhd2FpdCB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKTtcblx0XHRcdFx0XHRcdH0pXG5cdFx0XHRcdCk7XG5cblx0XHRcdC8vIExpbmsgYmFzZSBwYXRoXG5cdFx0XHRjb25zdCBsaW5rQ29udGFpbmVyID0gc2V0dGluZ3NDb250YWluZXIuY3JlYXRlRGl2KCk7XG5cdFx0XHRuZXcgU2V0dGluZyhsaW5rQ29udGFpbmVyKVxuXHRcdFx0XHQuc2V0TmFtZShcIkxpbmsgYmFzZSBwYXRoXCIpXG5cdFx0XHRcdC5zZXREZXNjKFwiQmFzZSBwYXRoIGZvciBjb252ZXJ0ZWQgbGlua3MgKCcvcHJvamVjdHMvJywgJy9ub3Rlcy90dXRvcmlhbHMvJywgbGVhdmUgYmxhbmsgZm9yIHJvb3QgLykuXCIpXG5cdFx0XHRcdC5hZGRUZXh0KHRleHQgPT4ge1xuXHRcdFx0XHRcdHRleHRcblx0XHRcdFx0XHRcdC5zZXRQbGFjZWhvbGRlcihcIkVudGVyIGxpbmsgYmFzZSBwYXRoXCIpXG5cdFx0XHRcdFx0XHQuc2V0VmFsdWUoY3VzdG9tVHlwZS5saW5rQmFzZVBhdGggfHwgXCJcIilcblx0XHRcdFx0XHRcdC5vbkNoYW5nZShhc3luYyAodmFsdWU6IHN0cmluZykgPT4ge1xuXHRcdFx0XHRcdFx0XHRjdXN0b21UeXBlLmxpbmtCYXNlUGF0aCA9IHZhbHVlO1xuXHRcdFx0XHRcdFx0XHRhd2FpdCB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKTtcblx0XHRcdFx0XHRcdH0pO1xuXHRcdFx0XHR9KTtcblxuXHRcdFx0Ly8gQ3JlYXRpb24gbW9kZVxuXHRcdFx0Y29uc3QgY3JlYXRpb25Nb2RlQ29udGFpbmVyID0gc2V0dGluZ3NDb250YWluZXIuY3JlYXRlRGl2KCk7XG5cdFx0XHRuZXcgU2V0dGluZyhjcmVhdGlvbk1vZGVDb250YWluZXIpXG5cdFx0XHRcdC5zZXROYW1lKFwiQ3JlYXRpb24gbW9kZVwiKVxuXHRcdFx0XHQuc2V0RGVzYyhcIkhvdyB0byBjcmVhdGUgbmV3IGVudHJpZXM6IGZpbGUtYmFzZWQgb3IgZm9sZGVyLWJhc2VkIHdpdGggYW4gaW5kZXggZmlsZS5cIilcblx0XHRcdFx0LmFkZERyb3Bkb3duKGRyb3Bkb3duID0+XG5cdFx0XHRcdFx0ZHJvcGRvd25cblx0XHRcdFx0XHRcdC5hZGRPcHRpb24oXCJmaWxlXCIsIFwiRmlsZS1iYXNlZCAoY29udGVudC10aXRsZS5tZClcIilcblx0XHRcdFx0XHRcdC5hZGRPcHRpb24oXCJmb2xkZXJcIiwgXCJGb2xkZXItYmFzZWQgKGNvbnRlbnQtdGl0bGUvaW5kZXgubWQpXCIpXG5cdFx0XHRcdFx0XHQuc2V0VmFsdWUoY3VzdG9tVHlwZS5jcmVhdGlvbk1vZGUpXG5cdFx0XHRcdFx0XHQub25DaGFuZ2UoYXN5bmMgKHZhbHVlOiBzdHJpbmcpID0+IHtcblx0XHRcdFx0XHRcdFx0Y3VzdG9tVHlwZS5jcmVhdGlvbk1vZGUgPSB2YWx1ZSBhcyBcImZpbGVcIiB8IFwiZm9sZGVyXCI7XG5cdFx0XHRcdFx0XHRcdGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xuXHRcdFx0XHRcdFx0XHR0aGlzLnVwZGF0ZUN1c3RvbUNvbnRlbnRUeXBlSW5kZXhGaWxlRmllbGQoY3VzdG9tVHlwZS5pZCk7XG5cdFx0XHRcdFx0XHR9KVxuXHRcdFx0XHQpO1xuXG5cdFx0XHQvLyBJbmRleCBmaWxlIG5hbWUgKG9ubHkgc2hvdyBmb3IgZm9sZGVyLWJhc2VkKVxuXHRcdFx0Y29uc3QgaW5kZXhGaWxlQ29udGFpbmVyID0gc2V0dGluZ3NDb250YWluZXIuY3JlYXRlRGl2KHsgY2xzOiBcImN1c3RvbS1pbmRleC1maWxlLWZpZWxkXCIgfSk7XG5cdFx0XHRpbmRleEZpbGVDb250YWluZXIuY2xhc3NMaXN0LnRvZ2dsZShcImFzdHJvLWNvbXBvc2VyLXNldHRpbmctY29udGFpbmVyLXZpc2libGVcIiwgY3VzdG9tVHlwZS5jcmVhdGlvbk1vZGUgPT09IFwiZm9sZGVyXCIpO1xuXHRcdFx0aW5kZXhGaWxlQ29udGFpbmVyLmNsYXNzTGlzdC50b2dnbGUoXCJhc3Ryby1jb21wb3Nlci1zZXR0aW5nLWNvbnRhaW5lci1oaWRkZW5cIiwgY3VzdG9tVHlwZS5jcmVhdGlvbk1vZGUgIT09IFwiZm9sZGVyXCIpO1xuXHRcdFx0bmV3IFNldHRpbmcoaW5kZXhGaWxlQ29udGFpbmVyKVxuXHRcdFx0XHQuc2V0TmFtZShcIkluZGV4IGZpbGUgbmFtZVwiKVxuXHRcdFx0XHQuc2V0RGVzYyhcIk5hbWUgZm9yIGluZGV4IGZpbGVzIGluIGZvbGRlci1iYXNlZCBjb250ZW50ICh3aXRob3V0IC5tZCBleHRlbnNpb24pLiBEZWZhdWx0cyB0byAnaW5kZXgnIGlmIGxlZnQgYmxhbmsuXCIpXG5cdFx0XHRcdC5hZGRUZXh0KHRleHQgPT5cblx0XHRcdFx0XHR0ZXh0XG5cdFx0XHRcdFx0XHQuc2V0UGxhY2Vob2xkZXIoXCJpbmRleFwiKVxuXHRcdFx0XHRcdFx0LnNldFZhbHVlKGN1c3RvbVR5cGUuaW5kZXhGaWxlTmFtZSlcblx0XHRcdFx0XHRcdC5vbkNoYW5nZShhc3luYyAodmFsdWU6IHN0cmluZykgPT4ge1xuXHRcdFx0XHRcdFx0XHRjdXN0b21UeXBlLmluZGV4RmlsZU5hbWUgPSB2YWx1ZTtcblx0XHRcdFx0XHRcdFx0YXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XG5cdFx0XHRcdFx0XHR9KVxuXHRcdFx0XHQpO1xuXG5cdFx0XHQvLyBVc2UgTURYIGV4dGVuc2lvblxuXHRcdFx0Y29uc3QgdXNlTWR4Q29udGFpbmVyID0gc2V0dGluZ3NDb250YWluZXIuY3JlYXRlRGl2KCk7XG5cdFx0XHRuZXcgU2V0dGluZyh1c2VNZHhDb250YWluZXIpXG5cdFx0XHRcdC8vIFwiTURYXCIgaXMgYSBwcm9wZXIgbm91biAoZmlsZSBmb3JtYXQpIGFuZCBzaG91bGQgYmUgY2FwaXRhbGl6ZWRcblx0XHRcdFx0LnNldE5hbWUoXCJVc2UgTURYIGluc3RlYWQgb2YgTURcIilcblx0XHRcdFx0LnNldERlc2MoXCJDcmVhdGUgZmlsZXMgd2l0aCAubWR4IGV4dGVuc2lvbiBpbnN0ZWFkIG9mIC5tZCBleHRlbnNpb24uXCIpXG5cdFx0XHRcdC5hZGRUb2dnbGUodG9nZ2xlID0+XG5cdFx0XHRcdFx0dG9nZ2xlXG5cdFx0XHRcdFx0XHQuc2V0VmFsdWUoY3VzdG9tVHlwZS51c2VNZHhFeHRlbnNpb24gfHwgZmFsc2UpXG5cdFx0XHRcdFx0XHQub25DaGFuZ2UoYXN5bmMgKHZhbHVlOiBib29sZWFuKSA9PiB7XG5cdFx0XHRcdFx0XHRcdGN1c3RvbVR5cGUudXNlTWR4RXh0ZW5zaW9uID0gdmFsdWU7XG5cdFx0XHRcdFx0XHRcdGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xuXHRcdFx0XHRcdFx0fSlcblx0XHRcdFx0KTtcblxuXHRcdFx0Ly8gTW9kaWZpZWQgZGF0ZSBwcm9wZXJ0eVxuXHRcdFx0Y29uc3QgbW9kaWZpZWREYXRlQ29udGFpbmVyID0gc2V0dGluZ3NDb250YWluZXIuY3JlYXRlRGl2KCk7XG5cdFx0XHRuZXcgU2V0dGluZyhtb2RpZmllZERhdGVDb250YWluZXIpXG5cdFx0XHRcdC5zZXROYW1lKFwiTW9kaWZpZWQgZGF0ZSBwcm9wZXJ0eVwiKVxuXHRcdFx0XHQuc2V0RGVzYyhcIlRoZSBwcm9wZXJ0eSBmaWVsZCB0byB1cGRhdGUgd2l0aCB0aGUgbW9kaWZpZWQgZGF0ZSBmb3IgdGhpcyBjb250ZW50IHR5cGUuIExlYXZlIGJsYW5rIHRvIGRpc2FibGUuXCIpXG5cdFx0XHRcdC5hZGRUZXh0KHRleHQgPT5cblx0XHRcdFx0XHR0ZXh0XG5cdFx0XHRcdFx0XHQuc2V0UGxhY2Vob2xkZXIoXCJtb2RpZmllZFwiKVxuXHRcdFx0XHRcdFx0LnNldFZhbHVlKGN1c3RvbVR5cGUubW9kaWZpZWREYXRlRmllbGQgfHwgXCJcIilcblx0XHRcdFx0XHRcdC5vbkNoYW5nZShhc3luYyAodmFsdWU6IHN0cmluZykgPT4ge1xuXHRcdFx0XHRcdFx0XHRjdXN0b21UeXBlLm1vZGlmaWVkRGF0ZUZpZWxkID0gdmFsdWU7XG5cdFx0XHRcdFx0XHRcdGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xuXHRcdFx0XHRcdFx0fSlcblx0XHRcdFx0KTtcblxuXHRcdFx0Ly8gVGVtcGxhdGVcblx0XHRcdGNvbnN0IHRlbXBsYXRlQ29udGFpbmVyID0gc2V0dGluZ3NDb250YWluZXIuY3JlYXRlRGl2KCk7XG5cdFx0XHRuZXcgU2V0dGluZyh0ZW1wbGF0ZUNvbnRhaW5lcilcblx0XHRcdFx0LnNldE5hbWUoXCJQcm9wZXJ0aWVzIHRlbXBsYXRlXCIpXG5cdFx0XHRcdC5hZGRUZXh0QXJlYSh0ZXh0ID0+IHtcblx0XHRcdFx0XHR0ZXh0XG5cdFx0XHRcdFx0XHQuc2V0UGxhY2Vob2xkZXIoJy0tLVxcbnRpdGxlOiBcInt7dGl0bGV9fVwiXFxuZGF0ZToge3tkYXRlfX1cXG4tLS1cXG4nKVxuXHRcdFx0XHRcdFx0LnNldFZhbHVlKGN1c3RvbVR5cGUudGVtcGxhdGUpXG5cdFx0XHRcdFx0XHQub25DaGFuZ2UoYXN5bmMgKHZhbHVlOiBzdHJpbmcpID0+IHtcblx0XHRcdFx0XHRcdFx0Y3VzdG9tVHlwZS50ZW1wbGF0ZSA9IHZhbHVlO1xuXHRcdFx0XHRcdFx0XHRhd2FpdCB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKTtcblx0XHRcdFx0XHRcdH0pO1xuXHRcdFx0XHRcdHRleHQuaW5wdXRFbC5jbGFzc0xpc3QuYWRkKFwiYXN0cm8tY29tcG9zZXItdGVtcGxhdGUtdGV4dGFyZWFcIik7XG5cdFx0XHRcdFx0cmV0dXJuIHRleHQ7XG5cdFx0XHRcdH0pXG5cdFx0XHRcdC50aGVuKChzZXR0aW5nKSA9PiB7XG5cdFx0XHRcdFx0c2V0dGluZy5kZXNjRWwuZW1wdHkoKTtcblx0XHRcdFx0XHRjb25zdCBkZXNjRGl2ID0gc2V0dGluZy5kZXNjRWwuY3JlYXRlRWwoXCJkaXZcIik7XG5cdFx0XHRcdFx0ZGVzY0Rpdi5jcmVhdGVFbChcImRpdlwiLCB7IHRleHQ6IFwiVGVtcGxhdGUgZm9yIG5ldyBmaWxlcyBvZiB0aGlzIGNvbnRlbnQgdHlwZS5cIiB9KTtcblx0XHRcdFx0XHRkZXNjRGl2LmNyZWF0ZUVsKFwiZGl2XCIsIHsgdGV4dDogXCJWYXJpYWJsZXMgaW5jbHVkZSB7e3RpdGxlfX0sIHt7ZGF0ZX19LCBhbmQge3tzbHVnfX0uXCIgfSk7XG5cdFx0XHRcdFx0ZGVzY0Rpdi5jcmVhdGVFbChcImRpdlwiLCB7IHRleHQ6IFwiRG8gbm90IHdyYXAge3tkYXRlfX0gaW4gcXVvdGVzIGFzIGl0IHJlcHJlc2VudHMgYSBkYXRldGltZSB2YWx1ZSwgbm90IGEgc3RyaW5nLlwiIH0pO1xuXHRcdFx0XHR9KTtcblxuXHRcdFx0Ly8gUmVtb3ZlIGJ1dHRvbiBhdCB0aGUgYm90dG9tIChubyBkaXZpZGVyKVxuXHRcdFx0Y29uc3QgcmVtb3ZlQ29udGFpbmVyID0gc2V0dGluZ3NDb250YWluZXIuY3JlYXRlRGl2KCk7XG5cdFx0XHRjb25zdCByZW1vdmVTZXR0aW5nID0gbmV3IFNldHRpbmcocmVtb3ZlQ29udGFpbmVyKVxuXHRcdFx0XHQuc2V0TmFtZShcIlwiKVxuXHRcdFx0XHQuYWRkQnV0dG9uKGJ1dHRvbiA9PiB7XG5cdFx0XHRcdFx0YnV0dG9uXG5cdFx0XHRcdFx0XHQuc2V0QnV0dG9uVGV4dChcIlJlbW92ZVwiKVxuXHRcdFx0XHRcdFx0LnNldFdhcm5pbmcoKVxuXHRcdFx0XHRcdFx0Lm9uQ2xpY2soYXN5bmMgKCkgPT4ge1xuXHRcdFx0XHRcdFx0XHRjb25zdCBjb250ZW50VHlwZSA9IHRoaXMucGx1Z2luLnNldHRpbmdzLmNvbnRlbnRUeXBlcy5maW5kKGN0ID0+IGN0LmlkID09PSBjdXN0b21UeXBlLmlkKTtcblx0XHRcdFx0XHRcdFx0Y29uc3QgdHlwZU5hbWUgPSBjb250ZW50VHlwZT8ubmFtZSB8fCBcImNvbnRlbnQgdHlwZVwiO1xuXHRcdFx0XHRcdFx0XHRjb25zdCBtb2RhbCA9IG5ldyBDb25maXJtTW9kYWwoXG5cdFx0XHRcdFx0XHRcdFx0dGhpcy5hcHAsXG5cdFx0XHRcdFx0XHRcdFx0YEFyZSB5b3Ugc3VyZSB5b3Ugd2FudCB0byByZW1vdmUgXCIke3R5cGVOYW1lfVwiPyBUaGlzIGFjdGlvbiBjYW5ub3QgYmUgdW5kb25lLmAsXG5cdFx0XHRcdFx0XHRcdFx0XCJSZW1vdmVcIixcblx0XHRcdFx0XHRcdFx0XHRcIkNhbmNlbFwiXG5cdFx0XHRcdFx0XHRcdCk7XG5cdFx0XHRcdFx0XHRcdGNvbnN0IGNvbmZpcm1lZCA9IGF3YWl0IG1vZGFsLndhaXRGb3JSZXN1bHQoKTtcblx0XHRcdFx0XHRcdFx0aWYgKGNvbmZpcm1lZCkge1xuXHRcdFx0XHRcdFx0XHRcdGF3YWl0IHRoaXMucmVtb3ZlQ3VzdG9tQ29udGVudFR5cGUoY3VzdG9tVHlwZS5pZCk7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH0pO1xuXHRcdFx0XHR9KTtcblxuXHRcdFx0Ly8gSGlkZSB0aGUgZGl2aWRlciBsaW5lIGZvciB0aGUgcmVtb3ZlIGJ1dHRvblxuXHRcdFx0cmVtb3ZlU2V0dGluZy5zZXR0aW5nRWwuY2xhc3NMaXN0LmFkZChcImFzdHJvLWNvbXBvc2VyLXJlbW92ZS1zZXR0aW5nXCIpO1xuXG5cdFx0XHQvLyBTZXQgaW5pdGlhbCB2aXNpYmlsaXR5IChjaGVja3MgYm90aCBlbmFibGVkIGFuZCBjb2xsYXBzZWQgc3RhdGUpXG5cdFx0XHR0aGlzLnVwZGF0ZUN1c3RvbUNvbnRlbnRUeXBlVmlzaWJpbGl0eShjdXN0b21UeXBlLmlkLCBjdXN0b21UeXBlLmVuYWJsZWQpO1xuXHRcdH0pO1xuXG5cdFx0Ly8gVXBkYXRlIGNvbmZsaWN0IHdhcm5pbmdzIGZvciBhbGwgdHlwZXMgYWZ0ZXIgcmVuZGVyaW5nIChmb2xkZXIgY2hhbmdlcyBtYXkgYWZmZWN0IG90aGVycylcblx0XHRjb250ZW50VHlwZXMuZm9yRWFjaCgoY3VzdG9tVHlwZTogQ29udGVudFR5cGUpID0+IHtcblx0XHRcdHRoaXMudXBkYXRlRm9sZGVyQ29uZmxpY3RXYXJuaW5nKGN1c3RvbVR5cGUuaWQsIG51bGwpO1xuXHRcdH0pO1xuXG5cdFx0Ly8gQWRkIGZsb2F0aW5nIGJ1dHRvbiBmb3IgY3JlYXRpbmcgbmV3IGN1c3RvbSBjb250ZW50IHR5cGVzIChubyBzZXR0aW5ncyBiYWNrZ3JvdW5kKVxuXHRcdGNvbnN0IGFkZEJ1dHRvbkNvbnRhaW5lciA9IHRoaXMuY3VzdG9tQ29udGVudFR5cGVzQ29udGFpbmVyLmNyZWF0ZURpdih7IGNsczogXCJhc3Ryby1jb21wb3Nlci1hZGQtYnV0dG9uLWNvbnRhaW5lclwiIH0pO1xuXHRcdGNvbnN0IGFkZEJ1dHRvbiA9IGFkZEJ1dHRvbkNvbnRhaW5lci5jcmVhdGVFbChcImJ1dHRvblwiLCB7XG5cdFx0XHRjbHM6IFwibW9kLWN0YVwiLFxuXHRcdFx0dGV4dDogXCJBZGQgY29udGVudCB0eXBlXCJcblx0XHR9KTtcblx0XHRhZGRCdXR0b24uYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsICgpID0+IHtcblx0XHRcdHRoaXMuYWRkQ3VzdG9tQ29udGVudFR5cGUoKTtcblx0XHR9KTtcblx0fVxuXG5cdHByaXZhdGUgdXBkYXRlQ3VzdG9tQ29udGVudFR5cGVWaXNpYmlsaXR5KHR5cGVJZDogc3RyaW5nLCBlbmFibGVkOiBib29sZWFuKSB7XG5cdFx0Y29uc3Qgc2V0dGluZ3NDb250YWluZXIgPSB0aGlzLmN1c3RvbUNvbnRlbnRUeXBlc0NvbnRhaW5lcj8ucXVlcnlTZWxlY3RvcihgW2RhdGEtdHlwZS1pZD1cIiR7dHlwZUlkfVwiXS5jdXN0b20tY29udGVudC10eXBlLXNldHRpbmdzYCkgYXMgSFRNTEVsZW1lbnQ7XG5cdFx0aWYgKHNldHRpbmdzQ29udGFpbmVyKSB7XG5cdFx0XHRjb25zdCBjb250ZW50VHlwZXMgPSB0aGlzLnBsdWdpbi5zZXR0aW5ncy5jb250ZW50VHlwZXMgfHwgW107XG5cdFx0XHRjb25zdCBjb250ZW50VHlwZSA9IGNvbnRlbnRUeXBlcy5maW5kKChjdDogQ29udGVudFR5cGUpID0+IGN0LmlkID09PSB0eXBlSWQpO1xuXHRcdFx0Y29uc3QgaXNDb2xsYXBzZWQgPSBjb250ZW50VHlwZT8uY29sbGFwc2VkID8/IGZhbHNlO1xuXHRcdFx0Y29uc3Qgc2hvdWxkQmVWaXNpYmxlID0gZW5hYmxlZCAmJiAhaXNDb2xsYXBzZWQ7XG5cblx0XHRcdHNldHRpbmdzQ29udGFpbmVyLmNsYXNzTGlzdC50b2dnbGUoXCJhc3Ryby1jb21wb3Nlci1zZXR0aW5nLWNvbnRhaW5lci12aXNpYmxlXCIsIHNob3VsZEJlVmlzaWJsZSk7XG5cdFx0XHRzZXR0aW5nc0NvbnRhaW5lci5jbGFzc0xpc3QudG9nZ2xlKFwiYXN0cm8tY29tcG9zZXItc2V0dGluZy1jb250YWluZXItaGlkZGVuXCIsICFzaG91bGRCZVZpc2libGUpO1xuXHRcdH1cblx0fVxuXG5cdHByaXZhdGUgdXBkYXRlQ3VzdG9tQ29udGVudFR5cGVJbmRleEZpbGVGaWVsZCh0eXBlSWQ6IHN0cmluZykge1xuXHRcdGNvbnN0IGNvbnRlbnRUeXBlcyA9IHRoaXMucGx1Z2luLnNldHRpbmdzLmNvbnRlbnRUeXBlcyB8fCBbXTtcblx0XHRjb25zdCBjdXN0b21UeXBlID0gY29udGVudFR5cGVzLmZpbmQodHlwZSA9PiB0eXBlLmlkID09PSB0eXBlSWQpO1xuXHRcdGlmICghY3VzdG9tVHlwZSkgcmV0dXJuO1xuXG5cdFx0Y29uc3QgaW5kZXhGaWxlQ29udGFpbmVyID0gdGhpcy5jdXN0b21Db250ZW50VHlwZXNDb250YWluZXI/LnF1ZXJ5U2VsZWN0b3IoYFtkYXRhLXR5cGUtaWQ9XCIke3R5cGVJZH1cIl0gLmN1c3RvbS1pbmRleC1maWxlLWZpZWxkYCkgYXMgSFRNTEVsZW1lbnQ7XG5cdFx0aWYgKGluZGV4RmlsZUNvbnRhaW5lcikge1xuXHRcdFx0aW5kZXhGaWxlQ29udGFpbmVyLmNsYXNzTGlzdC50b2dnbGUoXCJhc3Ryby1jb21wb3Nlci1zZXR0aW5nLWNvbnRhaW5lci12aXNpYmxlXCIsIGN1c3RvbVR5cGUuY3JlYXRpb25Nb2RlID09PSBcImZvbGRlclwiKTtcblx0XHRcdGluZGV4RmlsZUNvbnRhaW5lci5jbGFzc0xpc3QudG9nZ2xlKFwiYXN0cm8tY29tcG9zZXItc2V0dGluZy1jb250YWluZXItaGlkZGVuXCIsIGN1c3RvbVR5cGUuY3JlYXRpb25Nb2RlICE9PSBcImZvbGRlclwiKTtcblx0XHR9XG5cdH1cblxuXHRwcml2YXRlIHVwZGF0ZUN1c3RvbUNvbnRlbnRUeXBlSWdub3JlU3ViZm9sZGVyc0ZpZWxkKHR5cGVJZDogc3RyaW5nKSB7XG5cdFx0Y29uc3QgY29udGVudFR5cGVzID0gdGhpcy5wbHVnaW4uc2V0dGluZ3MuY29udGVudFR5cGVzIHx8IFtdO1xuXHRcdGNvbnN0IGN1c3RvbVR5cGUgPSBjb250ZW50VHlwZXMuZmluZCh0eXBlID0+IHR5cGUuaWQgPT09IHR5cGVJZCk7XG5cdFx0aWYgKCFjdXN0b21UeXBlKSByZXR1cm47XG5cblx0XHRjb25zdCBpZ25vcmVTdWJmb2xkZXJzQ29udGFpbmVyID0gdGhpcy5jdXN0b21Db250ZW50VHlwZXNDb250YWluZXI/LnF1ZXJ5U2VsZWN0b3IoYFtkYXRhLXR5cGUtaWQ9XCIke3R5cGVJZH1cIl0uY3VzdG9tLWlnbm9yZS1zdWJmb2xkZXJzLWZpZWxkYCkgYXMgSFRNTEVsZW1lbnQ7XG5cdFx0aWYgKGlnbm9yZVN1YmZvbGRlcnNDb250YWluZXIpIHtcblx0XHRcdGlnbm9yZVN1YmZvbGRlcnNDb250YWluZXIuY2xhc3NMaXN0LnRvZ2dsZShcImFzdHJvLWNvbXBvc2VyLXNldHRpbmctY29udGFpbmVyLXZpc2libGVcIiwgISFjdXN0b21UeXBlLmZvbGRlciAmJiBjdXN0b21UeXBlLmZvbGRlci50cmltKCkgIT09IFwiXCIpO1xuXHRcdFx0aWdub3JlU3ViZm9sZGVyc0NvbnRhaW5lci5jbGFzc0xpc3QudG9nZ2xlKFwiYXN0cm8tY29tcG9zZXItc2V0dGluZy1jb250YWluZXItaGlkZGVuXCIsICFjdXN0b21UeXBlLmZvbGRlciB8fCBjdXN0b21UeXBlLmZvbGRlci50cmltKCkgPT09IFwiXCIpO1xuXHRcdH1cblx0fVxuXG5cdHByaXZhdGUgdXBkYXRlRm9sZGVyQ29uZmxpY3RXYXJuaW5nKHR5cGVJZDogc3RyaW5nLCBzZXR0aW5nOiBTZXR0aW5nIHwgbnVsbCkge1xuXHRcdGNvbnN0IGNvbnRlbnRUeXBlcyA9IHRoaXMucGx1Z2luLnNldHRpbmdzLmNvbnRlbnRUeXBlcyB8fCBbXTtcblx0XHRjb25zdCBjdXJyZW50VHlwZSA9IGNvbnRlbnRUeXBlcy5maW5kKHR5cGUgPT4gdHlwZS5pZCA9PT0gdHlwZUlkKTtcblx0XHRpZiAoIWN1cnJlbnRUeXBlKSByZXR1cm47XG5cblx0XHRjb25zdCBjb25mbGljdFdhcm5pbmdFbCA9IHRoaXMuY3VzdG9tQ29udGVudFR5cGVzQ29udGFpbmVyPy5xdWVyeVNlbGVjdG9yKGBbZGF0YS10eXBlLWlkPVwiJHt0eXBlSWR9XCJdLmFzdHJvLWNvbXBvc2VyLWNvbmZsaWN0LXdhcm5pbmdgKSBhcyBIVE1MRWxlbWVudDtcblx0XHRpZiAoIWNvbmZsaWN0V2FybmluZ0VsKSByZXR1cm47XG5cblx0XHQvLyBGaW5kIGNvbmZsaWN0cyAtIG90aGVyIGNvbnRlbnQgdHlwZXMgd2l0aCB0aGUgc2FtZSBmb2xkZXIgcGF0dGVyblxuXHRcdGNvbnN0IGN1cnJlbnRGb2xkZXIgPSAoY3VycmVudFR5cGUuZm9sZGVyIHx8IFwiXCIpLnRyaW0oKTtcblx0XHRjb25zdCBjb25mbGljdGluZ1R5cGVzOiBzdHJpbmdbXSA9IFtdO1xuXG5cdFx0Zm9yIChjb25zdCBvdGhlclR5cGUgb2YgY29udGVudFR5cGVzKSB7XG5cdFx0XHRpZiAob3RoZXJUeXBlLmlkID09PSB0eXBlSWQgfHwgIW90aGVyVHlwZS5lbmFibGVkKSBjb250aW51ZTtcblxuXHRcdFx0Y29uc3Qgb3RoZXJGb2xkZXIgPSAob3RoZXJUeXBlLmZvbGRlciB8fCBcIlwiKS50cmltKCk7XG5cblx0XHRcdC8vIENoZWNrIGlmIGZvbGRlcnMgY29uZmxpY3Rcblx0XHRcdC8vIEJvdGggYmxhbmsgPSBjb25mbGljdCAoYm90aCBtYXRjaCB2YXVsdCByb290KVxuXHRcdFx0aWYgKGN1cnJlbnRGb2xkZXIgPT09IFwiXCIgJiYgb3RoZXJGb2xkZXIgPT09IFwiXCIpIHtcblx0XHRcdFx0Y29uZmxpY3RpbmdUeXBlcy5wdXNoKG90aGVyVHlwZS5uYW1lIHx8IFwiVW5uYW1lZFwiKTtcblx0XHRcdH1cblx0XHRcdC8vIFNhbWUgZm9sZGVyID0gY29uZmxpY3Rcblx0XHRcdGVsc2UgaWYgKGN1cnJlbnRGb2xkZXIgPT09IG90aGVyRm9sZGVyICYmIGN1cnJlbnRGb2xkZXIgIT09IFwiXCIpIHtcblx0XHRcdFx0Y29uZmxpY3RpbmdUeXBlcy5wdXNoKG90aGVyVHlwZS5uYW1lIHx8IFwiVW5uYW1lZFwiKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRpZiAoY29uZmxpY3RpbmdUeXBlcy5sZW5ndGggPiAwKSB7XG5cdFx0XHRjb25mbGljdFdhcm5pbmdFbC5yZW1vdmVDbGFzcyhcImhpZGRlblwiKTtcblx0XHRcdGNvbmZsaWN0V2FybmluZ0VsLnRleHRDb250ZW50ID0gYENvbmZsaWN0OiAke2NvbmZsaWN0aW5nVHlwZXMuam9pbihcIiwgXCIpfSBhbHNvIHVzZSR7Y29uZmxpY3RpbmdUeXBlcy5sZW5ndGggPT09IDEgPyBcInNcIiA6IFwiXCJ9IHRoaXMgZm9sZGVyLiBNb3JlIHNwZWNpZmljIHBhdHRlcm5zIHdpbGwgdGFrZSBwcmlvcml0eS5gO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRjb25mbGljdFdhcm5pbmdFbC5hZGRDbGFzcyhcImhpZGRlblwiKTtcblx0XHR9XG5cdH1cblxuXG5cdHByaXZhdGUgYXN5bmMgbW92ZUNvbnRlbnRUeXBlVXAodHlwZUlkOiBzdHJpbmcpIHtcblx0XHRjb25zdCBzZXR0aW5ncyA9IHRoaXMucGx1Z2luLnNldHRpbmdzO1xuXHRcdGNvbnN0IGNvbnRlbnRUeXBlcyA9IHNldHRpbmdzLmNvbnRlbnRUeXBlcyB8fCBbXTtcblx0XHRjb25zdCBjdXJyZW50SW5kZXggPSBjb250ZW50VHlwZXMuZmluZEluZGV4KChjdDogQ29udGVudFR5cGUpID0+IGN0LmlkID09PSB0eXBlSWQpO1xuXG5cdFx0aWYgKGN1cnJlbnRJbmRleCA8PSAwKSByZXR1cm47IC8vIEFscmVhZHkgYXQgdGhlIHRvcFxuXG5cdFx0Ly8gU3dhcCB3aXRoIHByZXZpb3VzIGl0ZW1cblx0XHRbY29udGVudFR5cGVzW2N1cnJlbnRJbmRleF0sIGNvbnRlbnRUeXBlc1tjdXJyZW50SW5kZXggLSAxXV0gPSBbY29udGVudFR5cGVzW2N1cnJlbnRJbmRleCAtIDFdLCBjb250ZW50VHlwZXNbY3VycmVudEluZGV4XV07XG5cdFx0c2V0dGluZ3MuY29udGVudFR5cGVzID0gY29udGVudFR5cGVzO1xuXHRcdGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xuXHRcdHRoaXMucmVuZGVyQ3VzdG9tQ29udGVudFR5cGVzKCk7XG5cdH1cblxuXHRwcml2YXRlIGFzeW5jIG1vdmVDb250ZW50VHlwZURvd24odHlwZUlkOiBzdHJpbmcpIHtcblx0XHRjb25zdCBzZXR0aW5ncyA9IHRoaXMucGx1Z2luLnNldHRpbmdzO1xuXHRcdGNvbnN0IGNvbnRlbnRUeXBlcyA9IHNldHRpbmdzLmNvbnRlbnRUeXBlcyB8fCBbXTtcblx0XHRjb25zdCBjdXJyZW50SW5kZXggPSBjb250ZW50VHlwZXMuZmluZEluZGV4KChjdDogQ29udGVudFR5cGUpID0+IGN0LmlkID09PSB0eXBlSWQpO1xuXG5cdFx0aWYgKGN1cnJlbnRJbmRleCA8IDAgfHwgY3VycmVudEluZGV4ID49IGNvbnRlbnRUeXBlcy5sZW5ndGggLSAxKSByZXR1cm47IC8vIEFscmVhZHkgYXQgdGhlIGJvdHRvbVxuXG5cdFx0Ly8gU3dhcCB3aXRoIG5leHQgaXRlbVxuXHRcdFtjb250ZW50VHlwZXNbY3VycmVudEluZGV4XSwgY29udGVudFR5cGVzW2N1cnJlbnRJbmRleCArIDFdXSA9IFtjb250ZW50VHlwZXNbY3VycmVudEluZGV4ICsgMV0sIGNvbnRlbnRUeXBlc1tjdXJyZW50SW5kZXhdXTtcblx0XHRzZXR0aW5ncy5jb250ZW50VHlwZXMgPSBjb250ZW50VHlwZXM7XG5cdFx0YXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XG5cdFx0dGhpcy5yZW5kZXJDdXN0b21Db250ZW50VHlwZXMoKTtcblx0fVxuXG5cdHByaXZhdGUgYXN5bmMgdG9nZ2xlQ29udGVudFR5cGVDb2xsYXBzZSh0eXBlSWQ6IHN0cmluZykge1xuXHRcdGNvbnN0IHNldHRpbmdzID0gdGhpcy5wbHVnaW4uc2V0dGluZ3M7XG5cdFx0Y29uc3QgY29udGVudFR5cGVzID0gc2V0dGluZ3MuY29udGVudFR5cGVzIHx8IFtdO1xuXHRcdGNvbnN0IGNvbnRlbnRUeXBlID0gY29udGVudFR5cGVzLmZpbmQoKGN0OiBDb250ZW50VHlwZSkgPT4gY3QuaWQgPT09IHR5cGVJZCk7XG5cblx0XHRpZiAoIWNvbnRlbnRUeXBlKSByZXR1cm47XG5cblx0XHRjb250ZW50VHlwZS5jb2xsYXBzZWQgPSAhY29udGVudFR5cGUuY29sbGFwc2VkO1xuXHRcdGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xuXHRcdHRoaXMudXBkYXRlQ3VzdG9tQ29udGVudFR5cGVWaXNpYmlsaXR5KHR5cGVJZCwgY29udGVudFR5cGUuZW5hYmxlZCk7XG5cdH1cblxuXHRwcml2YXRlIGFzeW5jIHJlbW92ZUN1c3RvbUNvbnRlbnRUeXBlKHR5cGVJZDogc3RyaW5nKSB7XG5cdFx0Y29uc3Qgc2V0dGluZ3MgPSB0aGlzLnBsdWdpbi5zZXR0aW5ncztcblx0XHRjb25zdCBjb250ZW50VHlwZXMgPSBzZXR0aW5ncy5jb250ZW50VHlwZXMgfHwgW107XG5cdFx0c2V0dGluZ3MuY29udGVudFR5cGVzID0gY29udGVudFR5cGVzLmZpbHRlcigoY3Q6IENvbnRlbnRUeXBlKSA9PiBjdC5pZCAhPT0gdHlwZUlkKTtcblx0XHQvLyBDUklUSUNBTDogQXdhaXQgdGhlIHNhdmUgdG8gZW5zdXJlIGRlbGV0aW9uIGlzIHBlcnNpc3RlZCBiZWZvcmUgYW55IHJlbG9hZHMgaGFwcGVuXG5cdFx0YXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XG5cdFx0dGhpcy5yZW5kZXJDdXN0b21Db250ZW50VHlwZXMoKTtcblx0XHR0aGlzLnBsdWdpbi5yZWdpc3RlckNyZWF0ZUV2ZW50KCk7XG5cdFx0Ly8gUmUtcmVnaXN0ZXIgY29udGVudCB0eXBlIGNvbW1hbmRzIHRvIHJlbW92ZSB0aGUgZGVsZXRlZCB0eXBlXG5cdFx0cmVnaXN0ZXJDb250ZW50VHlwZUNvbW1hbmRzKHRoaXMucGx1Z2luIGFzIHVua25vd24gYXMgUGx1Z2luLCBzZXR0aW5ncyk7XG5cdH1cblxuXHRwcml2YXRlIGdldENvbW1hbmROYW1lKGNvbW1hbmRJZDogc3RyaW5nKTogc3RyaW5nIHtcblx0XHRpZiAoIWNvbW1hbmRJZCkgcmV0dXJuICcnO1xuXHRcdHRyeSB7XG5cdFx0XHRjb25zdCBjb21tYW5kUmVnaXN0cnkgPSAodGhpcy5hcHAgYXMgdW5rbm93biBhcyB7IGNvbW1hbmRzPzogeyBsaXN0Q29tbWFuZHM/OiAoKSA9PiBBcnJheTx7IGlkOiBzdHJpbmc7IG5hbWU6IHN0cmluZyB9PjsgY29tbWFuZHM/OiBSZWNvcmQ8c3RyaW5nLCB7IGlkOiBzdHJpbmc7IG5hbWU6IHN0cmluZyB9PiB9IH0pLmNvbW1hbmRzO1xuXG5cdFx0XHQvLyBNZXRob2QgMTogVHJ5IGxpc3RDb21tYW5kcygpXG5cdFx0XHRpZiAoY29tbWFuZFJlZ2lzdHJ5ICYmIHR5cGVvZiBjb21tYW5kUmVnaXN0cnkubGlzdENvbW1hbmRzID09PSAnZnVuY3Rpb24nKSB7XG5cdFx0XHRcdHRyeSB7XG5cdFx0XHRcdFx0Y29uc3QgYWxsQ29tbWFuZHMgPSBjb21tYW5kUmVnaXN0cnkubGlzdENvbW1hbmRzKCk7XG5cdFx0XHRcdFx0Y29uc3QgY29tbWFuZCA9IGFsbENvbW1hbmRzLmZpbmQoKGNtZDogeyBpZDogc3RyaW5nOyBuYW1lPzogc3RyaW5nIH0pID0+IGNtZC5pZCA9PT0gY29tbWFuZElkKTtcblx0XHRcdFx0XHRpZiAoY29tbWFuZD8ubmFtZSkge1xuXHRcdFx0XHRcdFx0cmV0dXJuIGNvbW1hbmQubmFtZTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0gY2F0Y2ggKGUpIHtcblx0XHRcdFx0XHRjb25zb2xlLndhcm4oJ1tBc3RybyBDb21wb3Nlcl0gRXJyb3IgZ2V0dGluZyBjb21tYW5kIG5hbWUgdmlhIGxpc3RDb21tYW5kcygpOicsIGUpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdC8vIE1ldGhvZCAyOiBUcnkgYWNjZXNzaW5nIHRoZSBpbnRlcm5hbCBjb21tYW5kcyByZWdpc3RyeSBkaXJlY3RseVxuXHRcdFx0dHJ5IHtcblx0XHRcdFx0Y29uc3QgcmVnaXN0cnkgPSBjb21tYW5kUmVnaXN0cnk/LmNvbW1hbmRzO1xuXHRcdFx0XHRpZiAocmVnaXN0cnkgJiYgdHlwZW9mIHJlZ2lzdHJ5ID09PSAnb2JqZWN0Jykge1xuXHRcdFx0XHRcdGNvbnN0IGNvbW1hbmQgPSAocmVnaXN0cnkgYXMgUmVjb3JkPHN0cmluZywgeyBuYW1lPzogc3RyaW5nIH0+KVtjb21tYW5kSWRdO1xuXHRcdFx0XHRcdGlmIChjb21tYW5kPy5uYW1lKSB7XG5cdFx0XHRcdFx0XHRyZXR1cm4gY29tbWFuZC5uYW1lO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fSBjYXRjaCAoZSkge1xuXHRcdFx0XHRjb25zb2xlLndhcm4oJ1tBc3RybyBDb21wb3Nlcl0gRXJyb3IgZ2V0dGluZyBjb21tYW5kIG5hbWUgdmlhIHJlZ2lzdHJ5OicsIGUpO1xuXHRcdFx0fVxuXHRcdH0gY2F0Y2ggKGUpIHtcblx0XHRcdGNvbnNvbGUud2FybignW0FzdHJvIENvbXBvc2VyXSBFcnJvciBnZXR0aW5nIGNvbW1hbmQgbmFtZTonLCBlKTtcblx0XHR9XG5cdFx0Ly8gUmV0dXJuIGVtcHR5IHN0cmluZyBpZiBjb21tYW5kIG5vdCBmb3VuZCwgc28gaXQgc2hvd3MgXCJTZWxlY3QgY29tbWFuZC4uLlwiIHBsYWNlaG9sZGVyXG5cdFx0cmV0dXJuICcnO1xuXHR9XG5cblx0cHJpdmF0ZSBnZXRJY29uTmFtZShpY29uSWQ6IHN0cmluZyk6IHN0cmluZyB7XG5cdFx0aWYgKCFpY29uSWQpIHJldHVybiAnJztcblx0XHQvLyBDb252ZXJ0IGljb24gSUQgdG8gYSByZWFkYWJsZSBuYW1lLCByZW1vdmluZyBsdWNpZGUtIHByZWZpeCBpZiBwcmVzZW50XG5cdFx0cmV0dXJuIGljb25JZFxuXHRcdFx0LnJlcGxhY2UoL15sdWNpZGUtLywgJycpIC8vIFJlbW92ZSBsdWNpZGUtIHByZWZpeFxuXHRcdFx0LnNwbGl0KCctJylcblx0XHRcdC5tYXAod29yZCA9PiB3b3JkLmNoYXJBdCgwKS50b1VwcGVyQ2FzZSgpICsgd29yZC5zbGljZSgxKSlcblx0XHRcdC5qb2luKCcgJyk7XG5cdH1cbn1cbiIsICIvKipcclxuICogQ29tbWFuZCBQaWNrZXIgTW9kYWxcclxuICogU2VhcmNoYWJsZSBtb2RhbCBmb3Igc2VsZWN0aW5nIGFuIE9ic2lkaWFuIGNvbW1hbmRcclxuICovXHJcblxyXG5pbXBvcnQgeyBBcHAsIEZ1enp5U3VnZ2VzdE1vZGFsIH0gZnJvbSAnb2JzaWRpYW4nO1xyXG5cclxuaW50ZXJmYWNlIENvbW1hbmRPcHRpb24ge1xyXG5cdGlkOiBzdHJpbmc7XHJcblx0bmFtZTogc3RyaW5nO1xyXG59XHJcblxyXG5leHBvcnQgY2xhc3MgQ29tbWFuZFBpY2tlck1vZGFsIGV4dGVuZHMgRnV6enlTdWdnZXN0TW9kYWw8Q29tbWFuZE9wdGlvbj4ge1xyXG5cdHByaXZhdGUgb25TZWxlY3Q6IChjb21tYW5kSWQ6IHN0cmluZykgPT4gdm9pZDtcclxuXHJcblx0Y29uc3RydWN0b3IoYXBwOiBBcHAsIG9uU2VsZWN0OiAoY29tbWFuZElkOiBzdHJpbmcpID0+IHZvaWQpIHtcclxuXHRcdHN1cGVyKGFwcCk7XHJcblx0XHR0aGlzLm9uU2VsZWN0ID0gb25TZWxlY3Q7XHJcblx0fVxyXG5cclxuXHRnZXRJdGVtcygpOiBDb21tYW5kT3B0aW9uW10ge1xyXG5cdFx0Ly8gR2V0IGFsbCBhdmFpbGFibGUgY29tbWFuZHNcclxuXHRcdC8vIFRyeSBtdWx0aXBsZSBtZXRob2RzIHRvIGVuc3VyZSB3ZSBnZXQgQUxMIGNvbW1hbmRzLCBub3QganVzdCBjb250ZXh0LWZpbHRlcmVkIG9uZXNcclxuXHRcdGNvbnN0IGNvbW1hbmRSZWdpc3RyeSA9ICh0aGlzLmFwcCBhcyB7IGNvbW1hbmRzPzogeyBsaXN0Q29tbWFuZHM/OiAoKSA9PiBDb21tYW5kT3B0aW9uW107IGNvbW1hbmRzPzogUmVjb3JkPHN0cmluZywgQ29tbWFuZE9wdGlvbj47IGNvbW1hbmRSZWdpc3RyeT86IFJlY29yZDxzdHJpbmcsIENvbW1hbmRPcHRpb24+IH0gfSkuY29tbWFuZHM7XHJcblx0XHRcclxuXHRcdC8vIFVzZSBhIFNldCB0byBkZWR1cGxpY2F0ZSBieSBjb21tYW5kIElEXHJcblx0XHRjb25zdCBjb21tYW5kTWFwID0gbmV3IE1hcDxzdHJpbmcsIENvbW1hbmRPcHRpb24+KCk7XHJcblx0XHRcclxuXHRcdC8vIE1ldGhvZCAxOiBUcnkgbGlzdENvbW1hbmRzKCkgLSBidXQgdGhpcyBtaWdodCBiZSBjb250ZXh0LWZpbHRlcmVkXHJcblx0XHRpZiAoY29tbWFuZFJlZ2lzdHJ5ICYmIHR5cGVvZiBjb21tYW5kUmVnaXN0cnkubGlzdENvbW1hbmRzID09PSAnZnVuY3Rpb24nKSB7XHJcblx0XHRcdHRyeSB7XHJcblx0XHRcdFx0Y29uc3QgY29tbWFuZHMgPSBjb21tYW5kUmVnaXN0cnkubGlzdENvbW1hbmRzKCk7XHJcblx0XHRcdFx0Zm9yIChjb25zdCBjb21tYW5kIG9mIGNvbW1hbmRzKSB7XHJcblx0XHRcdFx0XHRpZiAoY29tbWFuZCAmJiBjb21tYW5kLmlkICYmIGNvbW1hbmQubmFtZSAmJiAhY29tbWFuZE1hcC5oYXMoY29tbWFuZC5pZCkpIHtcclxuXHRcdFx0XHRcdFx0Y29tbWFuZE1hcC5zZXQoY29tbWFuZC5pZCwge1xyXG5cdFx0XHRcdFx0XHRcdGlkOiBjb21tYW5kLmlkLFxyXG5cdFx0XHRcdFx0XHRcdG5hbWU6IGNvbW1hbmQubmFtZVxyXG5cdFx0XHRcdFx0XHR9KTtcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHR9XHJcblx0XHRcdH0gY2F0Y2ggKGUpIHtcclxuXHRcdFx0XHRjb25zb2xlLndhcm4oJ1tBc3RybyBDb21wb3Nlcl0gRXJyb3IgZ2V0dGluZyBjb21tYW5kcyB2aWEgbGlzdENvbW1hbmRzKCk6JywgZSk7XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHRcdFxyXG5cdFx0Ly8gTWV0aG9kIDI6IFRyeSBhY2Nlc3NpbmcgdGhlIGludGVybmFsIGNvbW1hbmRzIHJlZ2lzdHJ5IGRpcmVjdGx5XHJcblx0XHQvLyBUaGlzIHNob3VsZCBnaXZlIHVzIEFMTCBjb21tYW5kcyByZWdhcmRsZXNzIG9mIGNvbnRleHRcclxuXHRcdHRyeSB7XHJcblx0XHRcdGNvbnN0IHJlZ2lzdHJ5ID0gY29tbWFuZFJlZ2lzdHJ5Py5jb21tYW5kcztcclxuXHRcdFx0aWYgKHJlZ2lzdHJ5ICYmIHR5cGVvZiByZWdpc3RyeSA9PT0gJ29iamVjdCcpIHtcclxuXHRcdFx0XHRjb25zdCBhbGxDb21tYW5kcyA9IE9iamVjdC52YWx1ZXMocmVnaXN0cnkpO1xyXG5cdFx0XHRcdGZvciAoY29uc3QgY29tbWFuZCBvZiBhbGxDb21tYW5kcykge1xyXG5cdFx0XHRcdFx0aWYgKGNvbW1hbmQgJiYgY29tbWFuZC5pZCAmJiBjb21tYW5kLm5hbWUgJiYgIWNvbW1hbmRNYXAuaGFzKGNvbW1hbmQuaWQpKSB7XHJcblx0XHRcdFx0XHRcdGNvbW1hbmRNYXAuc2V0KGNvbW1hbmQuaWQsIHtcclxuXHRcdFx0XHRcdFx0XHRpZDogY29tbWFuZC5pZCxcclxuXHRcdFx0XHRcdFx0XHRuYW1lOiBjb21tYW5kLm5hbWVcclxuXHRcdFx0XHRcdFx0fSk7XHJcblx0XHRcdFx0XHR9XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblx0XHR9IGNhdGNoIChlKSB7XHJcblx0XHRcdGNvbnNvbGUud2FybignW0FzdHJvIENvbXBvc2VyXSBFcnJvciBnZXR0aW5nIGNvbW1hbmRzIHZpYSByZWdpc3RyeTonLCBlKTtcclxuXHRcdH1cclxuXHRcdFxyXG5cdFx0Ly8gTWV0aG9kIDM6IFRyeSBhY2Nlc3NpbmcgdmlhIGludGVybmFsIHN0cnVjdHVyZSAoZmFsbGJhY2spXHJcblx0XHR0cnkge1xyXG5cdFx0XHRjb25zdCBpbnRlcm5hbFJlZ2lzdHJ5ID0gY29tbWFuZFJlZ2lzdHJ5Py5jb21tYW5kUmVnaXN0cnk7XHJcblx0XHRcdGlmIChpbnRlcm5hbFJlZ2lzdHJ5ICYmIHR5cGVvZiBpbnRlcm5hbFJlZ2lzdHJ5ID09PSAnb2JqZWN0Jykge1xyXG5cdFx0XHRcdGNvbnN0IGFsbENvbW1hbmRzID0gT2JqZWN0LnZhbHVlcyhpbnRlcm5hbFJlZ2lzdHJ5KTtcclxuXHRcdFx0XHRmb3IgKGNvbnN0IGNvbW1hbmQgb2YgYWxsQ29tbWFuZHMpIHtcclxuXHRcdFx0XHRcdGlmIChjb21tYW5kICYmIGNvbW1hbmQuaWQgJiYgY29tbWFuZC5uYW1lICYmICFjb21tYW5kTWFwLmhhcyhjb21tYW5kLmlkKSkge1xyXG5cdFx0XHRcdFx0XHRjb21tYW5kTWFwLnNldChjb21tYW5kLmlkLCB7XHJcblx0XHRcdFx0XHRcdFx0aWQ6IGNvbW1hbmQuaWQsXHJcblx0XHRcdFx0XHRcdFx0bmFtZTogY29tbWFuZC5uYW1lXHJcblx0XHRcdFx0XHRcdH0pO1xyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdH1cclxuXHRcdFx0fVxyXG5cdFx0fSBjYXRjaCAoZSkge1xyXG5cdFx0XHRjb25zb2xlLndhcm4oJ1tBc3RybyBDb21wb3Nlcl0gRXJyb3IgZ2V0dGluZyBjb21tYW5kcyB2aWEgaW50ZXJuYWwgcmVnaXN0cnk6JywgZSk7XHJcblx0XHR9XHJcblx0XHRcclxuXHRcdGNvbnN0IGNvbW1hbmRPcHRpb25zID0gQXJyYXkuZnJvbShjb21tYW5kTWFwLnZhbHVlcygpKTtcclxuXHRcdFxyXG5cdFx0Ly8gU29ydCBhbHBoYWJldGljYWxseSBieSBuYW1lXHJcblx0XHRjb21tYW5kT3B0aW9ucy5zb3J0KChhLCBiKSA9PiBhLm5hbWUubG9jYWxlQ29tcGFyZShiLm5hbWUpKTtcclxuXHRcdFxyXG5cdFx0cmV0dXJuIGNvbW1hbmRPcHRpb25zO1xyXG5cdH1cclxuXHJcblx0Z2V0SXRlbVRleHQoaXRlbTogQ29tbWFuZE9wdGlvbik6IHN0cmluZyB7XHJcblx0XHRyZXR1cm4gaXRlbS5uYW1lO1xyXG5cdH1cclxuXHJcblx0b25DaG9vc2VJdGVtKGl0ZW06IENvbW1hbmRPcHRpb24sIGV2dDogTW91c2VFdmVudCB8IEtleWJvYXJkRXZlbnQpOiB2b2lkIHtcclxuXHRcdHRoaXMub25TZWxlY3QoaXRlbS5pZCk7XHJcblx0fVxyXG5cclxuXHQvLyBPdmVycmlkZSB0byBzaG93IGNvbW1hbmQgbmFtZSBvbmx5XHJcblx0cmVuZGVyU3VnZ2VzdGlvbihtYXRjaDogeyBpdGVtOiBDb21tYW5kT3B0aW9uIH0sIGVsOiBIVE1MRWxlbWVudCk6IHZvaWQge1xyXG5cdFx0Y29uc3QgaXRlbSA9IG1hdGNoLml0ZW07XHJcblx0XHRlbC5jcmVhdGVEaXYoeyBjbHM6ICdzdWdnZXN0aW9uLXRpdGxlJywgdGV4dDogaXRlbS5uYW1lIH0pO1xyXG5cdH1cclxufVxyXG5cclxuIiwgIi8qKlxyXG4gKiBJY29uIFBpY2tlciBNb2RhbFxyXG4gKiBTZWFyY2hhYmxlIG1vZGFsIGZvciBzZWxlY3RpbmcgYSBMdWNpZGUgaWNvblxyXG4gKi9cclxuXHJcbmltcG9ydCB7IEFwcCwgRnV6enlTdWdnZXN0TW9kYWwsIHNldEljb24sIGdldEljb25JZHMsIHJlcXVpcmVBcGlWZXJzaW9uIH0gZnJvbSAnb2JzaWRpYW4nO1xyXG5cclxuaW50ZXJmYWNlIEljb25PcHRpb24ge1xyXG5cdGlkOiBzdHJpbmc7XHJcblx0bmFtZTogc3RyaW5nO1xyXG59XHJcblxyXG4vLyBHZXQgaWNvbiBsaXN0IGZyb20gT2JzaWRpYW4gQVBJIGlmIGF2YWlsYWJsZSwgb3RoZXJ3aXNlIHVzZSBmYWxsYmFjayBsaXN0XHJcbmNvbnN0IGdldEljb25MaXN0ID0gKCk6IHN0cmluZ1tdID0+IHtcclxuXHRpZiAocmVxdWlyZUFwaVZlcnNpb24gJiYgcmVxdWlyZUFwaVZlcnNpb24oJzEuNy4zJykgJiYgZ2V0SWNvbklkcykge1xyXG5cdFx0dHJ5IHtcclxuXHRcdFx0cmV0dXJuIGdldEljb25JZHMoKTtcclxuXHRcdH0gY2F0Y2ggKGUpIHtcclxuXHRcdFx0Y29uc29sZS53YXJuKCdbQXN0cm8gQ29tcG9zZXJdIEVycm9yIGdldHRpbmcgaWNvbiBJRHMgZnJvbSBPYnNpZGlhbjonLCBlKTtcclxuXHRcdH1cclxuXHR9XHJcblx0Ly8gRmFsbGJhY2sgdG8gYSBiYXNpYyBsaXN0IGlmIEFQSSBpcyBub3QgYXZhaWxhYmxlXHJcblx0cmV0dXJuIFtcclxuXHRcdCdzZXR0aW5ncy0yJywgJ3NldHRpbmdzJywgJ2hlbHAtY2lyY2xlJywgJ2luZm8nLCAnc3RhcicsICdoZWFydCcsICdib29rbWFyaycsXHJcblx0XHQnaG9tZScsICdzZWFyY2gnLCAnYmVsbCcsICdtYWlsJywgJ3VzZXInLCAndXNlcnMnLCAnZm9sZGVyJywgJ2ZpbGUnLCAnZmlsZS10ZXh0JyxcclxuXHRcdCdpbWFnZScsICd2aWRlbycsICdtdXNpYycsICdjYWxlbmRhcicsICdjbG9jaycsICdlZGl0JywgJ3BlbmNpbCcsICd0cmFzaCcsXHJcblx0XHQnY29weScsICdjdXQnLCAncGFzdGUnLCAnZG93bmxvYWQnLCAndXBsb2FkJywgJ3NhdmUnLCAnc2hhcmUnLCAnbGluaycsXHJcblx0XHQnZXh0ZXJuYWwtbGluaycsICdsb2NrJywgJ3VubG9jaycsICdleWUnLCAnZXllLW9mZicsICdrZXknLCAnc2hpZWxkJyxcclxuXHRcdCdjaGVjaycsICd4JywgJ3BsdXMnLCAnbWludXMnLCAnYXJyb3ctbGVmdCcsICdhcnJvdy1yaWdodCcsICdhcnJvdy11cCcsXHJcblx0XHQnYXJyb3ctZG93bicsICdjaGV2cm9uLWxlZnQnLCAnY2hldnJvbi1yaWdodCcsICdjaGV2cm9uLXVwJywgJ2NoZXZyb24tZG93bicsXHJcblx0XHQnbWVudScsICdtb3JlLWhvcml6b250YWwnLCAnbW9yZS12ZXJ0aWNhbCcsICdncmlkJywgJ2xpc3QnLCAnbGF5b3V0JyxcclxuXHRcdCdjb2x1bW5zJywgJ3Jvd3MnLCAnbWF4aW1pemUnLCAnbWluaW1pemUnLCAnem9vbS1pbicsICd6b29tLW91dCcsXHJcblx0XHQncmVmcmVzaC1jdycsICdwbGF5JywgJ3BhdXNlJywgJ3N0b3AnLCAnc3VuJywgJ21vb24nLCAnY2xvdWQnLCAnemFwJyxcclxuXHRcdCd3YW5kLTInLCAnd2FuZCcsICd3YW5kLXNwYXJrbGVzJywgJ3BhbGV0dGUnLCAnYnJ1c2gnLCAnc2xpZGVycycsXHJcblx0XHQncG93ZXInLCAnd2lmaScsICdibHVldG9vdGgnLCAnbW9uaXRvcicsICdsYXB0b3AnLCAnc21hcnRwaG9uZScsXHJcblx0XHQnY2FtZXJhJywgJ21pYycsICdoZWFkcGhvbmVzJywgJ2NvZGUnLCAndGVybWluYWwnLCAndGVybWluYWwtc3F1YXJlJyxcclxuXHRcdCdnaXRodWInLCAnZ2l0bGFiJywgJ2dpdC1icmFuY2gnLCAnZ2l0LWNvbW1pdCcsICdkYXRhYmFzZScsICdzZXJ2ZXInLFxyXG5cdFx0J2Nsb3VkLWRvd25sb2FkJywgJ2Nsb3VkLXVwbG9hZCcsICd0YWcnLCAndGFncycsICdmbGFnJywgJ3BpbicsXHJcblx0XHQnbWFwLXBpbicsICdjb21wYXNzJywgJ2dsb2JlJywgJ3JvY2tldCcsICdjYXInLCAnYmlrZScsICdyb2JvdCcsXHJcblx0XHQnYXBwbGUnLCAnd2luZG93cycsICdsaW51eCcsICdjaHJvbWUnLCAnZmlyZWZveCcsICdzYWZhcmknLFxyXG5cdFx0J2NyZWRpdC1jYXJkJywgJ3dhbGxldCcsICdjb2lucycsICdib29rJywgJ2Jvb2stb3BlbicsICdhd2FyZCcsXHJcblx0XHQndHJvcGh5JywgJ2JhZGdlJywgJ3dyZW5jaCcsICd0b29sJywgJ3BhY2thZ2UnLCAnYm94JywgJ2FyY2hpdmUnLFxyXG5cdFx0J3NlbmQnLCAncmVwbHknLCAnZm9yd2FyZCcsICdtYWlsLW9wZW4nLCAndGFnLXBsdXMnLCAndGFnLW1pbnVzJyxcclxuXHRcdCdmbGFnLW9mZicsICdwaW4tb2ZmJywgJ21hcC1waW4tb2ZmJywgJ25hdmlnYXRpb24nLCAnbWFwJywgJ2VhcnRoJyxcclxuXHRcdCdwbGFuZScsICdzaGlwJywgJ2FuY2hvcicsICdoZWxpY29wdGVyJywgJ2Ryb25lJywgJ2FuZHJvaWQnLFxyXG5cdFx0J2tleWhvbGUnLCAna2V5cycsICdmaW5nZXJwcmludCcsICdzY2FuJywgJ3FyLWNvZGUnLCAnYmFyY29kZScsXHJcblx0XHQncmVjZWlwdCcsICdwaWdneS1iYW5rJywgJ2Jhbmtub3RlJ1xyXG5cdF07XHJcbn07XHJcblxyXG4vLyBDb252ZXJ0IGljb24gSURzIHRvIEljb25PcHRpb24gZm9ybWF0XHJcbmNvbnN0IExVQ0lERV9JQ09OUzogSWNvbk9wdGlvbltdID0gZ2V0SWNvbkxpc3QoKS5tYXAoaWQgPT4gKHtcclxuXHRpZDogaWQsXHJcblx0bmFtZTogaWRcclxuXHRcdC5yZXBsYWNlKC9ebHVjaWRlLS8sICcnKSAvLyBSZW1vdmUgbHVjaWRlLSBwcmVmaXggZm9yIGRpc3BsYXlcclxuXHRcdC5yZXBsYWNlKC8tL2csICcgJylcclxuXHRcdC5yZXBsYWNlKC8oXlxcd3sxfSl8KFxccytcXHd7MX0pL2csIChsZXR0ZXIpID0+IGxldHRlci50b1VwcGVyQ2FzZSgpKVxyXG59KSkuc29ydCgoYSwgYikgPT4gYS5uYW1lLmxvY2FsZUNvbXBhcmUoYi5uYW1lKSk7XHJcblxyXG5leHBvcnQgY2xhc3MgSWNvblBpY2tlck1vZGFsIGV4dGVuZHMgRnV6enlTdWdnZXN0TW9kYWw8SWNvbk9wdGlvbj4ge1xyXG5cdHByaXZhdGUgb25TZWxlY3Q6IChpY29uSWQ6IHN0cmluZykgPT4gdm9pZDtcclxuXHJcblx0Y29uc3RydWN0b3IoYXBwOiBBcHAsIG9uU2VsZWN0OiAoaWNvbklkOiBzdHJpbmcpID0+IHZvaWQpIHtcclxuXHRcdHN1cGVyKGFwcCk7XHJcblx0XHR0aGlzLm9uU2VsZWN0ID0gb25TZWxlY3Q7XHJcblx0fVxyXG5cclxuXHRnZXRJdGVtcygpOiBJY29uT3B0aW9uW10ge1xyXG5cdFx0cmV0dXJuIExVQ0lERV9JQ09OUztcclxuXHR9XHJcblxyXG5cdGdldEl0ZW1UZXh0KGl0ZW06IEljb25PcHRpb24pOiBzdHJpbmcge1xyXG5cdFx0cmV0dXJuIGl0ZW0ubmFtZTtcclxuXHR9XHJcblxyXG5cdG9uQ2hvb3NlSXRlbShpdGVtOiBJY29uT3B0aW9uLCBldnQ6IE1vdXNlRXZlbnQgfCBLZXlib2FyZEV2ZW50KTogdm9pZCB7XHJcblx0XHQvLyBTdGFuZGFyZGl6ZSBpY29uIElEIGJ5IHJlbW92aW5nIGx1Y2lkZS0gcHJlZml4XHJcblx0XHRjb25zdCBub3JtYWxpemVkSWQgPSBpdGVtLmlkLnJlcGxhY2UoL15sdWNpZGUtLywgJycpO1xyXG5cdFx0dGhpcy5vblNlbGVjdChub3JtYWxpemVkSWQpO1xyXG5cdH1cclxuXHJcblx0Ly8gT3ZlcnJpZGUgdG8gc2hvdyBpY29uIHByZXZpZXdcclxuXHRyZW5kZXJTdWdnZXN0aW9uKG1hdGNoOiB7IGl0ZW06IEljb25PcHRpb24gfSwgZWw6IEhUTUxFbGVtZW50KTogdm9pZCB7XHJcblx0XHRjb25zdCBpdGVtID0gbWF0Y2guaXRlbTtcclxuXHRcdGVsLmFkZENsYXNzKCdtb2QtY29tcGxleCcpO1xyXG5cdFx0Y29uc3QgY29udGVudCA9IGVsLmNyZWF0ZURpdih7IGNsczogJ3N1Z2dlc3Rpb24tY29udGVudCcgfSk7XHJcblx0XHRjb250ZW50LmNyZWF0ZURpdih7IGNsczogJ3N1Z2dlc3Rpb24tdGl0bGUnLCB0ZXh0OiBpdGVtLm5hbWUgfSk7XHJcblxyXG5cdFx0Ly8gQ3JlYXRlIGljb24gcHJldmlldyB1c2luZyBPYnNpZGlhbidzIHNldEljb25cclxuXHRcdGNvbnN0IGF1eCA9IGVsLmNyZWF0ZURpdih7IGNsczogJ3N1Z2dlc3Rpb24tYXV4JyB9KTtcclxuXHRcdHNldEljb24oYXV4LmNyZWF0ZVNwYW4oeyBjbHM6ICdzdWdnZXN0aW9uLWZsYWlyJyB9KSwgaXRlbS5pZCk7XHJcblx0fVxyXG59XHJcblxyXG4iLCAiaW1wb3J0IHsgQXBwLCBNb2RhbCB9IGZyb20gXCJvYnNpZGlhblwiO1xyXG5cclxuZXhwb3J0IGNsYXNzIENvbmZpcm1Nb2RhbCBleHRlbmRzIE1vZGFsIHtcclxuXHRyZXN1bHQ6IGJvb2xlYW4gPSBmYWxzZTtcclxuXHRyZXNvbHZlUHJvbWlzZTogKChyZXN1bHQ6IGJvb2xlYW4pID0+IHZvaWQpIHwgbnVsbCA9IG51bGw7XHJcblxyXG5cdGNvbnN0cnVjdG9yKGFwcDogQXBwLCBwcml2YXRlIG1lc3NhZ2U6IHN0cmluZywgcHJpdmF0ZSBjb25maXJtVGV4dDogc3RyaW5nID0gXCJDb25maXJtXCIsIHByaXZhdGUgY2FuY2VsVGV4dDogc3RyaW5nID0gXCJDYW5jZWxcIikge1xyXG5cdFx0c3VwZXIoYXBwKTtcclxuXHR9XHJcblxyXG5cdG9uT3BlbigpIHtcclxuXHRcdGNvbnN0IHsgY29udGVudEVsIH0gPSB0aGlzO1xyXG5cdFx0Y29udGVudEVsLmVtcHR5KCk7XHJcblx0XHRjb250ZW50RWwuYWRkQ2xhc3MoXCJhc3Ryby1jb21wb3Nlci1jb25maXJtLW1vZGFsXCIpO1xyXG5cclxuXHRcdGNvbnRlbnRFbC5jcmVhdGVFbChcInBcIiwgeyB0ZXh0OiB0aGlzLm1lc3NhZ2UgfSk7XHJcblxyXG5cdFx0Y29uc3QgYnV0dG9uQ29udGFpbmVyID0gY29udGVudEVsLmNyZWF0ZURpdih7IGNsczogXCJtb2RhbC1idXR0b24tY29udGFpbmVyXCIgfSk7XHJcblxyXG5cdFx0Y29uc3QgY2FuY2VsQnV0dG9uID0gYnV0dG9uQ29udGFpbmVyLmNyZWF0ZUVsKFwiYnV0dG9uXCIsIHtcclxuXHRcdFx0dGV4dDogdGhpcy5jYW5jZWxUZXh0LFxyXG5cdFx0fSk7XHJcblx0XHRjYW5jZWxCdXR0b24ub25jbGljayA9ICgpID0+IHtcclxuXHRcdFx0dGhpcy5yZXN1bHQgPSBmYWxzZTtcclxuXHRcdFx0dGhpcy5jbG9zZSgpO1xyXG5cdFx0fTtcclxuXHJcblx0XHRjb25zdCBjb25maXJtQnV0dG9uID0gYnV0dG9uQ29udGFpbmVyLmNyZWF0ZUVsKFwiYnV0dG9uXCIsIHtcclxuXHRcdFx0dGV4dDogdGhpcy5jb25maXJtVGV4dCxcclxuXHRcdFx0Y2xzOiBcIm1vZC1jdGEgbW9kLXdhcm5pbmdcIixcclxuXHRcdH0pO1xyXG5cdFx0Y29uZmlybUJ1dHRvbi5vbmNsaWNrID0gKCkgPT4ge1xyXG5cdFx0XHR0aGlzLnJlc3VsdCA9IHRydWU7XHJcblx0XHRcdHRoaXMuY2xvc2UoKTtcclxuXHRcdH07XHJcblx0fVxyXG5cclxuXHRvbkNsb3NlKCkge1xyXG5cdFx0Y29uc3QgeyBjb250ZW50RWwgfSA9IHRoaXM7XHJcblx0XHRjb250ZW50RWwuZW1wdHkoKTtcclxuXHRcdGlmICh0aGlzLnJlc29sdmVQcm9taXNlKSB7XHJcblx0XHRcdHRoaXMucmVzb2x2ZVByb21pc2UodGhpcy5yZXN1bHQpO1xyXG5cdFx0fVxyXG5cdH1cclxuXHJcblx0YXN5bmMgd2FpdEZvclJlc3VsdCgpOiBQcm9taXNlPGJvb2xlYW4+IHtcclxuXHRcdHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4ge1xyXG5cdFx0XHR0aGlzLnJlc29sdmVQcm9taXNlID0gcmVzb2x2ZTtcclxuXHRcdFx0dGhpcy5vcGVuKCk7XHJcblx0XHR9KTtcclxuXHR9XHJcbn1cclxuXHJcbiIsICJpbXBvcnQgeyBURmlsZSwgSGVhZGluZ0NhY2hlLCBBcHAgfSBmcm9tIFwib2JzaWRpYW5cIjtcbmltcG9ydCB7IEFzdHJvQ29tcG9zZXJTZXR0aW5ncywgQXN0cm9Db21wb3NlclBsdWdpbkludGVyZmFjZSB9IGZyb20gXCIuLi90eXBlc1wiO1xuaW1wb3J0IHsgbWF0Y2hlc0ZvbGRlclBhdHRlcm4sIHNvcnRCeVBhdHRlcm5TcGVjaWZpY2l0eSB9IGZyb20gXCIuL3BhdGgtbWF0Y2hpbmdcIjtcbmltcG9ydCB7IHRvS2ViYWJDYXNlIH0gZnJvbSBcIi4vc3RyaW5nLXV0aWxzXCI7XG5cbmV4cG9ydCBjbGFzcyBIZWFkaW5nTGlua0dlbmVyYXRvciB7XG5cdGNvbnN0cnVjdG9yKHByaXZhdGUgc2V0dGluZ3M6IEFzdHJvQ29tcG9zZXJTZXR0aW5ncywgcHJpdmF0ZSBwbHVnaW4/OiBBc3Ryb0NvbXBvc2VyUGx1Z2luSW50ZXJmYWNlKSB7IH1cblxuXHQvLyBHZXQgZnJlc2ggc2V0dGluZ3MgZnJvbSBwbHVnaW4gaWYgYXZhaWxhYmxlLCBvdGhlcndpc2UgdXNlIHN0b3JlZCBzZXR0aW5nc1xuXHRwcml2YXRlIGdldFNldHRpbmdzKCk6IEFzdHJvQ29tcG9zZXJTZXR0aW5ncyB7XG5cdFx0Ly8gQWx3YXlzIHByZWZlciBwbHVnaW4gc2V0dGluZ3MgKHRoZXkncmUga2VwdCB1cCB0byBkYXRlKVxuXHRcdGlmICh0aGlzLnBsdWdpbj8uc2V0dGluZ3MpIHtcblx0XHRcdHJldHVybiB0aGlzLnBsdWdpbi5zZXR0aW5ncztcblx0XHR9XG5cdFx0cmV0dXJuIHRoaXMuc2V0dGluZ3M7XG5cdH1cblxuXHQvKipcblx0ICogQ29udmVydHMgdGV4dCB0byBrZWJhYi1jYXNlIHNsdWcgZm9yIFVSTHNcblx0ICovXG5cdC8vIExvY2FsIHRvS2ViYWJDYXNlIHJlbW92ZWQsIHVzaW5nIGltcG9ydGVkIG9uZSBpbnN0ZWFkXG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIEFzdHJvLWNvbXBhdGlibGUgVVJMIGZyb20gYW4gaW50ZXJuYWwgbGluayAoY29waWVkIGZyb20gTGlua0NvbnZlcnRlcilcblx0ICovXG5cdHByaXZhdGUgZ2V0QXN0cm9VcmxGcm9tSW50ZXJuYWxMaW5rKGxpbms6IHN0cmluZyk6IHN0cmluZyB7XG5cdFx0Y29uc3QgaGFzaEluZGV4ID0gbGluay5pbmRleE9mKCcjJyk7XG5cdFx0bGV0IHBhdGggPSBoYXNoSW5kZXggPj0gMCA/IGxpbmsuc2xpY2UoMCwgaGFzaEluZGV4KSA6IGxpbms7XG5cdFx0Y29uc3QgYW5jaG9yID0gaGFzaEluZGV4ID49IDAgPyBsaW5rLnNsaWNlKGhhc2hJbmRleCkgOiAnJztcblxuXHRcdHBhdGggPSBwYXRoLnJlcGxhY2UoL1xcLm1kJC8sIFwiXCIpO1xuXG5cdFx0Ly8gRGV0ZXJtaW5lIGNvbnRlbnQgdHlwZSBhbmQgYXBwcm9wcmlhdGUgYmFzZSBwYXRoXG5cdFx0bGV0IGJhc2VQYXRoID0gXCJcIjtcblx0XHRsZXQgY29udGVudEZvbGRlciA9IFwiXCI7XG5cdFx0bGV0IGNyZWF0aW9uTW9kZTogXCJmaWxlXCIgfCBcImZvbGRlclwiID0gXCJmaWxlXCI7XG5cdFx0bGV0IGluZGV4RmlsZU5hbWUgPSBcIlwiO1xuXG5cdFx0Ly8gQ2hlY2sgYWxsIGNvbnRlbnQgdHlwZXMsIHNvcnRlZCBieSBwYXR0ZXJuIHNwZWNpZmljaXR5IChtb3JlIHNwZWNpZmljIGZpcnN0KVxuXHRcdGNvbnN0IHNldHRpbmdzID0gdGhpcy5nZXRTZXR0aW5ncygpO1xuXHRcdGNvbnN0IGNvbnRlbnRUeXBlcyA9IHNldHRpbmdzLmNvbnRlbnRUeXBlcyB8fCBbXTtcblx0XHRjb25zdCBzb3J0ZWRUeXBlcyA9IHNvcnRCeVBhdHRlcm5TcGVjaWZpY2l0eShjb250ZW50VHlwZXMpO1xuXG5cdFx0Zm9yIChjb25zdCBjb250ZW50VHlwZSBvZiBzb3J0ZWRUeXBlcykge1xuXHRcdFx0aWYgKCFjb250ZW50VHlwZS5lbmFibGVkKSBjb250aW51ZTtcblxuXHRcdFx0bGV0IG1hdGNoZXMgPSBmYWxzZTtcblxuXHRcdFx0Ly8gSGFuZGxlIGJsYW5rIGZvbGRlciAocm9vdCkgLSBtYXRjaGVzIGZpbGVzIGluIHZhdWx0IHJvb3Qgb25seVxuXHRcdFx0aWYgKCFjb250ZW50VHlwZS5mb2xkZXIgfHwgY29udGVudFR5cGUuZm9sZGVyLnRyaW0oKSA9PT0gXCJcIikge1xuXHRcdFx0XHRpZiAoIXBhdGguaW5jbHVkZXMoXCIvXCIpIHx8IHBhdGguc3BsaXQoXCIvXCIpLmxlbmd0aCA9PT0gMSkge1xuXHRcdFx0XHRcdG1hdGNoZXMgPSB0cnVlO1xuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2UgaWYgKG1hdGNoZXNGb2xkZXJQYXR0ZXJuKHBhdGgsIGNvbnRlbnRUeXBlLmZvbGRlcikpIHtcblx0XHRcdFx0bWF0Y2hlcyA9IHRydWU7XG5cdFx0XHR9XG5cblx0XHRcdGlmIChtYXRjaGVzKSB7XG5cdFx0XHRcdGNvbnRlbnRGb2xkZXIgPSBjb250ZW50VHlwZS5mb2xkZXIgfHwgXCJcIjtcblx0XHRcdFx0YmFzZVBhdGggPSBjb250ZW50VHlwZS5saW5rQmFzZVBhdGggfHwgXCJcIjtcblx0XHRcdFx0Y3JlYXRpb25Nb2RlID0gY29udGVudFR5cGUuY3JlYXRpb25Nb2RlO1xuXHRcdFx0XHRpbmRleEZpbGVOYW1lID0gY29udGVudFR5cGUuaW5kZXhGaWxlTmFtZSB8fCBcIlwiO1xuXHRcdFx0XHRicmVhazsgLy8gTW9zdCBzcGVjaWZpYyBwYXR0ZXJuIHdpbnNcblx0XHRcdH1cblx0XHR9XG5cblx0XHQvLyBTdHJpcCBjb250ZW50IGZvbGRlciBpZiBwcmVzZW50XG5cdFx0aWYgKGNvbnRlbnRGb2xkZXIpIHtcblx0XHRcdHBhdGggPSBwYXRoLnNsaWNlKGNvbnRlbnRGb2xkZXIubGVuZ3RoICsgMSk7XG5cdFx0fVxuXG5cdFx0bGV0IGFkZFRyYWlsaW5nU2xhc2ggPSBmYWxzZTtcblxuXHRcdC8vIFNtYXJ0IGRldGVjdGlvbjogaWYgdGhlIGZpbGVuYW1lIG1hdGNoZXMgdGhlIGluZGV4IGZpbGUgbmFtZSAocmVnYXJkbGVzcyBvZiBjcmVhdGlvbiBtb2RlKSxcblx0XHQvLyB0cmVhdCBpdCBhcyBmb2xkZXItYmFzZWQgbG9naWNcblx0XHQvLyBOb3RlOiBXZSBvbmx5IHNldCBhZGRUcmFpbGluZ1NsYXNoIGhlcmU7IHRoZSBmaW5hbCBjaGVjayB3aWxsIHByZXZlbnQgaXQgaWYgdGhlcmUncyBhbiBhbmNob3Jcblx0XHRpZiAoaW5kZXhGaWxlTmFtZSAmJiBpbmRleEZpbGVOYW1lLnRyaW0oKSAhPT0gXCJcIikge1xuXHRcdFx0Y29uc3QgcGFydHMgPSBwYXRoLnNwbGl0KCcvJyk7XG5cdFx0XHRpZiAocGFydHNbcGFydHMubGVuZ3RoIC0gMV0gPT09IGluZGV4RmlsZU5hbWUpIHtcblx0XHRcdFx0cGFydHMucG9wKCk7XG5cdFx0XHRcdHBhdGggPSBwYXJ0cy5qb2luKCcvJyk7XG5cdFx0XHRcdGFkZFRyYWlsaW5nU2xhc2ggPSB0cnVlO1xuXHRcdFx0fVxuXHRcdH0gZWxzZSBpZiAoY3JlYXRpb25Nb2RlID09PSBcImZvbGRlclwiKSB7XG5cdFx0XHQvLyBGYWxsYmFjayB0byBvcmlnaW5hbCBsb2dpYyBpZiBubyBpbmRleCBmaWxlIG5hbWUgaXMgc3BlY2lmaWVkXG5cdFx0XHQvLyBEZWZhdWx0IHRvIFwiaW5kZXhcIiB3aGVuIGluZGV4RmlsZU5hbWUgaXMgYmxhbmtcblx0XHRcdGNvbnN0IGRlZmF1bHRJbmRleE5hbWUgPSBcImluZGV4XCI7XG5cdFx0XHRjb25zdCBwYXJ0cyA9IHBhdGguc3BsaXQoJy8nKTtcblx0XHRcdGlmIChwYXJ0c1twYXJ0cy5sZW5ndGggLSAxXSA9PT0gZGVmYXVsdEluZGV4TmFtZSkge1xuXHRcdFx0XHRwYXJ0cy5wb3AoKTtcblx0XHRcdFx0cGF0aCA9IHBhcnRzLmpvaW4oJy8nKTtcblx0XHRcdFx0YWRkVHJhaWxpbmdTbGFzaCA9IHRydWU7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Y29uc3Qgc2x1Z1BhcnRzID0gcGF0aC5zcGxpdCgnLycpLm1hcChwYXJ0ID0+IHRvS2ViYWJDYXNlKHBhcnQpKTtcblx0XHRjb25zdCBzbHVnID0gc2x1Z1BhcnRzLmpvaW4oJy8nKTtcblxuXHRcdC8vIEZvcm1hdCBiYXNlIHBhdGhcblx0XHRpZiAoYmFzZVBhdGgpIHtcblx0XHRcdGlmICghYmFzZVBhdGguc3RhcnRzV2l0aChcIi9cIikpIGJhc2VQYXRoID0gXCIvXCIgKyBiYXNlUGF0aDtcblx0XHRcdGlmICghYmFzZVBhdGguZW5kc1dpdGgoXCIvXCIpKSBiYXNlUGF0aCArPSBcIi9cIjtcblx0XHR9XG5cblx0XHQvLyBEZXRlcm1pbmUgaWYgd2Ugc2hvdWxkIGFkZCB0cmFpbGluZyBzbGFzaFxuXHRcdC8vIENSSVRJQ0FMOiBOZXZlciBhZGQgdHJhaWxpbmcgc2xhc2ggYmVmb3JlIGFuIGFuY2hvciAoZS5nLiwgL2Fib3V0I2hlYWRpbmcgbm90IC9hYm91dC8jaGVhZGluZylcblx0XHQvLyBUaGlzIGlzIGVzcGVjaWFsbHkgaW1wb3J0YW50IGZvciBhbmNob3IgbGlua3MgZnJvbSBjb3B5IGhlYWRpbmcgVVJMIGZ1bmN0aW9uYWxpdHlcblx0XHQvLyBBbmNob3IgbGlua3Mgc2hvdWxkIE5FVkVSIGhhdmUgdHJhaWxpbmcgc2xhc2hlcywgcmVnYXJkbGVzcyBvZiBzZXR0aW5nc1xuXHRcdGNvbnN0IHNob3VsZEFkZFRyYWlsaW5nU2xhc2ggPSAoc2V0dGluZ3MuYWRkVHJhaWxpbmdTbGFzaFRvTGlua3MgfHwgYWRkVHJhaWxpbmdTbGFzaCkgJiYgIWFuY2hvcjtcblxuXHRcdHJldHVybiBgJHtiYXNlUGF0aH0ke3NsdWd9JHtzaG91bGRBZGRUcmFpbGluZ1NsYXNoID8gJy8nIDogJyd9JHthbmNob3J9YDtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZW5lcmF0ZXMgYSBzdGFuZGFyZCBPYnNpZGlhbiBsaW5rIHRvIGEgaGVhZGluZywgcmVzcGVjdGluZyB1c2VyJ3MgbGluayBmb3JtYXQgcHJlZmVyZW5jZVxuXHQgKi9cblx0Z2VuZXJhdGVPYnNpZGlhbkxpbmsoYXBwOiBBcHAsIGZpbGU6IFRGaWxlLCBoZWFkaW5nOiBIZWFkaW5nQ2FjaGUpOiBzdHJpbmcge1xuXHRcdGNvbnN0IGhlYWRpbmdUZXh0ID0gaGVhZGluZy5oZWFkaW5nO1xuXG5cdFx0Ly8gQ2hlY2sgaWYgdXNlciBwcmVmZXJzIHdpa2lsaW5rcyBieSB0ZXN0aW5nIE9ic2lkaWFuJ3MgZGVmYXVsdCBiZWhhdmlvclxuXHRcdGNvbnN0IHRlc3RMaW5rID0gYXBwLmZpbGVNYW5hZ2VyLmdlbmVyYXRlTWFya2Rvd25MaW5rKGZpbGUsICcnLCAnJyk7XG5cdFx0aWYgKHRlc3RMaW5rLnN0YXJ0c1dpdGgoJ1tbJykpIHtcblx0XHRcdC8vIFVzZXIgcHJlZmVycyB3aWtpbGlua3MgLSB1c2UganVzdCB0aGUgZmlsZW5hbWUgKGJhc2VuYW1lKSB3aXRob3V0IHBhdGhcblx0XHRcdGNvbnN0IGZpbGVOYW1lID0gZmlsZS5iYXNlbmFtZTtcblx0XHRcdHJldHVybiBgW1ske2ZpbGVOYW1lfSMke2hlYWRpbmdUZXh0fXwke2hlYWRpbmdUZXh0fV1dYDtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Ly8gVXNlciBwcmVmZXJzIG1hcmtkb3duIGxpbmtzIC0gdXNlIE9ic2lkaWFuJ3MgbWV0aG9kIHdpdGggaGVhZGluZyB0ZXh0IGFzLWlzIChVUkwtZW5jb2RlZClcblx0XHRcdC8vIEdldCB0aGUgYmFzZSBsaW5rIGZyb20gT2JzaWRpYW4gKHJlc3BlY3RzIHVzZXIncyBwYXRoIHNldHRpbmdzKVxuXHRcdFx0Y29uc3QgYmFzZUxpbmsgPSBhcHAuZmlsZU1hbmFnZXIuZ2VuZXJhdGVNYXJrZG93bkxpbmsoZmlsZSwgJycsICcnKTtcblx0XHRcdC8vIEV4dHJhY3QgdGhlIHBhdGggcGFydCBhbmQgYWRkIG91ciBhbmNob3Igd2l0aCBwcm9wZXIgZGlzcGxheSB0ZXh0XG5cdFx0XHRpZiAoYmFzZUxpbmsuc3RhcnRzV2l0aCgnW1snKSkge1xuXHRcdFx0XHQvLyBUaGlzIHNob3VsZG4ndCBoYXBwZW4gc2luY2Ugd2UncmUgaW4gdGhlIG1hcmtkb3duIGJyYW5jaCwgYnV0IGp1c3QgaW4gY2FzZVxuXHRcdFx0XHRjb25zdCBmaWxlTmFtZSA9IGZpbGUuYmFzZW5hbWU7XG5cdFx0XHRcdHJldHVybiBgW1ske2ZpbGVOYW1lfSMke2hlYWRpbmdUZXh0fXwke2hlYWRpbmdUZXh0fV1dYDtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdC8vIEV4dHJhY3QgdGhlIHBhdGggZnJvbSB0aGUgZ2VuZXJhdGVkIGxpbmsgYW5kIHJlY29uc3RydWN0IHdpdGggcHJvcGVyIGRpc3BsYXkgdGV4dFxuXHRcdFx0XHRjb25zdCBtYXRjaCA9IGJhc2VMaW5rLm1hdGNoKC9cXFsoW15cXF1dKylcXF1cXCgoW14pXSspXFwpLyk7XG5cdFx0XHRcdGlmIChtYXRjaCkge1xuXHRcdFx0XHRcdGNvbnN0IFssICwgcGF0aF0gPSBtYXRjaDtcblx0XHRcdFx0XHQvLyBGb3IgT2JzaWRpYW4sIHVzZSB0aGUgaGVhZGluZyB0ZXh0IGFzLWlzIChVUkwtZW5jb2RlZCksIG5vdCBrZWJhYi1jYXNlXG5cdFx0XHRcdFx0cmV0dXJuIGBbJHtoZWFkaW5nVGV4dH1dKCR7cGF0aH0jJHtlbmNvZGVVUklDb21wb25lbnQoaGVhZGluZ1RleHQpfSlgO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdC8vIEZhbGxiYWNrIHRvIG1hbnVhbCBjb25zdHJ1Y3Rpb25cblx0XHRcdFx0XHRjb25zdCBlbmNvZGVkRmlsZW5hbWUgPSBlbmNvZGVVUklDb21wb25lbnQoZmlsZS5uYW1lKTtcblx0XHRcdFx0XHQvLyBGb3IgT2JzaWRpYW4sIHVzZSB0aGUgaGVhZGluZyB0ZXh0IGFzLWlzIChVUkwtZW5jb2RlZClcblx0XHRcdFx0XHRyZXR1cm4gYFske2hlYWRpbmdUZXh0fV0oJHtlbmNvZGVkRmlsZW5hbWV9IyR7ZW5jb2RlVVJJQ29tcG9uZW50KGhlYWRpbmdUZXh0KX0pYDtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBHZW5lcmF0ZXMgYSBzdGFuZGFyZCBPYnNpZGlhbiB3aWtpbGluayB0byBhIGhlYWRpbmdcblx0ICovXG5cdGdlbmVyYXRlT2JzaWRpYW5XaWtpbGluayhmaWxlOiBURmlsZSwgaGVhZGluZzogSGVhZGluZ0NhY2hlKTogc3RyaW5nIHtcblx0XHRjb25zdCBoZWFkaW5nVGV4dCA9IGhlYWRpbmcuaGVhZGluZztcblx0XHQvLyBVc2UganVzdCB0aGUgZmlsZW5hbWUgKGJhc2VuYW1lKSwgbm90IHRoZSBmdWxsIHBhdGhcblx0XHRjb25zdCBmaWxlTmFtZSA9IGZpbGUuYmFzZW5hbWU7XG5cdFx0cmV0dXJuIGBbWyR7ZmlsZU5hbWV9IyR7aGVhZGluZ1RleHR9fCR7aGVhZGluZ1RleHR9XV1gO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdlbmVyYXRlcyBhbiBBc3Ryby1jb21wYXRpYmxlIG1hcmtkb3duIGxpbmsgdG8gYSBoZWFkaW5nXG5cdCAqL1xuXHRnZW5lcmF0ZUFzdHJvTGluayhmaWxlOiBURmlsZSwgaGVhZGluZzogSGVhZGluZ0NhY2hlKTogc3RyaW5nIHtcblx0XHRjb25zdCBoZWFkaW5nVGV4dCA9IGhlYWRpbmcuaGVhZGluZztcblx0XHRjb25zdCBhbmNob3IgPSB0b0tlYmFiQ2FzZShoZWFkaW5nVGV4dCk7XG5cdFx0Ly8gVXNlIHRoZSBzYW1lIGxvZ2ljIGFzIHRoZSBleGlzdGluZyBsaW5rIGNvbnZlcnRlclxuXHRcdGNvbnN0IGludGVybmFsTGluayA9IGAke2ZpbGUucGF0aH0jJHthbmNob3J9YDtcblx0XHRjb25zdCBhc3Ryb1VybCA9IHRoaXMuZ2V0QXN0cm9VcmxGcm9tSW50ZXJuYWxMaW5rKGludGVybmFsTGluayk7XG5cdFx0cmV0dXJuIGBbJHtoZWFkaW5nVGV4dH1dKCR7YXN0cm9Vcmx9KWA7XG5cdH1cblxuXHQvKipcblx0ICogR2VuZXJhdGVzIGFuIEFzdHJvLWNvbXBhdGlibGUgd2lraWxpbmsgdG8gYSBoZWFkaW5nXG5cdCAqL1xuXHRnZW5lcmF0ZUFzdHJvV2lraWxpbmsoZmlsZTogVEZpbGUsIGhlYWRpbmc6IEhlYWRpbmdDYWNoZSk6IHN0cmluZyB7XG5cdFx0Y29uc3QgaGVhZGluZ1RleHQgPSBoZWFkaW5nLmhlYWRpbmc7XG5cdFx0Y29uc3QgYW5jaG9yID0gdG9LZWJhYkNhc2UoaGVhZGluZ1RleHQpO1xuXHRcdC8vIFVzZSB0aGUgc2FtZSBsb2dpYyBhcyB0aGUgZXhpc3RpbmcgbGluayBjb252ZXJ0ZXJcblx0XHRjb25zdCBpbnRlcm5hbExpbmsgPSBgJHtmaWxlLnBhdGh9IyR7YW5jaG9yfWA7XG5cdFx0Y29uc3QgYXN0cm9VcmwgPSB0aGlzLmdldEFzdHJvVXJsRnJvbUludGVybmFsTGluayhpbnRlcm5hbExpbmspO1xuXHRcdC8vIENyZWF0ZSBhIHdpa2lsaW5rIHdpdGggdGhlIEFzdHJvIFVSTCBhcyB0aGUgdGFyZ2V0XG5cdFx0cmV0dXJuIGBbWyR7aGVhZGluZ1RleHR9fCR7YXN0cm9Vcmx9XV1gO1xuXHR9XG5cblx0LyoqXG5cdCAqIEV4dHJhY3RzIHRoZSBVUkwgZnJvbSBhIG1hcmtkb3duIGxpbmsgb3Igd2lraWxpbmtcblx0ICovXG5cdGV4dHJhY3RVcmwobGluazogc3RyaW5nKTogc3RyaW5nIHtcblx0XHQvLyBIYW5kbGUgbWFya2Rvd24gbGlua3M6IFt0ZXh0XSh1cmwpXG5cdFx0Y29uc3QgbWFya2Rvd25NYXRjaCA9IGxpbmsubWF0Y2goL1xcWyhbXlxcXV0rKVxcXVxcKChbXildKylcXCkvKTtcblx0XHRpZiAobWFya2Rvd25NYXRjaCkge1xuXHRcdFx0cmV0dXJuIG1hcmtkb3duTWF0Y2hbMl07XG5cdFx0fVxuXG5cdFx0Ly8gSGFuZGxlIHdpa2lsaW5rczogW1twYXRoI2hlYWRpbmd8dGV4dF1dIG9yIFtbcGF0aCNoZWFkaW5nXV1cblx0XHRjb25zdCB3aWtpbGlua01hdGNoID0gbGluay5tYXRjaCgvXFxbXFxbKFteXFxdXSspXFxdXFxdLyk7XG5cdFx0aWYgKHdpa2lsaW5rTWF0Y2gpIHtcblx0XHRcdGNvbnN0IGNvbnRlbnQgPSB3aWtpbGlua01hdGNoWzFdO1xuXHRcdFx0Ly8gRXh0cmFjdCB0aGUgcGF0aCBwYXJ0IChiZWZvcmUgfCBpZiBwcmVzZW50KVxuXHRcdFx0Y29uc3QgcGF0aFBhcnQgPSBjb250ZW50LnNwbGl0KCd8JylbMF07XG5cdFx0XHRyZXR1cm4gcGF0aFBhcnQ7XG5cdFx0fVxuXG5cdFx0Ly8gSWYgaXQgZG9lc24ndCBtYXRjaCBlaXRoZXIgZm9ybWF0LCByZXR1cm4gYXMtaXMgKG1pZ2h0IGFscmVhZHkgYmUgYSBVUkwpXG5cdFx0cmV0dXJuIGxpbms7XG5cdH1cblxuXHQvKipcblx0ICogR2VuZXJhdGVzIHRoZSBhcHByb3ByaWF0ZSBsaW5rIGZvcm1hdCBiYXNlZCBvbiBzZXR0aW5nc1xuXHQgKi9cblx0Z2VuZXJhdGVMaW5rKGFwcDogQXBwLCBmaWxlOiBURmlsZSwgaGVhZGluZzogSGVhZGluZ0NhY2hlKTogc3RyaW5nIHtcblx0XHRjb25zdCBzZXR0aW5ncyA9IHRoaXMuZ2V0U2V0dGluZ3MoKTtcblx0XHRpZiAoc2V0dGluZ3MuY29weUhlYWRpbmdMaW5rRm9ybWF0ID09PSBcImFzdHJvXCIpIHtcblx0XHRcdC8vIEFzdHJvIGZvcm1hdCBhbHdheXMgdXNlcyBtYXJrZG93biBsaW5rcyAod2lraWxpbmtzIHdpdGggQXN0cm8gVVJMcyBkb24ndCBtYWtlIHNlbnNlKVxuXHRcdFx0cmV0dXJuIHRoaXMuZ2VuZXJhdGVBc3Ryb0xpbmsoZmlsZSwgaGVhZGluZyk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdC8vIFVzZSBPYnNpZGlhbidzIGJ1aWx0LWluIG1ldGhvZCB3aGljaCByZXNwZWN0cyB1c2VyIHNldHRpbmdzXG5cdFx0XHRyZXR1cm4gdGhpcy5nZW5lcmF0ZU9ic2lkaWFuTGluayhhcHAsIGZpbGUsIGhlYWRpbmcpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBGaW5kcyB0aGUgaGVhZGluZyBhdCBhIHNwZWNpZmljIGxpbmUgaW4gYSBmaWxlXG5cdCAqL1xuXHRmaW5kSGVhZGluZ0F0TGluZShhcHA6IEFwcCwgZmlsZTogVEZpbGUsIGxpbmU6IG51bWJlcik6IEhlYWRpbmdDYWNoZSB8IG51bGwge1xuXHRcdGNvbnN0IGNhY2hlID0gYXBwLm1ldGFkYXRhQ2FjaGUuZ2V0RmlsZUNhY2hlKGZpbGUpO1xuXHRcdGlmICghY2FjaGUgfHwgIWNhY2hlLmhlYWRpbmdzKSB7XG5cdFx0XHRyZXR1cm4gbnVsbDtcblx0XHR9XG5cblx0XHQvLyBGaW5kIHRoZSBoZWFkaW5nIHRoYXQgY29udGFpbnMgdGhpcyBsaW5lXG5cdFx0Zm9yIChsZXQgaSA9IGNhY2hlLmhlYWRpbmdzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG5cdFx0XHRjb25zdCBoZWFkaW5nID0gY2FjaGUuaGVhZGluZ3NbaV07XG5cdFx0XHRpZiAoaGVhZGluZy5wb3NpdGlvbi5zdGFydC5saW5lIDw9IGxpbmUpIHtcblx0XHRcdFx0cmV0dXJuIGhlYWRpbmc7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0cmV0dXJuIG51bGw7XG5cdH1cbn1cbiIsICJpbXBvcnQgeyBBcHAsIE5vdGljZSB9IGZyb20gXCJvYnNpZGlhblwiO1xyXG5pbXBvcnQgeyBDb250ZW50VHlwZSwgQXN0cm9Db21wb3NlclBsdWdpbkludGVyZmFjZSB9IGZyb20gXCIuLi90eXBlc1wiO1xyXG5pbXBvcnQgeyBNaWdyYXRpb25Nb2RhbCwgTWlncmF0aW9uQ29uZmxpY3RSZXN1bHQgfSBmcm9tIFwiLi4vdWkvY29tcG9uZW50cy9NaWdyYXRpb25Nb2RhbFwiO1xyXG5pbXBvcnQgeyBBc3Ryb0NvbXBvc2VyU2V0dGluZ1RhYiB9IGZyb20gXCIuLi91aS9zZXR0aW5ncy10YWJcIjtcclxuXHJcbmV4cG9ydCBjbGFzcyBNaWdyYXRpb25TZXJ2aWNlIHtcclxuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgYXBwOiBBcHAsIHByaXZhdGUgcGx1Z2luOiBBc3Ryb0NvbXBvc2VyUGx1Z2luSW50ZXJmYWNlKSB7IH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIE1pZ3JhdGUgb2xkIHBvc3RzL3BhZ2VzIHNldHRpbmdzIHRvIHVuaWZpZWQgY29udGVudCB0eXBlc1xyXG4gICAgICovXHJcbiAgICBwdWJsaWMgYXN5bmMgbWlncmF0ZVNldHRpbmdzSWZOZWVkZWQoKTogUHJvbWlzZTx2b2lkPiB7XHJcbiAgICAgICAgY29uc3Qgc2V0dGluZ3MgPSB0aGlzLnBsdWdpbi5zZXR0aW5ncztcclxuXHJcbiAgICAgICAgLy8gQ2hlY2sgaWYgbWlncmF0aW9uIGlzIGFscmVhZHkgY29tcGxldGVkXHJcbiAgICAgICAgaWYgKHNldHRpbmdzLm1pZ3JhdGlvbkNvbXBsZXRlZCkge1xyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyBDaGVjayBpZiB0aGVyZSBhcmUgb2xkIHNldHRpbmdzIHRvIG1pZ3JhdGVcclxuICAgICAgICBjb25zdCBoYXNQb3N0c1NldHRpbmdzID0gc2V0dGluZ3MuYXV0b21hdGVQb3N0Q3JlYXRpb24gIT09IHVuZGVmaW5lZCAmJiBzZXR0aW5ncy5hdXRvbWF0ZVBvc3RDcmVhdGlvbjtcclxuICAgICAgICBjb25zdCBoYXNQYWdlc1NldHRpbmdzID0gc2V0dGluZ3MuZW5hYmxlUGFnZXMgIT09IHVuZGVmaW5lZCAmJiBzZXR0aW5ncy5lbmFibGVQYWdlcztcclxuXHJcbiAgICAgICAgaWYgKCFoYXNQb3N0c1NldHRpbmdzICYmICFoYXNQYWdlc1NldHRpbmdzKSB7XHJcbiAgICAgICAgICAgIC8vIE5vIG9sZCBzZXR0aW5ncyB0byBtaWdyYXRlLCBtYXJrIGFzIGNvbXBsZXRlZFxyXG4gICAgICAgICAgICBzZXR0aW5ncy5taWdyYXRpb25Db21wbGV0ZWQgPSB0cnVlO1xyXG4gICAgICAgICAgICBhd2FpdCB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKTtcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gQ2hlY2sgZm9yIG5hbWluZyBjb25mbGljdHNcclxuICAgICAgICBjb25zdCBsZWdhY3lDb250ZW50VHlwZXMgPSAoc2V0dGluZ3MgYXMgdW5rbm93biBhcyB7IGN1c3RvbUNvbnRlbnRUeXBlcz86IENvbnRlbnRUeXBlW10gfSkuY3VzdG9tQ29udGVudFR5cGVzO1xyXG4gICAgICAgIGNvbnN0IGV4aXN0aW5nQ29udGVudFR5cGVzID0gc2V0dGluZ3MuY29udGVudFR5cGVzIHx8IGxlZ2FjeUNvbnRlbnRUeXBlcyB8fCBbXTtcclxuICAgICAgICBjb25zdCBjb25mbGljdHM6IHN0cmluZ1tdID0gW107XHJcbiAgICAgICAgaWYgKGV4aXN0aW5nQ29udGVudFR5cGVzLnNvbWUoKGN0OiBDb250ZW50VHlwZSkgPT4gY3QubmFtZSA9PT0gXCJQb3N0c1wiKSkge1xyXG4gICAgICAgICAgICBjb25mbGljdHMucHVzaChcIlBvc3RzXCIpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAoZXhpc3RpbmdDb250ZW50VHlwZXMuc29tZSgoY3Q6IENvbnRlbnRUeXBlKSA9PiBjdC5uYW1lID09PSBcIlBhZ2VzXCIpKSB7XHJcbiAgICAgICAgICAgIGNvbmZsaWN0cy5wdXNoKFwiUGFnZXNcIik7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBsZXQgc2hvdWxkTWlncmF0ZSA9IHRydWU7XHJcblxyXG4gICAgICAgIC8vIElmIGNvbmZsaWN0cyBleGlzdCwgcHJvbXB0IHVzZXJcclxuICAgICAgICBpZiAoY29uZmxpY3RzLmxlbmd0aCA+IDApIHtcclxuICAgICAgICAgICAgYXdhaXQgbmV3IFByb21pc2U8dm9pZD4oKHJlc29sdmUpID0+IHtcclxuICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgIHZvaWQgKGFzeW5jICgpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1vZGFsID0gbmV3IE1pZ3JhdGlvbk1vZGFsKHRoaXMuYXBwLCBjb25mbGljdHMpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdGltZW91dFByb21pc2UgPSBuZXcgUHJvbWlzZTxNaWdyYXRpb25Db25mbGljdFJlc3VsdD4oKHRpbWVvdXRSZXNvbHZlKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRpbWVvdXRSZXNvbHZlKHsgYWN0aW9uOiBcInNraXBcIiB9KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LCAzMDAwMCk7IC8vIDMwIHNlY29uZCB0aW1lb3V0XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBQcm9taXNlLnJhY2UoW1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1vZGFsLndhaXRGb3JSZXN1bHQoKSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aW1lb3V0UHJvbWlzZVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXSk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJlc3VsdC5hY3Rpb24gPT09IFwic2tpcFwiKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2hvdWxkTWlncmF0ZSA9IGZhbHNlO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ldyBOb3RpY2UoXCJNaWdyYXRpb24gc2tpcHBlZC4gT2xkIHBvc3RzL3BhZ2VzIHNldHRpbmdzIHdpbGwgYmUgaWdub3JlZC5cIik7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oXCJNaWdyYXRpb24gbW9kYWwgZXJyb3I6XCIsIGVycm9yKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNob3VsZE1pZ3JhdGUgPSBmYWxzZTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ldyBOb3RpY2UoXCJNaWdyYXRpb24gc2tpcHBlZCBkdWUgdG8gZXJyb3IuIFlvdSBjYW4gbWlncmF0ZSBtYW51YWxseSBpbiBzZXR0aW5ncy5cIik7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xyXG4gICAgICAgICAgICAgICAgICAgIH0pKCk7XHJcbiAgICAgICAgICAgICAgICB9LCA1MDApOyAvLyBTbWFsbCBkZWxheSB0byBlbnN1cmUgVUkgaXMgcmVhZHlcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAoIXNob3VsZE1pZ3JhdGUpIHtcclxuICAgICAgICAgICAgc2V0dGluZ3MubWlncmF0aW9uQ29tcGxldGVkID0gdHJ1ZTtcclxuICAgICAgICAgICAgYXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIFBlcmZvcm0gbWlncmF0aW9uXHJcbiAgICAgICAgY29uc3QgbWlncmF0ZWRUeXBlczogQ29udGVudFR5cGVbXSA9IFtdO1xyXG5cclxuICAgICAgICAvLyBNaWdyYXRlIFBvc3RzXHJcbiAgICAgICAgaWYgKGhhc1Bvc3RzU2V0dGluZ3MgJiYgIWNvbmZsaWN0cy5pbmNsdWRlcyhcIlBvc3RzXCIpKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IHBvc3RzVHlwZTogQ29udGVudFR5cGUgPSB7XHJcbiAgICAgICAgICAgICAgICBpZDogYHBvc3RzLSR7RGF0ZS5ub3coKX1gLFxyXG4gICAgICAgICAgICAgICAgbmFtZTogXCJQb3N0c1wiLFxyXG4gICAgICAgICAgICAgICAgZm9sZGVyOiBzZXR0aW5ncy5wb3N0c0ZvbGRlciB8fCBcIlwiLFxyXG4gICAgICAgICAgICAgICAgbGlua0Jhc2VQYXRoOiBzZXR0aW5ncy5wb3N0c0xpbmtCYXNlUGF0aCB8fCBcIlwiLFxyXG4gICAgICAgICAgICAgICAgdGVtcGxhdGU6IHNldHRpbmdzLmRlZmF1bHRUZW1wbGF0ZSB8fCAnLS0tXFxudGl0bGU6IFwie3t0aXRsZX19XCJcXG5kYXRlOiB7e2RhdGV9fVxcbnRhZ3M6IFtdXFxuLS0tXFxuJyxcclxuICAgICAgICAgICAgICAgIGVuYWJsZWQ6IHRydWUsXHJcbiAgICAgICAgICAgICAgICBjcmVhdGlvbk1vZGU6IHNldHRpbmdzLmNyZWF0aW9uTW9kZSB8fCBcImZpbGVcIixcclxuICAgICAgICAgICAgICAgIGluZGV4RmlsZU5hbWU6IHNldHRpbmdzLmluZGV4RmlsZU5hbWUgfHwgXCJcIixcclxuICAgICAgICAgICAgICAgIGlnbm9yZVN1YmZvbGRlcnM6IHNldHRpbmdzLm9ubHlBdXRvbWF0ZUluUG9zdHNGb2xkZXIgfHwgZmFsc2UsXHJcbiAgICAgICAgICAgICAgICBlbmFibGVVbmRlcnNjb3JlUHJlZml4OiBzZXR0aW5ncy5lbmFibGVVbmRlcnNjb3JlUHJlZml4IHx8IGZhbHNlLFxyXG4gICAgICAgICAgICAgICAgdXNlTWR4RXh0ZW5zaW9uOiBmYWxzZSxcclxuICAgICAgICAgICAgICAgIG1vZGlmaWVkRGF0ZUZpZWxkOiBcIlwiLFxyXG4gICAgICAgICAgICB9O1xyXG4gICAgICAgICAgICBtaWdyYXRlZFR5cGVzLnB1c2gocG9zdHNUeXBlKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIE1pZ3JhdGUgUGFnZXNcclxuICAgICAgICBpZiAoaGFzUGFnZXNTZXR0aW5ncyAmJiAhY29uZmxpY3RzLmluY2x1ZGVzKFwiUGFnZXNcIikpIHtcclxuICAgICAgICAgICAgY29uc3QgcGFnZXNUeXBlOiBDb250ZW50VHlwZSA9IHtcclxuICAgICAgICAgICAgICAgIGlkOiBgcGFnZXMtJHtEYXRlLm5vdygpfWAsXHJcbiAgICAgICAgICAgICAgICBuYW1lOiBcIlBhZ2VzXCIsXHJcbiAgICAgICAgICAgICAgICBmb2xkZXI6IHNldHRpbmdzLnBhZ2VzRm9sZGVyIHx8IFwiXCIsXHJcbiAgICAgICAgICAgICAgICBsaW5rQmFzZVBhdGg6IHNldHRpbmdzLnBhZ2VzTGlua0Jhc2VQYXRoIHx8IFwiXCIsXHJcbiAgICAgICAgICAgICAgICB0ZW1wbGF0ZTogc2V0dGluZ3MucGFnZVRlbXBsYXRlIHx8ICctLS1cXG50aXRsZTogXCJ7e3RpdGxlfX1cIlxcbmRlc2NyaXB0aW9uOiBcIlwiXFxuLS0tXFxuJyxcclxuICAgICAgICAgICAgICAgIGVuYWJsZWQ6IHRydWUsXHJcbiAgICAgICAgICAgICAgICBjcmVhdGlvbk1vZGU6IHNldHRpbmdzLnBhZ2VzQ3JlYXRpb25Nb2RlIHx8IFwiZmlsZVwiLFxyXG4gICAgICAgICAgICAgICAgaW5kZXhGaWxlTmFtZTogc2V0dGluZ3MucGFnZXNJbmRleEZpbGVOYW1lIHx8IFwiXCIsXHJcbiAgICAgICAgICAgICAgICBpZ25vcmVTdWJmb2xkZXJzOiBzZXR0aW5ncy5vbmx5QXV0b21hdGVJblBhZ2VzRm9sZGVyIHx8IGZhbHNlLFxyXG4gICAgICAgICAgICAgICAgZW5hYmxlVW5kZXJzY29yZVByZWZpeDogZmFsc2UsXHJcbiAgICAgICAgICAgICAgICB1c2VNZHhFeHRlbnNpb246IGZhbHNlLFxyXG4gICAgICAgICAgICAgICAgbW9kaWZpZWREYXRlRmllbGQ6IFwiXCIsXHJcbiAgICAgICAgICAgIH07XHJcbiAgICAgICAgICAgIG1pZ3JhdGVkVHlwZXMucHVzaChwYWdlc1R5cGUpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgY29uc3QgZXhpc3RpbmdGcm9tTmV3ID0gc2V0dGluZ3MuY29udGVudFR5cGVzIHx8IFtdO1xyXG4gICAgICAgIGNvbnN0IGV4aXN0aW5nRnJvbUxlZ2FjeSA9IGxlZ2FjeUNvbnRlbnRUeXBlcyB8fCBbXTtcclxuXHJcbiAgICAgICAgbGV0IGV4aXN0aW5nVHlwZXM6IENvbnRlbnRUeXBlW10gPSBleGlzdGluZ0Zyb21OZXcubGVuZ3RoID4gMCA/IGV4aXN0aW5nRnJvbU5ldyA6IGV4aXN0aW5nRnJvbUxlZ2FjeTtcclxuICAgICAgICBsZXQgZmluYWxUeXBlczogQ29udGVudFR5cGVbXSA9IFsuLi5leGlzdGluZ1R5cGVzXTtcclxuXHJcbiAgICAgICAgaWYgKG1pZ3JhdGVkVHlwZXMubGVuZ3RoID4gMCkge1xyXG4gICAgICAgICAgICBjb25zdCBleGlzdGluZ05hbWVzID0gbmV3IFNldChleGlzdGluZ1R5cGVzLm1hcChjdCA9PiBjdC5uYW1lKSk7XHJcbiAgICAgICAgICAgIGNvbnN0IG5ld01pZ3JhdGVkVHlwZXMgPSBtaWdyYXRlZFR5cGVzLmZpbHRlcihtdCA9PiAhZXhpc3RpbmdOYW1lcy5oYXMobXQubmFtZSkpO1xyXG5cclxuICAgICAgICAgICAgaWYgKG5ld01pZ3JhdGVkVHlwZXMubGVuZ3RoID4gMCkge1xyXG4gICAgICAgICAgICAgICAgZmluYWxUeXBlcyA9IFsuLi5leGlzdGluZ1R5cGVzLCAuLi5uZXdNaWdyYXRlZFR5cGVzXTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgc2V0dGluZ3MuY29udGVudFR5cGVzID0gZmluYWxUeXBlcztcclxuXHJcbiAgICAgICAgLy8gQ2xlYW4gdXAgbGVnYWN5IGZpZWxkc1xyXG4gICAgICAgIGNvbnN0IGxlZ2FjeUZpZWxkcyA9IFtcclxuICAgICAgICAgICAgJ2N1c3RvbUNvbnRlbnRUeXBlcycsICdlbmFibGVVbmRlcnNjb3JlUHJlZml4JywgJ3Bvc3RzRm9sZGVyJywgJ3Bvc3RzTGlua0Jhc2VQYXRoJyxcclxuICAgICAgICAgICAgJ2F1dG9tYXRlUG9zdENyZWF0aW9uJywgJ2NyZWF0aW9uTW9kZScsICdpbmRleEZpbGVOYW1lJywgJ2V4Y2x1ZGVkRGlyZWN0b3JpZXMnLFxyXG4gICAgICAgICAgICAnb25seUF1dG9tYXRlSW5Qb3N0c0ZvbGRlcicsICdlbmFibGVQYWdlcycsICdwYWdlc0ZvbGRlcicsICdwYWdlc0xpbmtCYXNlUGF0aCcsXHJcbiAgICAgICAgICAgICdwYWdlc0NyZWF0aW9uTW9kZScsICdwYWdlc0luZGV4RmlsZU5hbWUnLCAncGFnZVRlbXBsYXRlJywgJ29ubHlBdXRvbWF0ZUluUGFnZXNGb2xkZXInXHJcbiAgICAgICAgXTtcclxuXHJcbiAgICAgICAgY29uc3Qgc2V0dGluZ3NSZWNvcmQgPSBzZXR0aW5ncyBhcyB1bmtub3duIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xyXG4gICAgICAgIGZvciAoY29uc3QgZmllbGQgb2YgbGVnYWN5RmllbGRzKSB7XHJcbiAgICAgICAgICAgIGRlbGV0ZSBzZXR0aW5nc1JlY29yZFtmaWVsZF07XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBzZXR0aW5ncy5taWdyYXRpb25Db21wbGV0ZWQgPSB0cnVlO1xyXG4gICAgICAgIGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xyXG4gICAgICAgIGF3YWl0IHRoaXMucGx1Z2luLmxvYWRTZXR0aW5ncygpO1xyXG5cclxuICAgICAgICBpZiAobWlncmF0ZWRUeXBlcy5sZW5ndGggPiAwKSB7XHJcbiAgICAgICAgICAgIG5ldyBOb3RpY2UoYE1pZ3JhdGlvbiBjb21wbGV0ZWQ6ICR7bWlncmF0ZWRUeXBlcy5sZW5ndGh9IGNvbnRlbnQgdHlwZShzKSBtaWdyYXRlZC5gKTtcclxuXHJcbiAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMucGx1Z2luLnNldHRpbmdzVGFiIGluc3RhbmNlb2YgQXN0cm9Db21wb3NlclNldHRpbmdUYWIpIHtcclxuICAgICAgICAgICAgICAgICAgICBjb25zdCBzZXR0aW5nc1RhYiA9IHRoaXMucGx1Z2luLnNldHRpbmdzVGFiO1xyXG4gICAgICAgICAgICAgICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzZXR0aW5nc1RhYi5jdXN0b21Db250ZW50VHlwZXNDb250YWluZXIgfHwgc2V0dGluZ3NUYWIuY29udGFpbmVyRWwpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNldHRpbmdzVGFiLmRpc3BsYXkoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS53YXJuKFwiQ291bGQgbm90IHJlZnJlc2ggc2V0dGluZ3MgdGFiIGFmdGVyIG1pZ3JhdGlvbjpcIiwgZSk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9LCAzMDApO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxufVxyXG4iLCAiaW1wb3J0IHsgQXBwLCBNb2RhbCB9IGZyb20gXCJvYnNpZGlhblwiO1xyXG5cclxuZXhwb3J0IGludGVyZmFjZSBNaWdyYXRpb25Db25mbGljdFJlc3VsdCB7XHJcblx0YWN0aW9uOiBcInNraXBcIiB8IFwibWlncmF0ZVwiO1xyXG59XHJcblxyXG5leHBvcnQgY2xhc3MgTWlncmF0aW9uTW9kYWwgZXh0ZW5kcyBNb2RhbCB7XHJcblx0cmVzdWx0OiBNaWdyYXRpb25Db25mbGljdFJlc3VsdCB8IG51bGwgPSBudWxsO1xyXG5cdHJlc29sdmVQcm9taXNlOiAoKHJlc3VsdDogTWlncmF0aW9uQ29uZmxpY3RSZXN1bHQpID0+IHZvaWQpIHwgbnVsbCA9IG51bGw7XHJcblxyXG5cdGNvbnN0cnVjdG9yKGFwcDogQXBwLCBjb25mbGljdHM6IHN0cmluZ1tdKSB7XHJcblx0XHRzdXBlcihhcHApO1xyXG5cdH1cclxuXHJcblx0b25PcGVuKCkge1xyXG5cdFx0Y29uc3QgeyBjb250ZW50RWwgfSA9IHRoaXM7XHJcblx0XHRjb250ZW50RWwuZW1wdHkoKTtcclxuXHRcdGNvbnRlbnRFbC5hZGRDbGFzcyhcImFzdHJvLWNvbXBvc2VyLW1pZ3JhdGlvbi1tb2RhbFwiKTtcclxuXHJcblx0XHRjb250ZW50RWwuY3JlYXRlRWwoXCJoMlwiLCB7IHRleHQ6IFwiTWlncmF0aW9uIGNvbmZsaWN0IGRldGVjdGVkXCIgfSk7XHJcblxyXG5cdFx0Y29udGVudEVsLmNyZWF0ZUVsKFwicFwiLCB7XHJcblx0XHRcdHRleHQ6IFwiWW91IGhhdmUgZXhpc3RpbmcgY29udGVudCB0eXBlcyB3aXRoIG5hbWVzIHRoYXQgY29uZmxpY3Qgd2l0aCBwb3N0cyBvciBwYWdlcy4gSG93IHdvdWxkIHlvdSBsaWtlIHRvIHByb2NlZWQ/XCIsXHJcblx0XHR9KTtcclxuXHJcblx0XHRjb25zdCBjb25mbGljdExpc3QgPSBjb250ZW50RWwuY3JlYXRlRWwoXCJ1bFwiKTtcclxuXHRcdGNvbmZsaWN0TGlzdC5jcmVhdGVFbChcImxpXCIsIHsgdGV4dDogXCJTa2lwIG1pZ3JhdGlvbjoga2VlcCB5b3VyIGV4aXN0aW5nIHBvc3RzL3BhZ2VzIHNldHRpbmdzICh0aGV5IHdpbGwgYmUgaWdub3JlZClcIiB9KTtcclxuXHRcdGNvbmZsaWN0TGlzdC5jcmVhdGVFbChcImxpXCIsIHsgdGV4dDogXCJNaWdyYXRlIHdpdGggcmVuYW1lZCB0eXBlczogY3JlYXRlICdwb3N0cyAobWlncmF0ZWQpJyBhbmQgJ3BhZ2VzIChtaWdyYXRlZCknIGNvbnRlbnQgdHlwZXNcIiB9KTtcclxuXHJcblx0XHRjb25zdCBidXR0b25Db250YWluZXIgPSBjb250ZW50RWwuY3JlYXRlRGl2KHsgY2xzOiBcIm1vZGFsLWJ1dHRvbi1jb250YWluZXJcIiB9KTtcclxuXHJcblx0XHRjb25zdCBza2lwQnV0dG9uID0gYnV0dG9uQ29udGFpbmVyLmNyZWF0ZUVsKFwiYnV0dG9uXCIsIHtcclxuXHRcdFx0dGV4dDogXCJTa2lwIG1pZ3JhdGlvblwiLFxyXG5cdFx0XHRjbHM6IFwibW9kLWN0YVwiLFxyXG5cdFx0fSk7XHJcblx0XHRza2lwQnV0dG9uLm9uY2xpY2sgPSAoKSA9PiB7XHJcblx0XHRcdHRoaXMucmVzdWx0ID0geyBhY3Rpb246IFwic2tpcFwiIH07XHJcblx0XHRcdHRoaXMuY2xvc2UoKTtcclxuXHRcdH07XHJcblxyXG5cdFx0Y29uc3QgbWlncmF0ZUJ1dHRvbiA9IGJ1dHRvbkNvbnRhaW5lci5jcmVhdGVFbChcImJ1dHRvblwiLCB7XHJcblx0XHRcdHRleHQ6IFwiTWlncmF0ZSB3aXRoIHJlbmFtZWQgdHlwZXNcIixcclxuXHRcdFx0Y2xzOiBcIm1vZC1jdGFcIixcclxuXHRcdH0pO1xyXG5cdFx0bWlncmF0ZUJ1dHRvbi5vbmNsaWNrID0gKCkgPT4ge1xyXG5cdFx0XHR0aGlzLnJlc3VsdCA9IHsgYWN0aW9uOiBcIm1pZ3JhdGVcIiB9O1xyXG5cdFx0XHR0aGlzLmNsb3NlKCk7XHJcblx0XHR9O1xyXG5cdH1cclxuXHJcblx0b25DbG9zZSgpIHtcclxuXHRcdGNvbnN0IHsgY29udGVudEVsIH0gPSB0aGlzO1xyXG5cdFx0Y29udGVudEVsLmVtcHR5KCk7XHJcblx0XHRpZiAodGhpcy5yZXNvbHZlUHJvbWlzZSAmJiB0aGlzLnJlc3VsdCkge1xyXG5cdFx0XHR0aGlzLnJlc29sdmVQcm9taXNlKHRoaXMucmVzdWx0KTtcclxuXHRcdH1cclxuXHR9XHJcblxyXG5cdGFzeW5jIHdhaXRGb3JSZXN1bHQoKTogUHJvbWlzZTxNaWdyYXRpb25Db25mbGljdFJlc3VsdD4ge1xyXG5cdFx0cmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB7XHJcblx0XHRcdHRoaXMucmVzb2x2ZVByb21pc2UgPSByZXNvbHZlO1xyXG5cdFx0XHR0aGlzLm9wZW4oKTtcclxuXHRcdH0pO1xyXG5cdH1cclxufVxyXG5cclxuIiwgImltcG9ydCB7IEFwcCwgVEZpbGUsIE5vdGljZSB9IGZyb20gXCJvYnNpZGlhblwiO1xyXG5pbXBvcnQgeyBDb250ZW50VHlwZSwgQXN0cm9Db21wb3NlclBsdWdpbkludGVyZmFjZSB9IGZyb20gXCIuLi90eXBlc1wiO1xyXG5pbXBvcnQgeyBDT05TVEFOVFMgfSBmcm9tIFwiLi4vc2V0dGluZ3NcIjtcclxuaW1wb3J0IHsgbWF0Y2hlc0ZvbGRlclBhdHRlcm4sIHNvcnRCeVBhdHRlcm5TcGVjaWZpY2l0eSB9IGZyb20gXCIuLi91dGlscy9wYXRoLW1hdGNoaW5nXCI7XHJcbmltcG9ydCB7IFRpdGxlTW9kYWwgfSBmcm9tIFwiLi4vdWkvdGl0bGUtbW9kYWxcIjtcclxuXHJcbmV4cG9ydCBjbGFzcyBDcmVhdGVFdmVudFNlcnZpY2Uge1xyXG4gICAgcHJpdmF0ZSBsYXN0UHJvY2Vzc2VkRmlsZXM6IE1hcDxzdHJpbmcsIG51bWJlcj4gPSBuZXcgTWFwKCk7XHJcblxyXG4gICAgY29uc3RydWN0b3IoXHJcbiAgICAgICAgcHJpdmF0ZSBhcHA6IEFwcCxcclxuICAgICAgICBwcml2YXRlIHBsdWdpbjogQXN0cm9Db21wb3NlclBsdWdpbkludGVyZmFjZVxyXG4gICAgKSB7IH1cclxuXHJcbiAgICBwdWJsaWMgaGFuZGxlQ3JlYXRlKGZpbGU6IFRGaWxlKTogdm9pZCB7XHJcbiAgICAgICAgdm9pZCAoYXN5bmMgKCkgPT4ge1xyXG4gICAgICAgICAgICBjb25zdCBub3cgPSBEYXRlLm5vdygpO1xyXG5cclxuICAgICAgICAgICAgaWYgKCEoZmlsZSBpbnN0YW5jZW9mIFRGaWxlKSB8fCAoZmlsZS5leHRlbnNpb24gIT09IFwibWRcIiAmJiBmaWxlLmV4dGVuc2lvbiAhPT0gXCJtZHhcIikpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgY29uc3QgZmlsZVBhdGggPSBmaWxlLnBhdGg7XHJcblxyXG4gICAgICAgICAgICAvLyBTa2lwIGlmIHRoaXMgZmlsZSB3YXMgY3JlYXRlZCBieSB0aGUgcGx1Z2luIGl0c2VsZiAoVFRMIGNoZWNrKVxyXG4gICAgICAgICAgICBjb25zdCBjcmVhdGVkVGltZSA9IHRoaXMucGx1Z2luLnBsdWdpbkNyZWF0ZWRGaWxlcy5nZXQoZmlsZVBhdGgpO1xyXG4gICAgICAgICAgICBpZiAoY3JlYXRlZFRpbWUgJiYgbm93IC0gY3JlYXRlZFRpbWUgPCA1ICogNjAgKiAxMDAwKSB7IC8vIDUgbWludXRlcyBUVExcclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgLy8gUGVyLWZpbGUgZGVib3VuY2UgY2hlY2tcclxuICAgICAgICAgICAgY29uc3QgbGFzdFByb2Nlc3NlZCA9IHRoaXMubGFzdFByb2Nlc3NlZEZpbGVzLmdldChmaWxlUGF0aCkgfHwgMDtcclxuICAgICAgICAgICAgaWYgKGxhc3RQcm9jZXNzZWQgPiAwICYmIG5vdyAtIGxhc3RQcm9jZXNzZWQgPCBDT05TVEFOVFMuREVCT1VOQ0VfTVMpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgLy8gQ2xlYW4gdXAgb2xkIGVudHJpZXMgaW4gbG9jYWwgZGVib3VuY2UgbWFwXHJcbiAgICAgICAgICAgIGlmIChsYXN0UHJvY2Vzc2VkID4gMCAmJiBub3cgLSBsYXN0UHJvY2Vzc2VkID4gMjAwMCkge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5sYXN0UHJvY2Vzc2VkRmlsZXMuZGVsZXRlKGZpbGVQYXRoKTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgLy8gUGVyaW9kaWMgY2xlYW51cCBvZiBkZWJvdW5jZSBtYXBcclxuICAgICAgICAgICAgY29uc3QgcGVyaW9kaWNDdXRvZmYgPSBub3cgLSBDT05TVEFOVFMuREVCT1VOQ0VfTVMgKiAyO1xyXG4gICAgICAgICAgICBmb3IgKGNvbnN0IFtwYXRoLCB0aW1lXSBvZiB0aGlzLmxhc3RQcm9jZXNzZWRGaWxlcy5lbnRyaWVzKCkpIHtcclxuICAgICAgICAgICAgICAgIGlmICh0aW1lIDwgcGVyaW9kaWNDdXRvZmYpIHtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLmxhc3RQcm9jZXNzZWRGaWxlcy5kZWxldGUocGF0aCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGNvbnN0IGNvbnRlbnRUeXBlcyA9IHRoaXMucGx1Z2luLnNldHRpbmdzLmNvbnRlbnRUeXBlcyB8fCBbXTtcclxuICAgICAgICAgICAgY29uc3QgaGFzRW5hYmxlZENvbnRlbnRUeXBlcyA9IGNvbnRlbnRUeXBlcy5zb21lKGN0ID0+IGN0LmVuYWJsZWQpO1xyXG5cclxuICAgICAgICAgICAgaWYgKCFoYXNFbmFibGVkQ29udGVudFR5cGVzKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGNvbnN0IHNvcnRlZENvbnRlbnRUeXBlcyA9IHNvcnRCeVBhdHRlcm5TcGVjaWZpY2l0eShjb250ZW50VHlwZXMpO1xyXG4gICAgICAgICAgICBsZXQgbWF0Y2hlZENvbnRlbnRUeXBlSWQ6IHN0cmluZyB8IG51bGwgPSBudWxsO1xyXG4gICAgICAgICAgICBjb25zdCBtYXRjaGluZ1R5cGVzOiBDb250ZW50VHlwZVtdID0gW107XHJcblxyXG4gICAgICAgICAgICBmb3IgKGNvbnN0IGNvbnRlbnRUeXBlIG9mIHNvcnRlZENvbnRlbnRUeXBlcykge1xyXG4gICAgICAgICAgICAgICAgaWYgKCFjb250ZW50VHlwZS5lbmFibGVkKSBjb250aW51ZTtcclxuXHJcbiAgICAgICAgICAgICAgICBsZXQgbWF0Y2hlcyA9IGZhbHNlO1xyXG5cclxuICAgICAgICAgICAgICAgIGlmICghY29udGVudFR5cGUuZm9sZGVyIHx8IGNvbnRlbnRUeXBlLmZvbGRlci50cmltKCkgPT09IFwiXCIpIHtcclxuICAgICAgICAgICAgICAgICAgICBpZiAoIWZpbGVQYXRoLmluY2x1ZGVzKFwiL1wiKSB8fCBmaWxlUGF0aC5zcGxpdChcIi9cIikubGVuZ3RoID09PSAxKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoZXMgPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAobWF0Y2hlc0ZvbGRlclBhdHRlcm4oZmlsZVBhdGgsIGNvbnRlbnRUeXBlLmZvbGRlcikpIHtcclxuICAgICAgICAgICAgICAgICAgICBpZiAoY29udGVudFR5cGUuaWdub3JlU3ViZm9sZGVycykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBwYXRoU2VnbWVudHMgPSBmaWxlUGF0aC5zcGxpdChcIi9cIik7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHBhdGhEZXB0aCA9IHBhdGhTZWdtZW50cy5sZW5ndGg7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHBhdHRlcm5TZWdtZW50cyA9IGNvbnRlbnRUeXBlLmZvbGRlci5zcGxpdChcIi9cIik7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGV4cGVjdGVkRGVwdGggPSBwYXR0ZXJuU2VnbWVudHMubGVuZ3RoO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNvbnRlbnRUeXBlLmNyZWF0aW9uTW9kZSA9PT0gXCJmb2xkZXJcIikge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZm9sZGVyRGVwdGggPSBwYXRoRGVwdGggLSAxO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGZvbGRlckRlcHRoID09PSBleHBlY3RlZERlcHRoIHx8IGZvbGRlckRlcHRoID09PSBleHBlY3RlZERlcHRoICsgMSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoZXMgPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHBhdGhEZXB0aCA9PT0gZXhwZWN0ZWREZXB0aCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoZXMgPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2hlcyA9IHRydWU7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIGlmIChtYXRjaGVzKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgbWF0Y2hpbmdUeXBlcy5wdXNoKGNvbnRlbnRUeXBlKTtcclxuICAgICAgICAgICAgICAgICAgICBpZiAoIW1hdGNoZWRDb250ZW50VHlwZUlkKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoZWRDb250ZW50VHlwZUlkID0gY29udGVudFR5cGUuaWQ7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBpZiAobWF0Y2hpbmdUeXBlcy5sZW5ndGggPiAxKSB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCB0eXBlTmFtZXMgPSBtYXRjaGluZ1R5cGVzLm1hcChjdCA9PiBjdC5uYW1lIHx8IFwiVW5uYW1lZFwiKS5qb2luKFwiLCBcIik7XHJcbiAgICAgICAgICAgICAgICBuZXcgTm90aWNlKGBNdWx0aXBsZSBjb250ZW50IHR5cGVzICgke3R5cGVOYW1lc30pIG1hdGNoIHRoaXMgZmlsZS4gVXNpbmcgbW9zdCBzcGVjaWZpYzogJHttYXRjaGluZ1R5cGVzWzBdLm5hbWUgfHwgXCJVbm5hbWVkXCJ9YCk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGlmICghbWF0Y2hlZENvbnRlbnRUeXBlSWQpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgLy8gUHJpbWFyeSBjaGVjazogSXMgdGhpcyBhbiBcIlVudGl0bGVkXCIgZmlsZT8gKHVzZXIgY2xpY2tlZCBuZXcgbm90ZSlcclxuICAgICAgICAgICAgLy8gR2l0LXN5bmNlZCBmaWxlcyBhbHdheXMgaGF2ZSByZWFsIG5hbWVzLCBzbyB0aGlzIHJlbGlhYmx5IGRpc3Rpbmd1aXNoZXNcclxuICAgICAgICAgICAgLy8gdXNlci1jcmVhdGVkIG5vdGVzIGZyb20gYmFja2dyb3VuZCBzeW5jLlxyXG4gICAgICAgICAgICBjb25zdCBmaWxlTmFtZSA9IGZpbGUuYmFzZW5hbWU7XHJcbiAgICAgICAgICAgIGNvbnN0IGlzVW50aXRsZWQgPSAvXlVudGl0bGVkKFxcc1xcZCspPyQvLnRlc3QoZmlsZU5hbWUpO1xyXG5cclxuICAgICAgICAgICAgaWYgKCFpc1VudGl0bGVkKSB7XHJcbiAgICAgICAgICAgICAgICAvLyBOb3QgYW4gVW50aXRsZWQgZmlsZS4gT25seSBwcm9jZXNzIGlmIGJhY2tncm91bmQgcHJvY2Vzc2luZyBpcyBlbmFibGVkLlxyXG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLnBsdWdpbi5zZXR0aW5ncy5wcm9jZXNzQmFja2dyb3VuZEZpbGVDaGFuZ2VzKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIC8vIEV2ZW4gd2l0aCBiYWNrZ3JvdW5kIHByb2Nlc3NpbmcsIHNraXAgZmlsZXMgdGhhdCBoYXZlIHJlYWwgY29udGVudFxyXG4gICAgICAgICAgICAgICAgLy8gKHRoZXkgd2VyZSBzeW5jZWQgZnJvbSBnaXQsIG5vdCBmcmVzaGx5IGNyZWF0ZWQpXHJcbiAgICAgICAgICAgICAgICBjb25zdCBzdGF0ID0gYXdhaXQgdGhpcy5hcHAudmF1bHQuYWRhcHRlci5zdGF0KGZpbGUucGF0aCk7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBpc1JlY2VudCA9IHN0YXQ/Lm10aW1lICYmIChub3cgLSBzdGF0Lm10aW1lIDwgQ09OU1RBTlRTLlNUQVRfTVRJTUVfVEhSRVNIT0xEKTtcclxuICAgICAgICAgICAgICAgIGlmICghaXNSZWNlbnQpIHtcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgbGV0IGNvbnRlbnQ6IHN0cmluZztcclxuICAgICAgICAgICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgICAgICAgICAgY29udGVudCA9IGF3YWl0IHRoaXMuYXBwLnZhdWx0LnJlYWQoZmlsZSk7XHJcbiAgICAgICAgICAgICAgICB9IGNhdGNoIHtcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgLy8gSWYgZmlsZSBoYXMgY29udGVudCBiZXlvbmQgYW4gZW1wdHkgdGVtcGxhdGUsIGl0J3Mgbm90IG5ld1xyXG4gICAgICAgICAgICAgICAgaWYgKGNvbnRlbnQudHJpbSgpLmxlbmd0aCA+IDApIHtcclxuICAgICAgICAgICAgICAgICAgICBjb25zdCBjb250ZW50V2l0aG91dEZyb250bWF0dGVyID0gY29udGVudC5zdGFydHNXaXRoKCctLS0nKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICA/IGNvbnRlbnQuc2xpY2UoY29udGVudC5pbmRleE9mKCdcXG4tLS0nLCAzKSArIDQpLnRyaW0oKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICA6IGNvbnRlbnQudHJpbSgpO1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChjb250ZW50V2l0aG91dEZyb250bWF0dGVyLmxlbmd0aCA+IDApIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgLy8gU21hbGwgZGVsYXkgdG8gbGV0IE9ic2lkaWFuIGZpbmlzaCBzd2l0Y2hpbmcgdG8gdGhlIGZpbGVcclxuICAgICAgICAgICAgYXdhaXQgbmV3IFByb21pc2UocmVzb2x2ZSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIDEwMCkpO1xyXG5cclxuICAgICAgICAgICAgdGhpcy5sYXN0UHJvY2Vzc2VkRmlsZXMuc2V0KGZpbGUucGF0aCwgbm93KTtcclxuXHJcbiAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5sYXN0UHJvY2Vzc2VkRmlsZXMuZGVsZXRlKGZpbGUucGF0aCk7XHJcbiAgICAgICAgICAgIH0sIENPTlNUQU5UUy5ERUJPVU5DRV9NUyArIDEwMCk7XHJcblxyXG4gICAgICAgICAgICBuZXcgVGl0bGVNb2RhbCh0aGlzLmFwcCwgZmlsZSwgdGhpcy5wbHVnaW4sIG1hdGNoZWRDb250ZW50VHlwZUlkLCBmYWxzZSwgdHJ1ZSkub3BlbigpO1xyXG4gICAgICAgIH0pKCk7XHJcbiAgICB9XHJcbn1cclxuIiwgImltcG9ydCB7IEFwcCwgVEZpbGUsIG1vbWVudCwgVEFic3RyYWN0RmlsZSB9IGZyb20gXCJvYnNpZGlhblwiO1xyXG5pbXBvcnQgeyBBc3Ryb0NvbXBvc2VyUGx1Z2luSW50ZXJmYWNlLCBDb250ZW50VHlwZSB9IGZyb20gXCIuLi90eXBlc1wiO1xyXG5cclxuZXhwb3J0IGNsYXNzIEZyb250bWF0dGVyU2VydmljZSB7XHJcbiAgICBwcml2YXRlIGxhc3RQcm9jZXNzZWRGaWxlOiBzdHJpbmcgPSBcIlwiO1xyXG4gICAgcHJpdmF0ZSBsYXN0UHJvY2Vzc2VkVGltZTogbnVtYmVyID0gMDtcclxuICAgIHByaXZhdGUgZGVib3VuY2VUaW1lb3V0OiBudW1iZXIgfCBudWxsID0gbnVsbDtcclxuICAgIHByaXZhdGUgZHJhZnRTdGF0dXNNYXA6IE1hcDxzdHJpbmcsIGJvb2xlYW4+ID0gbmV3IE1hcCgpO1xyXG4gICAgcHJpdmF0ZSBjb250ZW50SGFzaENhY2hlOiBNYXA8c3RyaW5nLCBzdHJpbmc+ID0gbmV3IE1hcCgpO1xyXG5cclxuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgYXBwOiBBcHAsIHByaXZhdGUgcGx1Z2luOiBBc3Ryb0NvbXBvc2VyUGx1Z2luSW50ZXJmYWNlKSB7XHJcbiAgICAgICAgdGhpcy5yZWdpc3RlckV2ZW50cygpO1xyXG5cclxuICAgICAgICAvLyBBbHNvIHJlLWluaXRpYWxpemUgd2hlbiBsYXlvdXQgaXMgcmVhZHkganVzdCBpbiBjYXNlXHJcbiAgICAgICAgdGhpcy5hcHAud29ya3NwYWNlLm9uTGF5b3V0UmVhZHkoKCkgPT4ge1xyXG4gICAgICAgICAgICB0aGlzLmluaXRpYWxpemVEcmFmdFN0YXR1c01hcCgpO1xyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBkZXN0cm95KCkge1xyXG4gICAgICAgIC8vIE5vLW9wLCBrZXB0IGZvciBpbnRlcmZhY2UgY29tcGF0aWJpbGl0eVxyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBpbml0aWFsaXplRHJhZnRTdGF0dXNNYXAoKSB7XHJcbiAgICAgICAgdGhpcy5kcmFmdFN0YXR1c01hcC5jbGVhcigpO1xyXG4gICAgICAgIGNvbnN0IHNldHRpbmdzID0gdGhpcy5wbHVnaW4uc2V0dGluZ3M7XHJcbiAgICAgICAgY29uc3QgaXNVbmRlcnNjb3JlTW9kZSA9IHNldHRpbmdzLmRyYWZ0RGV0ZWN0aW9uTW9kZSA9PT0gJ3VuZGVyc2NvcmUtcHJlZml4JztcclxuICAgICAgICBjb25zdCBkcmFmdFByb3AgPSBzZXR0aW5ncy5kcmFmdFByb3BlcnR5IHx8IFwiZHJhZnRcIjtcclxuICAgICAgICAvLyBJbmNsdWRlIGJvdGggLm1kIGFuZCAubWR4IGZpbGVzXHJcbiAgICAgICAgY29uc3QgZmlsZXMgPSB0aGlzLmFwcC52YXVsdC5nZXRGaWxlcygpLmZpbHRlcihmID0+IGYgaW5zdGFuY2VvZiBURmlsZSAmJiAoZi5leHRlbnNpb24gPT09ICdtZCcgfHwgZi5leHRlbnNpb24gPT09ICdtZHgnKSkgYXMgVEZpbGVbXTtcclxuXHJcbiAgICAgICAgZm9yIChjb25zdCBmaWxlIG9mIGZpbGVzKSB7XHJcbiAgICAgICAgICAgIGlmIChpc1VuZGVyc2NvcmVNb2RlKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmRyYWZ0U3RhdHVzTWFwLnNldChmaWxlLnBhdGgsIGZpbGUubmFtZS5zdGFydHNXaXRoKCdfJykpO1xyXG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgY29uc3QgY2FjaGUgPSB0aGlzLmFwcC5tZXRhZGF0YUNhY2hlLmdldEZpbGVDYWNoZShmaWxlKTtcclxuICAgICAgICAgICAgICAgIGNvbnN0IHJhd1ZhbHVlID0gY2FjaGU/LmZyb250bWF0dGVyPy5bZHJhZnRQcm9wXTtcclxuICAgICAgICAgICAgICAgIHRoaXMuZHJhZnRTdGF0dXNNYXAuc2V0KGZpbGUucGF0aCwgdGhpcy5jYWxjdWxhdGVJc0RyYWZ0KHJhd1ZhbHVlLCBzZXR0aW5ncykpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgY2FsY3VsYXRlSXNEcmFmdChyYXdWYWx1ZTogYW55LCBzZXR0aW5nczogYW55KTogYm9vbGVhbiB7XHJcbiAgICAgICAgLy8gSWYgdW5kZWZpbmVkL251bGwsIGFzc3VtZSBpdCdzIE5PVCBhIGRyYWZ0IHVubGVzcyBsb2dpYyBzYXlzIG90aGVyd2lzZVxyXG4gICAgICAgIGlmIChyYXdWYWx1ZSA9PT0gdW5kZWZpbmVkIHx8IHJhd1ZhbHVlID09PSBudWxsKSByZXR1cm4gZmFsc2U7XHJcblxyXG4gICAgICAgIC8vIENvbnZlcnQgdG8gc3RyaW5nIGZvciBlYXNpZXIgbWF0Y2hpbmcgaWYgaXQncyBub3QgYSBib29sZWFuXHJcbiAgICAgICAgY29uc3QgdmFsID0gU3RyaW5nKHJhd1ZhbHVlKS50b0xvd2VyQ2FzZSgpO1xyXG5cclxuICAgICAgICBpZiAoc2V0dGluZ3MuZHJhZnRMb2dpYyA9PT0gJ2ZhbHNlLWlzLWRyYWZ0Jykge1xyXG4gICAgICAgICAgICAvLyBcIkZhbHNlID0gUHVibGlzaGVkXCIsIHNvIGl0J3MgYSBkcmFmdCBpZiBpdCBpcyBmYWxzZSwgXCJmYWxzZVwiLCBcIjBcIiwgZXRjLlxyXG4gICAgICAgICAgICByZXR1cm4gdmFsID09PSAnZmFsc2UnIHx8IHZhbCA9PT0gJzAnIHx8IHJhd1ZhbHVlID09PSBmYWxzZTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAvLyBcIlRydWUgPSBEcmFmdFwiLCBzbyBpdCdzIGEgZHJhZnQgaWYgaXQgaXMgdHJ1ZSwgXCJ0cnVlXCIsIFwiMVwiLCBldGMuXHJcbiAgICAgICAgICAgIHJldHVybiB2YWwgPT09ICd0cnVlJyB8fCB2YWwgPT09ICcxJyB8fCByYXdWYWx1ZSA9PT0gdHJ1ZTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSByZWdpc3RlckV2ZW50cygpIHtcclxuICAgICAgICAvLyBXYXRjaCBmb3IgbWV0YWRhdGEgY2hhbmdlcyAocHJvcGVydHktYmFzZWQgZHJhZnQgc3luYylcclxuICAgICAgICB0aGlzLnBsdWdpbi5yZWdpc3RlckV2ZW50KFxyXG4gICAgICAgICAgICB0aGlzLmFwcC5tZXRhZGF0YUNhY2hlLm9uKFwiY2hhbmdlZFwiLCAoZmlsZSkgPT4ge1xyXG4gICAgICAgICAgICAgICAgaWYgKGZpbGUgaW5zdGFuY2VvZiBURmlsZSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMub25NZXRhZGF0YUNoYW5nZShmaWxlKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfSlcclxuICAgICAgICApO1xyXG5cclxuICAgICAgICAvLyBXYXRjaCBmb3IgcmVuYW1lcyAodW5kZXJzY29yZS1wcmVmaXggZHJhZnQgc3luYylcclxuICAgICAgICB0aGlzLnBsdWdpbi5yZWdpc3RlckV2ZW50KFxyXG4gICAgICAgICAgICB0aGlzLmFwcC52YXVsdC5vbihcInJlbmFtZVwiLCAoZmlsZSwgb2xkUGF0aCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgaWYgKGZpbGUgaW5zdGFuY2VvZiBURmlsZSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMub25SZW5hbWUoZmlsZSwgb2xkUGF0aCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0pXHJcbiAgICAgICAgKTtcclxuXHJcbiAgICAgICAgLy8gV2F0Y2ggZm9yIGZpbGUgb3BlbiB0byBsYXppbHkgcG9wdWxhdGUgaGFzaCBjYWNoZSBmb3IgdGhlIGFjdGl2ZSBmaWxlXHJcbiAgICAgICAgdGhpcy5wbHVnaW4ucmVnaXN0ZXJFdmVudChcclxuICAgICAgICAgICAgdGhpcy5hcHAud29ya3NwYWNlLm9uKFwiZmlsZS1vcGVuXCIsIChmaWxlKSA9PiB7XHJcbiAgICAgICAgICAgICAgICBpZiAoZmlsZSBpbnN0YW5jZW9mIFRGaWxlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdm9pZCAoYXN5bmMgKCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY29udGVudCA9IGF3YWl0IHRoaXMuYXBwLnZhdWx0LnJlYWQoZmlsZSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbnRlbnRIYXNoQ2FjaGUuc2V0KGZpbGUucGF0aCwgdGhpcy5nZXRDb250ZW50SGFzaChjb250ZW50KSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYEZhaWxlZCB0byBsYXppbHkgaW5pdGlhbGl6ZSBjb250ZW50IGhhc2ggZm9yICR7ZmlsZS5wYXRofTpgLCBlKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIH0pKCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0pXHJcbiAgICAgICAgKTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIG9uUmVuYW1lKGZpbGU6IFRGaWxlLCBvbGRQYXRoOiBzdHJpbmcpIHtcclxuICAgICAgICBjb25zdCBzZXR0aW5ncyA9IHRoaXMucGx1Z2luLnNldHRpbmdzO1xyXG4gICAgICAgIGlmICghc2V0dGluZ3Muc3luY0RyYWZ0RGF0ZSkgcmV0dXJuO1xyXG5cclxuICAgICAgICBjb25zdCBvbGROYW1lID0gb2xkUGF0aC5zcGxpdChcIi9cIikucG9wKCkgfHwgXCJcIjtcclxuICAgICAgICBjb25zdCBuZXdOYW1lID0gZmlsZS5uYW1lO1xyXG5cclxuICAgICAgICAvLyBDaGVjayBpZiBpdCB3YXMgYW4gdW5kZXJzY29yZSBkcmFmdCBhbmQgaXMgbm93IG5vdFxyXG4gICAgICAgIGlmIChvbGROYW1lLnN0YXJ0c1dpdGgoXCJfXCIpICYmICFuZXdOYW1lLnN0YXJ0c1dpdGgoXCJfXCIpKSB7XHJcbiAgICAgICAgICAgIC8vIENoZWNrIGdsb2JhbCBzZXR0aW5nIG9yIHBlci1jb250ZW50LXR5cGUgc2V0dGluZ1xyXG4gICAgICAgICAgICBpZiAoc2V0dGluZ3MuZHJhZnREZXRlY3Rpb25Nb2RlID09PSAndW5kZXJzY29yZS1wcmVmaXgnKSB7XHJcbiAgICAgICAgICAgICAgICB2b2lkIHRoaXMudXBkYXRlRGF0ZShmaWxlKTtcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgIGNvbnN0IGNvbnRlbnRUeXBlID0gdGhpcy5wbHVnaW4uZmlsZU9wcz8uZ2V0Q29udGVudFR5cGVCeVBhdGgoZmlsZS5wYXRoKTtcclxuICAgICAgICAgICAgICAgIGlmIChjb250ZW50VHlwZT8uZW5hYmxlVW5kZXJzY29yZVByZWZpeCkge1xyXG4gICAgICAgICAgICAgICAgICAgIHZvaWQgdGhpcy51cGRhdGVEYXRlKGZpbGUpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgb25NZXRhZGF0YUNoYW5nZShmaWxlOiBURmlsZSkge1xyXG4gICAgICAgIGNvbnN0IHNldHRpbmdzID0gdGhpcy5wbHVnaW4uc2V0dGluZ3M7XHJcblxyXG4gICAgICAgIC8vIEluIHVuZGVyc2NvcmUtcHJlZml4IG1vZGUsIGRyYWZ0IHRyYW5zaXRpb25zIGFyZSBoYW5kbGVkIGJ5IG9uUmVuYW1lLCBub3QgbWV0YWRhdGEgY2hhbmdlcy5cclxuICAgICAgICAvLyBTa2lwIHByb3BlcnR5LWJhc2VkIGRyYWZ0IGRldGVjdGlvbiBlbnRpcmVseSB0byBhdm9pZCBwaGFudG9tIHRyYW5zaXRpb25zLlxyXG4gICAgICAgIGlmIChzZXR0aW5ncy5kcmFmdERldGVjdGlvbk1vZGUgPT09ICd1bmRlcnNjb3JlLXByZWZpeCcpIHtcclxuICAgICAgICAgICAgLy8gU3RpbGwgaGFuZGxlIG1vZGlmaWVkIGRhdGUgc3luYyBpZiBhcHBsaWNhYmxlXHJcbiAgICAgICAgICAgIGNvbnN0IGNvbnRlbnRUeXBlID0gdGhpcy5wbHVnaW4uZmlsZU9wcz8uZ2V0Q29udGVudFR5cGVCeVBhdGgoZmlsZS5wYXRoKTtcclxuICAgICAgICAgICAgY29uc3QgaGFzTW9kaWZpZWRGaWVsZCA9ICEhY29udGVudFR5cGU/Lm1vZGlmaWVkRGF0ZUZpZWxkO1xyXG4gICAgICAgICAgICBpZiAoIWhhc01vZGlmaWVkRmllbGQpIHJldHVybjtcclxuXHJcbiAgICAgICAgICAgIGNvbnN0IGFjdGl2ZUZpbGUgPSB0aGlzLmFwcC53b3Jrc3BhY2UuZ2V0QWN0aXZlRmlsZSgpO1xyXG4gICAgICAgICAgICBjb25zdCBpc0FjdGl2ZUZpbGUgPSBhY3RpdmVGaWxlICYmIGFjdGl2ZUZpbGUucGF0aCA9PT0gZmlsZS5wYXRoO1xyXG4gICAgICAgICAgICBpZiAoIXNldHRpbmdzLnByb2Nlc3NCYWNrZ3JvdW5kRmlsZUNoYW5nZXMgJiYgIWlzQWN0aXZlRmlsZSkgcmV0dXJuO1xyXG5cclxuICAgICAgICAgICAgdm9pZCB0aGlzLnByb2Nlc3NGaWxlKGZpbGUsIGZhbHNlLCBjb250ZW50VHlwZSk7XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIENoZWNrIGJhY2tncm91bmQgcHJvY2Vzc2luZ1xyXG4gICAgICAgIGNvbnN0IGFjdGl2ZUZpbGUgPSB0aGlzLmFwcC53b3Jrc3BhY2UuZ2V0QWN0aXZlRmlsZSgpO1xyXG4gICAgICAgIGNvbnN0IGlzQWN0aXZlRmlsZSA9IGFjdGl2ZUZpbGUgJiYgYWN0aXZlRmlsZS5wYXRoID09PSBmaWxlLnBhdGg7XHJcbiAgICAgICAgaWYgKCFzZXR0aW5ncy5wcm9jZXNzQmFja2dyb3VuZEZpbGVDaGFuZ2VzICYmICFpc0FjdGl2ZUZpbGUpIHtcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gTmVlZCB0byBjaGVjayBjb250ZW50IHR5cGUgdG8gc2VlIGlmIG1vZGlmaWVkIGRhdGUgaXMgZW5hYmxlZCBmb3IgVEhJUyB0eXBlXHJcbiAgICAgICAgY29uc3QgY29udGVudFR5cGUgPSB0aGlzLnBsdWdpbi5maWxlT3BzPy5nZXRDb250ZW50VHlwZUJ5UGF0aChmaWxlLnBhdGgpO1xyXG4gICAgICAgIGNvbnN0IGhhc01vZGlmaWVkRmllbGQgPSAhIWNvbnRlbnRUeXBlPy5tb2RpZmllZERhdGVGaWVsZDtcclxuXHJcbiAgICAgICAgaWYgKCFzZXR0aW5ncy5zeW5jRHJhZnREYXRlICYmICFoYXNNb2RpZmllZEZpZWxkKSB7XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIFRyYWNrIGRyYWZ0IHN0YXR1cyBjaGFuZ2VzIChwcm9wZXJ0eS1iYXNlZCBvbmx5KVxyXG4gICAgICAgIGNvbnN0IGNhY2hlID0gdGhpcy5hcHAubWV0YWRhdGFDYWNoZS5nZXRGaWxlQ2FjaGUoZmlsZSk7XHJcbiAgICAgICAgY29uc3QgZHJhZnRQcm9wID0gc2V0dGluZ3MuZHJhZnRQcm9wZXJ0eSB8fCBcImRyYWZ0XCI7XHJcbiAgICAgICAgY29uc3QgcmF3VmFsdWUgPSBjYWNoZT8uZnJvbnRtYXR0ZXI/LltkcmFmdFByb3BdO1xyXG5cclxuICAgICAgICAvLyBMb2dpYzogdHJ1ZS1pcy1kcmFmdCB2cyBmYWxzZS1pcy1kcmFmdFxyXG4gICAgICAgIGNvbnN0IGlzQ3VycmVudGx5RHJhZnQgPSB0aGlzLmNhbGN1bGF0ZUlzRHJhZnQocmF3VmFsdWUsIHNldHRpbmdzKTtcclxuXHJcbiAgICAgICAgLy8gSWYgaXQncyB0aGUgZmlyc3QgdGltZSB3ZSBzZWUgdGhpcyBmaWxlLCBqdXN0IHJlY29yZCBpdCBhbmQgc2tpcFxyXG4gICAgICAgIGlmICghdGhpcy5kcmFmdFN0YXR1c01hcC5oYXMoZmlsZS5wYXRoKSkge1xyXG4gICAgICAgICAgICB0aGlzLmRyYWZ0U3RhdHVzTWFwLnNldChmaWxlLnBhdGgsIGlzQ3VycmVudGx5RHJhZnQpO1xyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjb25zdCBwcmV2aW91c0RyYWZ0U3RhdHVzID0gdGhpcy5kcmFmdFN0YXR1c01hcC5nZXQoZmlsZS5wYXRoKTtcclxuXHJcbiAgICAgICAgbGV0IGRyYWZ0U3RhdHVzQ2hhbmdlZFRvUHVibGlzaGVkID0gZmFsc2U7XHJcbiAgICAgICAgLy8gVHJhbnNpdGlvbiBmcm9tIGRyYWZ0IHRvIG5vbi1kcmFmdFxyXG4gICAgICAgIGlmIChwcmV2aW91c0RyYWZ0U3RhdHVzID09PSB0cnVlICYmIGlzQ3VycmVudGx5RHJhZnQgPT09IGZhbHNlKSB7XHJcbiAgICAgICAgICAgIGRyYWZ0U3RhdHVzQ2hhbmdlZFRvUHVibGlzaGVkID0gdHJ1ZTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIFVwZGF0ZSB0aGUgbWFwIGZvciBuZXh0IHRpbWVcclxuICAgICAgICB0aGlzLmRyYWZ0U3RhdHVzTWFwLnNldChmaWxlLnBhdGgsIGlzQ3VycmVudGx5RHJhZnQpO1xyXG5cclxuICAgICAgICAvLyBJZiBubyBwdWJsaWNhdGlvbiBjaGFuZ2UgYW5kIG5vIG1vZGlmaWVkIGZpZWxkIHRvIHVwZGF0ZSwgc2tpcCBwcm9jZXNzaW5nXHJcbiAgICAgICAgaWYgKCFkcmFmdFN0YXR1c0NoYW5nZWRUb1B1Ymxpc2hlZCAmJiAhaGFzTW9kaWZpZWRGaWVsZCkge1xyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyBQcmV2ZW50IGluZmluaXRlIGxvb3BzIGFuZCByZWR1bmRhbnQgcHJvY2Vzc2luZ1xyXG4gICAgICAgIGNvbnN0IG5vdyA9IERhdGUubm93KCk7XHJcbiAgICAgICAgaWYgKHRoaXMubGFzdFByb2Nlc3NlZEZpbGUgPT09IGZpbGUucGF0aCAmJiBub3cgLSB0aGlzLmxhc3RQcm9jZXNzZWRUaW1lIDwgMjAwMCkge1xyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyBVc2UgYSBkZWJvdW5jZSB0byB3YWl0IGZvciB3cml0aW5nIHRvIGZpbmlzaFxyXG4gICAgICAgIGlmICh0aGlzLmRlYm91bmNlVGltZW91dCkge1xyXG4gICAgICAgICAgICB3aW5kb3cuY2xlYXJUaW1lb3V0KHRoaXMuZGVib3VuY2VUaW1lb3V0KTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHRoaXMuZGVib3VuY2VUaW1lb3V0ID0gd2luZG93LnNldFRpbWVvdXQoYXN5bmMgKCkgPT4ge1xyXG4gICAgICAgICAgICAvLyBDaGVjayBpZiBjb250ZW50IChleGNsdWRpbmcgZnJvbnRtYXR0ZXIpIGhhcyBhY3R1YWxseSBjaGFuZ2VkXHJcbiAgICAgICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBjb250ZW50ID0gYXdhaXQgdGhpcy5hcHAudmF1bHQucmVhZChmaWxlKTtcclxuICAgICAgICAgICAgICAgIGNvbnN0IGN1cnJlbnRIYXNoID0gdGhpcy5nZXRDb250ZW50SGFzaChjb250ZW50KTtcclxuICAgICAgICAgICAgICAgIGNvbnN0IHByZXZpb3VzSGFzaCA9IHRoaXMuY29udGVudEhhc2hDYWNoZS5nZXQoZmlsZS5wYXRoKTtcclxuXHJcbiAgICAgICAgICAgICAgICAvLyBVcGRhdGUgY2FjaGUgaW1tZWRpYXRlbHkgdG8gcHJldmVudCByZS1wcm9jZXNzaW5nIGV2ZW4gaWYgd2Ugc2tpcFxyXG4gICAgICAgICAgICAgICAgdGhpcy5jb250ZW50SGFzaENhY2hlLnNldChmaWxlLnBhdGgsIGN1cnJlbnRIYXNoKTtcclxuXHJcbiAgICAgICAgICAgICAgICBpZiAocHJldmlvdXNIYXNoID09PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgICAgICAgICAgICAvLyBGaXJzdCB0aW1lIHdlJ3JlIHNlZWluZyB0aGUgY29udGVudCBvZiBhbiBleGlzdGluZyBmaWxlIChsYXp5IGluaXQgdmlhIGV2ZW50KVxyXG4gICAgICAgICAgICAgICAgICAgIC8vIElmIHdlIG1pc3NlZCB0aGUgZmlsZS1vcGVuIChlLmcuIGl0IHdhcyBhbHJlYWR5IG9wZW4gb24gc3RhcnQpLCBcclxuICAgICAgICAgICAgICAgICAgICAvLyB3ZSdsbCB0cmVhdCB0aGlzIGZpcnN0IGNoYW5nZSBhcyB0aGUgYmFzZWxpbmUgdW5sZXNzIGl0J3MgYSBwdWJsaWNhdGlvbiBjaGFuZ2UuXHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFkcmFmdFN0YXR1c0NoYW5nZWRUb1B1Ymxpc2hlZCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcmV2aW91c0hhc2ggPT09IGN1cnJlbnRIYXNoKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgLy8gT25seSBzdWItcHVibGljYXRpb24gY2hhbmdlcyAobGlrZSBtZXRhZGF0YSkgaGFwcGVuZWQsIHNraXAgbW9kaWZpZWQgZGF0ZSB1cGRhdGVcclxuICAgICAgICAgICAgICAgICAgICBpZiAoIWRyYWZ0U3RhdHVzQ2hhbmdlZFRvUHVibGlzaGVkKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAvLyBJZiBoYXNoZXMgZGlmZmVyLCBvciBpdCdzIGEgcHVibGljYXRpb24gY2hhbmdlLCB3ZSBwcm9jZWVkIHRvIHByb2Nlc3NGaWxlXHJcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcclxuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYEZhaWxlZCB0byBjaGVjayBjb250ZW50IGhhc2ggZm9yICR7ZmlsZS5wYXRofTpgLCBlKTtcclxuICAgICAgICAgICAgICAgIC8vIEZhbGxiYWNrIHRvIHByb2Nlc3NpbmcgaWYgcmVhZCBmYWlscywgb3IgcmV0dXJuPyBcclxuICAgICAgICAgICAgICAgIC8vIEJldHRlciB0byByZXR1cm4gdG8gYmUgc2FmZSBhZ2FpbnN0IGFjY2lkZW50YWwgdXBkYXRlc1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICB2b2lkIHRoaXMucHJvY2Vzc0ZpbGUoZmlsZSwgZHJhZnRTdGF0dXNDaGFuZ2VkVG9QdWJsaXNoZWQsIGNvbnRlbnRUeXBlKTtcclxuICAgICAgICB9LCA1MDApO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgZ2V0Q29udGVudEhhc2goY29udGVudDogc3RyaW5nKTogc3RyaW5nIHtcclxuICAgICAgICAvLyAxLiBTdHJpcCBmcm9udG1hdHRlclxyXG4gICAgICAgIGxldCBib2R5ID0gY29udGVudDtcclxuICAgICAgICBpZiAoY29udGVudC5zdGFydHNXaXRoKCctLS0nKSkge1xyXG4gICAgICAgICAgICBjb25zdCBlbmQgPSBjb250ZW50LmluZGV4T2YoJ1xcbi0tLScsIDMpO1xyXG4gICAgICAgICAgICBpZiAoZW5kICE9PSAtMSkge1xyXG4gICAgICAgICAgICAgICAgYm9keSA9IGNvbnRlbnQuc2xpY2UoZW5kICsgNCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIDIuIE5vcm1hbGl6ZSB3aGl0ZXNwYWNlOiBjb2xsYXBzZSBhbGwgd2hpdGVzcGFjZSBpbnRvIHNpbmdsZSBzcGFjZXMgYW5kIHRyaW1cclxuICAgICAgICBjb25zdCBub3JtYWxpemVkID0gYm9keS5yZXBsYWNlKC9cXHMrL2csICcgJykudHJpbSgpO1xyXG5cclxuICAgICAgICAvLyAzLiBTaW1wbGUgaGFzaGluZyAoY29uY2F0ZW5hdGluZyBsZW5ndGggYW5kIGZpcnN0L2xhc3QgYml0cyBpcyB1c3VhbGx5IGVub3VnaCBmb3IgbG9jYWwgY2hhbmdlIGRldGVjdGlvbiwgXHJcbiAgICAgICAgLy8gYnV0IGxldCdzIGRvIGEgc2xpZ2h0bHkgYmV0dGVyIG9uZSBpZiB3ZSB3YW50IHRvIGJlIHJvYnVzdCwgb3IganVzdCB1c2UgdGhlIG5vcm1hbGl6ZWQgc3RyaW5nIGlmIG1lbW9yeSBhbGxvd3MpXHJcbiAgICAgICAgLy8gR2l2ZW4gT2JzaWRpYW4gdmF1bHRzIGNhbiBiZSBsYXJnZSwgYSBzbWFsbCBoYXNoIGlzIHNhZmVyLlxyXG4gICAgICAgIHJldHVybiB0aGlzLnNpbXBsZUhhc2gobm9ybWFsaXplZCk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBzaW1wbGVIYXNoKHN0cjogc3RyaW5nKTogc3RyaW5nIHtcclxuICAgICAgICBsZXQgaGFzaCA9IDA7XHJcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgICAgY29uc3QgY2hhciA9IHN0ci5jaGFyQ29kZUF0KGkpO1xyXG4gICAgICAgICAgICBoYXNoID0gKChoYXNoIDw8IDUpIC0gaGFzaCkgKyBjaGFyO1xyXG4gICAgICAgICAgICBoYXNoIHw9IDA7IC8vIENvbnZlcnQgdG8gMzJiaXQgaW50ZWdlclxyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gaGFzaC50b1N0cmluZygpICsgXCJfXCIgKyBzdHIubGVuZ3RoO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgYXN5bmMgdXBkYXRlRGF0ZShmaWxlOiBURmlsZSkge1xyXG4gICAgICAgIGNvbnN0IHNldHRpbmdzID0gdGhpcy5wbHVnaW4uc2V0dGluZ3M7XHJcbiAgICAgICAgY29uc3QgZGF0ZUZpZWxkID0gc2V0dGluZ3MucHVibGlzaERhdGVGaWVsZCB8fCBcImRhdGVcIjtcclxuXHJcbiAgICAgICAgYXdhaXQgdGhpcy5hcHAuZmlsZU1hbmFnZXIucHJvY2Vzc0Zyb250TWF0dGVyKGZpbGUsIChmcm9udG1hdHRlcikgPT4ge1xyXG4gICAgICAgICAgICBjb25zdCB0b2RheSA9IG1vbWVudCgpLmZvcm1hdChzZXR0aW5ncy5kYXRlRm9ybWF0KTtcclxuICAgICAgICAgICAgaWYgKGZyb250bWF0dGVyW2RhdGVGaWVsZF0gIT09IHRvZGF5KSB7XHJcbiAgICAgICAgICAgICAgICBmcm9udG1hdHRlcltkYXRlRmllbGRdID0gdG9kYXk7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmxhc3RQcm9jZXNzZWRGaWxlID0gZmlsZS5wYXRoO1xyXG4gICAgICAgICAgICAgICAgdGhpcy5sYXN0UHJvY2Vzc2VkVGltZSA9IERhdGUubm93KCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIGFzeW5jIHByb2Nlc3NGaWxlKGZpbGU6IFRGaWxlLCBkcmFmdFN0YXR1c0NoYW5nZWRUb1B1Ymxpc2hlZDogYm9vbGVhbiwgY29udGVudFR5cGU6IENvbnRlbnRUeXBlIHwgbnVsbCB8IHVuZGVmaW5lZCkge1xyXG4gICAgICAgIGNvbnN0IHNldHRpbmdzID0gdGhpcy5wbHVnaW4uc2V0dGluZ3M7XHJcbiAgICAgICAgY29uc3QgcHVibGlzaERhdGVGaWVsZCA9IHNldHRpbmdzLnB1Ymxpc2hEYXRlRmllbGQgfHwgXCJkYXRlXCI7XHJcblxyXG4gICAgICAgIGF3YWl0IHRoaXMuYXBwLmZpbGVNYW5hZ2VyLnByb2Nlc3NGcm9udE1hdHRlcihmaWxlLCAoZnJvbnRtYXR0ZXIpID0+IHtcclxuICAgICAgICAgICAgbGV0IGNoYW5nZWQgPSBmYWxzZTtcclxuXHJcbiAgICAgICAgICAgIC8vIEhhbmRsZSBEcmFmdCBTeW5jICh0cmlnZ2VyZWQgb25seSBvbiB0aGUgc3BlY2lmaWMgdHJhbnNpdGlvbilcclxuICAgICAgICAgICAgaWYgKHNldHRpbmdzLnN5bmNEcmFmdERhdGUgJiYgZHJhZnRTdGF0dXNDaGFuZ2VkVG9QdWJsaXNoZWQpIHtcclxuICAgICAgICAgICAgICAgIGNvbnN0IHRvZGF5ID0gbW9tZW50KCkuZm9ybWF0KHNldHRpbmdzLmRhdGVGb3JtYXQpO1xyXG4gICAgICAgICAgICAgICAgaWYgKGZyb250bWF0dGVyW3B1Ymxpc2hEYXRlRmllbGRdICE9PSB0b2RheSkge1xyXG4gICAgICAgICAgICAgICAgICAgIGZyb250bWF0dGVyW3B1Ymxpc2hEYXRlRmllbGRdID0gdG9kYXk7XHJcbiAgICAgICAgICAgICAgICAgICAgY2hhbmdlZCA9IHRydWU7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIC8vIEhhbmRsZSBNb2RpZmllZCBEYXRlIFN5bmNcclxuICAgICAgICAgICAgY29uc3QgbW9kaWZpZWRGaWVsZCA9IGNvbnRlbnRUeXBlPy5tb2RpZmllZERhdGVGaWVsZDtcclxuICAgICAgICAgICAgaWYgKG1vZGlmaWVkRmllbGQgJiYgZnJvbnRtYXR0ZXJbbW9kaWZpZWRGaWVsZF0gIT09IHVuZGVmaW5lZCkge1xyXG4gICAgICAgICAgICAgICAgY29uc3Qgbm93ID0gbW9tZW50KCkuZm9ybWF0KHNldHRpbmdzLmRhdGVGb3JtYXQpO1xyXG4gICAgICAgICAgICAgICAgaWYgKGZyb250bWF0dGVyW21vZGlmaWVkRmllbGRdICE9PSBub3cpIHtcclxuICAgICAgICAgICAgICAgICAgICBmcm9udG1hdHRlclttb2RpZmllZEZpZWxkXSA9IG5vdztcclxuICAgICAgICAgICAgICAgICAgICBjaGFuZ2VkID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgaWYgKGNoYW5nZWQpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMubGFzdFByb2Nlc3NlZEZpbGUgPSBmaWxlLnBhdGg7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmxhc3RQcm9jZXNzZWRUaW1lID0gRGF0ZS5ub3coKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG59XHJcbiJdLAogICJtYXBwaW5ncyI6ICI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsSUFBQUEsb0JBT087OztBQ3dGQSxJQUFNLG1CQUFtQixDQUFDLFFBQVEsV0FBVyxZQUFZO0FBRXpELElBQU0sWUFBWTtBQUFBLEVBQ3hCLGFBQWE7QUFBQSxFQUNiLHNCQUFzQjtBQUFBLEVBQ3RCLHdCQUF3QjtBQUFBLEVBQ3hCLDRCQUE0QjtBQUM3Qjs7O0FDakdPLElBQU0sbUJBQTBDO0FBQUEsRUFDdEQsaUJBQ0M7QUFBQSxFQUNELHNCQUFzQjtBQUFBLEVBQ3RCLFlBQVk7QUFBQSxFQUNaLHVCQUF1QjtBQUFBLEVBQ3ZCLHVCQUF1QjtBQUFBLEVBQ3ZCLHlCQUF5QjtBQUFBLEVBQ3pCLDJCQUEyQjtBQUFBLEVBQzNCLHlCQUF5QjtBQUFBLEVBQ3pCLHlCQUF5QjtBQUFBLEVBQ3pCLDRCQUE0QjtBQUFBLEVBQzVCLDBCQUEwQjtBQUFBLEVBQzFCLDZCQUE2QjtBQUFBLEVBQzdCLGdCQUFnQjtBQUFBLEVBQ2hCLHdCQUF3QjtBQUFBLEVBQ3hCLGNBQWMsQ0FBQztBQUFBLEVBQ2Ysb0JBQW9CO0FBQUEsRUFDcEIsdUJBQXVCO0FBQUEsSUFDdEIsU0FBUztBQUFBLElBQ1QsV0FBVztBQUFBLElB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Q0EsU0FBSyxvQkFBb0I7QUFBQSxFQUMxQjtBQUFBLEVBRVEsaUNBQWlDLGFBQTBCO0FBMWZwRTtBQTJmRSxVQUFNLHlCQUF5QixDQUFDLEtBQUssU0FBUyw0QkFBNEIsQ0FBQyxLQUFLLFNBQVM7QUFDekYsVUFBTSx1QkFBdUIsQ0FBQyxLQUFLLFNBQVMsMEJBQTBCLENBQUMsS0FBSyxTQUFTO0FBRXJGLFVBQU0sWUFBWSxZQUFZLGlCQUFpQixZQUFZO0FBQzNELGVBQVcsUUFBUSxNQUFNLEtBQUssU0FBUyxHQUFHO0FBQ3pDLFlBQU0sTUFBTSxLQUFLLGNBQWMsS0FBSztBQUNwQyxVQUFJLEtBQUs7QUFDUixZQUFJLFdBQVcsSUFBSSxhQUFhLGFBQWEsS0FBSyxJQUFJLGFBQWEsY0FBYyxLQUNoRixJQUFJLGFBQWEsV0FBVyxNQUMzQixJQUFJLFVBQVUsU0FBUyx3QkFBd0IsSUFBSSxvQkFBb0IsVUFDdkUsSUFBSSxVQUFVLFNBQVMsZUFBZSxJQUFJLFdBQVcsVUFDckQsSUFBSSxVQUFVLFNBQVMsZUFBZSxJQUFJLFdBQVc7QUFFdkQsWUFBSSxTQUFVLFlBQVcsU0FBUyxRQUFRLFlBQVksRUFBRTtBQUV4RCxZQUFJLDBCQUEwQixhQUFhLG1CQUFtQjtBQUM3RCxlQUFJLFVBQUssZ0JBQUwsbUJBQWtCLGNBQWMsU0FBUyxZQUFhLE1BQUssT0FBTztBQUFBLFFBQ3ZFO0FBQ0EsWUFBSSx5QkFBeUIsYUFBYSxZQUFZLGFBQWEsV0FBVztBQUM3RSxlQUFJLFVBQUssZ0JBQUwsbUJBQWtCLGNBQWMsU0FBUyxVQUFXLE1BQUssT0FBTztBQUFBLFFBQ3JFO0FBQUEsTUFDRDtBQUFBLElBQ0Q7QUFBQSxFQUNEO0FBQ0Q7IiwKICAibmFtZXMiOiBbImltcG9ydF9vYnNpZGlhbiIsICJpbXBvcnRfb2JzaWRpYW4iLCAibmV3RmlsZSIsICJpbXBvcnRfb2JzaWRpYW4iLCAiaW1wb3J0X29ic2lkaWFuIiwgImltcG9ydF9vYnNpZGlhbiIsICJjb250ZW50VHlwZSIsICJfYSIsICJoYXNNYXRjaGluZ0NvbnRlbnRUeXBlIiwgInNldHRpbmdzIiwgInBsdWdpbkludGVyZmFjZSIsICJmaWxlIiwgInR5cGUiLCAiaW1wb3J0X29ic2lkaWFuIiwgImltcG9ydF9vYnNpZGlhbiIsICJpbXBvcnRfb2JzaWRpYW4iLCAiaW1wb3J0X29ic2lkaWFuIiwgIl9hIiwgInRvZ2dsZSIsICJpbXBvcnRfb2JzaWRpYW4iLCAiaW1wb3J0X29ic2lkaWFuIiwgImltcG9ydF9vYnNpZGlhbiIsICJpbXBvcnRfb2JzaWRpYW4iLCAiY29udGVudFR5cGUiLCAiaGFzTW9kaWZpZWRGaWVsZCIsICJhY3RpdmVGaWxlIiwgImlzQWN0aXZlRmlsZSIsICJfYSIsICJfYiJdCn0K