You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3186 lines
496 KiB
3186 lines
496 KiB
/*
|
|
THIS IS A GENERATED/BUNDLED FILE BY ROLLUP
|
|
if you want to view the source visit the plugins github repository
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
var obsidian = require('obsidian');
|
|
var state = require('@codemirror/state');
|
|
var view = require('@codemirror/view');
|
|
var language = require('@codemirror/language');
|
|
|
|
/******************************************************************************
|
|
Copyright (c) Microsoft Corporation.
|
|
|
|
Permission to use, copy, modify, and/or distribute this software for any
|
|
purpose with or without fee is hereby granted.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
PERFORMANCE OF THIS SOFTWARE.
|
|
***************************************************************************** */
|
|
|
|
function __awaiter(thisArg, _arguments, P, generator) {
|
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
});
|
|
}
|
|
|
|
/*
|
|
* Filename: multi-column-markdown/src/regionSettings.ts
|
|
* Created Date: Tuesday, February 1st 2022, 12:23:53 pm
|
|
* Author: Cameron Robinson
|
|
*
|
|
* Copyright (c) 2022 Cameron Robinson
|
|
*/
|
|
var BorderOption;
|
|
(function (BorderOption) {
|
|
BorderOption[BorderOption["enabled"] = 0] = "enabled";
|
|
BorderOption[BorderOption["on"] = 1] = "on";
|
|
BorderOption[BorderOption["true"] = 2] = "true";
|
|
BorderOption[BorderOption["disabled"] = 3] = "disabled";
|
|
BorderOption[BorderOption["off"] = 4] = "off";
|
|
BorderOption[BorderOption["false"] = 5] = "false";
|
|
})(BorderOption || (BorderOption = {}));
|
|
var ShadowOption;
|
|
(function (ShadowOption) {
|
|
ShadowOption[ShadowOption["enabled"] = 0] = "enabled";
|
|
ShadowOption[ShadowOption["on"] = 1] = "on";
|
|
ShadowOption[ShadowOption["true"] = 2] = "true";
|
|
ShadowOption[ShadowOption["disabled"] = 3] = "disabled";
|
|
ShadowOption[ShadowOption["off"] = 4] = "off";
|
|
ShadowOption[ShadowOption["false"] = 5] = "false";
|
|
})(ShadowOption || (ShadowOption = {}));
|
|
var ColumnLayout;
|
|
(function (ColumnLayout) {
|
|
ColumnLayout[ColumnLayout["standard"] = 0] = "standard";
|
|
ColumnLayout[ColumnLayout["left"] = 1] = "left";
|
|
ColumnLayout[ColumnLayout["first"] = 2] = "first";
|
|
ColumnLayout[ColumnLayout["center"] = 3] = "center";
|
|
ColumnLayout[ColumnLayout["middle"] = 4] = "middle";
|
|
ColumnLayout[ColumnLayout["second"] = 5] = "second";
|
|
ColumnLayout[ColumnLayout["right"] = 6] = "right";
|
|
ColumnLayout[ColumnLayout["third"] = 7] = "third";
|
|
ColumnLayout[ColumnLayout["last"] = 8] = "last";
|
|
})(ColumnLayout || (ColumnLayout = {}));
|
|
var SingleColumnSize;
|
|
(function (SingleColumnSize) {
|
|
SingleColumnSize[SingleColumnSize["small"] = 0] = "small";
|
|
SingleColumnSize[SingleColumnSize["medium"] = 1] = "medium";
|
|
SingleColumnSize[SingleColumnSize["large"] = 2] = "large";
|
|
})(SingleColumnSize || (SingleColumnSize = {}));
|
|
var ContentOverflowType;
|
|
(function (ContentOverflowType) {
|
|
ContentOverflowType[ContentOverflowType["scroll"] = 0] = "scroll";
|
|
ContentOverflowType[ContentOverflowType["hidden"] = 1] = "hidden";
|
|
})(ContentOverflowType || (ContentOverflowType = {}));
|
|
function getDefaultMultiColumnSettings() {
|
|
return {
|
|
numberOfColumns: 2,
|
|
columnLayout: ColumnLayout.standard,
|
|
drawBorder: true,
|
|
drawShadow: true,
|
|
autoLayout: false,
|
|
columnSize: SingleColumnSize.medium,
|
|
columnPosition: ColumnLayout.standard,
|
|
columnSpacing: "",
|
|
contentOverflow: ContentOverflowType.scroll
|
|
};
|
|
}
|
|
|
|
/**
|
|
* File: /src/utilities/settingsParser.ts
|
|
* Created Date: Friday, June 3rd 2022, 8:16 pm
|
|
* Author: Cameron Robinson
|
|
*
|
|
* Copyright (c) 2022 Cameron Robinson
|
|
*/
|
|
/**
|
|
* Here we define all of the valid settings strings that the user can enter for each setting type.
|
|
* The strings are then mapped twice, first to a valid regex string that searches for the setting
|
|
* name, ignoring all extra spaces and letter case, and then maped to a RegEx object to be used
|
|
* when parsing.
|
|
*/
|
|
const COL_POSITION_OPTION_STRS = [
|
|
"column position",
|
|
"col position",
|
|
"column location",
|
|
"col location",
|
|
"single column location",
|
|
"single column position",
|
|
];
|
|
const COL_POSITION_REGEX_ARR = COL_POSITION_OPTION_STRS.map(convertStringToSettingsRegex).map((value) => {
|
|
return new RegExp(value, "i");
|
|
});
|
|
const COL_SIZE_OPTION_STRS = [
|
|
"column size",
|
|
"column width",
|
|
"col size",
|
|
"col width",
|
|
"single column size",
|
|
"single col size",
|
|
"single column width",
|
|
"single col width"
|
|
];
|
|
const COL_SIZE_OPTION_REGEX_ARR = COL_SIZE_OPTION_STRS.map(convertStringToSettingsRegex).map((value) => {
|
|
return new RegExp(value, "i");
|
|
});
|
|
const NUMBER_OF_COLUMNS_STRS = [
|
|
"number of columns"
|
|
];
|
|
const NUMBER_OF_COLUMNS_REGEX_ARR = NUMBER_OF_COLUMNS_STRS.map(convertStringToSettingsRegex).map((value) => {
|
|
return new RegExp(value, "i");
|
|
});
|
|
const LARGEST_COLUMN_STRS = [
|
|
"largest column"
|
|
];
|
|
const LARGEST_COLUMN_REGEX_ARR = LARGEST_COLUMN_STRS.map(convertStringToSettingsRegex).map((value) => {
|
|
return new RegExp(value, "i");
|
|
});
|
|
const DRAW_BORDER_STRS = [
|
|
"border"
|
|
];
|
|
const DRAW_BORDER_REGEX_ARR = DRAW_BORDER_STRS.map(convertStringToSettingsRegex).map((value) => {
|
|
return new RegExp(value, "i");
|
|
});
|
|
const DRAW_SHADOW_STRS = [
|
|
"shadow"
|
|
];
|
|
const DRAW_SHADOW_REGEX_ARR = DRAW_SHADOW_STRS.map(convertStringToSettingsRegex).map((value) => {
|
|
return new RegExp(value, "i");
|
|
});
|
|
const AUTO_LAYOUT_SETTING_STRS = [
|
|
"auto layout"
|
|
];
|
|
const AUTO_LAYOUT_REGEX_ARR = AUTO_LAYOUT_SETTING_STRS.map(convertStringToSettingsRegex).map((value) => {
|
|
return new RegExp(value, "i");
|
|
});
|
|
const COLUMN_SPACING_REGEX_ARR = [
|
|
"column spacing",
|
|
].map((value) => {
|
|
return new RegExp(convertStringToSettingsRegex(value), "i");
|
|
});
|
|
const CONTENT_OVERFLOW_REGEX_ARR = [
|
|
"overflow",
|
|
"content overflow"
|
|
].map((value) => {
|
|
return new RegExp(convertStringToSettingsRegex(value), "i");
|
|
});
|
|
/**
|
|
* This function searches the settings string through each regex option. If one of the regex
|
|
* values match, it returns the first group found by the regex. This is depended on proper
|
|
* regex formatting which is done by the convertStringToSettingsRegex function defined below.
|
|
*
|
|
* @param settingsString The value that may match one of the setting options.
|
|
* @param validSettingFormatRegEx The settings options through which to check all options. If one of these regex
|
|
* values match on the string we break from the loop returning the found value.
|
|
*
|
|
* @returns the user entered data if the setting is a match, or null if non of the options matched.
|
|
*/
|
|
function getSettingsDataFromKeys(settingsString, validSettingFormatRegEx) {
|
|
for (let i = 0; i < validSettingFormatRegEx.length; i++) {
|
|
let regexSearchData = validSettingFormatRegEx[i].exec(settingsString);
|
|
if (regexSearchData !== null) {
|
|
return regexSearchData[1].trim();
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
function parseSingleColumnSettings(settingsStr, originalSettings) {
|
|
let settingsLines = settingsStr.split("\n");
|
|
for (let i = 0; i < settingsLines.length; i++) {
|
|
let settingsLine = settingsLines[i];
|
|
let settingsData = getSettingsDataFromKeys(settingsLine, COL_POSITION_REGEX_ARR);
|
|
if (settingsData !== null) {
|
|
originalSettings.columnPosition = parseForSingleColumnLocation(settingsData);
|
|
}
|
|
settingsData = getSettingsDataFromKeys(settingsLine, COL_SIZE_OPTION_REGEX_ARR);
|
|
if (settingsData !== null) {
|
|
originalSettings.columnSize = parseForSingleColumnSize(settingsData);
|
|
}
|
|
}
|
|
return originalSettings;
|
|
}
|
|
function parseColumnSettings(settingsStr) {
|
|
let parsedSettings = getDefaultMultiColumnSettings();
|
|
let settingsLines = settingsStr.split("\n");
|
|
for (let i = 0; i < settingsLines.length; i++) {
|
|
let settingsLine = settingsLines[i];
|
|
let settingsData = getSettingsDataFromKeys(settingsLine, NUMBER_OF_COLUMNS_REGEX_ARR);
|
|
if (settingsData !== null) {
|
|
let numOfCols = parseInt(settingsData);
|
|
if (Number.isNaN(numOfCols) === false) {
|
|
if (numOfCols >= 1 && numOfCols <= 3) {
|
|
parsedSettings.numberOfColumns = numOfCols;
|
|
}
|
|
}
|
|
}
|
|
settingsData = getSettingsDataFromKeys(settingsLine, LARGEST_COLUMN_REGEX_ARR);
|
|
if (settingsData !== null) {
|
|
let userDefLayout = ColumnLayout[settingsData];
|
|
if (userDefLayout !== undefined) {
|
|
parsedSettings.columnLayout = userDefLayout;
|
|
parsedSettings.columnPosition = userDefLayout;
|
|
}
|
|
}
|
|
settingsData = getSettingsDataFromKeys(settingsLine, DRAW_BORDER_REGEX_ARR);
|
|
if (settingsData !== null) {
|
|
let isBorderDrawn = BorderOption[settingsData];
|
|
if (isBorderDrawn !== undefined) {
|
|
switch (isBorderDrawn) {
|
|
case (BorderOption.disabled):
|
|
case (BorderOption.off):
|
|
case (BorderOption.false):
|
|
parsedSettings.drawBorder = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
settingsData = getSettingsDataFromKeys(settingsLine, DRAW_SHADOW_REGEX_ARR);
|
|
if (settingsData !== null) {
|
|
let isShadowDrawn = ShadowOption[settingsData];
|
|
if (isShadowDrawn !== undefined) {
|
|
switch (isShadowDrawn) {
|
|
case (ShadowOption.disabled):
|
|
case (ShadowOption.off):
|
|
case (ShadowOption.false):
|
|
parsedSettings.drawShadow = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
settingsData = getSettingsDataFromKeys(settingsLine, AUTO_LAYOUT_REGEX_ARR);
|
|
if (settingsData !== null) {
|
|
if (settingsData === "true") {
|
|
parsedSettings.autoLayout = true;
|
|
}
|
|
}
|
|
settingsData = getSettingsDataFromKeys(settingsLine, COLUMN_SPACING_REGEX_ARR);
|
|
if (settingsData !== null) {
|
|
let parsed = getLengthUnit(settingsData.trim());
|
|
let spacingStr = "";
|
|
if (parsed.isValid) {
|
|
let noUnitsStr = settingsData.replace(parsed.unitStr, "").trim();
|
|
let noUnitsNum = parseInt(noUnitsStr);
|
|
if (isNaN(noUnitsNum) === false) {
|
|
spacingStr = `${noUnitsStr}${parsed.unitStr}`;
|
|
}
|
|
}
|
|
else {
|
|
let noUnitsNum = parseInt(settingsData.trim());
|
|
if (isNaN(noUnitsNum) === false) {
|
|
spacingStr = `${noUnitsNum}pt`;
|
|
}
|
|
}
|
|
parsedSettings.columnSpacing = spacingStr;
|
|
}
|
|
settingsData = getSettingsDataFromKeys(settingsLine, CONTENT_OVERFLOW_REGEX_ARR);
|
|
if (settingsData !== null) {
|
|
let overflowType = ContentOverflowType.scroll;
|
|
settingsData = settingsData.toLowerCase().trim();
|
|
if (settingsData === "hidden") {
|
|
overflowType = ContentOverflowType.hidden;
|
|
}
|
|
parsedSettings.contentOverflow = overflowType;
|
|
}
|
|
}
|
|
return parsedSettings;
|
|
}
|
|
function getLengthUnit(lengthStr) {
|
|
let lastChar = lengthStr.slice(lengthStr.length - 1);
|
|
let lastTwoChars = lengthStr.slice(lengthStr.length - 2);
|
|
let unitStr = "";
|
|
let isValid = false;
|
|
if (lastChar === "%") {
|
|
unitStr = lastChar;
|
|
isValid = true;
|
|
}
|
|
else if (lastTwoChars === "cm" ||
|
|
lastTwoChars === "mm" ||
|
|
lastTwoChars === "in" ||
|
|
lastTwoChars === "px" ||
|
|
lastTwoChars === "pt" ||
|
|
lastTwoChars === "pc" ||
|
|
lastTwoChars === "em" ||
|
|
lastTwoChars === "ex" ||
|
|
lastTwoChars === "ch" ||
|
|
lastTwoChars === "vw" ||
|
|
lastTwoChars === "vh") {
|
|
unitStr = lastTwoChars;
|
|
isValid = true;
|
|
}
|
|
return { isValid: isValid, unitStr: unitStr };
|
|
}
|
|
const CODEBLOCK_REGION_ID_REGEX_STRS = [
|
|
"id",
|
|
"region id"
|
|
];
|
|
const CODEBLOCK_REGION_ID_REGEX_ARR = CODEBLOCK_REGION_ID_REGEX_STRS.map(convertStringToSettingsRegex).map((value) => {
|
|
return new RegExp(value, "i");
|
|
});
|
|
function parseStartRegionCodeBlockID(settingsStr) {
|
|
let codeBlockRegionID = "";
|
|
let settingsLines = settingsStr.split("\n");
|
|
for (let i = 0; i < settingsLines.length; i++) {
|
|
let settingsLine = settingsLines[i];
|
|
let settingsData = getSettingsDataFromKeys(settingsLine, CODEBLOCK_REGION_ID_REGEX_ARR);
|
|
if (settingsData !== null) {
|
|
codeBlockRegionID = settingsData;
|
|
}
|
|
}
|
|
return codeBlockRegionID;
|
|
}
|
|
function parseForSingleColumnLocation(locationString) {
|
|
switch (locationString.toLowerCase().trim().replace(" ", "")) {
|
|
case "left":
|
|
case "leftside":
|
|
case "leftmargin":
|
|
case "leftalign":
|
|
case "leftaligned":
|
|
case "leftalignement":
|
|
case "first":
|
|
case "start":
|
|
case "beginning":
|
|
return ColumnLayout.left;
|
|
case "middle":
|
|
case "middlealigned":
|
|
case "middlealignment":
|
|
case "center":
|
|
case "centeraligned":
|
|
case "centeralignment":
|
|
case "centered":
|
|
case "standard":
|
|
return ColumnLayout.center;
|
|
case "right":
|
|
case "rightside":
|
|
case "rightmargin":
|
|
case "rightalign":
|
|
case "rightaligned":
|
|
case "rightalignment":
|
|
case "last":
|
|
case "end":
|
|
return ColumnLayout.right;
|
|
}
|
|
return ColumnLayout.center;
|
|
}
|
|
function parseForSingleColumnSize(sizeString) {
|
|
switch (sizeString = sizeString.toLowerCase().trim().replace(" ", "")) {
|
|
case "small":
|
|
case "sm":
|
|
return SingleColumnSize.small;
|
|
case "medium":
|
|
case "med":
|
|
return SingleColumnSize.medium;
|
|
case "large":
|
|
case "lg":
|
|
return SingleColumnSize.large;
|
|
}
|
|
return SingleColumnSize.medium;
|
|
}
|
|
function convertStringToSettingsRegex(originalString) {
|
|
originalString = originalString.replace(" ", " *");
|
|
let regexString = `(?:${originalString} *: *)(.*)`;
|
|
return regexString;
|
|
}
|
|
|
|
/*
|
|
* File: multi-column-markdown/src/MultiColumnParser.ts
|
|
* Created Date: Saturday, January 22nd 2022, 6:02:46 pm
|
|
* Author: Cameron Robinson
|
|
*
|
|
* Copyright (c) 2022 Cameron Robinson
|
|
*/
|
|
const START_REGEX_STRS = ["=== *start-multi-column(:?[a-zA-Z0-9-_\\s]*)?",
|
|
"=== *multi-column-start(:?[a-zA-Z0-9-_\\s]*)?"];
|
|
const START_REGEX_ARR = [];
|
|
for (let i = 0; i < START_REGEX_STRS.length; i++) {
|
|
START_REGEX_ARR.push(new RegExp(START_REGEX_STRS[i]));
|
|
}
|
|
const START_REGEX_STRS_WHOLE_LINE = ["^=== *start-multi-column(:?[a-zA-Z0-9-_\\s]*)?$",
|
|
"^=== *multi-column-start(:?[a-zA-Z0-9-_\\s]*)?$"];
|
|
const START_REGEX_ARR_WHOLE_LINE = [];
|
|
for (let i = 0; i < START_REGEX_STRS_WHOLE_LINE.length; i++) {
|
|
START_REGEX_ARR_WHOLE_LINE.push(new RegExp(START_REGEX_STRS_WHOLE_LINE[i]));
|
|
}
|
|
function findStartTag(text) {
|
|
let found = false;
|
|
let startPosition = -1;
|
|
let matchLength = 0;
|
|
for (let i = 0; i < START_REGEX_ARR.length; i++) {
|
|
let regexData = START_REGEX_ARR[i].exec(text);
|
|
if (regexData !== null && regexData.length > 0) {
|
|
startPosition = regexData.index;
|
|
matchLength = regexData[0].length;
|
|
let line = text.slice(startPosition, startPosition + matchLength);
|
|
if (START_REGEX_ARR_WHOLE_LINE[i].test(line)) {
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
let endPosition = startPosition + matchLength;
|
|
return { found, startPosition, endPosition, matchLength };
|
|
}
|
|
function containsStartTag(text) {
|
|
return findStartTag(text).found;
|
|
}
|
|
function isStartTagWithID(text) {
|
|
let startTagData = findStartTag(text);
|
|
if (startTagData.found === true) {
|
|
let key = getStartTagKey(text);
|
|
if (key === null || key === "") {
|
|
return { isStartTag: true, hasKey: false };
|
|
}
|
|
return { isStartTag: true, hasKey: true };
|
|
}
|
|
return { isStartTag: false, hasKey: false };
|
|
}
|
|
const END_REGEX_STRS = ["=== *end-multi-column",
|
|
"=== *multi-column-end"];
|
|
const END_REGEX_ARR = [];
|
|
for (let i = 0; i < END_REGEX_STRS.length; i++) {
|
|
END_REGEX_ARR.push(new RegExp(END_REGEX_STRS[i]));
|
|
}
|
|
function findEndTag(text) {
|
|
let found = false;
|
|
let startPosition = -1;
|
|
for (let i = 0; i < END_REGEX_ARR.length; i++) {
|
|
if (END_REGEX_ARR[i].test(text)) {
|
|
found = true;
|
|
startPosition = text.search(END_REGEX_STRS[i]);
|
|
break;
|
|
}
|
|
}
|
|
let endPosition = -1;
|
|
let matchLength = 0;
|
|
for (let i = 0; i < END_REGEX_ARR.length; i++) {
|
|
let regexData = END_REGEX_ARR[i].exec(text);
|
|
if (regexData !== null && regexData.length > 0) {
|
|
found = true;
|
|
startPosition = regexData.index;
|
|
matchLength = regexData[0].length;
|
|
break;
|
|
}
|
|
}
|
|
endPosition = startPosition + matchLength;
|
|
return { found, startPosition, endPosition, matchLength };
|
|
}
|
|
function containsEndTag(text) {
|
|
return findEndTag(text).found;
|
|
}
|
|
const COL_REGEX_STRS = ["=== *column-end *===",
|
|
"=== *end-column *===",
|
|
"=== *column-break *===",
|
|
"=== *break-column *===",
|
|
"--- *column-end *---",
|
|
"--- *end-column *---",
|
|
"--- *column-break *---",
|
|
"--- *break-column *---"];
|
|
const COL_REGEX_ARR = [];
|
|
for (let i = 0; i < COL_REGEX_STRS.length; i++) {
|
|
COL_REGEX_ARR.push(new RegExp(COL_REGEX_STRS[i]));
|
|
}
|
|
function containsColEndTag(text) {
|
|
let found = false;
|
|
for (let i = 0; i < COL_REGEX_ARR.length; i++) {
|
|
if (COL_REGEX_ARR[i].test(text)) {
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
return found;
|
|
}
|
|
const COL_ELEMENT_INNER_TEXT_REGEX_STRS = ["= *column-end *=",
|
|
"= *end-column *=",
|
|
"= *column-break *=",
|
|
"= *break-column *="];
|
|
for (let i = 0; i < COL_ELEMENT_INNER_TEXT_REGEX_STRS.length; i++) {
|
|
COL_REGEX_ARR.push(new RegExp(COL_ELEMENT_INNER_TEXT_REGEX_STRS[i]));
|
|
}
|
|
function elInnerTextContainsColEndTag(text) {
|
|
let found = false;
|
|
for (let i = 0; i < COL_REGEX_ARR.length; i++) {
|
|
if (COL_REGEX_ARR[i].test(text)) {
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
return found;
|
|
}
|
|
const COL_SETTINGS_REGEX_STRS = ["```settings",
|
|
"```column-settings",
|
|
"```multi-column-settings"];
|
|
const COL_SETTINGS_REGEX_ARR = [];
|
|
for (let i = 0; i < COL_SETTINGS_REGEX_STRS.length; i++) {
|
|
COL_SETTINGS_REGEX_ARR.push(new RegExp(COL_SETTINGS_REGEX_STRS[i]));
|
|
}
|
|
function containsColSettingsTag(text) {
|
|
let found = false;
|
|
for (let i = 0; i < COL_SETTINGS_REGEX_ARR.length; i++) {
|
|
if (COL_SETTINGS_REGEX_ARR[i].test(text)) {
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
return found;
|
|
}
|
|
function findSettingsCodeblock(text) {
|
|
let found = false;
|
|
let startPosition = -1;
|
|
let endPosition = -1;
|
|
let matchLength = 0;
|
|
for (let i = 0; i < COL_SETTINGS_REGEX_ARR.length; i++) {
|
|
let regexData = COL_SETTINGS_REGEX_ARR[i].exec(text);
|
|
if (regexData !== null && regexData.length > 0) {
|
|
found = true;
|
|
startPosition = regexData.index;
|
|
matchLength = regexData[0].length;
|
|
endPosition = startPosition + matchLength;
|
|
let remainingText = text.slice(endPosition);
|
|
regexData = CODEBLOCK_END_REGEX.exec(remainingText);
|
|
if (regexData !== null && regexData.length > 0) {
|
|
found = true;
|
|
endPosition += regexData.index + regexData[0].length;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
return { found, startPosition, endPosition, matchLength };
|
|
}
|
|
const START_CODEBLOCK_REGEX_ARR = [
|
|
"```multi-column-start",
|
|
"```start-multi-column"
|
|
].map((val) => {
|
|
return new RegExp(val);
|
|
});
|
|
function findStartCodeblock(text) {
|
|
let found = false;
|
|
let startPosition = -1;
|
|
let endPosition = -1;
|
|
let matchLength = 0;
|
|
for (let i = 0; i < START_CODEBLOCK_REGEX_ARR.length; i++) {
|
|
let regexData = START_CODEBLOCK_REGEX_ARR[i].exec(text);
|
|
if (regexData !== null && regexData.length > 0) {
|
|
found = true;
|
|
startPosition = regexData.index;
|
|
matchLength = regexData[0].length;
|
|
endPosition = startPosition + matchLength;
|
|
let remainingText = text.slice(endPosition);
|
|
regexData = CODEBLOCK_END_REGEX.exec(remainingText);
|
|
if (regexData !== null && regexData.length > 0) {
|
|
found = true;
|
|
endPosition += regexData.index + regexData[0].length;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
return { found, startPosition, endPosition, matchLength };
|
|
}
|
|
function containsStartCodeBlock(text) {
|
|
return findStartCodeblock(text).found;
|
|
}
|
|
function containsRegionStart(text) {
|
|
return containsStartCodeBlock(text) || containsStartTag(text);
|
|
}
|
|
function countStartTags(initialText) {
|
|
let keys = [];
|
|
let text = initialText;
|
|
let startTagData = findStartTag(text);
|
|
while (startTagData.found) {
|
|
// Slice off everything before the tag
|
|
text = text.slice(startTagData.startPosition);
|
|
/**
|
|
* Get just the start tag line and then set text to everything just
|
|
* after the start tag.
|
|
*/
|
|
let tag = text.split("\n")[0];
|
|
text = text.slice(1); // This moves the text 1 character so we dont match the same tag.
|
|
// Parse out the key and append to the list.
|
|
let key = getStartTagKey(tag);
|
|
if (key === null) {
|
|
key = "";
|
|
}
|
|
keys.push(key);
|
|
// Search again for another tag before looping.
|
|
startTagData = findStartTag(text);
|
|
}
|
|
text = initialText;
|
|
startTagData = findStartCodeblock(text);
|
|
while (startTagData.found) {
|
|
let settingsText = text.slice(startTagData.startPosition, startTagData.endPosition);
|
|
text = text.slice(startTagData.endPosition);
|
|
let key = parseStartRegionCodeBlockID(settingsText);
|
|
if (key === null) {
|
|
key = "";
|
|
}
|
|
keys.push(key);
|
|
// Search again for another tag before looping.
|
|
startTagData = findStartCodeblock(text);
|
|
}
|
|
return { numberOfTags: keys.length, keys };
|
|
}
|
|
function getStartBlockOrCodeblockAboveLine(linesAboveArray) {
|
|
let startBlock = getStartBlockAboveLine(linesAboveArray);
|
|
if (startBlock !== null) {
|
|
return startBlock;
|
|
}
|
|
let codeBlock = getStartCodeBlockAboveLine(linesAboveArray);
|
|
if (codeBlock !== null) {
|
|
return codeBlock;
|
|
}
|
|
return null;
|
|
}
|
|
/**
|
|
* This function will filter a set of strings, returning all items starting
|
|
* from the closest open start tag through the last item in the set.
|
|
*
|
|
* The function filters out all end tags to make sure that the start tag we
|
|
* find is the proper start tag for the list sent.
|
|
* @param linesAboveArray
|
|
* @returns
|
|
*/
|
|
function getStartBlockAboveLine(linesAboveArray) {
|
|
// Reduce the array down into a single string so that we can
|
|
// easily RegEx over the string and find the indicies we're looking for.
|
|
let linesAboveStr = linesAboveArray.reduce((prev, current) => {
|
|
return prev + "\n" + current;
|
|
}, "");
|
|
/*
|
|
* First thing we need to do is check if there are any end tags in the
|
|
* set of strings (which logically would close start tags and therefore
|
|
* the start tag it closes is not what we want). If there are we want to
|
|
* slowly narrow down our set of strings until the last end tag is
|
|
* removed. This makes it easier to find the closest open start tag
|
|
* in the data.
|
|
*/
|
|
let endTagSerachData = findEndTag(linesAboveStr);
|
|
while (endTagSerachData.found === true) {
|
|
// Get the index of where the first regex match in the
|
|
// string is. then we slice from 0 to index off of the string
|
|
// split it by newline, cut off the first line (which actually
|
|
// contains the regex) then reduce back down to a single string.
|
|
//
|
|
// TODO: This could be simplified if we just slice the text after
|
|
// the end tag instead of the begining.
|
|
let indexOfRegex = endTagSerachData.startPosition;
|
|
linesAboveArray = linesAboveStr.slice(indexOfRegex).split("\n").splice(1);
|
|
linesAboveStr = linesAboveArray.reduce((prev, current) => {
|
|
return prev + "\n" + current;
|
|
}, "");
|
|
endTagSerachData = findEndTag(linesAboveStr);
|
|
}
|
|
/**
|
|
* Now we have the set of lines after all other end tags. We now
|
|
* need to check if there is still a start tag left in the data. If
|
|
* there is no start tag then we want to return an empty array and empty
|
|
* key.
|
|
*/
|
|
let startBlockKey = "";
|
|
let startTagSearchData = findStartTag(linesAboveStr);
|
|
if (startTagSearchData.found === false) {
|
|
return null;
|
|
}
|
|
else {
|
|
/**
|
|
* Now we know there is at least 1 start key left, however there
|
|
* may be multiple start keys if the user is not closing their
|
|
* blocks. We currently dont allow recusive splitting so we
|
|
* want to get the last key in our remaining set. Same idea as
|
|
* above.
|
|
*/
|
|
while (startTagSearchData.found === true) {
|
|
// Get the index of where the first regex match in the
|
|
// string is. then we slice from 0 to index off of the string
|
|
// split it by newline, cut off the first line (which actually
|
|
// contains the regex) then reduce back down to a single string.
|
|
//
|
|
// TODO: This could be simplified if we just slice the text after
|
|
// the end tag instead of the begining.
|
|
let startIndex = startTagSearchData.startPosition;
|
|
linesAboveArray = linesAboveStr.slice(startIndex).split("\n");
|
|
let startTag = linesAboveArray[0];
|
|
let key = getStartTagKey(startTag);
|
|
if (key !== null) {
|
|
startBlockKey = key;
|
|
}
|
|
linesAboveArray = linesAboveArray.splice(1);
|
|
linesAboveStr = linesAboveArray.reduce((prev, current) => {
|
|
return prev + "\n" + current;
|
|
}, "");
|
|
startTagSearchData = findStartTag(linesAboveStr);
|
|
}
|
|
}
|
|
if (startBlockKey === "") {
|
|
let codeBlockData = parseCodeBlockStart(linesAboveArray);
|
|
if (codeBlockData !== null) {
|
|
startBlockKey = codeBlockData.id;
|
|
if (codeBlockData.index > 0) {
|
|
linesAboveArray = linesAboveArray.slice(codeBlockData.index + 1);
|
|
}
|
|
}
|
|
}
|
|
return { startBlockKey, linesAboveArray };
|
|
}
|
|
function getStartCodeBlockAboveLine(linesAboveArray) {
|
|
let linesAboveStr = linesAboveArray.reduce((prev, current) => {
|
|
return prev + "\n" + current;
|
|
}, "");
|
|
/*
|
|
* First thing we need to do is check if there are any end tags in the
|
|
* set of strings (which logically would close start tags and therefore
|
|
* the start tag it closes is not what we want). If there are we want to
|
|
* slowly narrow down our set of strings until the last end tag is
|
|
* removed. This makes it easier to find the closest open start tag
|
|
* in the data.
|
|
*/
|
|
let endTagSerachData = findEndTag(linesAboveStr);
|
|
while (endTagSerachData.found === true) {
|
|
// Get the index of where the first regex match in the
|
|
// string is. then we slice from 0 to index off of the string
|
|
// split it by newline, cut off the first line (which actually
|
|
// contains the regex) then reduce back down to a single string.
|
|
linesAboveStr = linesAboveStr.slice(endTagSerachData.endPosition);
|
|
endTagSerachData = findEndTag(linesAboveStr);
|
|
}
|
|
let startCodeBlockData = findStartCodeblock(linesAboveStr);
|
|
let codeBlockText = linesAboveStr.slice(startCodeBlockData.startPosition, startCodeBlockData.endPosition);
|
|
let startBlockKey = "";
|
|
if (startCodeBlockData.found === false) {
|
|
return null;
|
|
}
|
|
else {
|
|
/**
|
|
* Now we know there is at least 1 start key left, however there
|
|
* may be multiple start keys if the user is not closing their
|
|
* blocks. We currently dont allow recusive splitting so we
|
|
* want to get the last key in our remaining set. Same idea as
|
|
* above.
|
|
*/
|
|
while (startCodeBlockData.found === true) {
|
|
// Get the index of where the first regex match in the
|
|
// string is. then we slice from 0 to index off of the string
|
|
// split it by newline, cut off the first line (which actually
|
|
// contains the regex) then reduce back down to a single string.
|
|
codeBlockText = linesAboveStr.slice(startCodeBlockData.startPosition, startCodeBlockData.endPosition);
|
|
startBlockKey = parseStartRegionCodeBlockID(codeBlockText);
|
|
linesAboveStr = linesAboveStr.slice(startCodeBlockData.endPosition);
|
|
startCodeBlockData = findStartCodeblock(linesAboveStr);
|
|
}
|
|
}
|
|
let retLinesAboveArray = linesAboveStr.split("\n");
|
|
return { startBlockKey, linesAboveArray: retLinesAboveArray };
|
|
}
|
|
function getEndBlockBelow(linesBelow) {
|
|
// Reduce the array down into a single string so that we can
|
|
// easily RegEx over the string and find the indicies we're looking for.
|
|
let linesBelowStr = linesBelow.reduce((prev, current) => {
|
|
return prev + "\n" + current;
|
|
}, "");
|
|
let endTagSerachData = findEndTag(linesBelowStr);
|
|
let startTagSearchData = findStartTag(linesBelowStr);
|
|
let sliceEndIndex = -1; // If neither start or end found we return the entire array.
|
|
if (endTagSerachData.found === true && startTagSearchData.found === false) {
|
|
sliceEndIndex = endTagSerachData.startPosition;
|
|
}
|
|
else if (endTagSerachData.found === false && startTagSearchData.found === true) {
|
|
sliceEndIndex = startTagSearchData.startPosition;
|
|
}
|
|
else if (endTagSerachData.found === true && startTagSearchData.found === true) {
|
|
sliceEndIndex = endTagSerachData.startPosition;
|
|
if (startTagSearchData.startPosition < endTagSerachData.startPosition) {
|
|
/**
|
|
* If we found a start tag before an end tag we want to use the start tag
|
|
* our current block is not properly ended and we use the next start tag
|
|
* as our limit
|
|
*/
|
|
sliceEndIndex = startTagSearchData.startPosition;
|
|
}
|
|
}
|
|
return linesBelow.slice(0, sliceEndIndex);
|
|
}
|
|
function getStartTagKey(startTag) {
|
|
let keySplit = startTag.split(":");
|
|
if (keySplit.length > 1) {
|
|
return keySplit[1].replace(" ", "");
|
|
}
|
|
return null;
|
|
}
|
|
const TAB_HEADER_END_REGEX_STR = "^```$";
|
|
const TAB_HEADER_END_REGEX = new RegExp(TAB_HEADER_END_REGEX_STR);
|
|
function parseCodeBlockStart(codeBlockLines) {
|
|
let id = null;
|
|
for (let i = 0; i < codeBlockLines.length; i++) {
|
|
let line = codeBlockLines[i];
|
|
if (id === null) {
|
|
let key = line.split(":")[0];
|
|
if (key.toLowerCase() === "region id") {
|
|
id = line.split(":")[1].trim();
|
|
}
|
|
}
|
|
else {
|
|
if (TAB_HEADER_END_REGEX.test(line)) {
|
|
return { id: id, index: i };
|
|
}
|
|
}
|
|
}
|
|
if (id === null) {
|
|
return null;
|
|
}
|
|
else {
|
|
return { id: id, index: -1 };
|
|
}
|
|
}
|
|
const CODEBLOCK_END_REGEX_STR = "```";
|
|
const CODEBLOCK_END_REGEX = new RegExp(CODEBLOCK_END_REGEX_STR);
|
|
|
|
/*
|
|
* Filename: multi-column-markdown/src/utilities/utils.ts
|
|
* Created Date: Tuesday, January 30th 2022, 4:02:19 pm
|
|
* Author: Cameron Robinson
|
|
*
|
|
* Copyright (c) 2022 Cameron Robinson
|
|
*/
|
|
function getUID(length = 10) {
|
|
if (length > 10) {
|
|
length = 10;
|
|
}
|
|
let UID = Math.random().toString(36).substring(2);
|
|
UID = UID.slice(0, length);
|
|
return UID;
|
|
}
|
|
/**
|
|
* BFS on the child nodes of the passed element searching for the first instance of the
|
|
* node type passed. Returning the element found or null if none found.
|
|
*
|
|
* @param root
|
|
* @param nodeTypeName
|
|
* @returns
|
|
*/
|
|
function searchChildrenForNodeType(root, nodeTypeName) {
|
|
nodeTypeName = nodeTypeName.toLowerCase();
|
|
let queue = [root];
|
|
while (queue.length > 0) {
|
|
for (let i = 0; i < queue.length; i++) {
|
|
let node = queue.shift();
|
|
let nodeName = node.nodeName.toLowerCase();
|
|
if (nodeName === nodeTypeName) {
|
|
return node;
|
|
}
|
|
for (let i = 0; i < node.children.length; i++) {
|
|
queue.push(node.children[i]);
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
function getLeafSourceMode(fileLeaf) {
|
|
return fileLeaf.getViewState().state.mode;
|
|
}
|
|
function fileStillInView(sourcePath) {
|
|
let fileLeaf = getFileLeaf(sourcePath);
|
|
if (fileLeaf === null) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
function getFileLeaf(sourcePath) {
|
|
let markdownLeaves = app.workspace.getLeavesOfType("markdown");
|
|
if (markdownLeaves.length === 0) {
|
|
return null;
|
|
}
|
|
for (let i = 0; i < markdownLeaves.length; i++) {
|
|
if (markdownLeaves[i].getViewState().state.file === sourcePath) {
|
|
return markdownLeaves[i];
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
var ElementRenderType;
|
|
(function (ElementRenderType) {
|
|
ElementRenderType[ElementRenderType["undefined"] = 0] = "undefined";
|
|
ElementRenderType[ElementRenderType["normalRender"] = 1] = "normalRender";
|
|
ElementRenderType[ElementRenderType["specialRender"] = 2] = "specialRender";
|
|
ElementRenderType[ElementRenderType["specialSingleElementRender"] = 3] = "specialSingleElementRender";
|
|
ElementRenderType[ElementRenderType["canvasRenderElement"] = 4] = "canvasRenderElement";
|
|
ElementRenderType[ElementRenderType["unRendered"] = 5] = "unRendered";
|
|
})(ElementRenderType || (ElementRenderType = {}));
|
|
function getElementRenderType(element) {
|
|
/**
|
|
* The Dataview plugin needs to be constantly checked if the clone should be
|
|
* updated but should not always update the "dual render" aspect, so we add
|
|
* a special case for that plugin and maybe others in the future.
|
|
*/
|
|
if (hasDataview(element) === true) {
|
|
return ElementRenderType.specialSingleElementRender;
|
|
}
|
|
/**
|
|
* Some types of content are rendered in canvases which are not rendered properly
|
|
* when we clone the original node. Here we are flagging the element as a canvas
|
|
* element so we can clone the canvas to a copy element within the region.
|
|
*
|
|
*/
|
|
if (hasDataviewJS(element) === true) {
|
|
return ElementRenderType.canvasRenderElement;
|
|
}
|
|
/**
|
|
* Look for specific kinds of elements by their CSS class names here. These
|
|
* are going to be brittle links as they rely on other plugin definitions but
|
|
* as this is only adding in extra compatability to the plugins defined here
|
|
* it should be ok.
|
|
*
|
|
* These may be classes on one of the simple elements (such as a paragraph)
|
|
* that we search for below so need to look for these first.
|
|
*/
|
|
if (hasDiceRoller(element) === true ||
|
|
hasCopyButton(element) === true ||
|
|
hasAdmonitionFold(element) === true) {
|
|
return ElementRenderType.specialRender;
|
|
}
|
|
/**
|
|
* This checks for special types of elements that should be rendered normally. Is
|
|
* slightly redundant with next check but differentiates between types of ements
|
|
* being checked.
|
|
*/
|
|
if (hasAdmonition(element) === true ||
|
|
isIFrame(element) === true) {
|
|
return ElementRenderType.normalRender;
|
|
}
|
|
/**
|
|
* If we didnt find a special element we want to check for simple elements
|
|
* such as paragraphs or lists. In the current implementation we only set up
|
|
* the special case for "specialRender" elements so this *should* be saving
|
|
* some rendering time by setting these tags properly.
|
|
*/
|
|
if (hasParagraph(element) ||
|
|
hasHeader(element) ||
|
|
hasList(element) ||
|
|
isHorizontalRule(element) ||
|
|
isTable(element)) {
|
|
return ElementRenderType.normalRender;
|
|
}
|
|
// If still nothing found we return other as the default response if nothing else found.
|
|
return ElementRenderType.specialRender;
|
|
}
|
|
function hasParagraph(element) {
|
|
return element.innerHTML.startsWith("<p");
|
|
}
|
|
function hasHeader(element) {
|
|
if (element.innerHTML.startsWith("<h1") ||
|
|
element.innerHTML.startsWith("<h2") ||
|
|
element.innerHTML.startsWith("<h3") ||
|
|
element.innerHTML.startsWith("<h4") ||
|
|
element.innerHTML.startsWith("<h5") ||
|
|
element.innerHTML.startsWith("<h6")) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
function hasList(element) {
|
|
if (element.innerHTML.startsWith("<ul") ||
|
|
element.innerHTML.startsWith("<ol")) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
function hasCopyButton(element) {
|
|
return element.getElementsByClassName("copy-code-button").length !== 0 ||
|
|
element.getElementsByClassName("admonition-content-copy").length !== 0;
|
|
}
|
|
function hasDiceRoller(element) {
|
|
return element.getElementsByClassName("dice-roller").length !== 0;
|
|
}
|
|
function hasAdmonition(element) {
|
|
return element.getElementsByClassName("admonition").length !== 0;
|
|
}
|
|
function isIFrame(element) {
|
|
if (element.children.length > 0) {
|
|
return element.firstChild.nodeName.toLowerCase() === "iframe";
|
|
}
|
|
return false;
|
|
}
|
|
function isHorizontalRule(element) {
|
|
return element.innerHTML.startsWith("<hr");
|
|
}
|
|
function isTable(element) {
|
|
return element.innerHTML.startsWith("<table");
|
|
}
|
|
function hasAdmonitionFold(element) {
|
|
return element.getElementsByClassName("callout-fold").length !== 0;
|
|
}
|
|
function hasDataview(element) {
|
|
let isDataview = element.getElementsByClassName("dataview").length !== 0;
|
|
return isDataview;
|
|
}
|
|
function hasDataviewJS(element) {
|
|
let isDataviewJS = element.getElementsByClassName("block-language-dataviewjs").length !== 0;
|
|
let canvas = searchChildrenForNodeType(element, "canvas");
|
|
/**
|
|
* This means only dataviewJS chart canvas elements should be rendered properly. Other canvases will
|
|
* need thier own case put in or the restriction removed after testing.
|
|
*/
|
|
return canvas !== null && isDataviewJS;
|
|
}
|
|
function getHeadingCollapseElement(element) {
|
|
if (element === null) {
|
|
return null;
|
|
}
|
|
let childElements = element.getElementsByClassName("heading-collapse-indicator");
|
|
if (childElements.length === 1) {
|
|
return childElements[0];
|
|
}
|
|
if (childElements.length > 1) {
|
|
console.debug("Found multiple heading collapse indicators in element.");
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/*
|
|
* Filename: multi-column-markdown/src/domObject.ts
|
|
* Created Date: Tuesday, February 1st 2022, 12:04:00 pm
|
|
* Author: Cameron Robinson
|
|
*
|
|
* Copyright (c) 2022 Cameron Robinson
|
|
*/
|
|
var DOMObjectTag;
|
|
(function (DOMObjectTag) {
|
|
DOMObjectTag[DOMObjectTag["none"] = 0] = "none";
|
|
DOMObjectTag[DOMObjectTag["startRegion"] = 1] = "startRegion";
|
|
DOMObjectTag[DOMObjectTag["regionSettings"] = 2] = "regionSettings";
|
|
DOMObjectTag[DOMObjectTag["columnBreak"] = 3] = "columnBreak";
|
|
DOMObjectTag[DOMObjectTag["endRegion"] = 4] = "endRegion";
|
|
})(DOMObjectTag || (DOMObjectTag = {}));
|
|
class DOMObject {
|
|
constructor(element, linesOfElement, randomID = getUID(), tag = DOMObjectTag.none) {
|
|
this.clonedElement = null;
|
|
this.elementType = ElementRenderType.undefined;
|
|
this.elementContainer = null;
|
|
this.elementRenderedHeight = 0;
|
|
this.nodeKey = element.innerText.trim();
|
|
this.originalElement = element;
|
|
this.UID = randomID;
|
|
this.tag = tag;
|
|
this.usingOriginalElement = false;
|
|
this.linesOfElement = linesOfElement;
|
|
if (this.tag === DOMObjectTag.none) {
|
|
this.setDomObjectTag();
|
|
}
|
|
}
|
|
setMainDOMElement(domElement) {
|
|
this.originalElement = domElement;
|
|
this.usingOriginalElement = true;
|
|
}
|
|
setDomObjectTag() {
|
|
let elementTextSpaced = this.linesOfElement.reduce((prev, curr) => {
|
|
return prev + "\n" + curr;
|
|
});
|
|
if (containsEndTag(this.originalElement.textContent) === true) {
|
|
this.elementType = ElementRenderType.unRendered;
|
|
this.tag = DOMObjectTag.endRegion;
|
|
// el.addClass(MultiColumnStyleCSS.RegionEndTag)
|
|
// regionalManager.updateElementTag(currentObject.UID, DOMObjectTag.endRegion);
|
|
}
|
|
else if (containsColEndTag(this.originalElement.textContent) === true ||
|
|
(this.originalElement.innerHTML.startsWith("<mark>")) && elInnerTextContainsColEndTag(this.originalElement.textContent)) {
|
|
this.elementType = ElementRenderType.unRendered;
|
|
this.tag = DOMObjectTag.columnBreak;
|
|
// el.addClass(MultiColumnStyleCSS.ColumnEndTag)
|
|
// regionalManager.updateElementTag(currentObject.UID, DOMObjectTag.columnBreak);
|
|
}
|
|
else if (containsStartTag(this.originalElement.textContent) === true) {
|
|
this.elementType = ElementRenderType.unRendered;
|
|
this.tag = DOMObjectTag.startRegion;
|
|
// el.addClass(MultiColumnStyleCSS.ColumnEndTag)
|
|
// regionalManager.updateElementTag(currentObject.UID, DOMObjectTag.columnBreak);
|
|
}
|
|
else if (containsColSettingsTag(elementTextSpaced) === true) {
|
|
this.elementType = ElementRenderType.unRendered;
|
|
// el.addClass(MultiColumnStyleCSS.RegionSettings)
|
|
// regionalManager = regionalContainer.setRegionSettings(elementTextSpaced)
|
|
// regionalManager.updateElementTag(currentObject.UID, DOMObjectTag.regionSettings);
|
|
}
|
|
}
|
|
}
|
|
class TaskListDOMObject extends DOMObject {
|
|
constructor(baseDOMObject) {
|
|
super(baseDOMObject.originalElement, baseDOMObject.linesOfElement, baseDOMObject.UID, DOMObjectTag.none);
|
|
this.originalCheckboxes = [];
|
|
}
|
|
checkboxClicked(index) {
|
|
if (index < this.originalCheckboxes.length) {
|
|
let originalInput = this.originalCheckboxes[index].firstChild;
|
|
originalInput.click();
|
|
}
|
|
}
|
|
static checkForTaskListElement(domElement) {
|
|
if (domElement.originalElement.getElementsByClassName("task-list-item").length > 0) {
|
|
return new TaskListDOMObject(domElement);
|
|
}
|
|
return domElement;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* File: multi-column-markdown/src/utilities/cssDefinitions.ts
|
|
* Created Date: Wednesday, February 16th 2022, 11:09:06 am
|
|
* Author: Cameron Robinson
|
|
*
|
|
* Copyright (c) 2022 Cameron Robinson
|
|
*/
|
|
var MultiColumnLayoutCSS;
|
|
(function (MultiColumnLayoutCSS) {
|
|
MultiColumnLayoutCSS["RegionRootContainerDiv"] = "mcm-column-root-container";
|
|
MultiColumnLayoutCSS["RegionErrorContainerDiv"] = "mcm-column-error-region-wrapper";
|
|
MultiColumnLayoutCSS["RegionContentContainerDiv"] = "mcm-column-region-wrapper";
|
|
MultiColumnLayoutCSS["RegionColumnContainerDiv"] = "mcm-column-parent-container";
|
|
MultiColumnLayoutCSS["ColumnDualElementContainer"] = "mcm-column-element-wrapper";
|
|
MultiColumnLayoutCSS["OriginalElementType"] = "mcm-original-column-element";
|
|
MultiColumnLayoutCSS["ClonedElementType"] = "mcm-cloned-column-element";
|
|
MultiColumnLayoutCSS["ContentOverflowAutoScroll"] = "mcm-content-overflow-auto-scroll";
|
|
MultiColumnLayoutCSS["ContentOverflowHidden"] = "mcm-content-overflow-hidden";
|
|
// ------------------------------------------------------ //
|
|
MultiColumnLayoutCSS["SingleColumnSmall"] = "mcm-single-column-small";
|
|
MultiColumnLayoutCSS["SingleColumnMed"] = "mcm-single-column-medium";
|
|
MultiColumnLayoutCSS["SingleColumnLarge"] = "mcm-single-column-large";
|
|
MultiColumnLayoutCSS["SingleColumnLeftLayout"] = "mcm-singlecol-layout-left";
|
|
MultiColumnLayoutCSS["SingleColumnCenterLayout"] = "mcm-singlecol-layout-center";
|
|
MultiColumnLayoutCSS["SingleColumnRightLayout"] = "mcm-singlecol-layout-right";
|
|
// ------------------------------------------------------ //
|
|
MultiColumnLayoutCSS["TwoEqualColumns"] = "mcm-two-equal-columns";
|
|
MultiColumnLayoutCSS["TwoColumnSmall"] = "mcm-two-column-small";
|
|
MultiColumnLayoutCSS["TwoColumnLarge"] = "mcm-two-column-large";
|
|
// ------------------------------------------------------ //
|
|
MultiColumnLayoutCSS["ThreeEqualColumns"] = "mcm-three-equal-columns";
|
|
MultiColumnLayoutCSS["ThreeColumn_Large"] = "mcm-three-column-large";
|
|
MultiColumnLayoutCSS["ThreeColumn_Small"] = "mcm-three-column-small";
|
|
})(MultiColumnLayoutCSS || (MultiColumnLayoutCSS = {}));
|
|
var MultiColumnStyleCSS;
|
|
(function (MultiColumnStyleCSS) {
|
|
MultiColumnStyleCSS["RegionErrorMessage"] = "mcm-column-error-message";
|
|
MultiColumnStyleCSS["RegionSettings"] = "mcm-column-settings-wrapper";
|
|
MultiColumnStyleCSS["RegionContent"] = "mcm-column-content-wrapper";
|
|
MultiColumnStyleCSS["RegionEndTag"] = "mcm-column-end-tag-wrapper";
|
|
MultiColumnStyleCSS["ColumnEndTag"] = "mcm-column-break-tag-wrapper";
|
|
MultiColumnStyleCSS["RegionShadow"] = "mcm-region-shadow";
|
|
MultiColumnStyleCSS["ColumnShadow"] = "mcm-column-shadow";
|
|
MultiColumnStyleCSS["ColumnBorder"] = "mcm-column-border";
|
|
MultiColumnStyleCSS["ColumnContent"] = "mcm-column-div";
|
|
})(MultiColumnStyleCSS || (MultiColumnStyleCSS = {}));
|
|
|
|
/**
|
|
* File: /src/dom_manager/regional_managers/RegionManager.ts *
|
|
* Created Date: Sunday, May 22nd 2022, 7:49 pm *
|
|
* Author: Cameron Robinson *
|
|
* *
|
|
* Copyright (c) 2022 Cameron Robinson *
|
|
*/
|
|
class RegionManager {
|
|
constructor(data) {
|
|
this.domList = [];
|
|
this.domObjectMap = new Map();
|
|
this.regionalSettings = getDefaultMultiColumnSettings();
|
|
this.domList = data.domList;
|
|
this.domObjectMap = data.domObjectMap;
|
|
this.regionParent = data.regionParent;
|
|
this.fileManager = data.fileManager;
|
|
this.regionalSettings = data.regionalSettings;
|
|
this.regionKey = data.regionKey;
|
|
}
|
|
get regionParent() {
|
|
return this._regionParent;
|
|
}
|
|
set regionParent(value) {
|
|
this._regionParent = value;
|
|
}
|
|
getRegionData() {
|
|
return {
|
|
domList: this.domList,
|
|
domObjectMap: this.domObjectMap,
|
|
regionParent: this.regionParent,
|
|
fileManager: this.fileManager,
|
|
regionalSettings: this.regionalSettings,
|
|
regionKey: this.regionKey,
|
|
rootElement: null
|
|
};
|
|
}
|
|
addObject(siblingsAbove, siblingsBelow, obj) {
|
|
let prevObj = siblingsAbove.children[siblingsAbove.children.length - 1];
|
|
let nextObj = siblingsBelow.children[0];
|
|
let addAtIndex = siblingsAbove.children.length;
|
|
if (prevObj !== undefined) {
|
|
prevObj.innerText;
|
|
for (let i = this.domList.length - 1; i >= 0; i--) {
|
|
if (this.domList[i].nodeKey === prevObj.innerText) {
|
|
addAtIndex = i + 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
let nextElIndex = addAtIndex;
|
|
if (nextObj !== undefined) {
|
|
nextObj.innerText;
|
|
for (let i = addAtIndex; i < this.domList.length; i++) {
|
|
if (this.domList[i].nodeKey === nextObj.innerText.trim()) {
|
|
nextElIndex = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
// console.log(" Prev: ", siblingsAbove.children[siblingsAbove.children.length - 1], "Adding: ", obj.element, " Next: ", siblingsBelow.children[0], "Overwriting:", this.domList.slice(addAtIndex, nextElIndex));
|
|
this.domList.splice(addAtIndex, nextElIndex - addAtIndex, obj);
|
|
this.domObjectMap.set(obj.UID, obj);
|
|
// /**
|
|
// * Make a copy of the list to log, only because
|
|
// * console log updates its references with updates in memory.
|
|
// */
|
|
// let x = this.domList.slice(0);
|
|
// console.log(x);
|
|
return addAtIndex;
|
|
}
|
|
removeObject(objectUID) {
|
|
// /**
|
|
// * Make a copy of the list to log
|
|
// */
|
|
// let x = domList.slice(0);
|
|
// console.log(x);
|
|
// Get the object by key, remove it from the map and then
|
|
// from the list.
|
|
let obj = this.domObjectMap.get(objectUID);
|
|
this.domObjectMap.delete(objectUID);
|
|
if (obj === undefined) {
|
|
return;
|
|
}
|
|
if (this.domList.contains(obj)) {
|
|
this.domList.remove(obj);
|
|
}
|
|
if (this.domList.length === 0 && this.fileManager !== null) {
|
|
this.fileManager.removeRegion(this.regionKey);
|
|
}
|
|
// x = domList.slice(0);
|
|
// console.log(x);
|
|
}
|
|
updateElementTag(objectUID, newTag) {
|
|
let obj = this.domObjectMap.get(objectUID);
|
|
let index = this.domList.indexOf(obj);
|
|
if (index !== -1) {
|
|
this.domList[index].tag = newTag;
|
|
}
|
|
}
|
|
setRegionalSettings(regionSettings) {
|
|
this.regionalSettings = regionSettings;
|
|
}
|
|
/**
|
|
* Creates an object containing all necessary information for the region
|
|
* to be rendered to the preview pane.
|
|
*
|
|
* @returns a MultiColumnRenderData object with the root DOM element, settings object, and
|
|
* all child objects in the order they should be rendered.
|
|
*/
|
|
getRegionRenderData() {
|
|
return {
|
|
parentRenderElement: this.regionParent,
|
|
parentRenderSettings: this.regionalSettings,
|
|
domObjects: this.domList
|
|
};
|
|
}
|
|
/**
|
|
* This fuction is called when a start tag is removed from view meaning
|
|
* our parent element storing the multi-column region is removed. It
|
|
* removes the CSS class from all of the elements so they will be
|
|
* re-rendered in the preview window.
|
|
*/
|
|
displayOriginalElements() {
|
|
for (let i = 0; i < this.domList.length; i++) {
|
|
if (this.domList[i].originalElement) {
|
|
this.domList[i].originalElement.removeClasses([MultiColumnStyleCSS.RegionEndTag,
|
|
MultiColumnStyleCSS.ColumnEndTag,
|
|
MultiColumnStyleCSS.RegionSettings,
|
|
MultiColumnStyleCSS.RegionContent]);
|
|
if (this.domList[i].originalElement.parentElement) {
|
|
this.domList[i].originalElement.parentElement.removeChild(this.domList[i].originalElement);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
getID() {
|
|
return this.regionKey;
|
|
}
|
|
updateRenderedMarkdown() {
|
|
/**
|
|
* This function acts as the update loop for the multi-column regions.
|
|
* Here we loop through all of the elements within the rendered region and
|
|
* potentially update how things are rendered. We need to do this for
|
|
* compatability with other plugins.
|
|
*
|
|
* If the multi-column region is rendered before other plugins that effect
|
|
* content within the region our rendered data may not properly display
|
|
* the content from the other plugin. Here we loop through the elements
|
|
* after all plugins have had a chance to run and can make changes to the
|
|
* DOM at this point.
|
|
*/
|
|
for (let i = 0; i < this.domList.length; i++) {
|
|
/**
|
|
* Here we check for special cases
|
|
*/
|
|
if (this.domList[i] instanceof TaskListDOMObject) {
|
|
this.fixClonedCheckListButtons(this.domList[i]);
|
|
}
|
|
let elementType = this.domList[i].elementType;
|
|
/**
|
|
* If the element is not currently a special render element we check again
|
|
* as the original element may have been updated.
|
|
*
|
|
* TODO: find a way to "Officially" mark normal elements rather than
|
|
* continuously search for special render types.
|
|
*/
|
|
if (elementType !== ElementRenderType.specialRender &&
|
|
elementType !== ElementRenderType.specialSingleElementRender &&
|
|
elementType !== ElementRenderType.unRendered) {
|
|
// If the new result returns as a special renderer we update so
|
|
// this wont run again for this item.
|
|
elementType = getElementRenderType(this.domList[i].originalElement);
|
|
this.domList[i].originalElement.clientHeight;
|
|
}
|
|
if (elementType === ElementRenderType.specialRender ||
|
|
elementType === ElementRenderType.specialSingleElementRender ||
|
|
elementType === ElementRenderType.canvasRenderElement) {
|
|
this.domList[i].elementType = elementType;
|
|
this.setUpDualRender(this.domList[i]);
|
|
}
|
|
}
|
|
}
|
|
/**
|
|
* This function takes in the original element and its clone and checks if
|
|
* the element contains a task-list-item class. If so it loops through all
|
|
* items in the list and fixes their checkboxes to properly fire an event.
|
|
* The new checkbox calls the click function on the original checkbox so
|
|
* compatability with other plugins *should* remain.
|
|
* @param domElement
|
|
* @param initalizeCheckboxes
|
|
*/
|
|
fixClonedCheckListButtons(domElement, initalizeCheckboxes = false) {
|
|
if (domElement.originalElement === null || domElement.clonedElement === null) {
|
|
return;
|
|
}
|
|
let element = domElement.originalElement;
|
|
let clonedElement = domElement.clonedElement;
|
|
let clonedListCheckboxes = Array.from(clonedElement.getElementsByClassName("task-list-item"));
|
|
let originalListCheckboxes = Array.from(element.getElementsByClassName("task-list-item"));
|
|
if (initalizeCheckboxes === true) {
|
|
// When we initalize we remove the old input checkbox that contains
|
|
// the weird callback situation causing the bug. Then we create a new
|
|
// checkbox to replace it and set it up to fire the click event on
|
|
// the original checkbox so functionality is restored.
|
|
for (let i = 0; i < originalListCheckboxes.length; i++) {
|
|
const checkbox = createEl('input');
|
|
let originalInput = originalListCheckboxes[i].firstChild;
|
|
checkbox.checked = originalInput.checked;
|
|
clonedListCheckboxes[i].replaceChild(checkbox, clonedListCheckboxes[i].children[0]);
|
|
checkbox.addClass('task-list-item-checkbox');
|
|
checkbox.type = 'checkbox';
|
|
checkbox.onClickEvent(() => {
|
|
domElement.checkboxClicked(i);
|
|
});
|
|
}
|
|
}
|
|
else {
|
|
// Whenever we reach this point we update our list of original checkboxes
|
|
// that may be different from our cache. This is due to how obsidian
|
|
// changes the DOM underneath us so we need to constantly update our cache.
|
|
domElement.originalCheckboxes = originalListCheckboxes;
|
|
}
|
|
// When the Tasks plugin is installed the cloned copy of the original element contains
|
|
// an extra element for some reason. If this occurs for other reasons here we adjust
|
|
// that to keep the clone the same as the original.
|
|
if (clonedListCheckboxes.length > originalListCheckboxes.length) {
|
|
for (let i = originalListCheckboxes.length; i < clonedListCheckboxes.length; i++) {
|
|
domElement.clonedElement.removeChild(clonedListCheckboxes[i]);
|
|
}
|
|
}
|
|
}
|
|
setUpDualRender(domElement) {
|
|
/**
|
|
* If our element is of "specialRender" type it *may* need to be rendered
|
|
* using the original element rather than a copy. For example, an element
|
|
* may have an onClick event that would not get coppied to the clone.
|
|
*
|
|
* If we just moved these elements into the region it would get
|
|
* moved back out into the original location in the DOM by obsidian
|
|
* when scrolling or when the file is updated. On the next refresh it
|
|
* would be moved back but that can lead to a region jumping
|
|
* around as the item is moved in and out.
|
|
*
|
|
* Here we set up the div to contain the element and create
|
|
* a visual only clone of it. The clone will only be visible
|
|
* when the original is not in the multi-column region so it
|
|
* saves us from the visual noise of the region jumping around.
|
|
*/
|
|
let originalElement = domElement.originalElement;
|
|
let clonedElement = domElement.clonedElement;
|
|
let containerElement = domElement.elementContainer;
|
|
// Get height of the original and cloned element. If the element is not currently rendered
|
|
// it will have 0 height so we need to temporarily render it to get the height.
|
|
let originalElementHeight = getElementClientHeight(originalElement, containerElement);
|
|
let clonedElementHeight = getElementClientHeight(clonedElement, containerElement);
|
|
/**
|
|
* We only want to clone the element once to reduce GC. But if the cloned
|
|
* element's height is not equal to the original element, this means the
|
|
* item element has been updated somewhere else without the dom being
|
|
* refreshed. This can occur when elements are updated by other plugins,
|
|
* such as Dataview.
|
|
*/
|
|
if (clonedElement === null ||
|
|
clonedElementHeight !== originalElementHeight) {
|
|
// Update clone and reference.
|
|
domElement.clonedElement = originalElement.cloneNode(true);
|
|
clonedElement = domElement.clonedElement;
|
|
/**
|
|
* If we updated the cloned element, we want to also update the
|
|
* element rendered in the parent container.
|
|
*/
|
|
for (let i = containerElement.children.length - 1; i >= 0; i--) {
|
|
containerElement.children[i].detach();
|
|
}
|
|
// Update CSS, we add cloned class and remove classes from originalElement that do not apply.
|
|
clonedElement.addClass(MultiColumnLayoutCSS.ClonedElementType);
|
|
clonedElement.removeClasses([MultiColumnStyleCSS.RegionContent, MultiColumnLayoutCSS.OriginalElementType]);
|
|
containerElement.appendChild(clonedElement);
|
|
}
|
|
if (domElement.elementType === ElementRenderType.canvasRenderElement) {
|
|
containerElement.appendChild(originalElement);
|
|
function cloneCanvas(originalCanvas) {
|
|
//create a new canvas
|
|
let clonedCanvas = originalCanvas.cloneNode(true);
|
|
let context = clonedCanvas.getContext('2d');
|
|
//set dimensions
|
|
clonedCanvas.width = originalCanvas.width;
|
|
clonedCanvas.height = originalCanvas.height;
|
|
if (clonedCanvas.width === 0 || clonedCanvas.height === 0) {
|
|
// Dont want to render if the width is 0 as it throws an error
|
|
// would happen if the old canvas hasnt been rendered yet.
|
|
return clonedCanvas;
|
|
}
|
|
//apply the old canvas to the new one
|
|
context.drawImage(originalCanvas, 0, 0);
|
|
//return the new canvas
|
|
return clonedCanvas;
|
|
}
|
|
let canvas = searchChildrenForNodeType(originalElement, "canvas");
|
|
if (canvas !== null) {
|
|
for (let i = clonedElement.children.length - 1; i >= 0; i--) {
|
|
clonedElement.children[i].detach();
|
|
}
|
|
clonedElement.appendChild(cloneCanvas(canvas));
|
|
}
|
|
containerElement.removeChild(originalElement);
|
|
}
|
|
/**
|
|
* If the container element has less than 2 children we need to move the
|
|
* original element back into it. However some elements constantly get moved
|
|
* in and out causing some unwanted behavior. Those element will be tagged
|
|
* as specialSingleElementRender so we ignore those elements here.
|
|
*/
|
|
if (domElement.elementContainer.children.length < 2 &&
|
|
domElement.elementType !== ElementRenderType.specialSingleElementRender) {
|
|
// console.log("Updating dual rendering.", domElement, domElement.originalElement.parentElement, domElement.originalElement.parentElement?.childElementCount);
|
|
// Make sure our CSS is up to date.
|
|
originalElement.addClass(MultiColumnLayoutCSS.OriginalElementType);
|
|
clonedElement.addClass(MultiColumnLayoutCSS.ClonedElementType);
|
|
clonedElement.removeClasses([MultiColumnStyleCSS.RegionContent, MultiColumnLayoutCSS.OriginalElementType]);
|
|
for (let i = containerElement.children.length - 1; i >= 0; i--) {
|
|
containerElement.children[i].detach();
|
|
}
|
|
containerElement.appendChild(originalElement);
|
|
containerElement.appendChild(clonedElement);
|
|
}
|
|
}
|
|
/**
|
|
* Sets up the CSS classes and the number of columns based on the passed settings.
|
|
* @param settings The user defined settings that determine what CSS is set here.
|
|
* @param multiColumnParent The parent object that the column divs will be created under.
|
|
* @returns The list of column divs created under the passed parent element.
|
|
*/
|
|
getColumnContentDivs(settings, multiColumnParent) {
|
|
let columnContentDivs = [];
|
|
let styleStr = "";
|
|
if (settings.columnSpacing !== "") {
|
|
styleStr = `margin-inline: ${settings.columnSpacing};`;
|
|
}
|
|
if (settings.numberOfColumns === 2) {
|
|
switch (settings.columnLayout) {
|
|
case (ColumnLayout.standard):
|
|
case (ColumnLayout.middle):
|
|
case (ColumnLayout.center):
|
|
case (ColumnLayout.third):
|
|
columnContentDivs.push(multiColumnParent.createDiv({
|
|
cls: `${MultiColumnStyleCSS.ColumnContent} ${MultiColumnLayoutCSS.TwoEqualColumns}`
|
|
}));
|
|
multiColumnParent.createDiv({
|
|
cls: `mcm-column-spacer`,
|
|
attr: { "style": styleStr }
|
|
});
|
|
columnContentDivs.push(multiColumnParent.createDiv({
|
|
cls: `${MultiColumnStyleCSS.ColumnContent} ${MultiColumnLayoutCSS.TwoEqualColumns}`
|
|
}));
|
|
break;
|
|
case (ColumnLayout.left):
|
|
case (ColumnLayout.first):
|
|
columnContentDivs.push(multiColumnParent.createDiv({
|
|
cls: `${MultiColumnStyleCSS.ColumnContent} ${MultiColumnLayoutCSS.TwoColumnLarge}`
|
|
}));
|
|
multiColumnParent.createDiv({
|
|
cls: `mcm-column-spacer`,
|
|
attr: { "style": styleStr }
|
|
});
|
|
columnContentDivs.push(multiColumnParent.createDiv({
|
|
cls: `${MultiColumnStyleCSS.ColumnContent} ${MultiColumnLayoutCSS.TwoColumnSmall}`
|
|
}));
|
|
break;
|
|
case (ColumnLayout.right):
|
|
case (ColumnLayout.second):
|
|
case (ColumnLayout.last):
|
|
columnContentDivs.push(multiColumnParent.createDiv({
|
|
cls: `${MultiColumnStyleCSS.ColumnContent} ${MultiColumnLayoutCSS.TwoColumnSmall}`
|
|
}));
|
|
multiColumnParent.createDiv({
|
|
cls: `mcm-column-spacer`,
|
|
attr: { "style": styleStr }
|
|
});
|
|
columnContentDivs.push(multiColumnParent.createDiv({
|
|
cls: `${MultiColumnStyleCSS.ColumnContent} ${MultiColumnLayoutCSS.TwoColumnLarge}`
|
|
}));
|
|
break;
|
|
}
|
|
}
|
|
else if (settings.numberOfColumns === 3) {
|
|
switch (settings.columnLayout) {
|
|
case (ColumnLayout.standard):
|
|
columnContentDivs.push(multiColumnParent.createDiv({
|
|
cls: `${MultiColumnStyleCSS.ColumnContent} ${MultiColumnLayoutCSS.ThreeEqualColumns}`
|
|
}));
|
|
multiColumnParent.createDiv({
|
|
cls: `mcm-column-spacer`,
|
|
attr: { "style": styleStr }
|
|
});
|
|
columnContentDivs.push(multiColumnParent.createDiv({
|
|
cls: `${MultiColumnStyleCSS.ColumnContent} ${MultiColumnLayoutCSS.ThreeEqualColumns}`
|
|
}));
|
|
multiColumnParent.createDiv({
|
|
cls: `mcm-column-spacer`,
|
|
attr: { "style": styleStr }
|
|
});
|
|
columnContentDivs.push(multiColumnParent.createDiv({
|
|
cls: `${MultiColumnStyleCSS.ColumnContent} ${MultiColumnLayoutCSS.ThreeEqualColumns}`
|
|
}));
|
|
break;
|
|
case (ColumnLayout.left):
|
|
case (ColumnLayout.first):
|
|
columnContentDivs.push(multiColumnParent.createDiv({
|
|
cls: `${MultiColumnStyleCSS.ColumnContent} ${MultiColumnLayoutCSS.ThreeColumn_Large}`
|
|
}));
|
|
multiColumnParent.createDiv({
|
|
cls: `mcm-column-spacer`,
|
|
attr: { "style": styleStr }
|
|
});
|
|
columnContentDivs.push(multiColumnParent.createDiv({
|
|
cls: `${MultiColumnStyleCSS.ColumnContent} ${MultiColumnLayoutCSS.ThreeColumn_Small}`
|
|
}));
|
|
multiColumnParent.createDiv({
|
|
cls: `mcm-column-spacer`,
|
|
attr: { "style": styleStr }
|
|
});
|
|
columnContentDivs.push(multiColumnParent.createDiv({
|
|
cls: `${MultiColumnStyleCSS.ColumnContent} ${MultiColumnLayoutCSS.ThreeColumn_Small}`
|
|
}));
|
|
break;
|
|
case (ColumnLayout.middle):
|
|
case (ColumnLayout.center):
|
|
case (ColumnLayout.second):
|
|
columnContentDivs.push(multiColumnParent.createDiv({
|
|
cls: `${MultiColumnStyleCSS.ColumnContent} ${MultiColumnLayoutCSS.ThreeColumn_Small}`
|
|
}));
|
|
multiColumnParent.createDiv({
|
|
cls: `mcm-column-spacer`,
|
|
attr: { "style": styleStr }
|
|
});
|
|
columnContentDivs.push(multiColumnParent.createDiv({
|
|
cls: `${MultiColumnStyleCSS.ColumnContent} ${MultiColumnLayoutCSS.ThreeColumn_Large}`
|
|
}));
|
|
multiColumnParent.createDiv({
|
|
cls: `mcm-column-spacer`,
|
|
attr: { "style": styleStr }
|
|
});
|
|
columnContentDivs.push(multiColumnParent.createDiv({
|
|
cls: `${MultiColumnStyleCSS.ColumnContent} ${MultiColumnLayoutCSS.ThreeColumn_Small}`
|
|
}));
|
|
break;
|
|
case (ColumnLayout.right):
|
|
case (ColumnLayout.third):
|
|
case (ColumnLayout.last):
|
|
columnContentDivs.push(multiColumnParent.createDiv({
|
|
cls: `${MultiColumnStyleCSS.ColumnContent} ${MultiColumnLayoutCSS.ThreeColumn_Small}`
|
|
}));
|
|
multiColumnParent.createDiv({
|
|
cls: `mcm-column-spacer`,
|
|
attr: { "style": styleStr }
|
|
});
|
|
columnContentDivs.push(multiColumnParent.createDiv({
|
|
cls: `${MultiColumnStyleCSS.ColumnContent} ${MultiColumnLayoutCSS.ThreeColumn_Small}`
|
|
}));
|
|
multiColumnParent.createDiv({
|
|
cls: `mcm-column-spacer`,
|
|
attr: { "style": styleStr }
|
|
});
|
|
columnContentDivs.push(multiColumnParent.createDiv({
|
|
cls: `${MultiColumnStyleCSS.ColumnContent} ${MultiColumnLayoutCSS.ThreeColumn_Large}`
|
|
}));
|
|
break;
|
|
}
|
|
}
|
|
return columnContentDivs;
|
|
}
|
|
}
|
|
function getElementClientHeight(element, parentRenderElement) {
|
|
let height = element.clientHeight;
|
|
if (height === 0) {
|
|
parentRenderElement.appendChild(element);
|
|
height = element.clientHeight;
|
|
parentRenderElement.removeChild(element);
|
|
}
|
|
return height;
|
|
}
|
|
|
|
/**
|
|
* File: /src/dom_manager/regional_managers/regionDOMManager.ts *
|
|
* Created Date: Sunday, May 22nd 2022, 7:46 pm *
|
|
* Author: Cameron Robinson *
|
|
* *
|
|
* Copyright (c) 2022 Cameron Robinson *
|
|
*/
|
|
class StandardMultiColumnRegionManager extends RegionManager {
|
|
renderRegionElementsToScreen() {
|
|
this.renderColumnMarkdown(this.regionParent, this.domList, this.regionalSettings);
|
|
}
|
|
exportRegionElementsToPDF(pdfParentElement) {
|
|
// Default set shadow to off for exporting PDFs
|
|
let renderSettings = this.regionalSettings;
|
|
renderSettings.drawShadow = false;
|
|
this.renderColumnMarkdown(pdfParentElement, this.domList.slice(), renderSettings);
|
|
}
|
|
renderRegionElementsToLivePreview(parentElement) {
|
|
this.renderColumnMarkdown(parentElement, this.domList, this.regionalSettings);
|
|
}
|
|
/**
|
|
* This function takes in the data for the multi-column region and sets up the
|
|
* user defined number of children with the proper css classes to be rendered properly.
|
|
*
|
|
* @param parentElement The element that the multi-column region will be rendered under.
|
|
* @param regionElements The list of DOM objects that will be coppied under the parent object
|
|
* @param settings The settings the user has defined for the region.
|
|
*/
|
|
renderColumnMarkdown(parentElement, regionElements, settings) {
|
|
let multiColumnParent = createDiv({
|
|
cls: MultiColumnLayoutCSS.RegionColumnContainerDiv,
|
|
});
|
|
/**
|
|
* Pass our parent div and settings to parser to create the required
|
|
* column divs as children of the parent.
|
|
*/
|
|
let columnContentDivs = this.getColumnContentDivs(settings, multiColumnParent);
|
|
if (settings.drawShadow === true) {
|
|
multiColumnParent.addClass(MultiColumnStyleCSS.RegionShadow);
|
|
}
|
|
for (let i = 0; i < columnContentDivs.length; i++) {
|
|
if (settings.drawBorder === true) {
|
|
columnContentDivs[i].addClass(MultiColumnStyleCSS.ColumnBorder);
|
|
}
|
|
if (settings.drawShadow === true) {
|
|
columnContentDivs[i].addClass(MultiColumnStyleCSS.ColumnShadow);
|
|
}
|
|
}
|
|
// Create markdown renderer to parse the passed markdown
|
|
// between the tags.
|
|
let markdownRenderChild = new obsidian.MarkdownRenderChild(multiColumnParent);
|
|
// Remove every other child from the parent so
|
|
// we dont end up with multiple sets of data. This should
|
|
// really only need to loop once for i = 0 but loop just
|
|
// in case.
|
|
for (let i = parentElement.children.length - 1; i >= 0; i--) {
|
|
parentElement.children[i].detach();
|
|
}
|
|
parentElement.appendChild(markdownRenderChild.containerEl);
|
|
this.appendElementsToColumns(regionElements, columnContentDivs, settings);
|
|
}
|
|
appendElementsToColumns(regionElements, columnContentDivs, settings) {
|
|
let columnIndex = 0;
|
|
for (let i = 0; i < regionElements.length; i++) {
|
|
if (regionElements[i].tag === DOMObjectTag.none ||
|
|
regionElements[i].tag === DOMObjectTag.columnBreak) {
|
|
// We store the elements in a wrapper container until we determine
|
|
let element = createDiv({
|
|
cls: MultiColumnLayoutCSS.ColumnDualElementContainer,
|
|
});
|
|
if (settings.contentOverflow === ContentOverflowType.hidden) {
|
|
element.addClass(MultiColumnLayoutCSS.ContentOverflowHidden);
|
|
}
|
|
else {
|
|
element.addClass(MultiColumnLayoutCSS.ContentOverflowAutoScroll);
|
|
}
|
|
regionElements[i].elementContainer = element;
|
|
// Otherwise we just make a copy of the original element to display.
|
|
let clonedElement = regionElements[i].originalElement.cloneNode(true);
|
|
let headingCollapseElement = getHeadingCollapseElement(clonedElement);
|
|
if (headingCollapseElement !== null) {
|
|
// This removes the collapse arrow from the view if it exists.
|
|
headingCollapseElement.detach();
|
|
}
|
|
regionElements[i].clonedElement = clonedElement;
|
|
element.appendChild(clonedElement);
|
|
if (regionElements[i] instanceof TaskListDOMObject) {
|
|
this.fixClonedCheckListButtons(regionElements[i], true);
|
|
}
|
|
if (element !== null && regionElements[i].tag !== DOMObjectTag.columnBreak) {
|
|
columnContentDivs[columnIndex].appendChild(element);
|
|
}
|
|
/**
|
|
* If the tag is a column break we update the column index after
|
|
* appending the item to the column div. This keeps the main DOM
|
|
* cleaner by removing other items and placing them all within
|
|
* a region container.
|
|
*/
|
|
if (regionElements[i].tag === DOMObjectTag.columnBreak &&
|
|
(columnIndex + 1) < settings.numberOfColumns) {
|
|
columnIndex++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
class SingleColumnRegionManager extends RegionManager {
|
|
renderRegionElementsToScreen() {
|
|
this.renderColumnMarkdown(this.regionParent, this.domList, this.regionalSettings);
|
|
}
|
|
exportRegionElementsToPDF(pdfParentElement) {
|
|
// Default set shadow to off for exporting PDFs
|
|
let renderSettings = this.regionalSettings;
|
|
renderSettings.drawShadow = false;
|
|
this.renderColumnMarkdown(pdfParentElement, this.domList.slice(), renderSettings);
|
|
}
|
|
renderRegionElementsToLivePreview(parentElement) {
|
|
this.renderColumnMarkdown(parentElement, this.domList, this.regionalSettings);
|
|
}
|
|
/**
|
|
* This function takes in the data for the multi-column region and sets up the
|
|
* user defined number of children with the proper css classes to be rendered properly.
|
|
*
|
|
* @param parentElement The element that the multi-column region will be rendered under.
|
|
* @param regionElements The list of DOM objects that will be coppied under the parent object
|
|
* @param settings The settings the user has defined for the region.
|
|
*/
|
|
renderColumnMarkdown(parentElement, regionElements, settings) {
|
|
let multiColumnParent = createDiv({
|
|
cls: MultiColumnLayoutCSS.RegionColumnContainerDiv,
|
|
});
|
|
if (isLeftLayout(this.regionalSettings.columnPosition)) {
|
|
multiColumnParent.addClass(MultiColumnLayoutCSS.SingleColumnLeftLayout);
|
|
}
|
|
else if (isRightLayout(this.regionalSettings.columnPosition)) {
|
|
multiColumnParent.addClass(MultiColumnLayoutCSS.SingleColumnRightLayout);
|
|
}
|
|
else {
|
|
multiColumnParent.addClass(MultiColumnLayoutCSS.SingleColumnCenterLayout);
|
|
}
|
|
/**
|
|
* Pass our parent div and settings to parser to create the required
|
|
* column divs as children of the parent.
|
|
*/
|
|
let columnContentDiv = this.createColumnContentDivs(multiColumnParent);
|
|
if (settings.drawBorder === true) {
|
|
columnContentDiv.addClass(MultiColumnStyleCSS.ColumnBorder);
|
|
}
|
|
if (settings.drawShadow === true) {
|
|
columnContentDiv.addClass(MultiColumnStyleCSS.ColumnShadow);
|
|
}
|
|
// Create markdown renderer to parse the passed markdown
|
|
// between the tags.
|
|
let markdownRenderChild = new obsidian.MarkdownRenderChild(multiColumnParent);
|
|
// Remove every other child from the parent so
|
|
// we dont end up with multiple sets of data. This should
|
|
// really only need to loop once for i = 0 but loop just
|
|
// in case.
|
|
for (let i = parentElement.children.length - 1; i >= 0; i--) {
|
|
parentElement.children[i].detach();
|
|
}
|
|
parentElement.appendChild(markdownRenderChild.containerEl);
|
|
this.appendElementsToColumns(regionElements, columnContentDiv, settings);
|
|
}
|
|
appendElementsToColumns(regionElements, columnContentDiv, settings) {
|
|
for (let i = 0; i < regionElements.length; i++) {
|
|
if (regionElements[i].tag === DOMObjectTag.none ||
|
|
regionElements[i].tag === DOMObjectTag.columnBreak) {
|
|
// We store the elements in a wrapper container until we determine
|
|
let element = createDiv({
|
|
cls: MultiColumnLayoutCSS.ColumnDualElementContainer,
|
|
});
|
|
regionElements[i].elementContainer = element;
|
|
// Otherwise we just make a copy of the original element to display.
|
|
let clonedElement = regionElements[i].originalElement.cloneNode(true);
|
|
let headingCollapseElement = getHeadingCollapseElement(clonedElement);
|
|
if (headingCollapseElement !== null) {
|
|
// This removes the collapse arrow from the view if it exists.
|
|
headingCollapseElement.detach();
|
|
}
|
|
regionElements[i].clonedElement = clonedElement;
|
|
element.appendChild(clonedElement);
|
|
if (regionElements[i] instanceof TaskListDOMObject) {
|
|
this.fixClonedCheckListButtons(regionElements[i], true);
|
|
}
|
|
if (element !== null) {
|
|
columnContentDiv.appendChild(element);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
createColumnContentDivs(multiColumnParent) {
|
|
let contentDiv = multiColumnParent.createDiv({
|
|
cls: `${MultiColumnStyleCSS.ColumnContent}`
|
|
});
|
|
if (this.regionalSettings.columnSize === SingleColumnSize.small) {
|
|
contentDiv.addClass(`${MultiColumnLayoutCSS.SingleColumnSmall}`);
|
|
}
|
|
else if (this.regionalSettings.columnSize === SingleColumnSize.large) {
|
|
contentDiv.addClass(`${MultiColumnLayoutCSS.SingleColumnLarge}`);
|
|
}
|
|
else {
|
|
contentDiv.addClass(`${MultiColumnLayoutCSS.SingleColumnMed}`);
|
|
}
|
|
return contentDiv;
|
|
}
|
|
}
|
|
function isLeftLayout(layout) {
|
|
if (layout === ColumnLayout.left ||
|
|
layout === ColumnLayout.first) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
function isRightLayout(layout) {
|
|
if (layout === ColumnLayout.right ||
|
|
layout === ColumnLayout.third ||
|
|
layout === ColumnLayout.last) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* File: /src/dom_manager/regional_managers/autoLayoutRegionManager.ts *
|
|
* Created Date: Sunday, May 22nd 2022, 10:23 pm *
|
|
* Author: Cameron Robinson *
|
|
* *
|
|
* Copyright (c) 2022 Cameron Robinson *
|
|
*/
|
|
class AutoLayoutRegionManager extends RegionManager {
|
|
constructor() {
|
|
super(...arguments);
|
|
this.previousColumnHeights = [];
|
|
}
|
|
renderRegionElementsToScreen() {
|
|
this.renderColumnMarkdown(this.regionParent, this.domList, this.regionalSettings);
|
|
}
|
|
exportRegionElementsToPDF(pdfParentElement) {
|
|
// Default set shadow to off for exporting PDFs
|
|
let renderSettings = this.regionalSettings;
|
|
renderSettings.drawShadow = false;
|
|
this.renderColumnMarkdown(pdfParentElement, this.domList.slice(), renderSettings);
|
|
}
|
|
renderRegionElementsToLivePreview(parentElement) {
|
|
this.renderColumnMarkdown(parentElement, this.domList, this.regionalSettings);
|
|
}
|
|
/**
|
|
* This function takes in the data for the multi-column region and sets up the
|
|
* user defined number of children with the proper css classes to be rendered properly.
|
|
*
|
|
* @param parentElement The element that the multi-column region will be rendered under.
|
|
* @param regionElements The list of DOM objects that will be coppied under the parent object
|
|
* @param settings The settings the user has defined for the region.
|
|
*/
|
|
renderColumnMarkdown(parentElement, regionElements, settings) {
|
|
let multiColumnParent = createDiv({
|
|
cls: MultiColumnLayoutCSS.RegionColumnContainerDiv,
|
|
});
|
|
this.columnParent = multiColumnParent;
|
|
/**
|
|
* Pass our parent div and settings to parser to create the required
|
|
* column divs as children of the parent.
|
|
*/
|
|
this.columnDivs = this.getColumnContentDivs(settings, multiColumnParent);
|
|
if (settings.drawShadow === true) {
|
|
multiColumnParent.addClass(MultiColumnStyleCSS.RegionShadow);
|
|
}
|
|
for (let i = 0; i < this.columnDivs.length; i++) {
|
|
if (settings.drawBorder === true) {
|
|
this.columnDivs[i].addClass(MultiColumnStyleCSS.ColumnBorder);
|
|
}
|
|
if (settings.drawShadow === true) {
|
|
this.columnDivs[i].addClass(MultiColumnStyleCSS.ColumnShadow);
|
|
}
|
|
}
|
|
// Remove every other child from the parent so
|
|
// we dont end up with multiple sets of data. This should
|
|
// really only need to loop once for i = 0 but loop just
|
|
// in case.
|
|
for (let i = parentElement.children.length - 1; i >= 0; i--) {
|
|
parentElement.children[i].detach();
|
|
}
|
|
parentElement.appendChild(multiColumnParent);
|
|
this.appendElementsToColumns(regionElements, this.columnDivs, settings);
|
|
}
|
|
appendElementsToColumns(regionElements, columnContentDivs, settings) {
|
|
function balanceElements() {
|
|
let totalHeight = regionElements.map((el, index) => {
|
|
// We only want to attempt to update the elementRenderedHeight if it is 0 and if it is not an unrendered element such as a endregion tag.
|
|
if (el.elementRenderedHeight === 0 &&
|
|
el.tag !== DOMObjectTag.columnBreak &&
|
|
el.tag !== DOMObjectTag.endRegion &&
|
|
el.tag !== DOMObjectTag.regionSettings &&
|
|
el.tag !== DOMObjectTag.startRegion) {
|
|
// Add element to rendered div so we can extract the rendered height.
|
|
columnContentDivs[0].appendChild(el.originalElement);
|
|
el.elementRenderedHeight = el.originalElement.clientHeight;
|
|
columnContentDivs[0].removeChild(el.originalElement);
|
|
}
|
|
return el.elementRenderedHeight;
|
|
}).reduce((prev, curr) => { return prev + curr; }, 0);
|
|
let maxColumnContentHeight = Math.trunc(totalHeight / settings.numberOfColumns);
|
|
for (let i = 0; i < columnContentDivs.length; i++) {
|
|
for (let j = columnContentDivs[i].children.length - 1; j >= 0; j--) {
|
|
columnContentDivs[i].children[j].detach();
|
|
}
|
|
}
|
|
let columnIndex = 0;
|
|
let currentColumnHeight = 0;
|
|
function checkShouldSwitchColumns(nextElementHeight) {
|
|
if (currentColumnHeight + nextElementHeight > maxColumnContentHeight &&
|
|
(columnIndex + 1) < settings.numberOfColumns) {
|
|
columnIndex++;
|
|
currentColumnHeight = 0;
|
|
}
|
|
}
|
|
for (let i = 0; i < regionElements.length; i++) {
|
|
if (regionElements[i].tag === DOMObjectTag.none ||
|
|
regionElements[i].tag === DOMObjectTag.columnBreak) {
|
|
/**
|
|
* Here we check if we need to swap to the next column for the current element.
|
|
* If the user wants to keep headings with the content below it we also make sure
|
|
* that the last item in a column is not a header element by using the header and
|
|
* the next element's height as the height value.
|
|
*/
|
|
if (hasHeader(regionElements[i].originalElement) === true) { // TODO: Add this as selectable option.
|
|
let headerAndNextElementHeight = regionElements[i].elementRenderedHeight;
|
|
if (i < regionElements.length - 1) {
|
|
headerAndNextElementHeight += regionElements[i + 1].elementRenderedHeight;
|
|
}
|
|
checkShouldSwitchColumns(headerAndNextElementHeight);
|
|
}
|
|
else {
|
|
checkShouldSwitchColumns(regionElements[i].elementRenderedHeight);
|
|
}
|
|
currentColumnHeight += regionElements[i].elementRenderedHeight;
|
|
/**
|
|
* We store the elements in a wrapper container until we determine if we want to
|
|
* use the original element or a clone of the element. This helps us by allowing
|
|
* us to create a visual only clone while the update loop moves the original element
|
|
* into the columns.
|
|
*/
|
|
let element = createDiv({
|
|
cls: MultiColumnLayoutCSS.ColumnDualElementContainer,
|
|
});
|
|
regionElements[i].elementContainer = element;
|
|
let clonedElement = regionElements[i].clonedElement;
|
|
if (regionElements[i].clonedElement === null) {
|
|
clonedElement = regionElements[i].originalElement.cloneNode(true);
|
|
let headingCollapseElement = getHeadingCollapseElement(clonedElement);
|
|
if (headingCollapseElement !== null) {
|
|
// This removes the collapse arrow from the view if it exists.
|
|
headingCollapseElement.detach();
|
|
}
|
|
regionElements[i].clonedElement = clonedElement;
|
|
}
|
|
element.appendChild(clonedElement);
|
|
if (regionElements[i] instanceof TaskListDOMObject) {
|
|
this.fixClonedCheckListButtons(regionElements[i], true);
|
|
}
|
|
if (element !== null &&
|
|
columnContentDivs[columnIndex] &&
|
|
regionElements[i].tag !== DOMObjectTag.columnBreak) {
|
|
columnContentDivs[columnIndex].appendChild(element);
|
|
regionElements[i].elementRenderedHeight = element.clientHeight;
|
|
}
|
|
/**
|
|
* If the tag is a column break we update the column index after
|
|
* appending the item to the column div. This keeps the main DOM
|
|
* cleaner by removing other items and placing them all within
|
|
* a region container.
|
|
*
|
|
* Removing the end column tag as an option for now.
|
|
*/
|
|
// if (regionElements[i].tag === DOMObjectTag.columnBreak &&
|
|
// (columnIndex + 1) < settings.numberOfColumns) {
|
|
// columnIndex++;
|
|
// currentColumnHeight = 0;
|
|
// }
|
|
}
|
|
}
|
|
}
|
|
/**
|
|
* Attempt to balanced the elements. We need to iterate over the elements multiple times because
|
|
* our initial balance estimate may not be perfectly balanced due to different column widths causing
|
|
* elements within them to be of different heights. This can cause the elements to jump around on
|
|
* subsiquent update loops which is not ideal. Here we render the elements to the screen and update
|
|
* their height after being rendered into the estimated position.
|
|
*
|
|
* Once everything is rendered we check all of the column heights against our last iteration and
|
|
* if nothing has changed we know we are balanced.
|
|
*
|
|
* There is probably a better way of accomplishing this task but this works for the time being.
|
|
*/
|
|
for (let i = 0; i < 5; i++) {
|
|
balanceElements();
|
|
let balanced = true;
|
|
for (let j = 0; j < columnContentDivs.length; j++) {
|
|
// If the column heights are undefined we set default to zero so not to encounter an error.
|
|
if (!this.previousColumnHeights[j]) {
|
|
this.previousColumnHeights.push(0);
|
|
}
|
|
// if this render height is not the same as the previous height we are still balancing.
|
|
if (this.previousColumnHeights[j] !== columnContentDivs[j].clientHeight) {
|
|
this.previousColumnHeights[j] = columnContentDivs[j].clientHeight;
|
|
balanced = false;
|
|
}
|
|
}
|
|
// if we made it out of the loop and all of the columns are the same height as last update
|
|
// we're balanced so we can break out of the loop.
|
|
if (balanced === true) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
updateRenderedMarkdown() {
|
|
for (let i = 0; i < this.domList.length; i++) {
|
|
let el = this.domList[i];
|
|
let originalClientHeight = 0;
|
|
if (el.originalElement) {
|
|
originalClientHeight = el.originalElement.clientHeight;
|
|
}
|
|
let clonedClientHeight = 0;
|
|
if (el.clonedElement) {
|
|
clonedClientHeight = el.clonedElement.clientHeight;
|
|
}
|
|
if (originalClientHeight < clonedClientHeight) {
|
|
this.domList[i].elementRenderedHeight = clonedClientHeight;
|
|
}
|
|
else {
|
|
this.domList[i].elementRenderedHeight = originalClientHeight;
|
|
}
|
|
}
|
|
let validColumns = true;
|
|
if (this.columnParent !== null && this.columnDivs !== null && this.columnDivs !== undefined &&
|
|
this.columnDivs.length === this.regionalSettings.numberOfColumns) {
|
|
let totalHeight = this.domList.map((el, index) => {
|
|
// We only want to attempt to update the elementRenderedHeight if it is 0 and if it is not an unrendered element such as a endregion tag.
|
|
if (el.elementRenderedHeight === 0 &&
|
|
el.tag !== DOMObjectTag.columnBreak &&
|
|
el.tag !== DOMObjectTag.endRegion &&
|
|
el.tag !== DOMObjectTag.regionSettings &&
|
|
el.tag !== DOMObjectTag.startRegion) {
|
|
// Add element to rendered div so we can extract the rendered height.
|
|
this.columnParent.appendChild(el.originalElement);
|
|
el.elementRenderedHeight = el.originalElement.clientHeight;
|
|
this.columnParent.removeChild(el.originalElement);
|
|
}
|
|
return el.elementRenderedHeight;
|
|
}).reduce((prev, curr) => { return prev + curr; }, 0);
|
|
let maxColumnContentHeight = Math.trunc(totalHeight / this.regionalSettings.numberOfColumns);
|
|
for (let i = 0; i < this.columnDivs.length - 1; i++) {
|
|
let columnHeight = 0;
|
|
for (let j = 0; j < this.columnDivs[i].children.length; j++) {
|
|
columnHeight += this.columnDivs[i].children[j].clientHeight;
|
|
}
|
|
if (columnHeight > maxColumnContentHeight) {
|
|
validColumns = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (validColumns === false) {
|
|
this.renderColumnMarkdown(this.regionParent, this.domList, this.regionalSettings);
|
|
}
|
|
super.updateRenderedMarkdown();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* File: /src/dom_manager/regional_managers/regionManagerContainer.ts *
|
|
* Created Date: Sunday, May 22nd 2022, 7:50 pm *
|
|
* Author: Cameron Robinson *
|
|
* *
|
|
* Copyright (c) 2022 Cameron Robinson *
|
|
*/
|
|
/**
|
|
* This class acts as an abstraction for the actual regional manager. It is used to update the
|
|
* subclass of RegionalManager depending on user preferences to make rendering more simplified.
|
|
*/
|
|
class RegionManagerContainer {
|
|
constructor(parentFileManager, regionKey, rootElement, regionParent) {
|
|
this.region = new StandardMultiColumnRegionManager(createDefaultRegionManagerData(regionParent, parentFileManager, regionKey, rootElement));
|
|
}
|
|
getRegion() {
|
|
return this.region;
|
|
}
|
|
setRegionSettings(settingsText) {
|
|
let regionalSettings = parseColumnSettings(settingsText);
|
|
if (regionalSettings.numberOfColumns === 1) {
|
|
regionalSettings = parseSingleColumnSettings(settingsText, regionalSettings);
|
|
}
|
|
this.region.setRegionalSettings(regionalSettings);
|
|
if (regionalSettings.numberOfColumns === 1) {
|
|
if (this.region instanceof SingleColumnRegionManager === false) {
|
|
console.debug("Converting region to single column.");
|
|
this.convertToSingleColumn();
|
|
}
|
|
}
|
|
else if (regionalSettings.autoLayout === true) {
|
|
if (this.region instanceof AutoLayoutRegionManager === false) {
|
|
console.debug("Converting region to auto layout.");
|
|
this.convertToAutoLayout();
|
|
}
|
|
}
|
|
else if (regionalSettings.numberOfColumns >= 2) {
|
|
if (this.region instanceof StandardMultiColumnRegionManager === false) {
|
|
console.debug("Converting region to standard multi-column");
|
|
this.convertToStandardMultiColumn();
|
|
}
|
|
}
|
|
return this.region;
|
|
}
|
|
convertToSingleColumn() {
|
|
let data = this.region.getRegionData();
|
|
this.region = new SingleColumnRegionManager(data);
|
|
return this.region;
|
|
}
|
|
convertToStandardMultiColumn() {
|
|
let data = this.region.getRegionData();
|
|
this.region = new StandardMultiColumnRegionManager(data);
|
|
return this.region;
|
|
}
|
|
convertToAutoLayout() {
|
|
let data = this.region.getRegionData();
|
|
this.region = new AutoLayoutRegionManager(data);
|
|
return this.region;
|
|
}
|
|
}
|
|
function createDefaultRegionManagerData(regionParent, fileManager, regionKey, rootElement) {
|
|
return {
|
|
domList: [],
|
|
domObjectMap: new Map(),
|
|
regionParent: regionParent,
|
|
fileManager: fileManager,
|
|
regionalSettings: getDefaultMultiColumnSettings(),
|
|
regionKey: regionKey,
|
|
rootElement: rootElement
|
|
};
|
|
}
|
|
|
|
/*
|
|
* File: multi-column-markdown/src/domManager.ts
|
|
* Created Date: Saturday, January 30th 2022, 3:16:32 pm
|
|
* Author: Cameron Robinson
|
|
*
|
|
* Copyright (c) 2022 Cameron Robinson
|
|
*/
|
|
/**
|
|
* This class handles the global managers keeping track of all open files that
|
|
* contain MCM-Regions.
|
|
*/
|
|
class GlobalDOMManager {
|
|
constructor() {
|
|
this.managers = new Map();
|
|
}
|
|
removeFileManagerCallback(key) {
|
|
if (this.managers.has(key) === true) {
|
|
this.managers.delete(key);
|
|
}
|
|
}
|
|
getFileManager(key) {
|
|
let fileManager = null;
|
|
if (this.managers.has(key) === true) {
|
|
fileManager = this.managers.get(key);
|
|
}
|
|
else {
|
|
fileManager = createFileDOMManager(this, key);
|
|
this.managers.set(key, fileManager);
|
|
}
|
|
return fileManager;
|
|
}
|
|
getAllFileManagers() {
|
|
return Array.from(this.managers.values());
|
|
}
|
|
}
|
|
function createFileDOMManager(parentManager, fileKey) {
|
|
let regionMap = new Map();
|
|
let hasStartTag = false;
|
|
function removeRegion(regionKey) {
|
|
let regionContainer = regionMap.get(regionKey);
|
|
if (regionContainer) {
|
|
let regionalManager = regionContainer.getRegion();
|
|
regionalManager.displayOriginalElements();
|
|
}
|
|
regionMap.delete(regionKey);
|
|
if (regionMap.size === 0) {
|
|
parentManager.removeFileManagerCallback(fileKey);
|
|
}
|
|
}
|
|
function createRegionalManager(regionKey, rootElement, errorElement, renderRegionElement) {
|
|
//TODO: Use the error element whenever there is an error.
|
|
let regonalContainer = new RegionManagerContainer(this, regionKey, rootElement, renderRegionElement);
|
|
regionMap.set(regionKey, regonalContainer);
|
|
return regonalContainer.getRegion();
|
|
}
|
|
function getRegionalContainer(regionKey) {
|
|
let regonalManager = null;
|
|
if (regionMap.has(regionKey) === true) {
|
|
regonalManager = regionMap.get(regionKey);
|
|
}
|
|
return regonalManager;
|
|
}
|
|
function getAllRegionalManagers() {
|
|
let containers = Array.from(regionMap.values());
|
|
let regions = containers.map((curr) => { return curr.getRegion(); });
|
|
return regions;
|
|
}
|
|
function setHasStartTag() {
|
|
hasStartTag = true;
|
|
}
|
|
function getHasStartTag() {
|
|
return hasStartTag;
|
|
}
|
|
function getNumberOfRegions() {
|
|
return regionMap.size;
|
|
}
|
|
function checkKeyExists(checkKey) {
|
|
return regionMap.has(checkKey);
|
|
}
|
|
return { regionMap: regionMap,
|
|
hasStartTag: hasStartTag,
|
|
createRegionalManager: createRegionalManager,
|
|
getRegionalContainer: getRegionalContainer,
|
|
getAllRegionalManagers: getAllRegionalManagers,
|
|
removeRegion: removeRegion,
|
|
setHasStartTag: setHasStartTag,
|
|
getHasStartTag: getHasStartTag,
|
|
getNumberOfRegions: getNumberOfRegions,
|
|
checkKeyExists: checkKeyExists
|
|
};
|
|
}
|
|
|
|
/*
|
|
* Filename: multi-column-markdown/src/live_preview/MultiColumnMarkdown_Widget.ts
|
|
* Created Date: Tuesday, August 16th 2022, 4:38:43 pm
|
|
* Author: Cameron Robinson
|
|
*
|
|
* Copyright (c) 2022 Cameron Robinson
|
|
*/
|
|
class MultiColumnMarkdown_LivePreview_Widget extends view.WidgetType {
|
|
constructor(contentData) {
|
|
super();
|
|
this.domList = [];
|
|
this.regionSettings = getDefaultMultiColumnSettings();
|
|
this.contentData = contentData;
|
|
// Find the settings defined in the content, if it exists.
|
|
// If the settings codeblock isnt defined attempt to get the region codeblock type.
|
|
let settingsStartData = findSettingsCodeblock(this.contentData);
|
|
if (settingsStartData.found === false) {
|
|
settingsStartData = findStartCodeblock(this.contentData);
|
|
}
|
|
if (settingsStartData.found === true) {
|
|
this.settingsText = this.contentData.slice(settingsStartData.startPosition, settingsStartData.endPosition);
|
|
this.contentData = this.contentData.replace(this.settingsText, "");
|
|
// Parse the settings, updating the default settings.
|
|
this.regionSettings = parseColumnSettings(this.settingsText);
|
|
}
|
|
// Render the markdown content to our temp parent element.
|
|
this.tempParent = createDiv();
|
|
let elementMarkdownRenderer = new obsidian.MarkdownRenderChild(this.tempParent);
|
|
obsidian.MarkdownRenderer.renderMarkdown(this.contentData, this.tempParent, "", elementMarkdownRenderer);
|
|
// take all elements, in order, and create our DOM list.
|
|
let arr = Array.from(this.tempParent.children);
|
|
for (let i = 0; i < arr.length; i++) {
|
|
this.domList.push(new DOMObject(arr[i], [""]));
|
|
}
|
|
// Set up the region manager data before then creating our region manager.
|
|
let regionData = {
|
|
domList: this.domList,
|
|
domObjectMap: new Map(),
|
|
regionParent: createDiv(),
|
|
fileManager: null,
|
|
regionalSettings: this.regionSettings,
|
|
regionKey: getUID(),
|
|
rootElement: createDiv()
|
|
};
|
|
// Finally setup the type of region manager required.
|
|
if (this.regionSettings.numberOfColumns === 1) {
|
|
this.regionSettings = parseSingleColumnSettings(this.settingsText, this.regionSettings);
|
|
this.regionManager = new SingleColumnRegionManager(regionData);
|
|
}
|
|
else if (this.regionSettings.autoLayout === true) {
|
|
this.regionManager = new AutoLayoutRegionManager(regionData);
|
|
}
|
|
else {
|
|
this.regionManager = new StandardMultiColumnRegionManager(regionData);
|
|
}
|
|
}
|
|
toDOM() {
|
|
// Create our element to hold all of the live preview elements.
|
|
let el = document.createElement("div");
|
|
el.className = "mcm-cm-preview";
|
|
/**
|
|
* For situations where we need to know the rendered height, AutoLayout,
|
|
* the element must be rendered onto the screen to get the info, even if
|
|
* only for a moment. Here we attempt to get a leaf from the app so we
|
|
* can briefly append our element, check any data if required, and then
|
|
* remove it.
|
|
*/
|
|
let leaf = null;
|
|
if (app) {
|
|
let leaves = app.workspace.getLeavesOfType("markdown");
|
|
if (leaves.length > 0) {
|
|
leaf = leaves[0];
|
|
}
|
|
}
|
|
if (this.regionManager) {
|
|
if (leaf) {
|
|
leaf.view.containerEl.appendChild(el);
|
|
}
|
|
this.regionManager.renderRegionElementsToLivePreview(el);
|
|
if (leaf) {
|
|
leaf.view.containerEl.removeChild(el);
|
|
}
|
|
}
|
|
return el;
|
|
}
|
|
}
|
|
class MultiColumnMarkdown_DefinedSettings_LivePreview_Widget extends view.WidgetType {
|
|
constructor(contentData) {
|
|
super();
|
|
this.contentData = contentData;
|
|
}
|
|
toDOM() {
|
|
console.log("Rendering settings block");
|
|
// Create our element to hold all of the live preview elements.
|
|
let el = document.createElement("div");
|
|
el.className = "mcm-cm-settings-preview";
|
|
let labelDiv = el.createDiv();
|
|
let label = labelDiv.createSpan({
|
|
cls: "mcm-col-settings-preview"
|
|
});
|
|
label.textContent = "Column Settings:";
|
|
let list = el.createEl("ul");
|
|
let lines = this.contentData.split("\n");
|
|
for (let i = 1; i < lines.length - 1; i++) {
|
|
let item = list.createEl("li");
|
|
item.textContent = lines[i];
|
|
}
|
|
return el;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Filename: multi-column-markdown/src/live_preview/cm6_livePreview.ts
|
|
* Created Date: Monday, August 1st 2022, 1:51:16 pm
|
|
* Author: Cameron Robinson
|
|
*
|
|
* Copyright (c) 2022 Cameron Robinson
|
|
*/
|
|
const multiColumnMarkdown_StateField = state.StateField.define({
|
|
create(state) {
|
|
return view.Decoration.none;
|
|
},
|
|
update(oldState, transaction) {
|
|
const builder = new state.RangeSetBuilder();
|
|
let generated = false;
|
|
language.syntaxTree(transaction.state).iterate({
|
|
enter(node) {
|
|
// We only want to run the generation once per state change. If
|
|
// a previous node has sucessfully generated regions we ignore all
|
|
// other nodes in the state.
|
|
if (generated === true) {
|
|
return;
|
|
}
|
|
let markdownLeaves = app.workspace.getLeavesOfType("markdown");
|
|
if (markdownLeaves.length === 0) {
|
|
return;
|
|
}
|
|
// TODO: Check other ways to get if source is live preview? editorLivePreviewField
|
|
if (markdownLeaves[0].getViewState().state.source === true) {
|
|
console.debug("User disabled live preview.");
|
|
return;
|
|
}
|
|
// We want to run on the whole file so we dont just look for a single token.
|
|
const tokenProps = node.type.prop(language.tokenClassNodeProp);
|
|
if (tokenProps !== undefined) {
|
|
return;
|
|
}
|
|
/**
|
|
* When we have the while file we then get the entire doc text and check if it
|
|
* contains a MCM region so we know to break or not.
|
|
*/
|
|
let docLength = transaction.state.doc.length;
|
|
let docText = transaction.state.doc.sliceString(0, docLength);
|
|
if (containsRegionStart(docText) === false) {
|
|
console.debug("No start tag in document.");
|
|
return;
|
|
}
|
|
// We want to know where the user's cursor is, it can be
|
|
// selecting multiple regions of text as well so we need to know
|
|
// all locations. Used to know if we should render region as text or as preview.
|
|
let ranges = getCursorLineLocations();
|
|
// Setup our loop to render the regions as MCM.
|
|
let workingFileText = docText;
|
|
let startTagData = findStartTag(workingFileText);
|
|
if (startTagData.found === false) {
|
|
startTagData = findStartCodeblock(workingFileText);
|
|
}
|
|
let endTagData = findEndTag(workingFileText);
|
|
let loopIndex = 0;
|
|
let startIndexOffset = 0;
|
|
while (startTagData.found === true && endTagData.found === true) {
|
|
/**
|
|
* For the region we found get the start and end position of the tags so we
|
|
* can slice it out of the document.
|
|
*/
|
|
let startIndex = startIndexOffset + startTagData.startPosition;
|
|
let endIndex = startIndexOffset + endTagData.startPosition + endTagData.matchLength; // Without the matchLength will leave the end tag on the screen.
|
|
// This text is the entire region data including the start and end tags.
|
|
let elementText = docText.slice(startIndex, endIndex);
|
|
/**
|
|
* Update our start offset and the working text of the file so our next
|
|
* iteration knows where we left off
|
|
*/
|
|
startIndexOffset = endIndex;
|
|
workingFileText = docText.slice(endIndex);
|
|
// Here we check if the cursor is in this specific region.
|
|
let cursorInRegion = checkCursorInRegion(startIndex, endIndex, ranges);
|
|
if (cursorInRegion === true) {
|
|
// If the cursor is within the region we then need to know if
|
|
// it is within our settings block (if it exists.)
|
|
let settingsStartData = findStartCodeblock(elementText);
|
|
if (settingsStartData.found === false) {
|
|
settingsStartData = findSettingsCodeblock(elementText);
|
|
}
|
|
if (settingsStartData.found === true) {
|
|
// Since the settings block exists check if the cursor is within that region.
|
|
let codeblockStartIndex = startIndex + settingsStartData.startPosition;
|
|
let codeblockEndIndex = startIndex + settingsStartData.endPosition;
|
|
let settingsText = docText.slice(codeblockStartIndex, codeblockEndIndex);
|
|
let cursorInCodeblock = checkCursorInRegion(codeblockStartIndex, codeblockEndIndex, ranges);
|
|
if (cursorInCodeblock === false) {
|
|
// If the cursor is not within the region we pass the data to the
|
|
// settings view so it can be displayed in the region.
|
|
builder.add(codeblockStartIndex, codeblockEndIndex + 1, view.Decoration.replace({
|
|
widget: new MultiColumnMarkdown_DefinedSettings_LivePreview_Widget(settingsText),
|
|
}));
|
|
}
|
|
}
|
|
}
|
|
// At this point if the cursor isnt in the region we pass the data to the
|
|
// element to be rendered.
|
|
if (cursorInRegion === false) {
|
|
builder.add(startIndex, endIndex, view.Decoration.replace({
|
|
widget: new MultiColumnMarkdown_LivePreview_Widget(elementText),
|
|
}));
|
|
}
|
|
generated = true;
|
|
// ReCalculate additional start tags if there are more in document.
|
|
startTagData = findStartTag(workingFileText);
|
|
if (startTagData.found === false) {
|
|
startTagData = findStartCodeblock(workingFileText);
|
|
}
|
|
endTagData = findEndTag(workingFileText);
|
|
loopIndex++;
|
|
if (loopIndex > 100) {
|
|
console.warn("Potential issue with rendering Multi-Column Markdown live preview regions. If problem persists please file a bug report with developer.");
|
|
break;
|
|
}
|
|
}
|
|
},
|
|
});
|
|
return builder.finish();
|
|
function getCursorLineLocations() {
|
|
let ranges = [];
|
|
if (transaction.state.selection.ranges) {
|
|
ranges = transaction.state.selection.ranges.filter((range) => {
|
|
return range.empty;
|
|
}).map((range) => {
|
|
let line = transaction.state.doc.lineAt(range.head);
|
|
`${line.number}:${range.head - line.from}`;
|
|
return {
|
|
line: line,
|
|
position: range.head
|
|
};
|
|
});
|
|
}
|
|
return ranges;
|
|
}
|
|
function valueIsInRange(value, minVal, maxVal, inclusive = true) {
|
|
if (inclusive === true && (value === minVal || value === maxVal)) {
|
|
return true;
|
|
}
|
|
if (minVal < value && value < maxVal) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
function checkCursorInRegion(startIndex, endIndex, ranges) {
|
|
let cursorInRegion = false;
|
|
for (let i = 0; i < ranges.length; i++) {
|
|
// TODO: Maybe look into limiting this to the second and second to last line
|
|
// of the region as clicking right at the top or bottom of the region
|
|
// swaps it to unrendered.
|
|
let range = ranges[i];
|
|
if (valueIsInRange(range.position, startIndex, endIndex) === true) {
|
|
cursorInRegion = true;
|
|
break;
|
|
}
|
|
}
|
|
if (cursorInRegion === false && transaction.selection) {
|
|
for (let i = 0; i < transaction.selection.ranges.length; i++) {
|
|
let range = transaction.selection.ranges[i];
|
|
// If either the start or end of the selection is within the
|
|
// region range we do not render live preview.
|
|
if (valueIsInRange(range.from, startIndex, endIndex) ||
|
|
valueIsInRange(range.to, startIndex, endIndex)) {
|
|
cursorInRegion = true;
|
|
break;
|
|
}
|
|
// Or if the entire region is within the selection range
|
|
// we do not render the live preview.
|
|
if (valueIsInRange(startIndex, range.from, range.to) &&
|
|
valueIsInRange(endIndex, range.from, range.to)) {
|
|
cursorInRegion = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return cursorInRegion;
|
|
}
|
|
},
|
|
provide(field) {
|
|
return view.EditorView.decorations.from(field);
|
|
},
|
|
});
|
|
|
|
/*
|
|
* File: multi-column-markdown/src/main.ts
|
|
* Created Date: Tuesday, October 5th 2021, 1:09 pm
|
|
* Author: Cameron Robinson
|
|
*
|
|
* Copyright (c) 2022 Cameron Robinson
|
|
*/
|
|
const CODEBLOCK_START_STRS = [
|
|
"start-multi-column",
|
|
"multi-column-start"
|
|
];
|
|
class MultiColumnMarkdown extends obsidian.Plugin {
|
|
constructor() {
|
|
super(...arguments);
|
|
this.globalManager = new GlobalDOMManager();
|
|
}
|
|
onload() {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
console.log("Loading multi-column markdown");
|
|
this.globalManager = new GlobalDOMManager();
|
|
this.registerEditorExtension(multiColumnMarkdown_StateField);
|
|
for (let i = 0; i < CODEBLOCK_START_STRS.length; i++) {
|
|
let startStr = CODEBLOCK_START_STRS[i];
|
|
this.setupMarkdownCodeblockPostProcessor(startStr);
|
|
}
|
|
this.setupMarkdownPostProcessor();
|
|
//TODO: Set up this as a modal to set settings automatically
|
|
this.addCommand({
|
|
id: `insert-multi-column-region`,
|
|
name: `Insert Multi-Column Region`,
|
|
editorCallback: (editor, view) => {
|
|
try {
|
|
let cursorStartPosition = editor.getCursor("from");
|
|
editor.getDoc().replaceSelection(`
|
|
\`\`\`start-multi-column
|
|
ID: ID_${getUID(4)}
|
|
Number of Columns: 2
|
|
Largest Column: standard
|
|
\`\`\`
|
|
|
|
|
|
|
|
--- column-end ---
|
|
|
|
|
|
|
|
=== end-multi-column
|
|
|
|
${editor.getDoc().getSelection()}`);
|
|
cursorStartPosition.line = cursorStartPosition.line + 7;
|
|
cursorStartPosition.ch = 0;
|
|
editor.setCursor(cursorStartPosition);
|
|
}
|
|
catch (e) {
|
|
new obsidian.Notice("Encountered an error inserting a multi-column region. Please try again later.");
|
|
}
|
|
}
|
|
});
|
|
this.addCommand({
|
|
id: `add-IDs-To-multi-column-region`,
|
|
name: `Fix Missing IDs for Multi-Column Regions`,
|
|
editorCallback: (editor, view) => {
|
|
try {
|
|
/**
|
|
* Not sure if there is an easier way to do this.
|
|
*
|
|
* Get all of the lines of the document split by newlines.
|
|
*/
|
|
let docText = editor.getRange({ line: 0, ch: 0 }, { line: editor.getDoc().lineCount(), ch: 0 });
|
|
let lines = docText.split("\n");
|
|
let startCodeblock = findStartCodeblock(docText);
|
|
let lineOffset = 0;
|
|
let numCodeblocksUpdated = 0;
|
|
while (startCodeblock.found === true) {
|
|
let startReplaceLines = (docText.slice(0, startCodeblock.startPosition).split("\n").length - 1) + lineOffset; // -1 to Zero index the replace line
|
|
let settingsText = docText.slice(startCodeblock.startPosition, startCodeblock.endPosition);
|
|
let settingsID = parseStartRegionCodeBlockID(settingsText);
|
|
if (settingsID === "") {
|
|
let replacementText = editor.getRange({ line: startReplaceLines, ch: 0 }, { line: startReplaceLines, ch: startCodeblock.matchLength }) + `\nID: ID_${getUID(4)}`;
|
|
editor.replaceRange(replacementText, { line: startReplaceLines, ch: 0 }, { line: startReplaceLines, ch: startCodeblock.matchLength });
|
|
startReplaceLines += 1; // we added a line to the doc so update our offset.
|
|
numCodeblocksUpdated += 1;
|
|
}
|
|
lineOffset = startReplaceLines;
|
|
docText = docText.slice(startCodeblock.startPosition + startCodeblock.matchLength);
|
|
startCodeblock = findStartCodeblock(docText);
|
|
}
|
|
/**
|
|
* Loop through all of the lines checking if the line is a
|
|
* start tag and if so is it missing an ID.
|
|
*/
|
|
let linesWithoutIDs = [];
|
|
let textWithoutIDs = [];
|
|
for (let i = 0; i < lines.length; i++) {
|
|
let data = isStartTagWithID(lines[i]);
|
|
if (data.isStartTag === true && data.hasKey === false) {
|
|
linesWithoutIDs.push(i);
|
|
textWithoutIDs.push(lines[i]);
|
|
}
|
|
}
|
|
if (linesWithoutIDs.length === 0 && numCodeblocksUpdated === 0) {
|
|
new obsidian.Notice("Found 0 missing IDs in the current document.");
|
|
return;
|
|
}
|
|
/**
|
|
* Now loop through each line that is missing an ID and
|
|
* generate a random ID and replace the original text.
|
|
*/
|
|
for (let i = 0; i < linesWithoutIDs.length; i++) {
|
|
let originalText = textWithoutIDs[i];
|
|
let text = originalText;
|
|
text = text.trimEnd();
|
|
if (text.charAt(text.length - 1) === ":") {
|
|
text = text.slice(0, text.length - 1);
|
|
}
|
|
text = `${text}: ID_${getUID(4)}`;
|
|
editor.replaceRange(text, { line: linesWithoutIDs[i], ch: 0 }, { line: linesWithoutIDs[i], ch: originalText.length });
|
|
}
|
|
new obsidian.Notice(`Replaced ${linesWithoutIDs.length + numCodeblocksUpdated} missing ID(s) in the current document.`);
|
|
}
|
|
catch (e) {
|
|
new obsidian.Notice("Encountered an error addign IDs to multi-column regions. Please try again later.");
|
|
}
|
|
}
|
|
});
|
|
this.registerInterval(window.setInterval(() => {
|
|
this.UpdateOpenFilePreviews();
|
|
}, 500));
|
|
});
|
|
}
|
|
UpdateOpenFilePreviews() {
|
|
let fileManagers = this.globalManager.getAllFileManagers();
|
|
fileManagers.forEach(element => {
|
|
let regionalManagers = element.getAllRegionalManagers();
|
|
regionalManagers.forEach(regionManager => {
|
|
regionManager.updateRenderedMarkdown();
|
|
});
|
|
});
|
|
}
|
|
setupMarkdownPostProcessor() {
|
|
this.registerMarkdownPostProcessor((el, ctx) => __awaiter(this, void 0, void 0, function* () {
|
|
const sourcePath = ctx.sourcePath;
|
|
let fileDOMManager = this.globalManager.getFileManager(sourcePath);
|
|
if (fileDOMManager === null) {
|
|
console.log("Found null DOM manager. Could not process multi-column markdown.");
|
|
return;
|
|
}
|
|
/**
|
|
* Here we check if the export "print" flag is in the DOM so we can determine if we
|
|
* are exporting and handle that case.
|
|
*/
|
|
if (this.checkExporting(el)) {
|
|
this.exportDocumentToPDF(el, fileDOMManager, sourcePath);
|
|
}
|
|
// Get the info for our current context and then check
|
|
// if the entire text contains a start tag. If there is
|
|
// no start tag in the document we can just return and
|
|
// ignore the rest of the parsing.
|
|
let info = ctx.getSectionInfo(el);
|
|
/**
|
|
* We need the context info to properly parse so returning here
|
|
* info is null. TODO: Set error in view if this occurs.
|
|
*/
|
|
if (!info) {
|
|
return;
|
|
}
|
|
let docString = info.text;
|
|
let docLines = docString.split("\n");
|
|
/**
|
|
* If we encounter a start tag on the document we set the flag to start
|
|
* parsing the rest of the document.
|
|
*/
|
|
if (containsStartTag(el.textContent) ||
|
|
containsStartCodeBlock(docString)) {
|
|
fileDOMManager.setHasStartTag();
|
|
}
|
|
/**
|
|
* If the document does not contain any start tags we ignore the
|
|
* rest of the parsing. This is only set to true once the first
|
|
* start tag element is parsed above.
|
|
*/
|
|
if (fileDOMManager.getHasStartTag() === false) {
|
|
return;
|
|
}
|
|
/**
|
|
* Take the info provided and generate the required variables from
|
|
* the line start and end values.
|
|
*/
|
|
let linesAboveArray = docLines.slice(0, info.lineStart);
|
|
let linesOfElement = docLines.slice(info.lineStart, info.lineEnd + 1);
|
|
let textOfElement = linesOfElement.join("\n");
|
|
let linesBelowArray = docLines.slice(info.lineEnd + 1);
|
|
//#region Depreciated Start Tag
|
|
/**
|
|
* If the current line is a start tag we want to set up the
|
|
* region manager. The regional manager takes care
|
|
* of all items between it's start and end tags while the
|
|
* file manager we got above above takes care of all regional
|
|
* managers in each file.
|
|
*/
|
|
if (containsStartTag(textOfElement)) {
|
|
/**
|
|
* Set up the current element to act as the parent for the
|
|
* multi-column region.
|
|
*/
|
|
el.children[0].detach();
|
|
el.classList.add(MultiColumnLayoutCSS.RegionRootContainerDiv);
|
|
let renderErrorRegion = el.createDiv({
|
|
cls: `${MultiColumnLayoutCSS.RegionErrorContainerDiv} ${MultiColumnStyleCSS.RegionErrorMessage}`,
|
|
});
|
|
let renderColumnRegion = el.createDiv({
|
|
cls: MultiColumnLayoutCSS.RegionContentContainerDiv
|
|
});
|
|
let startBlockData = getStartBlockAboveLine(linesOfElement);
|
|
if (startBlockData === null) {
|
|
return;
|
|
}
|
|
let regionKey = startBlockData.startBlockKey;
|
|
if (fileDOMManager.checkKeyExists(regionKey) === true) {
|
|
let { numberOfTags, keys } = countStartTags(info.text);
|
|
let numMatches = 0;
|
|
for (let i = 0; i < numberOfTags; i++) {
|
|
// Because we checked if key exists one of these has to match.
|
|
if (keys[i] === regionKey) {
|
|
numMatches++;
|
|
}
|
|
}
|
|
// We only want to display an error if there are more than 2 of the same id across
|
|
// the whole document. This prevents erros when obsidian reloads the whole document
|
|
// and there are two of the same key in the map.
|
|
if (numMatches >= 2) {
|
|
if (regionKey === "") {
|
|
renderErrorRegion.innerText = "Found multiple regions with empty IDs. Please set a unique ID after each start tag.\nEG: '=== multi-column-start: randomID'\nOr use 'Fix Missing IDs' in the command palette and reload the document.";
|
|
}
|
|
else {
|
|
renderErrorRegion.innerText = "Region ID already exists in document, please set a unique ID.\nEG: '=== multi-column-start: randomID'";
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
el.id = `MultiColumnID:${regionKey}`;
|
|
let elementMarkdownRenderer = new obsidian.MarkdownRenderChild(el);
|
|
fileDOMManager.createRegionalManager(regionKey, el, renderErrorRegion, renderColumnRegion);
|
|
elementMarkdownRenderer.onunload = () => {
|
|
if (fileDOMManager) {
|
|
fileDOMManager.removeRegion(startBlockData.startBlockKey);
|
|
}
|
|
};
|
|
ctx.addChild(elementMarkdownRenderer);
|
|
/**
|
|
* Now we have created our regional manager and defined what elements
|
|
* need to be rendered into. So we can return without any more processing.
|
|
*/
|
|
return;
|
|
}
|
|
//#endregion Depreciated Start Tag
|
|
/**
|
|
* Check if any of the lines above us contain a start block, and if
|
|
* so get the lines from our current element to the start block.
|
|
*/
|
|
let startBockAbove = getStartBlockOrCodeblockAboveLine(linesAboveArray);
|
|
if (startBockAbove === null) {
|
|
return;
|
|
}
|
|
/**
|
|
* We now know we're within a multi-column region, so we update our
|
|
* list of lines above to just be the items within this region.
|
|
*/
|
|
linesAboveArray = startBockAbove.linesAboveArray;
|
|
/**
|
|
* We use the start block's key to get our regional manager. If this
|
|
* lookup fails we can not continue processing this element.
|
|
*/
|
|
let regionalContainer = fileDOMManager.getRegionalContainer(startBockAbove.startBlockKey);
|
|
if (regionalContainer === null) {
|
|
return;
|
|
}
|
|
let regionalManager = regionalContainer.getRegion();
|
|
/**
|
|
* To make sure we're placing the item in the right location (and
|
|
* overwrite elements that are now gone) we now want all of the
|
|
* lines after this element up to the end tag.
|
|
*/
|
|
linesBelowArray = getEndBlockBelow(linesBelowArray);
|
|
/**
|
|
* Now we take the lines above our current element up until the
|
|
* start region tag and render that into an HTML element. We will
|
|
* use these elements to determine where to place our current element.
|
|
*/
|
|
let siblingsAbove = renderMarkdownFromLines(linesAboveArray, sourcePath);
|
|
let siblingsBelow = renderMarkdownFromLines(linesBelowArray, sourcePath);
|
|
/**
|
|
* Set up our dom object to be added to the manager.
|
|
*/
|
|
let currentObject = new DOMObject(el, linesOfElement);
|
|
el.id = currentObject.UID;
|
|
currentObject = TaskListDOMObject.checkForTaskListElement(currentObject);
|
|
/**
|
|
* Now we add the object to the manager and then setup the
|
|
* callback for when the object is removed from view that will remove
|
|
* the item from the manager.
|
|
*/
|
|
regionalManager.addObject(siblingsAbove, siblingsBelow, currentObject);
|
|
let elementMarkdownRenderer = new obsidian.MarkdownRenderChild(el);
|
|
elementMarkdownRenderer.onunload = () => {
|
|
if (regionalContainer === null) {
|
|
return;
|
|
}
|
|
let regionalManager = regionalContainer.getRegion();
|
|
if (regionalManager) {
|
|
// We can attempt to update the view here after the item is removed
|
|
// but need to get the item's parent element before removing object from manager.
|
|
let regionRenderData = regionalManager.getRegionRenderData();
|
|
regionalManager.removeObject(currentObject.UID);
|
|
/**
|
|
* Need to check here if element is null as this closure will be called
|
|
* repeatedly on file change.
|
|
*/
|
|
if (regionRenderData.parentRenderElement === null) {
|
|
return;
|
|
}
|
|
regionalManager.renderRegionElementsToScreen();
|
|
}
|
|
};
|
|
ctx.addChild(elementMarkdownRenderer);
|
|
let elementTextSpaced = linesOfElement.reduce((prev, curr) => {
|
|
return prev + "\n" + curr;
|
|
});
|
|
/**
|
|
* Now we check if our current element is a special flag so we can
|
|
* properly set the element tag within the regional manager.
|
|
*/
|
|
if (containsEndTag(el.textContent) === true) {
|
|
currentObject.elementType = ElementRenderType.unRendered;
|
|
el.addClass(MultiColumnStyleCSS.RegionEndTag);
|
|
regionalManager.updateElementTag(currentObject.UID, DOMObjectTag.endRegion);
|
|
}
|
|
else if (containsColEndTag(elementTextSpaced) === true) {
|
|
currentObject.elementType = ElementRenderType.unRendered;
|
|
el.addClass(MultiColumnStyleCSS.ColumnEndTag);
|
|
regionalManager.updateElementTag(currentObject.UID, DOMObjectTag.columnBreak);
|
|
}
|
|
else if (containsColSettingsTag(elementTextSpaced) === true) {
|
|
currentObject.elementType = ElementRenderType.unRendered;
|
|
el.addClass(MultiColumnStyleCSS.RegionSettings);
|
|
regionalManager = regionalContainer.setRegionSettings(elementTextSpaced);
|
|
regionalManager.updateElementTag(currentObject.UID, DOMObjectTag.regionSettings);
|
|
}
|
|
else {
|
|
el.addClass(MultiColumnStyleCSS.RegionContent);
|
|
}
|
|
regionalManager.renderRegionElementsToScreen();
|
|
return;
|
|
}));
|
|
}
|
|
isStartCodeblockInExport(node) {
|
|
for (let i = 0; i < CODEBLOCK_START_STRS.length; i++) {
|
|
if (node.hasClass(`block-language-${CODEBLOCK_START_STRS[i]}`)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
exportDocumentToPDF(el, fileDOMManager, sourcePath) {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
// A true export will be passed an element with all other items in the doc as children.
|
|
// So if there are no children we can just return
|
|
let docChildren = Array.from(el.childNodes);
|
|
if (docChildren.length === 0) {
|
|
return;
|
|
}
|
|
let childrenToRemove = [];
|
|
// To export codeblocks we need to get the IDs so we can get the data from our managers.
|
|
// however since the ID isnt being stored in the element yet this means we need to read
|
|
// all of the IDs out of the full document.
|
|
let codeblockStartBlocks = [];
|
|
let aFile = this.app.vault.getAbstractFileByPath(sourcePath);
|
|
if (aFile instanceof obsidian.TFile) {
|
|
let file = aFile;
|
|
let fileText = yield this.app.vault.cachedRead(file); // Is cached read Ok here? It should be.
|
|
// Once we have our data we search the text for all codeblock start values.
|
|
// storing them into our queue.
|
|
let codeBlockData = findStartCodeblock(fileText);
|
|
while (codeBlockData.found === true) {
|
|
let codeblockText = fileText.slice(codeBlockData.startPosition, codeBlockData.endPosition);
|
|
fileText = fileText.slice(codeBlockData.endPosition);
|
|
codeblockStartBlocks.push(codeblockText);
|
|
codeBlockData = findStartCodeblock(fileText);
|
|
}
|
|
}
|
|
let inBlock = false;
|
|
for (let i = 0; i < docChildren.length; i++) {
|
|
let child = docChildren[i];
|
|
if (child instanceof HTMLElement) {
|
|
if (inBlock === false) {
|
|
let foundBlockData = false;
|
|
let regionKey = "";
|
|
let blockData = isStartTagWithID(child.textContent);
|
|
if (blockData.isStartTag === true) {
|
|
foundBlockData = true;
|
|
if (blockData.hasKey === true) {
|
|
let foundKey = getStartTagKey(child.textContent);
|
|
if (foundKey !== null) {
|
|
regionKey = foundKey;
|
|
}
|
|
}
|
|
}
|
|
else if (blockData.isStartTag === false && this.isStartCodeblockInExport(child)) {
|
|
// If the start tag from the old version is null we then check to see if the element is
|
|
// a codeblock start. If it is we use the next available codeblock data to retrieve our ID.
|
|
let codeblockText = codeblockStartBlocks.shift();
|
|
if (codeblockText === undefined) {
|
|
console.error("Found undefined codeblock data when exporting.");
|
|
return;
|
|
}
|
|
let id = parseStartRegionCodeBlockID(codeblockText);
|
|
if (id !== "") {
|
|
foundBlockData = true;
|
|
regionKey = id;
|
|
}
|
|
}
|
|
if (foundBlockData === true && regionKey !== "") {
|
|
inBlock = true;
|
|
for (let i = child.children.length - 1; i >= 0; i--) {
|
|
child.children[i].detach();
|
|
}
|
|
child.innerText = "";
|
|
child.classList.add(MultiColumnLayoutCSS.RegionRootContainerDiv);
|
|
let renderErrorRegion = child.createDiv({
|
|
cls: `${MultiColumnLayoutCSS.RegionErrorContainerDiv}, ${MultiColumnStyleCSS.RegionErrorMessage}`,
|
|
});
|
|
let renderColumnRegion = child.createDiv({
|
|
cls: MultiColumnLayoutCSS.RegionContentContainerDiv
|
|
});
|
|
let regionalContainer = fileDOMManager.getRegionalContainer(regionKey);
|
|
if (regionalContainer === null) {
|
|
renderErrorRegion.innerText = "Error rendering multi-column region.\nPlease close and reopen the file, then make sure you are in reading mode before exporting.";
|
|
}
|
|
else {
|
|
let regionalManager = regionalContainer.getRegion();
|
|
regionalManager.exportRegionElementsToPDF(renderColumnRegion);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
if (containsEndTag(child.textContent) === true) {
|
|
inBlock = false;
|
|
}
|
|
childrenToRemove.push(child);
|
|
}
|
|
}
|
|
}
|
|
childrenToRemove.forEach(child => {
|
|
el.removeChild(child);
|
|
});
|
|
});
|
|
}
|
|
checkExporting(element) {
|
|
if (element === null) {
|
|
return false;
|
|
}
|
|
if (element.classList.contains("print")) {
|
|
return true;
|
|
}
|
|
if (element.parentNode !== null) {
|
|
return this.checkExporting(element.parentElement);
|
|
}
|
|
return false;
|
|
}
|
|
setupMarkdownCodeblockPostProcessor(startStr) {
|
|
this.registerMarkdownCodeBlockProcessor(startStr, (source, el, ctx) => {
|
|
var _a;
|
|
const sourcePath = ctx.sourcePath;
|
|
// Set up our CSS so that the codeblock only renders this data in reading mode
|
|
// source/live preview mode is handled by the CM6 implementation.
|
|
(_a = el.parentElement) === null || _a === void 0 ? void 0 : _a.addClass("preivew-mcm-start-block");
|
|
// To determine what kind of view we are rendering in we need a markdown leaf.
|
|
// Really this should never return here since rendering is only done in markdown leaves.
|
|
let markdownLeaves = app.workspace.getLeavesOfType("markdown");
|
|
if (markdownLeaves.length === 0) {
|
|
return;
|
|
}
|
|
for (let i = 0; i < markdownLeaves.length; i++) {
|
|
let fileLeaf = getFileLeaf(sourcePath);
|
|
if (fileLeaf === null) {
|
|
continue;
|
|
}
|
|
if (getLeafSourceMode(fileLeaf) === "source") {
|
|
return;
|
|
}
|
|
}
|
|
if (this.globalManager === null || this.globalManager === undefined) {
|
|
console.log("Global manager is undefined?");
|
|
return;
|
|
}
|
|
let fileDOMManager = this.globalManager.getFileManager(sourcePath);
|
|
if (fileDOMManager === null) {
|
|
return;
|
|
}
|
|
// Set file to have start tag.
|
|
fileDOMManager.setHasStartTag();
|
|
// Get the info for our current context and then check
|
|
// if the entire text contains a start tag. If there is
|
|
// no start tag in the document we can just return and
|
|
// ignore the rest of the parsing.
|
|
let info = ctx.getSectionInfo(el);
|
|
/**
|
|
* We need the context info to properly parse so returning here
|
|
* info is null. TODO: Set error in view if this occurs.
|
|
*/
|
|
if (!info) {
|
|
return;
|
|
}
|
|
/**
|
|
* Set up the current element to act as the parent for the
|
|
* multi-column region.
|
|
*/
|
|
el.classList.add(MultiColumnLayoutCSS.RegionRootContainerDiv);
|
|
let renderErrorRegion = el.createDiv({
|
|
cls: `${MultiColumnLayoutCSS.RegionErrorContainerDiv} ${MultiColumnStyleCSS.RegionErrorMessage}`,
|
|
});
|
|
let renderColumnRegion = el.createDiv({
|
|
cls: MultiColumnLayoutCSS.RegionContentContainerDiv
|
|
});
|
|
let regionKey = parseStartRegionCodeBlockID(source);
|
|
let createNewRegionManager = true;
|
|
if (fileDOMManager.checkKeyExists(regionKey) === true) {
|
|
createNewRegionManager = false;
|
|
let { numberOfTags, keys } = countStartTags(info.text);
|
|
let numMatches = 0;
|
|
for (let i = 0; i < numberOfTags; i++) {
|
|
// Because we checked if key exists one of these has to match.
|
|
if (keys[i] === regionKey) {
|
|
numMatches++;
|
|
}
|
|
}
|
|
// We only want to display an error if there are more than 2 of the same id across
|
|
// the whole document. This prevents erros when obsidian reloads the whole document
|
|
// and there are two of the same key in the map.
|
|
if (numMatches >= 2) {
|
|
if (regionKey === "") {
|
|
renderErrorRegion.innerText = "Found multiple regions with empty IDs. Please set a unique ID after each start tag.\nEG: '=== multi-column-start: randomID'\nOr use 'Fix Missing IDs' in the command palette and reload the document.";
|
|
}
|
|
else {
|
|
renderErrorRegion.innerText = "Region ID already exists in document, please set a unique ID.\nEG: '=== multi-column-start: randomID'";
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
el.id = `MultiColumnID:${regionKey}`;
|
|
// If something changes in the codeblock we dont necessarily want to update our
|
|
// old reference to the region manager. This could be a potential bug area.
|
|
if (createNewRegionManager === true) {
|
|
// Create a new regional manager.
|
|
let elementMarkdownRenderer = new obsidian.MarkdownRenderChild(el);
|
|
fileDOMManager.createRegionalManager(regionKey, el, renderErrorRegion, renderColumnRegion);
|
|
// Set up the on unload callback. This can be called if the user changes
|
|
// the start/settings codeblock in any way. We only want to unload
|
|
// if the file is being removed from view.
|
|
elementMarkdownRenderer.onunload = () => {
|
|
if (fileDOMManager && fileStillInView(sourcePath) === false) {
|
|
console.debug("File not in any markdown leaf. Removing region from dom manager.");
|
|
fileDOMManager.removeRegion(regionKey);
|
|
}
|
|
};
|
|
ctx.addChild(elementMarkdownRenderer);
|
|
}
|
|
let regionalManagerContainer = fileDOMManager.getRegionalContainer(regionKey);
|
|
if (regionalManagerContainer !== null) {
|
|
let regionalManager = regionalManagerContainer.setRegionSettings(source);
|
|
regionalManager.regionParent = el;
|
|
}
|
|
});
|
|
}
|
|
}
|
|
function renderMarkdownFromLines(mdLines, sourcePath) {
|
|
/**
|
|
* We re-render all of the items above our element, until the start tag,
|
|
* so we can determine where to place the new item in the manager.
|
|
*
|
|
* TODO: Can reduce the amount needing to be rendered by only rendering to
|
|
* the start tag or a column-break whichever is closer.
|
|
*/
|
|
let siblings = createDiv();
|
|
let markdownRenderChild = new obsidian.MarkdownRenderChild(siblings);
|
|
obsidian.MarkdownRenderer.renderMarkdown(mdLines.reduce((prev, current) => {
|
|
return prev + "\n" + current;
|
|
}, ""), siblings, sourcePath, markdownRenderChild);
|
|
return siblings;
|
|
}
|
|
|
|
module.exports = MultiColumnMarkdown;
|
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFpbi5qcyIsInNvdXJjZXMiOlsibm9kZV9tb2R1bGVzL3RzbGliL3RzbGliLmVzNi5qcyIsInNyYy9yZWdpb25TZXR0aW5ncy50cyIsInNyYy91dGlsaXRpZXMvc2V0dGluZ3NQYXJzZXIudHMiLCJzcmMvdXRpbGl0aWVzL3RleHRQYXJzZXIudHMiLCJzcmMvdXRpbGl0aWVzL3V0aWxzLnRzIiwic3JjL3V0aWxpdGllcy9lbGVtZW50UmVuZGVyVHlwZVBhcnNlci50cyIsInNyYy9kb21fbWFuYWdlci9kb21PYmplY3QudHMiLCJzcmMvdXRpbGl0aWVzL2Nzc0RlZmluaXRpb25zLnRzIiwic3JjL2RvbV9tYW5hZ2VyL3JlZ2lvbmFsX21hbmFnZXJzL3JlZ2lvbk1hbmFnZXIudHMiLCJzcmMvZG9tX21hbmFnZXIvcmVnaW9uYWxfbWFuYWdlcnMvc3RhbmRhcmRNdWx0aUNvbHVtblJlZ2lvbk1hbmFnZXIudHMiLCJzcmMvZG9tX21hbmFnZXIvcmVnaW9uYWxfbWFuYWdlcnMvc2luZ2xlQ29sdW1uUmVnaW9uTWFuYWdlci50cyIsInNyYy9kb21fbWFuYWdlci9yZWdpb25hbF9tYW5hZ2Vycy9hdXRvTGF5b3V0UmVnaW9uTWFuYWdlci50cyIsInNyYy9kb21fbWFuYWdlci9yZWdpb25hbF9tYW5hZ2Vycy9yZWdpb25NYW5hZ2VyQ29udGFpbmVyLnRzIiwic3JjL2RvbV9tYW5hZ2VyL2RvbU1hbmFnZXIudHMiLCJzcmMvbGl2ZV9wcmV2aWV3L21jbV9saXZlUHJldmlld193aWRnZXQudHMiLCJzcmMvbGl2ZV9wcmV2aWV3L2NtNl9saXZlUHJldmlldy50cyIsInNyYy9tYWluLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcclxuQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uXHJcblxyXG5QZXJtaXNzaW9uIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBhbmQvb3IgZGlzdHJpYnV0ZSB0aGlzIHNvZnR3YXJlIGZvciBhbnlcclxucHVycG9zZSB3aXRoIG9yIHdpdGhvdXQgZmVlIGlzIGhlcmVieSBncmFudGVkLlxyXG5cclxuVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiBBTkQgVEhFIEFVVEhPUiBESVNDTEFJTVMgQUxMIFdBUlJBTlRJRVMgV0lUSFxyXG5SRUdBUkQgVE8gVEhJUyBTT0ZUV0FSRSBJTkNMVURJTkcgQUxMIElNUExJRUQgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFlcclxuQU5EIEZJVE5FU1MuIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1IgQkUgTElBQkxFIEZPUiBBTlkgU1BFQ0lBTCwgRElSRUNULFxyXG5JTkRJUkVDVCwgT1IgQ09OU0VRVUVOVElBTCBEQU1BR0VTIE9SIEFOWSBEQU1BR0VTIFdIQVRTT0VWRVIgUkVTVUxUSU5HIEZST01cclxuTE9TUyBPRiBVU0UsIERBVEEgT1IgUFJPRklUUywgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIE5FR0xJR0VOQ0UgT1JcclxuT1RIRVIgVE9SVElPVVMgQUNUSU9OLCBBUklTSU5HIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFVTRSBPUlxyXG5QRVJGT1JNQU5DRSBPRiBUSElTIFNPRlRXQVJFLlxyXG4qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiAqL1xyXG4vKiBnbG9iYWwgUmVmbGVjdCwgUHJvbWlzZSAqL1xyXG5cclxudmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbihkLCBiKSB7XHJcbiAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XHJcbiAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxyXG4gICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChiLCBwKSkgZFtwXSA9IGJbcF07IH07XHJcbiAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcclxufTtcclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2V4dGVuZHMoZCwgYikge1xyXG4gICAgaWYgKHR5cGVvZiBiICE9PSBcImZ1bmN0aW9uXCIgJiYgYiAhPT0gbnVsbClcclxuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2xhc3MgZXh0ZW5kcyB2YWx1ZSBcIiArIFN0cmluZyhiKSArIFwiIGlzIG5vdCBhIGNvbnN0cnVjdG9yIG9yIG51bGxcIik7XHJcbiAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xyXG4gICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XHJcbiAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XHJcbn1cclxuXHJcbmV4cG9ydCB2YXIgX19hc3NpZ24gPSBmdW5jdGlvbigpIHtcclxuICAgIF9fYXNzaWduID0gT2JqZWN0LmFzc2lnbiB8fCBmdW5jdGlvbiBfX2Fzc2lnbih0KSB7XHJcbiAgICAgICAgZm9yICh2YXIgcywgaSA9IDEsIG4gPSBhcmd1bWVudHMubGVuZ3RoOyBpIDwgbjsgaSsrKSB7XHJcbiAgICAgICAgICAgIHMgPSBhcmd1bWVudHNbaV07XHJcbiAgICAgICAgICAgIGZvciAodmFyIHAgaW4gcykgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzLCBwKSkgdFtwXSA9IHNbcF07XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiB0O1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIF9fYXNzaWduLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3Jlc3QocywgZSkge1xyXG4gICAgdmFyIHQgPSB7fTtcclxuICAgIGZvciAodmFyIHAgaW4gcykgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzLCBwKSAmJiBlLmluZGV4T2YocCkgPCAwKVxyXG4gICAgICAgIHRbcF0gPSBzW3BdO1xyXG4gICAgaWYgKHMgIT0gbnVsbCAmJiB0eXBlb2YgT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyA9PT0gXCJmdW5jdGlvblwiKVxyXG4gICAgICAgIGZvciAodmFyIGkgPSAwLCBwID0gT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhzKTsgaSA8IHAubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgICAgaWYgKGUuaW5kZXhPZihwW2ldKSA8IDAgJiYgT2JqZWN0LnByb3RvdHlwZS5wcm9wZXJ0eUlzRW51bWVyYWJsZS5jYWxsKHMsIHBbaV0pKVxyXG4gICAgICAgICAgICAgICAgdFtwW2ldXSA9IHNbcFtpXV07XHJcbiAgICAgICAgfVxyXG4gICAgcmV0dXJuIHQ7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2RlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XHJcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xyXG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcclxuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XHJcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19wYXJhbShwYXJhbUluZGV4LCBkZWNvcmF0b3IpIHtcclxuICAgIHJldHVybiBmdW5jdGlvbiAodGFyZ2V0LCBrZXkpIHsgZGVjb3JhdG9yKHRhcmdldCwga2V5LCBwYXJhbUluZGV4KTsgfVxyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19tZXRhZGF0YShtZXRhZGF0YUtleSwgbWV0YWRhdGFWYWx1ZSkge1xyXG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0Lm1ldGFkYXRhID09PSBcImZ1bmN0aW9uXCIpIHJldHVybiBSZWZsZWN0Lm1ldGFkYXRhKG1ldGFkYXRhS2V5LCBtZXRhZGF0YVZhbHVlKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fYXdhaXRlcih0aGlzQXJnLCBfYXJndW1lbnRzLCBQLCBnZW5lcmF0b3IpIHtcclxuICAgIGZ1bmN0aW9uIGFkb3B0KHZhbHVlKSB7IHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFAgPyB2YWx1ZSA6IG5ldyBQKGZ1bmN0aW9uIChyZXNvbHZlKSB7IHJlc29sdmUodmFsdWUpOyB9KTsgfVxyXG4gICAgcmV0dXJuIG5ldyAoUCB8fCAoUCA9IFByb21pc2UpKShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XHJcbiAgICAgICAgZnVuY3Rpb24gZnVsZmlsbGVkKHZhbHVlKSB7IHRyeSB7IHN0ZXAoZ2VuZXJhdG9yLm5leHQodmFsdWUpKTsgfSBjYXRjaCAoZSkgeyByZWplY3QoZSk7IH0gfVxyXG4gICAgICAgIGZ1bmN0aW9uIHJlamVjdGVkKHZhbHVlKSB7IHRyeSB7IHN0ZXAoZ2VuZXJhdG9yW1widGhyb3dcIl0odmFsdWUpKTsgfSBjYXRjaCAoZSkgeyByZWplY3QoZSk7IH0gfVxyXG4gICAgICAgIGZ1bmN0aW9uIHN0ZXAocmVzdWx0KSB7IHJlc3VsdC5kb25lID8gcmVzb2x2ZShyZXN1bHQudmFsdWUpIDogYWRvcHQocmVzdWx0LnZhbHVlKS50aGVuKGZ1bGZpbGxlZCwgcmVqZWN0ZWQpOyB9XHJcbiAgICAgICAgc3RlcCgoZ2VuZXJhdG9yID0gZ2VuZXJhdG9yLmFwcGx5KHRoaXNBcmcsIF9hcmd1bWVudHMgfHwgW10pKS5uZXh0KCkpO1xyXG4gICAgfSk7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2dlbmVyYXRvcih0aGlzQXJnLCBib2R5KSB7XHJcbiAgICB2YXIgXyA9IHsgbGFiZWw6IDAsIHNlbnQ6IGZ1bmN0aW9uKCkgeyBpZiAodFswXSAmIDEpIHRocm93IHRbMV07IHJldHVybiB0WzFdOyB9LCB0cnlzOiBbXSwgb3BzOiBbXSB9LCBmLCB5LCB0LCBnO1xyXG4gICAgcmV0dXJuIGcgPSB7IG5leHQ6IHZlcmIoMCksIFwidGhyb3dcIjogdmVyYigxKSwgXCJyZXR1cm5cIjogdmVyYigyKSB9LCB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgKGdbU3ltYm9sLml0ZXJhdG9yXSA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gdGhpczsgfSksIGc7XHJcbiAgICBmdW5jdGlvbiB2ZXJiKG4pIHsgcmV0dXJuIGZ1bmN0aW9uICh2KSB7IHJldHVybiBzdGVwKFtuLCB2XSk7IH07IH1cclxuICAgIGZ1bmN0aW9uIHN0ZXAob3ApIHtcclxuICAgICAgICBpZiAoZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkdlbmVyYXRvciBpcyBhbHJlYWR5IGV4ZWN1dGluZy5cIik7XHJcbiAgICAgICAgd2hpbGUgKF8pIHRyeSB7XHJcbiAgICAgICAgICAgIGlmIChmID0gMSwgeSAmJiAodCA9IG9wWzBdICYgMiA/IHlbXCJyZXR1cm5cIl0gOiBvcFswXSA/IHlbXCJ0aHJvd1wiXSB8fCAoKHQgPSB5W1wicmV0dXJuXCJdKSAmJiB0LmNhbGwoeSksIDApIDogeS5uZXh0KSAmJiAhKHQgPSB0LmNhbGwoeSwgb3BbMV0pKS5kb25lKSByZXR1cm4gdDtcclxuICAgICAgICAgICAgaWYgKHkgPSAwLCB0KSBvcCA9IFtvcFswXSAmIDIsIHQudmFsdWVdO1xyXG4gICAgICAgICAgICBzd2l0Y2ggKG9wWzBdKSB7XHJcbiAgICAgICAgICAgICAgICBjYXNlIDA6IGNhc2UgMTogdCA9IG9wOyBicmVhaztcclxuICAgICAgICAgICAgICAgIGNhc2UgNDogXy5sYWJlbCsrOyByZXR1cm4geyB2YWx1ZTogb3BbMV0sIGRvbmU6IGZhbHNlIH07XHJcbiAgICAgICAgICAgICAgICBjYXNlIDU6IF8ubGFiZWwrKzsgeSA9IG9wWzFdOyBvcCA9IFswXTsgY29udGludWU7XHJcbiAgICAgICAgICAgICAgICBjYXNlIDc6IG9wID0gXy5vcHMucG9wKCk7IF8udHJ5cy5wb3AoKTsgY29udGludWU7XHJcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxyXG4gICAgICAgICAgICAgICAgICAgIGlmICghKHQgPSBfLnRyeXMsIHQgPSB0Lmxlbmd0aCA+IDAgJiYgdFt0Lmxlbmd0aCAtIDFdKSAmJiAob3BbMF0gPT09IDYgfHwgb3BbMF0gPT09IDIpKSB7IF8gPSAwOyBjb250aW51ZTsgfVxyXG4gICAgICAgICAgICAgICAgICAgIGlmIChvcFswXSA9PT0gMyAmJiAoIXQgfHwgKG9wWzFdID4gdFswXSAmJiBvcFsxXSA8IHRbM10pKSkgeyBfLmxhYmVsID0gb3BbMV07IGJyZWFrOyB9XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wWzBdID09PSA2ICYmIF8ubGFiZWwgPCB0WzFdKSB7IF8ubGFiZWwgPSB0WzFdOyB0ID0gb3A7IGJyZWFrOyB9XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHQgJiYgXy5sYWJlbCA8IHRbMl0pIHsgXy5sYWJlbCA9IHRbMl07IF8ub3BzLnB1c2gob3ApOyBicmVhazsgfVxyXG4gICAgICAgICAgICAgICAgICAgIGlmICh0WzJdKSBfLm9wcy5wb3AoKTtcclxuICAgICAgICAgICAgICAgICAgICBfLnRyeXMucG9wKCk7IGNvbnRpbnVlO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIG9wID0gYm9keS5jYWxsKHRoaXNBcmcsIF8pO1xyXG4gICAgICAgIH0gY2F0Y2ggKGUpIHsgb3AgPSBbNiwgZV07IHkgPSAwOyB9IGZpbmFsbHkgeyBmID0gdCA9IDA7IH1cclxuICAgICAgICBpZiAob3BbMF0gJiA1KSB0aHJvdyBvcFsxXTsgcmV0dXJuIHsgdmFsdWU6IG9wWzBdID8gb3BbMV0gOiB2b2lkIDAsIGRvbmU6IHRydWUgfTtcclxuICAgIH1cclxufVxyXG5cclxuZXhwb3J0IHZhciBfX2NyZWF0ZUJpbmRpbmcgPSBPYmplY3QuY3JlYXRlID8gKGZ1bmN0aW9uKG8sIG0sIGssIGsyKSB7XHJcbiAgICBpZiAoazIgPT09IHVuZGVmaW5lZCkgazIgPSBrO1xyXG4gICAgdmFyIGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKG0sIGspO1xyXG4gICAgaWYgKCFkZXNjIHx8IChcImdldFwiIGluIGRlc2MgPyAhbS5fX2VzTW9kdWxlIDogZGVzYy53cml0YWJsZSB8fCBkZXNjLmNvbmZpZ3VyYWJsZSkpIHtcclxuICAgICAgICBkZXNjID0geyBlbnVtZXJhYmxlOiB0cnVlLCBnZXQ6IGZ1bmN0aW9uKCkgeyByZXR1cm4gbVtrXTsgfSB9O1xyXG4gICAgfVxyXG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG8sIGsyLCBkZXNjKTtcclxufSkgOiAoZnVuY3Rpb24obywgbSwgaywgazIpIHtcclxuICAgIGlmIChrMiA9PT0gdW5kZWZpbmVkKSBrMiA9IGs7XHJcbiAgICBvW2syXSA9IG1ba107XHJcbn0pO1xyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fZXhwb3J0U3RhcihtLCBvKSB7XHJcbiAgICBmb3IgKHZhciBwIGluIG0pIGlmIChwICE9PSBcImRlZmF1bHRcIiAmJiAhT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG8sIHApKSBfX2NyZWF0ZUJpbmRpbmcobywgbSwgcCk7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3ZhbHVlcyhvKSB7XHJcbiAgICB2YXIgcyA9IHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiBTeW1ib2wuaXRlcmF0b3IsIG0gPSBzICYmIG9bc10sIGkgPSAwO1xyXG4gICAgaWYgKG0pIHJldHVybiBtLmNhbGwobyk7XHJcbiAgICBpZiAobyAmJiB0eXBlb2Ygby5sZW5ndGggPT09IFwibnVtYmVyXCIpIHJldHVybiB7XHJcbiAgICAgICAgbmV4dDogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICBpZiAobyAmJiBpID49IG8ubGVuZ3RoKSBvID0gdm9pZCAwO1xyXG4gICAgICAgICAgICByZXR1cm4geyB2YWx1ZTogbyAmJiBvW2krK10sIGRvbmU6ICFvIH07XHJcbiAgICAgICAgfVxyXG4gICAgfTtcclxuICAgIHRocm93IG5ldyBUeXBlRXJyb3IocyA/IFwiT2JqZWN0IGlzIG5vdCBpdGVyYWJsZS5cIiA6IFwiU3ltYm9sLml0ZXJhdG9yIGlzIG5vdCBkZWZpbmVkLlwiKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fcmVhZChvLCBuKSB7XHJcbiAgICB2YXIgbSA9IHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiBvW1N5bWJvbC5pdGVyYXRvcl07XHJcbiAgICBpZiAoIW0pIHJldHVybiBvO1xyXG4gICAgdmFyIGkgPSBtLmNhbGwobyksIHIsIGFyID0gW10sIGU7XHJcbiAgICB0cnkge1xyXG4gICAgICAgIHdoaWxlICgobiA9PT0gdm9pZCAwIHx8IG4tLSA+IDApICYmICEociA9IGkubmV4dCgpKS5kb25lKSBhci5wdXNoKHIudmFsdWUpO1xyXG4gICAgfVxyXG4gICAgY2F0Y2ggKGVycm9yKSB7IGUgPSB7IGVycm9yOiBlcnJvciB9OyB9XHJcbiAgICBmaW5hbGx5IHtcclxuICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICBpZiAociAmJiAhci5kb25lICYmIChtID0gaVtcInJldHVyblwiXSkpIG0uY2FsbChpKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgZmluYWxseSB7IGlmIChlKSB0aHJvdyBlLmVycm9yOyB9XHJcbiAgICB9XHJcbiAgICByZXR1cm4gYXI7XHJcbn1cclxuXHJcbi8qKiBAZGVwcmVjYXRlZCAqL1xyXG5leHBvcnQgZnVuY3Rpb24gX19zcHJlYWQoKSB7XHJcbiAgICBmb3IgKHZhciBhciA9IFtdLCBpID0gMDsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKylcclxuICAgICAgICBhciA9IGFyLmNvbmNhdChfX3JlYWQoYXJndW1lbnRzW2ldKSk7XHJcbiAgICByZXR1cm4gYXI7XHJcbn1cclxuXHJcbi8qKiBAZGVwcmVjYXRlZCAqL1xyXG5leHBvcnQgZnVuY3Rpb24gX19zcHJlYWRBcnJheXMoKSB7XHJcbiAgICBmb3IgKHZhciBzID0gMCwgaSA9IDAsIGlsID0gYXJndW1lbnRzLmxlbmd0aDsgaSA8IGlsOyBpKyspIHMgKz0gYXJndW1lbnRzW2ldLmxlbmd0aDtcclxuICAgIGZvciAodmFyIHIgPSBBcnJheShzKSwgayA9IDAsIGkgPSAwOyBpIDwgaWw7IGkrKylcclxuICAgICAgICBmb3IgKHZhciBhID0gYXJndW1lbnRzW2ldLCBqID0gMCwgamwgPSBhLmxlbmd0aDsgaiA8IGpsOyBqKyssIGsrKylcclxuICAgICAgICAgICAgcltrXSA9IGFbal07XHJcbiAgICByZXR1cm4gcjtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fc3ByZWFkQXJyYXkodG8sIGZyb20sIHBhY2spIHtcclxuICAgIGlmIChwYWNrIHx8IGFyZ3VtZW50cy5sZW5ndGggPT09IDIpIGZvciAodmFyIGkgPSAwLCBsID0gZnJvbS5sZW5ndGgsIGFyOyBpIDwgbDsgaSsrKSB7XHJcbiAgICAgICAgaWYgKGFyIHx8ICEoaSBpbiBmcm9tKSkge1xyXG4gICAgICAgICAgICBpZiAoIWFyKSBhciA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGZyb20sIDAsIGkpO1xyXG4gICAgICAgICAgICBhcltpXSA9IGZyb21baV07XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG4gICAgcmV0dXJuIHRvLmNvbmNhdChhciB8fCBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChmcm9tKSk7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2F3YWl0KHYpIHtcclxuICAgIHJldHVybiB0aGlzIGluc3RhbmNlb2YgX19hd2FpdCA/ICh0aGlzLnYgPSB2LCB0aGlzKSA6IG5ldyBfX2F3YWl0KHYpO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19hc3luY0dlbmVyYXRvcih0aGlzQXJnLCBfYXJndW1lbnRzLCBnZW5lcmF0b3IpIHtcclxuICAgIGlmICghU3ltYm9sLmFzeW5jSXRlcmF0b3IpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJTeW1ib2wuYXN5bmNJdGVyYXRvciBpcyBub3QgZGVmaW5lZC5cIik7XHJcbiAgICB2YXIgZyA9IGdlbmVyYXRvci5hcHBseSh0aGlzQXJnLCBfYXJndW1lbnRzIHx8IFtdKSwgaSwgcSA9IFtdO1xyXG4gICAgcmV0dXJuIGkgPSB7fSwgdmVyYihcIm5leHRcIiksIHZlcmIoXCJ0aHJvd1wiKSwgdmVyYihcInJldHVyblwiKSwgaVtTeW1ib2wuYXN5bmNJdGVyYXRvcl0gPSBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzOyB9LCBpO1xyXG4gICAgZnVuY3Rpb24gdmVyYihuKSB7IGlmIChnW25dKSBpW25dID0gZnVuY3Rpb24gKHYpIHsgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChhLCBiKSB7IHEucHVzaChbbiwgdiwgYSwgYl0pID4gMSB8fCByZXN1bWUobiwgdik7IH0pOyB9OyB9XHJcbiAgICBmdW5jdGlvbiByZXN1bWUobiwgdikgeyB0cnkgeyBzdGVwKGdbbl0odikpOyB9IGNhdGNoIChlKSB7IHNldHRsZShxWzBdWzNdLCBlKTsgfSB9XHJcbiAgICBmdW5jdGlvbiBzdGVwKHIpIHsgci52YWx1ZSBpbnN0YW5jZW9mIF9fYXdhaXQgPyBQcm9taXNlLnJlc29sdmUoci52YWx1ZS52KS50aGVuKGZ1bGZpbGwsIHJlamVjdCkgOiBzZXR0bGUocVswXVsyXSwgcik7IH1cclxuICAgIGZ1bmN0aW9uIGZ1bGZpbGwodmFsdWUpIHsgcmVzdW1lKFwibmV4dFwiLCB2YWx1ZSk7IH1cclxuICAgIGZ1bmN0aW9uIHJlamVjdCh2YWx1ZSkgeyByZXN1bWUoXCJ0aHJvd1wiLCB2YWx1ZSk7IH1cclxuICAgIGZ1bmN0aW9uIHNldHRsZShmLCB2KSB7IGlmIChmKHYpLCBxLnNoaWZ0KCksIHEubGVuZ3RoKSByZXN1bWUocVswXVswXSwgcVswXVsxXSk7IH1cclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fYXN5bmNEZWxlZ2F0b3Iobykge1xyXG4gICAgdmFyIGksIHA7XHJcbiAgICByZXR1cm4gaSA9IHt9LCB2ZXJiKFwibmV4dFwiKSwgdmVyYihcInRocm93XCIsIGZ1bmN0aW9uIChlKSB7IHRocm93IGU7IH0pLCB2ZXJiKFwicmV0dXJuXCIpLCBpW1N5bWJvbC5pdGVyYXRvcl0gPSBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzOyB9LCBpO1xyXG4gICAgZnVuY3Rpb24gdmVyYihuLCBmKSB7IGlbbl0gPSBvW25dID8gZnVuY3Rpb24gKHYpIHsgcmV0dXJuIChwID0gIXApID8geyB2YWx1ZTogX19hd2FpdChvW25dKHYpKSwgZG9uZTogbiA9PT0gXCJyZXR1cm5cIiB9IDogZiA/IGYodikgOiB2OyB9IDogZjsgfVxyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19hc3luY1ZhbHVlcyhvKSB7XHJcbiAgICBpZiAoIVN5bWJvbC5hc3luY0l0ZXJhdG9yKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiU3ltYm9sLmFzeW5jSXRlcmF0b3IgaXMgbm90IGRlZmluZWQuXCIpO1xyXG4gICAgdmFyIG0gPSBvW1N5bWJvbC5hc3luY0l0ZXJhdG9yXSwgaTtcclxuICAgIHJldHVybiBtID8gbS5jYWxsKG8pIDogKG8gPSB0eXBlb2YgX192YWx1ZXMgPT09IFwiZnVuY3Rpb25cIiA/IF9fdmFsdWVzKG8pIDogb1tTeW1ib2wuaXRlcmF0b3JdKCksIGkgPSB7fSwgdmVyYihcIm5leHRcIiksIHZlcmIoXCJ0aHJvd1wiKSwgdmVyYihcInJldHVyblwiKSwgaVtTeW1ib2wuYXN5bmNJdGVyYXRvcl0gPSBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzOyB9LCBpKTtcclxuICAgIGZ1bmN0aW9uIHZlcmIobikgeyBpW25dID0gb1tuXSAmJiBmdW5jdGlvbiAodikgeyByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkgeyB2ID0gb1tuXSh2KSwgc2V0dGxlKHJlc29sdmUsIHJlamVjdCwgdi5kb25lLCB2LnZhbHVlKTsgfSk7IH07IH1cclxuICAgIGZ1bmN0aW9uIHNldHRsZShyZXNvbHZlLCByZWplY3QsIGQsIHYpIHsgUHJvbWlzZS5yZXNvbHZlKHYpLnRoZW4oZnVuY3Rpb24odikgeyByZXNvbHZlKHsgdmFsdWU6IHYsIGRvbmU6IGQgfSk7IH0sIHJlamVjdCk7IH1cclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fbWFrZVRlbXBsYXRlT2JqZWN0KGNvb2tlZCwgcmF3KSB7XHJcbiAgICBpZiAoT2JqZWN0LmRlZmluZVByb3BlcnR5KSB7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eShjb29rZWQsIFwicmF3XCIsIHsgdmFsdWU6IHJhdyB9KTsgfSBlbHNlIHsgY29va2VkLnJhdyA9IHJhdzsgfVxyXG4gICAgcmV0dXJuIGNvb2tlZDtcclxufTtcclxuXHJcbnZhciBfX3NldE1vZHVsZURlZmF1bHQgPSBPYmplY3QuY3JlYXRlID8gKGZ1bmN0aW9uKG8sIHYpIHtcclxuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvLCBcImRlZmF1bHRcIiwgeyBlbnVtZXJhYmxlOiB0cnVlLCB2YWx1ZTogdiB9KTtcclxufSkgOiBmdW5jdGlvbihvLCB2KSB7XHJcbiAgICBvW1wiZGVmYXVsdFwiXSA9IHY7XHJcbn07XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19pbXBvcnRTdGFyKG1vZCkge1xyXG4gICAgaWYgKG1vZCAmJiBtb2QuX19lc01vZHVsZSkgcmV0dXJuIG1vZDtcclxuICAgIHZhciByZXN1bHQgPSB7fTtcclxuICAgIGlmIChtb2QgIT0gbnVsbCkgZm9yICh2YXIgayBpbiBtb2QpIGlmIChrICE9PSBcImRlZmF1bHRcIiAmJiBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwobW9kLCBrKSkgX19jcmVhdGVCaW5kaW5nKHJlc3VsdCwgbW9kLCBrKTtcclxuICAgIF9fc2V0TW9kdWxlRGVmYXVsdChyZXN1bHQsIG1vZCk7XHJcbiAgICByZXR1cm4gcmVzdWx0O1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19pbXBvcnREZWZhdWx0KG1vZCkge1xyXG4gICAgcmV0dXJuIChtb2QgJiYgbW9kLl9fZXNNb2R1bGUpID8gbW9kIDogeyBkZWZhdWx0OiBtb2QgfTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fY2xhc3NQcml2YXRlRmllbGRHZXQocmVjZWl2ZXIsIHN0YXRlLCBraW5kLCBmKSB7XHJcbiAgICBpZiAoa2luZCA9PT0gXCJhXCIgJiYgIWYpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJQcml2YXRlIGFjY2Vzc29yIHdhcyBkZWZpbmVkIHdpdGhvdXQgYSBnZXR0ZXJcIik7XHJcbiAgICBpZiAodHlwZW9mIHN0YXRlID09PSBcImZ1bmN0aW9uXCIgPyByZWNlaXZlciAhPT0gc3RhdGUgfHwgIWYgOiAhc3RhdGUuaGFzKHJlY2VpdmVyKSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCByZWFkIHByaXZhdGUgbWVtYmVyIGZyb20gYW4gb2JqZWN0IHdob3NlIGNsYXNzIGRpZCBub3QgZGVjbGFyZSBpdFwiKTtcclxuICAgIHJldHVybiBraW5kID09PSBcIm1cIiA/IGYgOiBraW5kID09PSBcImFcIiA/IGYuY2FsbChyZWNlaXZlcikgOiBmID8gZi52YWx1ZSA6IHN0YXRlLmdldChyZWNlaXZlcik7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2NsYXNzUHJpdmF0ZUZpZWxkU2V0KHJlY2VpdmVyLCBzdGF0ZSwgdmFsdWUsIGtpbmQsIGYpIHtcclxuICAgIGlmIChraW5kID09PSBcIm1cIikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlByaXZhdGUgbWV0aG9kIGlzIG5vdCB3cml0YWJsZVwiKTtcclxuICAgIGlmIChraW5kID09PSBcImFcIiAmJiAhZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlByaXZhdGUgYWNjZXNzb3Igd2FzIGRlZmluZWQgd2l0aG91dCBhIHNldHRlclwiKTtcclxuICAgIGlmICh0eXBlb2Ygc3RhdGUgPT09IFwiZnVuY3Rpb25cIiA/IHJlY2VpdmVyICE9PSBzdGF0ZSB8fCAhZiA6ICFzdGF0ZS5oYXMocmVjZWl2ZXIpKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IHdyaXRlIHByaXZhdGUgbWVtYmVyIHRvIGFuIG9iamVjdCB3aG9zZSBjbGFzcyBkaWQgbm90IGRlY2xhcmUgaXRcIik7XHJcbiAgICByZXR1cm4gKGtpbmQgPT09IFwiYVwiID8gZi5jYWxsKHJlY2VpdmVyLCB2YWx1ZSkgOiBmID8gZi52YWx1ZSA9IHZhbHVlIDogc3RhdGUuc2V0KHJlY2VpdmVyLCB2YWx1ZSkpLCB2YWx1ZTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fY2xhc3NQcml2YXRlRmllbGRJbihzdGF0ZSwgcmVjZWl2ZXIpIHtcclxuICAgIGlmIChyZWNlaXZlciA9PT0gbnVsbCB8fCAodHlwZW9mIHJlY2VpdmVyICE9PSBcIm9iamVjdFwiICYmIHR5cGVvZiByZWNlaXZlciAhPT0gXCJmdW5jdGlvblwiKSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCB1c2UgJ2luJyBvcGVyYXRvciBvbiBub24tb2JqZWN0XCIpO1xyXG4gICAgcmV0dXJuIHR5cGVvZiBzdGF0ZSA9PT0gXCJmdW5jdGlvblwiID8gcmVjZWl2ZXIgPT09IHN0YXRlIDogc3RhdGUuaGFzKHJlY2VpdmVyKTtcclxufVxyXG4iLCIvKlxuICogRmlsZW5hbWU6IG11bHRpLWNvbHVtbi1tYXJrZG93bi9zcmMvcmVnaW9uU2V0dGluZ3MudHNcbiAqIENyZWF0ZWQgRGF0ZTogVHVlc2RheSwgRmVicnVhcnkgMXN0IDIwMjIsIDEyOjIzOjUzIHBtXG4gKiBBdXRob3I6IENhbWVyb24gUm9iaW5zb25cbiAqIFxuICogQ29weXJpZ2h0IChjKSAyMDIyIENhbWVyb24gUm9iaW5zb25cbiAqL1xuXG5leHBvcnQgZW51bSBCb3JkZXJPcHRpb24ge1xuICAgIGVuYWJsZWQsXG4gICAgb24sXG4gICAgdHJ1ZSxcbiAgICBkaXNhYmxlZCxcbiAgICBvZmYsXG4gICAgZmFsc2Vcbn1cblxuZXhwb3J0IGVudW0gU2hhZG93T3B0aW9uIHtcbiAgICBlbmFibGVkLFxuICAgIG9uLFxuICAgIHRydWUsXG4gICAgZGlzYWJsZWQsXG4gICAgb2ZmLFxuICAgIGZhbHNlXG59XG5cbmV4cG9ydCBlbnVtIENvbHVtbkxheW91dCB7IFxuICAgIHN0YW5kYXJkLFxuICAgIGxlZnQsXG4gICAgZmlyc3QsXG4gICAgY2VudGVyLFxuICAgIG1pZGRsZSxcbiAgICBzZWNvbmQsXG4gICAgcmlnaHQsXG4gICAgdGhpcmQsXG4gICAgbGFzdFxufTtcblxuZXhwb3J0IGVudW0gU2luZ2xlQ29sdW1uU2l6ZSB7XG4gICAgc21hbGwsXG4gICAgbWVkaXVtLFxuICAgIGxhcmdlXG59XG5cbmV4cG9ydCBlbnVtIENvbnRlbnRPdmVyZmxvd1R5cGUge1xuICAgIHNjcm9sbCxcbiAgICBoaWRkZW5cbn1cblxuZXhwb3J0IHR5cGUgTXVsdGlDb2x1bW5TZXR0aW5ncyA9IHtcbiAgICBudW1iZXJPZkNvbHVtbnM6IG51bWJlcixcbiAgICBjb2x1bW5MYXlvdXQ6IENvbHVtbkxheW91dCxcbiAgICBkcmF3Qm9yZGVyOiBib29sZWFuLFxuICAgIGRyYXdTaGFkb3c6IGJvb2xlYW4sXG4gICAgYXV0b0xheW91dDogYm9vbGVhblxuICAgIGNvbHVtblNpemU6IFNpbmdsZUNvbHVtblNpemUsXG4gICAgY29sdW1uUG9zaXRpb246IENvbHVtbkxheW91dCxcbiAgICBjb2x1bW5TcGFjaW5nOiBzdHJpbmcsXG4gICAgY29udGVudE92ZXJmbG93OiBDb250ZW50T3ZlcmZsb3dUeXBlXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXREZWZhdWx0TXVsdGlDb2x1bW5TZXR0aW5ncygpOiBNdWx0aUNvbHVtblNldHRpbmdzIHtcblxuICAgIHJldHVybiB7XG4gICAgICAgIG51bWJlck9mQ29sdW1uczogMixcbiAgICAgICAgY29sdW1uTGF5b3V0OiBDb2x1bW5MYXlvdXQuc3RhbmRhcmQsXG4gICAgICAgIGRyYXdCb3JkZXI6IHRydWUsXG4gICAgICAgIGRyYXdTaGFkb3c6IHRydWUsXG4gICAgICAgIGF1dG9MYXlvdXQ6IGZhbHNlLFxuICAgICAgICBjb2x1bW5TaXplOiBTaW5nbGVDb2x1bW5TaXplLm1lZGl1bSxcbiAgICAgICAgY29sdW1uUG9zaXRpb246IENvbHVtbkxheW91dC5zdGFuZGFyZCxcbiAgICAgICAgY29sdW1uU3BhY2luZzogXCJcIixcbiAgICAgICAgY29udGVudE92ZXJmbG93OiBDb250ZW50T3ZlcmZsb3dUeXBlLnNjcm9sbFxuICAgIH1cbn0iLCIvKipcbiAqIEZpbGU6IC9zcmMvdXRpbGl0aWVzL3NldHRpbmdzUGFyc2VyLnRzICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAqIENyZWF0ZWQgRGF0ZTogRnJpZGF5LCBKdW5lIDNyZCAyMDIyLCA4OjE2IHBtICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAqIEF1dGhvcjogQ2FtZXJvbiBSb2JpbnNvbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAqIENvcHlyaWdodCAoYykgMjAyMiBDYW1lcm9uIFJvYmluc29uICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAqL1xuXG5pbXBvcnQgeyBNdWx0aUNvbHVtblNldHRpbmdzLCBDb2x1bW5MYXlvdXQsIEJvcmRlck9wdGlvbiwgU2hhZG93T3B0aW9uLCBnZXREZWZhdWx0TXVsdGlDb2x1bW5TZXR0aW5ncywgU2luZ2xlQ29sdW1uU2l6ZSwgQ29udGVudE92ZXJmbG93VHlwZSB9IGZyb20gXCIuLi9yZWdpb25TZXR0aW5nc1wiO1xuXG4vKipcbiAqIEhlcmUgd2UgZGVmaW5lIGFsbCBvZiB0aGUgdmFsaWQgc2V0dGluZ3Mgc3RyaW5ncyB0aGF0IHRoZSB1c2VyIGNhbiBlbnRlciBmb3IgZWFjaCBzZXR0aW5nIHR5cGUuXG4gKiBUaGUgc3RyaW5ncyBhcmUgdGhlbiBtYXBwZWQgdHdpY2UsIGZpcnN0IHRvIGEgdmFsaWQgcmVnZXggc3RyaW5nIHRoYXQgc2VhcmNoZXMgZm9yIHRoZSBzZXR0aW5nXG4gKiBuYW1lLCBpZ25vcmluZyBhbGwgZXh0cmEgc3BhY2VzIGFuZCBsZXR0ZXIgY2FzZSwgYW5kIHRoZW4gbWFwZWQgdG8gYSBSZWdFeCBvYmplY3QgdG8gYmUgdXNlZCBcbiAqIHdoZW4gcGFyc2luZy5cbiAqL1xuY29uc3QgQ09MX1BPU0lUSU9OX09QVElPTl9TVFJTOiBzdHJpbmdbXSA9IFtcbiAgICBcImNvbHVtbiBwb3NpdGlvblwiLFxuICAgIFwiY29sIHBvc2l0aW9uXCIsXG4gICAgXCJjb2x1bW4gbG9jYXRpb25cIixcbiAgICBcImNvbCBsb2NhdGlvblwiLFxuICAgIFwic2luZ2xlIGNvbHVtbiBsb2NhdGlvblwiLFxuICAgIFwic2luZ2xlIGNvbHVtbiBwb3NpdGlvblwiLFxuXTtcbmNvbnN0IENPTF9QT1NJVElPTl9SRUdFWF9BUlI6IFJlZ0V4cFtdID0gQ09MX1BPU0lUSU9OX09QVElPTl9TVFJTLm1hcChjb252ZXJ0U3RyaW5nVG9TZXR0aW5nc1JlZ2V4KS5tYXAoKHZhbHVlKSA9PiB7XG4gICAgcmV0dXJuIG5ldyBSZWdFeHAodmFsdWUsIFwiaVwiKTtcbn0pO1xuXG5jb25zdCBDT0xfU0laRV9PUFRJT05fU1RSUzogc3RyaW5nW10gPSBbXG4gICAgXCJjb2x1bW4gc2l6ZVwiLFxuICAgIFwiY29sdW1uIHdpZHRoXCIsXG4gICAgXCJjb2wgc2l6ZVwiLFxuICAgIFwiY29sIHdpZHRoXCIsXG4gICAgXCJzaW5nbGUgY29sdW1uIHNpemVcIixcbiAgICBcInNpbmdsZSBjb2wgc2l6ZVwiLFxuICAgIFwic2luZ2xlIGNvbHVtbiB3aWR0aFwiLFxuICAgIFwic2luZ2xlIGNvbCB3aWR0aFwiXG5dO1xuY29uc3QgQ09MX1NJWkVfT1BUSU9OX1JFR0VYX0FSUjogUmVnRXhwW10gPSBDT0xfU0laRV9PUFRJT05fU1RSUy5tYXAoY29udmVydFN0cmluZ1RvU2V0dGluZ3NSZWdleCkubWFwKCh2YWx1ZSkgPT4ge1xuICAgIHJldHVybiBuZXcgUmVnRXhwKHZhbHVlLCBcImlcIik7XG59KTtcblxuY29uc3QgTlVNQkVSX09GX0NPTFVNTlNfU1RSUyA9IFtcbiAgICBcIm51bWJlciBvZiBjb2x1bW5zXCJcbl1cbmNvbnN0IE5VTUJFUl9PRl9DT0xVTU5TX1JFR0VYX0FSUjogUmVnRXhwW10gPSBOVU1CRVJfT0ZfQ09MVU1OU19TVFJTLm1hcChjb252ZXJ0U3RyaW5nVG9TZXR0aW5nc1JlZ2V4KS5tYXAoKHZhbHVlKSA9PiB7XG4gICAgcmV0dXJuIG5ldyBSZWdFeHAodmFsdWUsIFwiaVwiKTtcbn0pO1xuXG5jb25zdCBMQVJHRVNUX0NPTFVNTl9TVFJTID0gW1xuICAgIFwibGFyZ2VzdCBjb2x1bW5cIlxuXVxuY29uc3QgTEFSR0VTVF9DT0xVTU5fUkVHRVhfQVJSOiBSZWdFeHBbXSA9IExBUkdFU1RfQ09MVU1OX1NUUlMubWFwKGNvbnZlcnRTdHJpbmdUb1NldHRpbmdzUmVnZXgpLm1hcCgodmFsdWUpID0+IHtcbiAgICByZXR1cm4gbmV3IFJlZ0V4cCh2YWx1ZSwgXCJpXCIpO1xufSk7XG5cbmNvbnN0IERSQVdfQk9SREVSX1NUUlMgPSBbXG4gICAgXCJib3JkZXJcIlxuXVxuY29uc3QgRFJBV19CT1JERVJfUkVHRVhfQVJSOiBSZWdFeHBbXSA9IERSQVdfQk9SREVSX1NUUlMubWFwKGNvbnZlcnRTdHJpbmdUb1NldHRpbmdzUmVnZXgpLm1hcCgodmFsdWUpID0+IHtcbiAgICByZXR1cm4gbmV3IFJlZ0V4cCh2YWx1ZSwgXCJpXCIpO1xufSk7XG5cbmNvbnN0IERSQVdfU0hBRE9XX1NUUlMgPSBbXG4gICAgXCJzaGFkb3dcIlxuXVxuY29uc3QgRFJBV19TSEFET1dfUkVHRVhfQVJSOiBSZWdFeHBbXSA9IERSQVdfU0hBRE9XX1NUUlMubWFwKGNvbnZlcnRTdHJpbmdUb1NldHRpbmdzUmVnZXgpLm1hcCgodmFsdWUpID0+IHtcbiAgICByZXR1cm4gbmV3IFJlZ0V4cCh2YWx1ZSwgXCJpXCIpO1xufSk7XG5cbmNvbnN0IEFVVE9fTEFZT1VUX1NFVFRJTkdfU1RSUyA9IFtcbiAgICBcImF1dG8gbGF5b3V0XCJcbl1cbmNvbnN0IEFVVE9fTEFZT1VUX1JFR0VYX0FSUjogUmVnRXhwW10gPSBBVVRPX0xBWU9VVF9TRVRUSU5HX1NUUlMubWFwKGNvbnZlcnRTdHJpbmdUb1NldHRpbmdzUmVnZXgpLm1hcCgodmFsdWUpID0+IHtcbiAgICByZXR1cm4gbmV3IFJlZ0V4cCh2YWx1ZSwgXCJpXCIpO1xufSk7XG5cbmNvbnN0IENPTFVNTl9TUEFDSU5HX1JFR0VYX0FSUjogUmVnRXhwW10gPSBbXG4gICAgXCJjb2x1bW4gc3BhY2luZ1wiLFxuXS5tYXAoKHZhbHVlKSA9PiB7XG4gICAgcmV0dXJuIG5ldyBSZWdFeHAoY29udmVydFN0cmluZ1RvU2V0dGluZ3NSZWdleCh2YWx1ZSksIFwiaVwiKTtcbn0pO1xuXG5jb25zdCBDT05URU5UX09WRVJGTE9XX1JFR0VYX0FSUjogUmVnRXhwW10gPSBbXG4gICAgXCJvdmVyZmxvd1wiLFxuICAgIFwiY29udGVudCBvdmVyZmxvd1wiXG5dLm1hcCgodmFsdWUpID0+IHtcbiAgICByZXR1cm4gbmV3IFJlZ0V4cChjb252ZXJ0U3RyaW5nVG9TZXR0aW5nc1JlZ2V4KHZhbHVlKSwgXCJpXCIpXG59KVxuXG4vKipcbiAqIFRoaXMgZnVuY3Rpb24gc2VhcmNoZXMgdGhlIHNldHRpbmdzIHN0cmluZyB0aHJvdWdoIGVhY2ggcmVnZXggb3B0aW9uLiBJZiBvbmUgb2YgdGhlIHJlZ2V4XG4gKiB2YWx1ZXMgbWF0Y2gsIGl0IHJldHVybnMgdGhlIGZpcnN0IGdyb3VwIGZvdW5kIGJ5IHRoZSByZWdleC4gVGhpcyBpcyBkZXBlbmRlZCBvbiBwcm9wZXJcbiAqIHJlZ2V4IGZvcm1hdHRpbmcgd2hpY2ggaXMgZG9uZSBieSB0aGUgY29udmVydFN0cmluZ1RvU2V0dGluZ3NSZWdleCBmdW5jdGlvbiBkZWZpbmVkIGJlbG93LlxuICogXG4gKiBAcGFyYW0gc2V0dGluZ3NTdHJpbmcgVGhlIHZhbHVlIHRoYXQgbWF5IG1hdGNoIG9uZSBvZiB0aGUgc2V0dGluZyBvcHRpb25zLlxuICogQHBhcmFtIHZhbGlkU2V0dGluZ0Zvcm1hdFJlZ0V4IFRoZSBzZXR0aW5ncyBvcHRpb25zIHRocm91Z2ggd2hpY2ggdG8gY2hlY2sgYWxsIG9wdGlvbnMuIElmIG9uZSBvZiB0aGVzZSByZWdleCBcbiAqIHZhbHVlcyBtYXRjaCBvbiB0aGUgc3RyaW5nIHdlIGJyZWFrIGZyb20gdGhlIGxvb3AgcmV0dXJuaW5nIHRoZSBmb3VuZCB2YWx1ZS5cbiAqIFxuICogQHJldHVybnMgdGhlIHVzZXIgZW50ZXJlZCBkYXRhIGlmIHRoZSBzZXR0aW5nIGlzIGEgbWF0Y2gsIG9yIG51bGwgaWYgbm9uIG9mIHRoZSBvcHRpb25zIG1hdGNoZWQuXG4gKi9cbmZ1bmN0aW9uIGdldFNldHRpbmdzRGF0YUZyb21LZXlzKHNldHRpbmdzU3RyaW5nOiBzdHJpbmcsIHZhbGlkU2V0dGluZ0Zvcm1hdFJlZ0V4OiBSZWdFeHBbXSk6IHN0cmluZyB8IG51bGwge1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB2YWxpZFNldHRpbmdGb3JtYXRSZWdFeC5sZW5ndGg7IGkrKykge1xuXG4gICAgICAgIGxldCByZWdleFNlYXJjaERhdGEgPSB2YWxpZFNldHRpbmdGb3JtYXRSZWdFeFtpXS5leGVjKHNldHRpbmdzU3RyaW5nKVxuICAgICAgICBpZihyZWdleFNlYXJjaERhdGEgIT09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiByZWdleFNlYXJjaERhdGFbMV0udHJpbSgpXG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gbnVsbDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlU2luZ2xlQ29sdW1uU2V0dGluZ3Moc2V0dGluZ3NTdHI6IHN0cmluZywgb3JpZ2luYWxTZXR0aW5nczogTXVsdGlDb2x1bW5TZXR0aW5ncyk6IE11bHRpQ29sdW1uU2V0dGluZ3Mge1xuXG4gICAgbGV0IHNldHRpbmdzTGluZXMgPSBzZXR0aW5nc1N0ci5zcGxpdChcIlxcblwiKTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNldHRpbmdzTGluZXMubGVuZ3RoOyBpKyspIHtcblxuICAgICAgICBsZXQgc2V0dGluZ3NMaW5lID0gc2V0dGluZ3NMaW5lc1tpXTtcbiAgICAgICAgbGV0IHNldHRpbmdzRGF0YSA9IGdldFNldHRpbmdzRGF0YUZyb21LZXlzKHNldHRpbmdzTGluZSwgQ09MX1BPU0lUSU9OX1JFR0VYX0FSUik7XG4gICAgICAgIGlmIChzZXR0aW5nc0RhdGEgIT09IG51bGwpIHtcblxuICAgICAgICAgICAgb3JpZ2luYWxTZXR0aW5ncy5jb2x1bW5Qb3NpdGlvbiA9IHBhcnNlRm9yU2luZ2xlQ29sdW1uTG9jYXRpb24oc2V0dGluZ3NEYXRhKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHNldHRpbmdzRGF0YSA9IGdldFNldHRpbmdzRGF0YUZyb21LZXlzKHNldHRpbmdzTGluZSwgQ09MX1NJWkVfT1BUSU9OX1JFR0VYX0FSUik7XG4gICAgICAgIGlmIChzZXR0aW5nc0RhdGEgIT09IG51bGwpIHtcblxuICAgICAgICAgICAgb3JpZ2luYWxTZXR0aW5ncy5jb2x1bW5TaXplID0gcGFyc2VGb3JTaW5nbGVDb2x1bW5TaXplKHNldHRpbmdzRGF0YSlcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBvcmlnaW5hbFNldHRpbmdzO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VDb2x1bW5TZXR0aW5ncyhzZXR0aW5nc1N0cjogc3RyaW5nKTogTXVsdGlDb2x1bW5TZXR0aW5ncyB7XG5cbiAgICBsZXQgcGFyc2VkU2V0dGluZ3MgPSBnZXREZWZhdWx0TXVsdGlDb2x1bW5TZXR0aW5ncygpO1xuXG4gICAgbGV0IHNldHRpbmdzTGluZXMgPSBzZXR0aW5nc1N0ci5zcGxpdChcIlxcblwiKTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2V0dGluZ3NMaW5lcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBsZXQgc2V0dGluZ3NMaW5lID0gc2V0dGluZ3NMaW5lc1tpXTtcblxuICAgICAgICBsZXQgc2V0dGluZ3NEYXRhID0gZ2V0U2V0dGluZ3NEYXRhRnJvbUtleXMoc2V0dGluZ3NMaW5lLCBOVU1CRVJfT0ZfQ09MVU1OU19SRUdFWF9BUlIpO1xuICAgICAgICBpZiAoc2V0dGluZ3NEYXRhICE9PSBudWxsKSB7XG5cbiAgICAgICAgICAgIGxldCBudW1PZkNvbHMgPSBwYXJzZUludChzZXR0aW5nc0RhdGEpXG4gICAgICAgICAgICBpZiAoTnVtYmVyLmlzTmFOKG51bU9mQ29scykgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgICAgaWYgKG51bU9mQ29scyA+PSAxICYmIG51bU9mQ29scyA8PSAzKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcnNlZFNldHRpbmdzLm51bWJlck9mQ29sdW1ucyA9IG51bU9mQ29scztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBzZXR0aW5nc0RhdGEgPSBnZXRTZXR0aW5nc0RhdGFGcm9tS2V5cyhzZXR0aW5nc0xpbmUsIExBUkdFU1RfQ09MVU1OX1JFR0VYX0FSUilcbiAgICAgICAgaWYgKHNldHRpbmdzRGF0YSAhPT0gbnVsbCkge1xuXG4gICAgICAgICAgICBsZXQgdXNlckRlZkxheW91dDogQ29sdW1uTGF5b3V0ID0gKDxhbnk+Q29sdW1uTGF5b3V0KVtzZXR0aW5nc0RhdGFdO1xuICAgICAgICAgICAgaWYgKHVzZXJEZWZMYXlvdXQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIHBhcnNlZFNldHRpbmdzLmNvbHVtbkxheW91dCA9IHVzZXJEZWZMYXlvdXQ7XG4gICAgICAgICAgICAgICAgcGFyc2VkU2V0dGluZ3MuY29sdW1uUG9zaXRpb24gPSB1c2VyRGVmTGF5b3V0O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgc2V0dGluZ3NEYXRhID0gZ2V0U2V0dGluZ3NEYXRhRnJvbUtleXMoc2V0dGluZ3NMaW5lLCBEUkFXX0JPUkRFUl9SRUdFWF9BUlIpXG4gICAgICAgIGlmIChzZXR0aW5nc0RhdGEgIT09IG51bGwpIHtcblxuICAgICAgICAgICAgbGV0IGlzQm9yZGVyRHJhd246IEJvcmRlck9wdGlvbiA9ICg8YW55PkJvcmRlck9wdGlvbilbc2V0dGluZ3NEYXRhXTtcbiAgICAgICAgICAgIGlmIChpc0JvcmRlckRyYXduICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKGlzQm9yZGVyRHJhd24pIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAoQm9yZGVyT3B0aW9uLmRpc2FibGVkKTpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAoQm9yZGVyT3B0aW9uLm9mZik6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgKEJvcmRlck9wdGlvbi5mYWxzZSk6XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJzZWRTZXR0aW5ncy5kcmF3Qm9yZGVyID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBzZXR0aW5nc0RhdGEgPSBnZXRTZXR0aW5nc0RhdGFGcm9tS2V5cyhzZXR0aW5nc0xpbmUsIERSQVdfU0hBRE9XX1JFR0VYX0FSUilcbiAgICAgICAgaWYgKHNldHRpbmdzRGF0YSAhPT0gbnVsbCkge1xuXG4gICAgICAgICAgICBsZXQgaXNTaGFkb3dEcmF3bjogU2hhZG93T3B0aW9uID0gKDxhbnk+U2hhZG93T3B0aW9uKVtzZXR0aW5nc0RhdGFdO1xuICAgICAgICAgICAgaWYgKGlzU2hhZG93RHJhd24gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIHN3aXRjaCAoaXNTaGFkb3dEcmF3bikge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIChTaGFkb3dPcHRpb24uZGlzYWJsZWQpOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIChTaGFkb3dPcHRpb24ub2ZmKTpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAoU2hhZG93T3B0aW9uLmZhbHNlKTpcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhcnNlZFNldHRpbmdzLmRyYXdTaGFkb3cgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHNldHRpbmdzRGF0YSA9IGdldFNldHRpbmdzRGF0YUZyb21LZXlzKHNldHRpbmdzTGluZSwgQVVUT19MQVlPVVRfUkVHRVhfQVJSKVxuICAgICAgICBpZiAoc2V0dGluZ3NEYXRhICE9PSBudWxsKSB7XG5cbiAgICAgICAgICAgIGlmKHNldHRpbmdzRGF0YSA9PT0gXCJ0cnVlXCIpIHtcbiAgICAgICAgICAgICAgICBwYXJzZWRTZXR0aW5ncy5hdXRvTGF5b3V0ID0gdHJ1ZVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgc2V0dGluZ3NEYXRhID0gZ2V0U2V0dGluZ3NEYXRhRnJvbUtleXMoc2V0dGluZ3NMaW5lLCBDT0xVTU5fU1BBQ0lOR19SRUdFWF9BUlIpO1xuICAgICAgICBpZihzZXR0aW5nc0RhdGEgIT09IG51bGwpIHtcblxuICAgICAgICAgICAgbGV0IHBhcnNlZCA9IGdldExlbmd0aFVuaXQoc2V0dGluZ3NEYXRhLnRyaW0oKSk7XG4gICAgICAgICAgICBsZXQgc3BhY2luZ1N0ciA9IFwiXCI7XG5cbiAgICAgICAgICAgIGlmKHBhcnNlZC5pc1ZhbGlkKSB7XG5cbiAgICAgICAgICAgICAgICBsZXQgbm9Vbml0c1N0ciA9IHNldHRpbmdzRGF0YS5yZXBsYWNlKHBhcnNlZC51bml0U3RyLCBcIlwiKS50cmltKCk7XG4gICAgICAgICAgICAgICAgbGV0IG5vVW5pdHNOdW0gPSBwYXJzZUludChub1VuaXRzU3RyKTtcbiAgICAgICAgICAgICAgICBpZihpc05hTihub1VuaXRzTnVtKSA9PT0gZmFsc2UpIHtcblxuICAgICAgICAgICAgICAgICAgICBzcGFjaW5nU3RyID0gYCR7bm9Vbml0c1N0cn0ke3BhcnNlZC51bml0U3RyfWBcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICBsZXQgbm9Vbml0c051bSA9IHBhcnNlSW50KHNldHRpbmdzRGF0YS50cmltKCkpO1xuICAgICAgICAgICAgICAgIGlmKGlzTmFOKG5vVW5pdHNOdW0pID09PSBmYWxzZSkge1xuXG4gICAgICAgICAgICAgICAgICAgIHNwYWNpbmdTdHIgPSBgJHtub1VuaXRzTnVtfXB0YFxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcGFyc2VkU2V0dGluZ3MuY29sdW1uU3BhY2luZyA9IHNwYWNpbmdTdHI7XG4gICAgICAgIH1cblxuICAgICAgICBzZXR0aW5nc0RhdGEgPSBnZXRTZXR0aW5nc0RhdGFGcm9tS2V5cyhzZXR0aW5nc0xpbmUsIENPTlRFTlRfT1ZFUkZMT1dfUkVHRVhfQVJSKTtcbiAgICAgICAgaWYoc2V0dGluZ3NEYXRhICE9PSBudWxsKSB7XG5cbiAgICAgICAgICAgIGxldCBvdmVyZmxvd1R5cGUgPSBDb250ZW50T3ZlcmZsb3dUeXBlLnNjcm9sbDtcblxuICAgICAgICAgICAgc2V0dGluZ3NEYXRhID0gc2V0dGluZ3NEYXRhLnRvTG93ZXJDYXNlKCkudHJpbSgpO1xuICAgICAgICAgICAgaWYoc2V0dGluZ3NEYXRhID09PSBcImhpZGRlblwiKSB7XG4gICAgICAgICAgICAgICAgb3ZlcmZsb3dUeXBlID0gQ29udGVudE92ZXJmbG93VHlwZS5oaWRkZW47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHBhcnNlZFNldHRpbmdzLmNvbnRlbnRPdmVyZmxvdyA9IG92ZXJmbG93VHlwZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBwYXJzZWRTZXR0aW5ncztcbn1cblxuZnVuY3Rpb24gZ2V0TGVuZ3RoVW5pdChsZW5ndGhTdHI6IHN0cmluZyk6IHsgaXNWYWxpZDogYm9vbGVhbiwgdW5pdFN0cjogc3RyaW5nIH0ge1xuXG4gICAgbGV0IGxhc3RDaGFyID0gbGVuZ3RoU3RyLnNsaWNlKGxlbmd0aFN0ci5sZW5ndGggLSAxKTtcbiAgICBsZXQgbGFzdFR3b0NoYXJzID0gbGVuZ3RoU3RyLnNsaWNlKGxlbmd0aFN0ci5sZW5ndGggLSAyKTtcblxuICAgIGxldCB1bml0U3RyID0gXCJcIlxuICAgIGxldCBpc1ZhbGlkID0gZmFsc2U7XG4gICAgaWYobGFzdENoYXIgPT09IFwiJVwiKSB7XG4gICAgICAgIHVuaXRTdHIgPSBsYXN0Q2hhcjtcbiAgICAgICAgaXNWYWxpZCA9IHRydWU7XG4gICAgfVxuICAgIGVsc2UgaWYobGFzdFR3b0NoYXJzID09PSBcImNtXCIgfHxcbiAgICAgICAgICAgIGxhc3RUd29DaGFycyA9PT0gXCJtbVwiIHx8XG4gICAgICAgICAgICBsYXN0VHdvQ2hhcnMgPT09IFwiaW5cIiB8fFxuICAgICAgICAgICAgbGFzdFR3b0NoYXJzID09PSBcInB4XCIgfHxcbiAgICAgICAgICAgIGxhc3RUd29DaGFycyA9PT0gXCJwdFwiIHx8XG4gICAgICAgICAgICBsYXN0VHdvQ2hhcnMgPT09IFwicGNcIiB8fFxuICAgICAgICAgICAgbGFzdFR3b0NoYXJzID09PSBcImVtXCIgfHxcbiAgICAgICAgICAgIGxhc3RUd29DaGFycyA9PT0gXCJleFwiIHx8XG4gICAgICAgICAgICBsYXN0VHdvQ2hhcnMgPT09IFwiY2hcIiB8fFxuICAgICAgICAgICAgbGFzdFR3b0NoYXJzID09PSBcInZ3XCIgfHxcbiAgICAgICAgICAgIGxhc3RUd29DaGFycyA9PT0gXCJ2aFwiICkge1xuICAgICAgICB1bml0U3RyID0gbGFzdFR3b0NoYXJzO1xuICAgICAgICBpc1ZhbGlkID0gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4geyBpc1ZhbGlkOiBpc1ZhbGlkLCB1bml0U3RyOiB1bml0U3RyIH1cbn1cblxuY29uc3QgQ09ERUJMT0NLX1JFR0lPTl9JRF9SRUdFWF9TVFJTID0gW1xuICAgIFwiaWRcIixcbiAgICBcInJlZ2lvbiBpZFwiXG5dXG5jb25zdCBDT0RFQkxPQ0tfUkVHSU9OX0lEX1JFR0VYX0FSUjogUmVnRXhwW10gPSBDT0RFQkxPQ0tfUkVHSU9OX0lEX1JFR0VYX1NUUlMubWFwKGNvbnZlcnRTdHJpbmdUb1NldHRpbmdzUmVnZXgpLm1hcCgodmFsdWUpID0+IHtcbiAgICByZXR1cm4gbmV3IFJlZ0V4cCh2YWx1ZSwgXCJpXCIpO1xufSk7XG5leHBvcnQgZnVuY3Rpb24gcGFyc2VTdGFydFJlZ2lvbkNvZGVCbG9ja0lEKHNldHRpbmdzU3RyOiBzdHJpbmcpOiBzdHJpbmcge1xuXG4gICAgbGV0IGNvZGVCbG9ja1JlZ2lvbklEID0gXCJcIlxuICAgIGxldCBzZXR0aW5nc0xpbmVzID0gc2V0dGluZ3NTdHIuc3BsaXQoXCJcXG5cIik7XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNldHRpbmdzTGluZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgbGV0IHNldHRpbmdzTGluZSA9IHNldHRpbmdzTGluZXNbaV07XG5cbiAgICAgICAgbGV0IHNldHRpbmdzRGF0YSA9IGdldFNldHRpbmdzRGF0YUZyb21LZXlzKHNldHRpbmdzTGluZSwgQ09ERUJMT0NLX1JFR0lPTl9JRF9SRUdFWF9BUlIpO1xuICAgICAgICBpZiAoc2V0dGluZ3NEYXRhICE9PSBudWxsKSB7XG5cbiAgICAgICAgICAgIGNvZGVCbG9ja1JlZ2lvbklEID0gc2V0dGluZ3NEYXRhXG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gY29kZUJsb2NrUmVnaW9uSUQ7XG59XG5cbmZ1bmN0aW9uIHBhcnNlRm9yU2luZ2xlQ29sdW1uTG9jYXRpb24obG9jYXRpb25TdHJpbmc6IHN0cmluZyk6IENvbHVtbkxheW91dHtcblxuICAgIHN3aXRjaCAobG9jYXRpb25TdHJpbmcudG9Mb3dlckNhc2UoKS50cmltKCkucmVwbGFjZShcIiBcIiwgXCJcIikpIHtcbiAgICAgICAgY2FzZSBcImxlZnRcIjpcbiAgICAgICAgY2FzZSBcImxlZnRzaWRlXCI6XG4gICAgICAgIGNhc2UgXCJsZWZ0bWFyZ2luXCI6XG4gICAgICAgIGNhc2UgXCJsZWZ0YWxpZ25cIjpcbiAgICAgICAgY2FzZSBcImxlZnRhbGlnbmVkXCI6XG4gICAgICAgIGNhc2UgXCJsZWZ0YWxpZ25lbWVudFwiOlxuICAgICAgICBjYXNlIFwiZmlyc3RcIjpcbiAgICAgICAgY2FzZSBcInN0YXJ0XCI6XG4gICAgICAgIGNhc2UgXCJiZWdpbm5pbmdcIjpcbiAgICAgICAgICAgIHJldHVybiBDb2x1bW5MYXlvdXQubGVmdFxuICAgICAgICBjYXNlIFwibWlkZGxlXCI6XG4gICAgICAgIGNhc2UgXCJtaWRkbGVhbGlnbmVkXCI6XG4gICAgICAgIGNhc2UgXCJtaWRkbGVhbGlnbm1lbnRcIjpcbiAgICAgICAgY2FzZSBcImNlbnRlclwiOlxuICAgICAgICBjYXNlIFwiY2VudGVyYWxpZ25lZFwiOlxuICAgICAgICBjYXNlIFwiY2VudGVyYWxpZ25tZW50XCI6XG4gICAgICAgIGNhc2UgXCJjZW50ZXJlZFwiOlxuICAgICAgICBjYXNlIFwic3RhbmRhcmRcIjpcbiAgICAgICAgICAgIHJldHVybiBDb2x1bW5MYXlvdXQuY2VudGVyXG4gICAgICAgIGNhc2UgXCJyaWdodFwiOlxuICAgICAgICBjYXNlIFwicmlnaHRzaWRlXCI6XG4gICAgICAgIGNhc2UgXCJyaWdodG1hcmdpblwiOlxuICAgICAgICBjYXNlIFwicmlnaHRhbGlnblwiOlxuICAgICAgICBjYXNlIFwicmlnaHRhbGlnbmVkXCI6XG4gICAgICAgIGNhc2UgXCJyaWdodGFsaWdubWVudFwiOlxuICAgICAgICBjYXNlIFwibGFzdFwiOlxuICAgICAgICBjYXNlIFwiZW5kXCI6XG4gICAgICAgICAgICByZXR1cm4gQ29sdW1uTGF5b3V0LnJpZ2h0XG4gICAgfVxuXG4gICAgcmV0dXJuIENvbHVtbkxheW91dC5jZW50ZXJcbn1cblxuZnVuY3Rpb24gcGFyc2VGb3JTaW5nbGVDb2x1bW5TaXplKHNpemVTdHJpbmc6IHN0cmluZyk6IFNpbmdsZUNvbHVtblNpemUge1xuXG4gICAgc3dpdGNoIChzaXplU3RyaW5nID0gc2l6ZVN0cmluZy50b0xvd2VyQ2FzZSgpLnRyaW0oKS5yZXBsYWNlKFwiIFwiLCBcIlwiKSkge1xuICAgICAgICBjYXNlIFwic21hbGxcIjpcbiAgICAgICAgY2FzZSBcInNtXCI6XG4gICAgICAgICAgICByZXR1cm4gU2luZ2xlQ29sdW1uU2l6ZS5zbWFsbDtcbiAgICAgICAgY2FzZSBcIm1lZGl1bVwiOlxuICAgICAgICBjYXNlIFwibWVkXCI6XG4gICAgICAgICAgICByZXR1cm4gU2luZ2xlQ29sdW1uU2l6ZS5tZWRpdW07XG4gICAgICAgIGNhc2UgXCJsYXJnZVwiOlxuICAgICAgICBjYXNlIFwibGdcIjpcbiAgICAgICAgICAgIHJldHVybiBTaW5nbGVDb2x1bW5TaXplLmxhcmdlO1xuICAgIH1cblxuICAgIHJldHVybiBTaW5nbGVDb2x1bW5TaXplLm1lZGl1bVxufVxuXG5mdW5jdGlvbiBjb252ZXJ0U3RyaW5nVG9TZXR0aW5nc1JlZ2V4KG9yaWdpbmFsU3RyaW5nOiBTdHJpbmcpOiBzdHJpbmcge1xuXG4gICAgb3JpZ2luYWxTdHJpbmcgPSBvcmlnaW5hbFN0cmluZy5yZXBsYWNlKFwiIFwiLCBcIiAqXCIpO1xuICAgIFxuICAgIGxldCByZWdleFN0cmluZyA9IGAoPzoke29yaWdpbmFsU3RyaW5nfSAqOiAqKSguKilgO1xuICAgIHJldHVybiByZWdleFN0cmluZztcbn0iLCIvKlxuICogRmlsZTogbXVsdGktY29sdW1uLW1hcmtkb3duL3NyYy9NdWx0aUNvbHVtblBhcnNlci50c1xuICogQ3JlYXRlZCBEYXRlOiBTYXR1cmRheSwgSmFudWFyeSAyMm5kIDIwMjIsIDY6MDI6NDYgcG1cbiAqIEF1dGhvcjogQ2FtZXJvbiBSb2JpbnNvblxuICogXG4gKiBDb3B5cmlnaHQgKGMpIDIwMjIgQ2FtZXJvbiBSb2JpbnNvblxuICovXG5cbmltcG9ydCB7IHBhcnNlU3RhcnRSZWdpb25Db2RlQmxvY2tJRCB9IGZyb20gXCIuL3NldHRpbmdzUGFyc2VyXCI7XG5cbmNvbnN0IFNUQVJUX1JFR0VYX1NUUlMgPSBbXCI9PT0gKnN0YXJ0LW11bHRpLWNvbHVtbig6P1thLXpBLVowLTktX1xcXFxzXSopP1wiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICBcIj09PSAqbXVsdGktY29sdW1uLXN0YXJ0KDo/W2EtekEtWjAtOS1fXFxcXHNdKik/XCJdXG5jb25zdCBTVEFSVF9SRUdFWF9BUlI6IFJlZ0V4cFtdID0gW107XG5mb3IobGV0IGkgPSAwOyBpIDwgU1RBUlRfUkVHRVhfU1RSUy5sZW5ndGg7IGkrKykge1xuICAgIFNUQVJUX1JFR0VYX0FSUi5wdXNoKG5ldyBSZWdFeHAoU1RBUlRfUkVHRVhfU1RSU1tpXSkpO1xufVxuXG5jb25zdCBTVEFSVF9SRUdFWF9TVFJTX1dIT0xFX0xJTkUgPSBbXCJePT09ICpzdGFydC1tdWx0aS1jb2x1bW4oOj9bYS16QS1aMC05LV9cXFxcc10qKT8kXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJePT09ICptdWx0aS1jb2x1bW4tc3RhcnQoOj9bYS16QS1aMC05LV9cXFxcc10qKT8kXCJdXG5jb25zdCBTVEFSVF9SRUdFWF9BUlJfV0hPTEVfTElORTogUmVnRXhwW10gPSBbXTtcbmZvcihsZXQgaSA9IDA7IGkgPCBTVEFSVF9SRUdFWF9TVFJTX1dIT0xFX0xJTkUubGVuZ3RoOyBpKyspIHtcbiAgICBTVEFSVF9SRUdFWF9BUlJfV0hPTEVfTElORS5wdXNoKG5ldyBSZWdFeHAoU1RBUlRfUkVHRVhfU1RSU19XSE9MRV9MSU5FW2ldKSk7XG59XG5cblxuZXhwb3J0IGZ1bmN0aW9uIGZpbmRTdGFydFRhZyh0ZXh0OiBzdHJpbmcpOiB7IGZvdW5kOiBib29sZWFuLCBzdGFydFBvc2l0aW9uOiBudW1iZXIsIGVuZFBvc2l0aW9uOiBudW1iZXIsIG1hdGNoTGVuZ3RoOiBudW1iZXIgfSB7XG5cbiAgICBsZXQgZm91bmQgPSBmYWxzZTtcbiAgICBsZXQgc3RhcnRQb3NpdGlvbiA9IC0xO1xuICAgIGxldCBtYXRjaExlbmd0aCA9IDA7XG4gICAgZm9yKGxldCBpID0gMDsgaTwgU1RBUlRfUkVHRVhfQVJSLmxlbmd0aDsgaSsrKSB7XG5cbiAgICAgICAgbGV0IHJlZ2V4RGF0YSA9IFNUQVJUX1JFR0VYX0FSUltpXS5leGVjKHRleHQpXG4gICAgICAgIGlmKHJlZ2V4RGF0YSAhPT0gbnVsbCAmJiByZWdleERhdGEubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgc3RhcnRQb3NpdGlvbiA9IHJlZ2V4RGF0YS5pbmRleFxuICAgICAgICAgICAgbWF0Y2hMZW5ndGggPSByZWdleERhdGFbMF0ubGVuZ3RoO1xuXG4gICAgICAgICAgICBsZXQgbGluZSA9IHRleHQuc2xpY2Uoc3RhcnRQb3NpdGlvbiwgc3RhcnRQb3NpdGlvbiArIG1hdGNoTGVuZ3RoKTtcbiAgICAgICAgICAgIGlmKFNUQVJUX1JFR0VYX0FSUl9XSE9MRV9MSU5FW2ldLnRlc3QobGluZSkpIHtcbiAgICAgICAgICAgICAgICBmb3VuZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgbGV0IGVuZFBvc2l0aW9uID0gc3RhcnRQb3NpdGlvbiArIG1hdGNoTGVuZ3RoO1xuXG4gICAgcmV0dXJuIHsgZm91bmQsIHN0YXJ0UG9zaXRpb24sIGVuZFBvc2l0aW9uLCBtYXRjaExlbmd0aCB9O1xufVxuZXhwb3J0IGZ1bmN0aW9uIGNvbnRhaW5zU3RhcnRUYWcodGV4dDogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIGZpbmRTdGFydFRhZyh0ZXh0KS5mb3VuZFxufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNTdGFydFRhZ1dpdGhJRCh0ZXh0OiBzdHJpbmcpOiB7aXNTdGFydFRhZzogYm9vbGVhbiwgaGFzS2V5OiBib29sZWFufSB7XG5cbiAgICBsZXQgc3RhcnRUYWdEYXRhID0gZmluZFN0YXJ0VGFnKHRleHQpO1xuICAgIGlmKHN0YXJ0VGFnRGF0YS5mb3VuZCA9PT0gdHJ1ZSkge1xuXG4gICAgICAgIGxldCBrZXkgPSBnZXRTdGFydFRhZ0tleSh0ZXh0KVxuICAgICAgICBpZihrZXkgPT09IG51bGwgfHwga2V5ID09PSBcIlwiKSB7XG4gICAgICAgICAgICByZXR1cm4ge2lzU3RhcnRUYWc6IHRydWUsIGhhc0tleTogZmFsc2V9O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7aXNTdGFydFRhZzogdHJ1ZSwgaGFzS2V5OiB0cnVlfTtcbiAgICB9XG5cbiAgICByZXR1cm4ge2lzU3RhcnRUYWc6IGZhbHNlLCBoYXNLZXk6IGZhbHNlfTtcbn1cblxuY29uc3QgRU5EX1JFR0VYX1NUUlMgPSBbXCI9PT0gKmVuZC1tdWx0aS1jb2x1bW5cIixcbiAgICAgICAgICAgICAgICAgICAgICAgIFwiPT09ICptdWx0aS1jb2x1bW4tZW5kXCJdXG5jb25zdCBFTkRfUkVHRVhfQVJSOiBSZWdFeHBbXSA9IFtdO1xuZm9yKGxldCBpID0gMDsgaSA8IEVORF9SRUdFWF9TVFJTLmxlbmd0aDsgaSsrKSB7XG4gICAgRU5EX1JFR0VYX0FSUi5wdXNoKG5ldyBSZWdFeHAoRU5EX1JFR0VYX1NUUlNbaV0pKTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBmaW5kRW5kVGFnKHRleHQ6IHN0cmluZyk6IHsgZm91bmQ6IGJvb2xlYW4sIHN0YXJ0UG9zaXRpb246IG51bWJlciwgZW5kUG9zaXRpb246IG51bWJlciwgbWF0Y2hMZW5ndGg6IG51bWJlciB9IHtcblxuICAgIGxldCBmb3VuZCA9IGZhbHNlO1xuICAgIGxldCBzdGFydFBvc2l0aW9uID0gLTE7XG4gICAgZm9yKGxldCBpID0gMDsgaTwgRU5EX1JFR0VYX0FSUi5sZW5ndGg7IGkrKykge1xuXG4gICAgICAgIGlmKEVORF9SRUdFWF9BUlJbaV0udGVzdCh0ZXh0KSkge1xuICAgICAgICAgICAgZm91bmQgPSB0cnVlO1xuICAgICAgICAgICAgc3RhcnRQb3NpdGlvbiA9IHRleHQuc2VhcmNoKEVORF9SRUdFWF9TVFJTW2ldKVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBsZXQgZW5kUG9zaXRpb24gPSAtMVxuICAgIGxldCBtYXRjaExlbmd0aCA9IDA7XG4gICAgZm9yKGxldCBpID0gMDsgaTwgRU5EX1JFR0VYX0FSUi5sZW5ndGg7IGkrKykge1xuXG4gICAgICAgIGxldCByZWdleERhdGEgPSBFTkRfUkVHRVhfQVJSW2ldLmV4ZWModGV4dClcbiAgICAgICAgaWYocmVnZXhEYXRhICE9PSBudWxsICYmIHJlZ2V4RGF0YS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBmb3VuZCA9IHRydWU7XG4gICAgICAgICAgICBzdGFydFBvc2l0aW9uID0gcmVnZXhEYXRhLmluZGV4XG4gICAgICAgICAgICBtYXRjaExlbmd0aCA9IHJlZ2V4RGF0YVswXS5sZW5ndGg7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgIH1cbiAgICBlbmRQb3NpdGlvbiA9IHN0YXJ0UG9zaXRpb24gKyBtYXRjaExlbmd0aDtcblxuICAgIHJldHVybiB7IGZvdW5kLCBzdGFydFBvc2l0aW9uLCBlbmRQb3NpdGlvbiwgbWF0Y2hMZW5ndGggfTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBjb250YWluc0VuZFRhZyh0ZXh0OiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gZmluZEVuZFRhZyh0ZXh0KS5mb3VuZFxufVxuXG5jb25zdCBDT0xfUkVHRVhfU1RSUzogc3RyaW5nW10gPSBbXCI9PT0gKmNvbHVtbi1lbmQgKj09PVwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiPT09ICplbmQtY29sdW1uICo9PT1cIixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIj09PSAqY29sdW1uLWJyZWFrICo9PT1cIixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIj09PSAqYnJlYWstY29sdW1uICo9PT1cIixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIi0tLSAqY29sdW1uLWVuZCAqLS0tXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCItLS0gKmVuZC1jb2x1bW4gKi0tLVwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiLS0tICpjb2x1bW4tYnJlYWsgKi0tLVwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiLS0tICpicmVhay1jb2x1bW4gKi0tLVwiXTtcbmNvbnN0IENPTF9SRUdFWF9BUlI6IFJlZ0V4cFtdID0gW107XG5mb3IobGV0IGkgPSAwOyBpIDwgQ09MX1JFR0VYX1NUUlMubGVuZ3RoOyBpKyspIHtcbiAgICBDT0xfUkVHRVhfQVJSLnB1c2gobmV3IFJlZ0V4cChDT0xfUkVHRVhfU1RSU1tpXSkpO1xufVxuZXhwb3J0IGZ1bmN0aW9uIGNvbnRhaW5zQ29sRW5kVGFnKHRleHQ6IHN0cmluZyk6IGJvb2xlYW4ge1xuXG4gICAgbGV0IGZvdW5kID0gZmFsc2U7XG4gICAgZm9yKGxldCBpID0gMDsgaTwgQ09MX1JFR0VYX0FSUi5sZW5ndGg7IGkrKykge1xuXG4gICAgICAgIGlmKENPTF9SRUdFWF9BUlJbaV0udGVzdCh0ZXh0KSkge1xuICAgICAgICAgICAgZm91bmQgPSB0cnVlO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gZm91bmQ7XG59XG5cbmNvbnN0IENPTF9FTEVNRU5UX0lOTkVSX1RFWFRfUkVHRVhfU1RSUzogc3RyaW5nW10gPSBbXCI9ICpjb2x1bW4tZW5kICo9XCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCI9ICplbmQtY29sdW1uICo9XCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCI9ICpjb2x1bW4tYnJlYWsgKj1cIixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIj0gKmJyZWFrLWNvbHVtbiAqPVwiXVxuY29uc3QgQ09MX0VMRU1FTlRfSU5ORVJfVEVYVF9SRUdFWF9BUlI6IFJlZ0V4cFtdID0gW107XG5mb3IobGV0IGkgPSAwOyBpIDwgQ09MX0VMRU1FTlRfSU5ORVJfVEVYVF9SRUdFWF9TVFJTLmxlbmd0aDsgaSsrKSB7XG4gICAgQ09MX1JFR0VYX0FSUi5wdXNoKG5ldyBSZWdFeHAoQ09MX0VMRU1FTlRfSU5ORVJfVEVYVF9SRUdFWF9TVFJTW2ldKSk7XG59XG5leHBvcnQgZnVuY3Rpb24gZWxJbm5lclRleHRDb250YWluc0NvbEVuZFRhZyh0ZXh0OiBzdHJpbmcpOiBib29sZWFuIHtcblxuICAgIGxldCBmb3VuZCA9IGZhbHNlO1xuICAgIGZvcihsZXQgaSA9IDA7IGk8IENPTF9SRUdFWF9BUlIubGVuZ3RoOyBpKyspIHtcblxuICAgICAgICBpZihDT0xfUkVHRVhfQVJSW2ldLnRlc3QodGV4dCkpIHtcbiAgICAgICAgICAgIGZvdW5kID0gdHJ1ZTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGZvdW5kO1xufVxuXG5jb25zdCBDT0xfU0VUVElOR1NfUkVHRVhfU1RSUyA9IFtcImBgYHNldHRpbmdzXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImBgYGNvbHVtbi1zZXR0aW5nc1wiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJgYGBtdWx0aS1jb2x1bW4tc2V0dGluZ3NcIl07XG5jb25zdCBDT0xfU0VUVElOR1NfUkVHRVhfQVJSOiBSZWdFeHBbXSA9IFtdO1xuZm9yKGxldCBpID0gMDsgaSA8IENPTF9TRVRUSU5HU19SRUdFWF9TVFJTLmxlbmd0aDsgaSsrKSB7XG4gICAgQ09MX1NFVFRJTkdTX1JFR0VYX0FSUi5wdXNoKG5ldyBSZWdFeHAoQ09MX1NFVFRJTkdTX1JFR0VYX1NUUlNbaV0pKTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBjb250YWluc0NvbFNldHRpbmdzVGFnKHRleHQ6IHN0cmluZyk6IGJvb2xlYW4ge1xuXG4gICAgbGV0IGZvdW5kID0gZmFsc2U7XG4gICAgZm9yKGxldCBpID0gMDsgaTwgQ09MX1NFVFRJTkdTX1JFR0VYX0FSUi5sZW5ndGg7IGkrKykge1xuXG4gICAgICAgIGlmKENPTF9TRVRUSU5HU19SRUdFWF9BUlJbaV0udGVzdCh0ZXh0KSkge1xuICAgICAgICAgICAgZm91bmQgPSB0cnVlO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gZm91bmQ7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBmaW5kU2V0dGluZ3NDb2RlYmxvY2sodGV4dDogc3RyaW5nKTogeyBmb3VuZDogYm9vbGVhbiwgc3RhcnRQb3NpdGlvbjogbnVtYmVyLCBlbmRQb3NpdGlvbjogbnVtYmVyLCBtYXRjaExlbmd0aDogbnVtYmVyIH0ge1xuXG4gICAgbGV0IGZvdW5kID0gZmFsc2U7XG4gICAgbGV0IHN0YXJ0UG9zaXRpb24gPSAtMTtcbiAgICBsZXQgZW5kUG9zaXRpb24gPSAtMVxuICAgIGxldCBtYXRjaExlbmd0aCA9IDA7XG4gICAgZm9yKGxldCBpID0gMDsgaTwgQ09MX1NFVFRJTkdTX1JFR0VYX0FSUi5sZW5ndGg7IGkrKykge1xuXG4gICAgICAgIGxldCByZWdleERhdGEgPSBDT0xfU0VUVElOR1NfUkVHRVhfQVJSW2ldLmV4ZWModGV4dClcbiAgICAgICAgaWYocmVnZXhEYXRhICE9PSBudWxsICYmIHJlZ2V4RGF0YS5sZW5ndGggPiAwKSB7XG5cbiAgICAgICAgICAgIGZvdW5kID0gdHJ1ZTtcbiAgICAgICAgICAgIHN0YXJ0UG9zaXRpb24gPSByZWdleERhdGEuaW5kZXhcbiAgICAgICAgICAgIG1hdGNoTGVuZ3RoID0gcmVnZXhEYXRhWzBdLmxlbmd0aDtcbiAgICAgICAgICAgIGVuZFBvc2l0aW9uID0gc3RhcnRQb3NpdGlvbiArIG1hdGNoTGVuZ3RoO1xuXG4gICAgICAgICAgICBsZXQgcmVtYWluaW5nVGV4dCA9IHRleHQuc2xpY2UoZW5kUG9zaXRpb24pXG4gICAgICAgICAgICByZWdleERhdGEgPSBDT0RFQkxPQ0tfRU5EX1JFR0VYLmV4ZWMocmVtYWluaW5nVGV4dClcbiAgICAgICAgICAgIGlmKHJlZ2V4RGF0YSAhPT0gbnVsbCAmJiByZWdleERhdGEubGVuZ3RoID4gMCkge1xuXG4gICAgICAgICAgICAgICAgZm91bmQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIGVuZFBvc2l0aW9uICs9IHJlZ2V4RGF0YS5pbmRleCArIHJlZ2V4RGF0YVswXS5sZW5ndGggXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB7IGZvdW5kLCBzdGFydFBvc2l0aW9uLCBlbmRQb3NpdGlvbiwgbWF0Y2hMZW5ndGggfTtcbn1cblxuY29uc3QgU1RBUlRfQ09ERUJMT0NLX1JFR0VYX0FSUjogUmVnRXhwW10gPSBbXG5cImBgYG11bHRpLWNvbHVtbi1zdGFydFwiLFxuXCJgYGBzdGFydC1tdWx0aS1jb2x1bW5cIlxuXS5tYXAoKHZhbCkgPT4ge1xuICAgIHJldHVybiBuZXcgUmVnRXhwKHZhbCk7XG59KVxuZXhwb3J0IGZ1bmN0aW9uIGZpbmRTdGFydENvZGVibG9jayh0ZXh0OiBzdHJpbmcpOiB7IGZvdW5kOiBib29sZWFuLCBzdGFydFBvc2l0aW9uOiBudW1iZXIsIGVuZFBvc2l0aW9uOiBudW1iZXIsIG1hdGNoTGVuZ3RoOiBudW1iZXIgfSB7XG5cbiAgICBsZXQgZm91bmQgPSBmYWxzZTtcbiAgICBsZXQgc3RhcnRQb3NpdGlvbiA9IC0xO1xuICAgIGxldCBlbmRQb3NpdGlvbiA9IC0xXG4gICAgbGV0IG1hdGNoTGVuZ3RoID0gMDtcbiAgICBmb3IobGV0IGkgPSAwOyBpPCBTVEFSVF9DT0RFQkxPQ0tfUkVHRVhfQVJSLmxlbmd0aDsgaSsrKSB7XG5cbiAgICAgICAgbGV0IHJlZ2V4RGF0YSA9IFNUQVJUX0NPREVCTE9DS19SRUdFWF9BUlJbaV0uZXhlYyh0ZXh0KVxuICAgICAgICBpZihyZWdleERhdGEgIT09IG51bGwgJiYgcmVnZXhEYXRhLmxlbmd0aCA+IDApIHtcblxuICAgICAgICAgICAgZm91bmQgPSB0cnVlO1xuICAgICAgICAgICAgc3RhcnRQb3NpdGlvbiA9IHJlZ2V4RGF0YS5pbmRleFxuICAgICAgICAgICAgbWF0Y2hMZW5ndGggPSByZWdleERhdGFbMF0ubGVuZ3RoO1xuICAgICAgICAgICAgZW5kUG9zaXRpb24gPSBzdGFydFBvc2l0aW9uICsgbWF0Y2hMZW5ndGg7XG5cbiAgICAgICAgICAgIGxldCByZW1haW5pbmdUZXh0ID0gdGV4dC5zbGljZShlbmRQb3NpdGlvbilcbiAgICAgICAgICAgIHJlZ2V4RGF0YSA9IENPREVCTE9DS19FTkRfUkVHRVguZXhlYyhyZW1haW5pbmdUZXh0KVxuICAgICAgICAgICAgaWYocmVnZXhEYXRhICE9PSBudWxsICYmIHJlZ2V4RGF0YS5sZW5ndGggPiAwKSB7XG5cbiAgICAgICAgICAgICAgICBmb3VuZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgZW5kUG9zaXRpb24gKz0gcmVnZXhEYXRhLmluZGV4ICsgcmVnZXhEYXRhWzBdLmxlbmd0aCBcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4geyBmb3VuZCwgc3RhcnRQb3NpdGlvbiwgZW5kUG9zaXRpb24sIG1hdGNoTGVuZ3RoIH07XG59XG5leHBvcnQgZnVuY3Rpb24gY29udGFpbnNTdGFydENvZGVCbG9jayh0ZXh0OiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gZmluZFN0YXJ0Q29kZWJsb2NrKHRleHQpLmZvdW5kXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjb250YWluc1JlZ2lvblN0YXJ0KHRleHQ6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBjb250YWluc1N0YXJ0Q29kZUJsb2NrKHRleHQpIHx8IGNvbnRhaW5zU3RhcnRUYWcodGV4dCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjb3VudFN0YXJ0VGFncyhpbml0aWFsVGV4dDogc3RyaW5nKTogeyBudW1iZXJPZlRhZ3M6IG51bWJlciwga2V5czogc3RyaW5nW10gfSB7XG5cbiAgICBsZXQga2V5czogc3RyaW5nW10gPSBbXTtcbiAgICBsZXQgdGV4dCA9IGluaXRpYWxUZXh0XG4gICAgbGV0IHN0YXJ0VGFnRGF0YSA9IGZpbmRTdGFydFRhZyh0ZXh0KTtcbiAgICB3aGlsZShzdGFydFRhZ0RhdGEuZm91bmQpIHtcbiAgICAgICAgXG4gICAgICAgIC8vIFNsaWNlIG9mZiBldmVyeXRoaW5nIGJlZm9yZSB0aGUgdGFnXG4gICAgICAgIHRleHQgPSB0ZXh0LnNsaWNlKHN0YXJ0VGFnRGF0YS5zdGFydFBvc2l0aW9uKTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogR2V0IGp1c3QgdGhlIHN0YXJ0IHRhZyBsaW5lIGFuZCB0aGVuIHNldCB0ZXh0IHRvIGV2ZXJ5dGhpbmcganVzdFxuICAgICAgICAgKiBhZnRlciB0aGUgc3RhcnQgdGFnLlxuICAgICAgICAgKi9cbiAgICAgICAgbGV0IHRhZyA9IHRleHQuc3BsaXQoXCJcXG5cIilbMF07XG4gICAgICAgIHRleHQgPSB0ZXh0LnNsaWNlKDEpOyAvLyBUaGlzIG1vdmVzIHRoZSB0ZXh0IDEgY2hhcmFjdGVyIHNvIHdlIGRvbnQgbWF0Y2ggdGhlIHNhbWUgdGFnLlxuXG4gICAgICAgIC8vIFBhcnNlIG91dCB0aGUga2V5IGFuZCBhcHBlbmQgdG8gdGhlIGxpc3QuXG4gICAgICAgIGxldCBrZXkgPSBnZXRTdGFydFRhZ0tleSh0YWcpO1xuICAgICAgICBpZihrZXkgPT09IG51bGwpIHtcbiAgICAgICAgICAgIGtleSA9IFwiXCJcbiAgICAgICAgfVxuICAgICAgICBrZXlzLnB1c2goa2V5KTtcblxuICAgICAgICAvLyBTZWFyY2ggYWdhaW4gZm9yIGFub3RoZXIgdGFnIGJlZm9yZSBsb29waW5nLlxuICAgICAgICBzdGFydFRhZ0RhdGEgPSBmaW5kU3RhcnRUYWcodGV4dCk7XG4gICAgfVxuXG4gICAgdGV4dCA9IGluaXRpYWxUZXh0O1xuICAgIHN0YXJ0VGFnRGF0YSA9IGZpbmRTdGFydENvZGVibG9jayh0ZXh0KTtcbiAgICB3aGlsZShzdGFydFRhZ0RhdGEuZm91bmQpIHtcbiAgICAgICAgXG4gICAgICAgIGxldCBzZXR0aW5nc1RleHQgPSB0ZXh0LnNsaWNlKHN0YXJ0VGFnRGF0YS5zdGFydFBvc2l0aW9uLCBzdGFydFRhZ0RhdGEuZW5kUG9zaXRpb24pO1xuICAgICAgICB0ZXh0ID0gdGV4dC5zbGljZShzdGFydFRhZ0RhdGEuZW5kUG9zaXRpb24pO1xuXG4gICAgICAgIGxldCBrZXkgPSBwYXJzZVN0YXJ0UmVnaW9uQ29kZUJsb2NrSUQoc2V0dGluZ3NUZXh0KTtcbiAgICAgICAgaWYoa2V5ID09PSBudWxsKSB7XG4gICAgICAgICAgICBrZXkgPSBcIlwiXG4gICAgICAgIH1cbiAgICAgICAga2V5cy5wdXNoKGtleSk7XG5cbiAgICAgICAgLy8gU2VhcmNoIGFnYWluIGZvciBhbm90aGVyIHRhZyBiZWZvcmUgbG9vcGluZy5cbiAgICAgICAgc3RhcnRUYWdEYXRhID0gZmluZFN0YXJ0Q29kZWJsb2NrKHRleHQpO1xuICAgIH1cblxuICAgIHJldHVybiB7IG51bWJlck9mVGFnczoga2V5cy5sZW5ndGgsIGtleXMgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldFN0YXJ0QmxvY2tPckNvZGVibG9ja0Fib3ZlTGluZShsaW5lc0Fib3ZlQXJyYXk6IHN0cmluZ1tdKTogeyBcbnN0YXJ0QmxvY2tLZXk6IHN0cmluZywgXG5saW5lc0Fib3ZlQXJyYXk6IHN0cmluZ1tdIH0gfCBudWxsIHtcblxuICAgIGxldCBzdGFydEJsb2NrID0gZ2V0U3RhcnRCbG9ja0Fib3ZlTGluZShsaW5lc0Fib3ZlQXJyYXkpO1xuICAgIGlmKHN0YXJ0QmxvY2sgIT09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIHN0YXJ0QmxvY2s7XG4gICAgfVxuXG4gICAgbGV0IGNvZGVCbG9jayA9IGdldFN0YXJ0Q29kZUJsb2NrQWJvdmVMaW5lKGxpbmVzQWJvdmVBcnJheSlcbiAgICBpZihjb2RlQmxvY2sgIT09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIGNvZGVCbG9jaztcbiAgICB9XG4gICAgcmV0dXJuIG51bGxcbn1cblxuLyoqXG4gKiBUaGlzIGZ1bmN0aW9uIHdpbGwgZmlsdGVyIGEgc2V0IG9mIHN0cmluZ3MsIHJldHVybmluZyBhbGwgaXRlbXMgc3RhcnRpbmdcbiAqIGZyb20gdGhlIGNsb3Nlc3Qgb3BlbiBzdGFydCB0YWcgdGhyb3VnaCB0aGUgbGFzdCBpdGVtIGluIHRoZSBzZXQuIFxuICogXG4gKiBUaGUgZnVuY3Rpb24gZmlsdGVycyBvdXQgYWxsIGVuZCB0YWdzIHRvIG1ha2Ugc3VyZSB0aGF0IHRoZSBzdGFydCB0YWcgd2UgXG4gKiBmaW5kIGlzIHRoZSBwcm9wZXIgc3RhcnQgdGFnIGZvciB0aGUgbGlzdCBzZW50LiBcbiAqIEBwYXJhbSBsaW5lc0Fib3ZlQXJyYXkgXG4gKiBAcmV0dXJucyBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFN0YXJ0QmxvY2tBYm92ZUxpbmUobGluZXNBYm92ZUFycmF5OiBzdHJpbmdbXSk6IHsgc3RhcnRCbG9ja0tleTogc3RyaW5nLCBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGluZXNBYm92ZUFycmF5OiBzdHJpbmdbXSB9IHwgbnVsbCB7XG5cbiAgICAvLyBSZWR1Y2UgdGhlIGFycmF5IGRvd24gaW50byBhIHNpbmdsZSBzdHJpbmcgc28gdGhhdCB3ZSBjYW5cbiAgICAvLyBlYXNpbHkgUmVnRXggb3ZlciB0aGUgc3RyaW5nIGFuZCBmaW5kIHRoZSBpbmRpY2llcyB3ZSdyZSBsb29raW5nIGZvci5cbiAgICBsZXQgbGluZXNBYm92ZVN0ciA9IGxpbmVzQWJvdmVBcnJheS5yZWR1Y2UoKHByZXYsIGN1cnJlbnQpID0+IHtcbiAgICAgICAgcmV0dXJuIHByZXYgKyBcIlxcblwiICArIGN1cnJlbnQ7XG4gICAgfSwgXCJcIik7XG5cbiAgICAvKlxuICAgICAgICAqIEZpcnN0IHRoaW5nIHdlIG5lZWQgdG8gZG8gaXMgY2hlY2sgaWYgdGhlcmUgYXJlIGFueSBlbmQgdGFncyBpbiB0aGVcbiAgICAgICAgKiBzZXQgb2Ygc3RyaW5ncyAod2hpY2ggbG9naWNhbGx5IHdvdWxkIGNsb3NlIHN0YXJ0IHRhZ3MgYW5kIHRoZXJlZm9yZVxuICAgICAgICAqIHRoZSBzdGFydCB0YWcgaXQgY2xvc2VzIGlzIG5vdCB3aGF0IHdlIHdhbnQpLiBJZiB0aGVyZSBhcmUgd2Ugd2FudCB0byBcbiAgICAgICAgKiBzbG93bHkgbmFycm93IGRvd24gb3VyIHNldCBvZiBzdHJpbmdzIHVudGlsIHRoZSBsYXN0IGVuZCB0YWcgaXMgXG4gICAgICAgICogcmVtb3ZlZC4gVGhpcyBtYWtlcyBpdCBlYXNpZXIgdG8gZmluZCB0aGUgY2xvc2VzdCBvcGVuIHN0YXJ0IHRhZyBcbiAgICAgICAgKiBpbiB0aGUgZGF0YS5cbiAgICAgICAgKi9cbiAgICBsZXQgZW5kVGFnU2VyYWNoRGF0YSA9IGZpbmRFbmRUYWcobGluZXNBYm92ZVN0cik7XG4gICAgd2hpbGUoZW5kVGFnU2VyYWNoRGF0YS5mb3VuZCA9PT0gdHJ1ZSkge1xuXG4gICAgICAgIC8vIEdldCB0aGUgaW5kZXggb2Ygd2hlcmUgdGhlIGZpcnN0IHJlZ2V4IG1hdGNoIGluIHRoZVxuICAgICAgICAvLyBzdHJpbmcgaXMuIHRoZW4gd2Ugc2xpY2UgZnJvbSAwIHRvIGluZGV4IG9mZiBvZiB0aGUgc3RyaW5nXG4gICAgICAgIC8vIHNwbGl0IGl0IGJ5IG5ld2xpbmUsIGN1dCBvZmYgdGhlIGZpcnN0IGxpbmUgKHdoaWNoIGFjdHVhbGx5XG4gICAgICAgIC8vIGNvbnRhaW5zIHRoZSByZWdleCkgdGhlbiByZWR1Y2UgYmFjayBkb3duIHRvIGEgc2luZ2xlIHN0cmluZy5cbiAgICAgICAgLy9cbiAgICAgICAgLy8gVE9ETzogVGhpcyBjb3VsZCBiZSBzaW1wbGlmaWVkIGlmIHdlIGp1c3Qgc2xpY2UgdGhlIHRleHQgYWZ0ZXJcbiAgICAgICAgLy8gdGhlIGVuZCB0YWcgaW5zdGVhZCBvZiB0aGUgYmVnaW5pbmcuXG4gICAgICAgIGxldCBpbmRleE9mUmVnZXggPSBlbmRUYWdTZXJhY2hEYXRhLnN0YXJ0UG9zaXRpb247XG4gICAgICAgIGxpbmVzQWJvdmVBcnJheSA9IGxpbmVzQWJvdmVTdHIuc2xpY2UoaW5kZXhPZlJlZ2V4KS5zcGxpdChcIlxcblwiKS5zcGxpY2UoMSlcbiAgICAgICAgbGluZXNBYm92ZVN0ciA9IGxpbmVzQWJvdmVBcnJheS5yZWR1Y2UoKHByZXYsIGN1cnJlbnQpID0+IHtcbiAgICAgICAgICAgIHJldHVybiBwcmV2ICsgXCJcXG5cIiAgKyBjdXJyZW50O1xuICAgICAgICB9LCBcIlwiKTtcbiAgICAgICAgZW5kVGFnU2VyYWNoRGF0YSA9IGZpbmRFbmRUYWcobGluZXNBYm92ZVN0cik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTm93IHdlIGhhdmUgdGhlIHNldCBvZiBsaW5lcyBhZnRlciBhbGwgb3RoZXIgZW5kIHRhZ3MuIFdlIG5vd1xuICAgICAqIG5lZWQgdG8gY2hlY2sgaWYgdGhlcmUgaXMgc3RpbGwgYSBzdGFydCB0YWcgbGVmdCBpbiB0aGUgZGF0YS4gSWYgXG4gICAgICogdGhlcmUgaXMgbm8gc3RhcnQgdGFnIHRoZW4gd2Ugd2FudCB0byByZXR1cm4gYW4gZW1wdHkgYXJyYXkgYW5kIGVtcHR5IFxuICAgICAqIGtleS5cbiAgICAgKi8gXG4gICAgbGV0IHN0YXJ0QmxvY2tLZXkgPSBcIlwiO1xuICAgIGxldCBzdGFydFRhZ1NlYXJjaERhdGEgPSBmaW5kU3RhcnRUYWcobGluZXNBYm92ZVN0cik7XG4gICAgaWYoc3RhcnRUYWdTZWFyY2hEYXRhLmZvdW5kID09PSBmYWxzZSkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgZWxzZSB7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIE5vdyB3ZSBrbm93IHRoZXJlIGlzIGF0IGxlYXN0IDEgc3RhcnQga2V5IGxlZnQsIGhvd2V2ZXIgdGhlcmVcbiAgICAgICAgICogbWF5IGJlIG11bHRpcGxlIHN0YXJ0IGtleXMgaWYgdGhlIHVzZXIgaXMgbm90IGNsb3NpbmcgdGhlaXJcbiAgICAgICAgICogYmxvY2tzLiBXZSBjdXJyZW50bHkgZG9udCBhbGxvdyByZWN1c2l2ZSBzcGxpdHRpbmcgc28gd2UgXG4gICAgICAgICAqIHdhbnQgdG8gZ2V0IHRoZSBsYXN0IGtleSBpbiBvdXIgcmVtYWluaW5nIHNldC4gU2FtZSBpZGVhIGFzXG4gICAgICAgICAqIGFib3ZlLlxuICAgICAgICAgKi9cbiAgICAgICAgd2hpbGUoc3RhcnRUYWdTZWFyY2hEYXRhLmZvdW5kID09PSB0cnVlKSB7XG5cbiAgICAgICAgICAgIC8vIEdldCB0aGUgaW5kZXggb2Ygd2hlcmUgdGhlIGZpcnN0IHJlZ2V4IG1hdGNoIGluIHRoZVxuICAgICAgICAgICAgLy8gc3RyaW5nIGlzLiB0aGVuIHdlIHNsaWNlIGZyb20gMCB0byBpbmRleCBvZmYgb2YgdGhlIHN0cmluZ1xuICAgICAgICAgICAgLy8gc3BsaXQgaXQgYnkgbmV3bGluZSwgY3V0IG9mZiB0aGUgZmlyc3QgbGluZSAod2hpY2ggYWN0dWFsbHlcbiAgICAgICAgICAgIC8vIGNvbnRhaW5zIHRoZSByZWdleCkgdGhlbiByZWR1Y2UgYmFjayBkb3duIHRvIGEgc2luZ2xlIHN0cmluZy5cbiAgICAgICAgICAgIC8vXG4gICAgICAgICAgICAvLyBUT0RPOiBUaGlzIGNvdWxkIGJlIHNpbXBsaWZpZWQgaWYgd2UganVzdCBzbGljZSB0aGUgdGV4dCBhZnRlclxuICAgICAgICAgICAgLy8gdGhlIGVuZCB0YWcgaW5zdGVhZCBvZiB0aGUgYmVnaW5pbmcuXG4gICAgICAgICAgICBsZXQgc3RhcnRJbmRleCA9IHN0YXJ0VGFnU2VhcmNoRGF0YS5zdGFydFBvc2l0aW9uO1xuXG4gICAgICAgICAgICBsaW5lc0Fib3ZlQXJyYXkgPSBsaW5lc0Fib3ZlU3RyLnNsaWNlKHN0YXJ0SW5kZXgpLnNwbGl0KFwiXFxuXCIpXG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGxldCBzdGFydFRhZyA9IGxpbmVzQWJvdmVBcnJheVswXTtcbiAgICAgICAgICAgIGxldCBrZXkgPSBnZXRTdGFydFRhZ0tleShzdGFydFRhZyk7XG4gICAgICAgICAgICBpZihrZXkgIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICBzdGFydEJsb2NrS2V5ID0ga2V5O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBsaW5lc0Fib3ZlQXJyYXkgPSBsaW5lc0Fib3ZlQXJyYXkuc3BsaWNlKDEpXG4gICAgICAgICAgICBsaW5lc0Fib3ZlU3RyID0gbGluZXNBYm92ZUFycmF5LnJlZHVjZSgocHJldiwgY3VycmVudCkgPT4ge1xuICAgICAgICAgICAgICAgIHJldHVybiBwcmV2ICsgXCJcXG5cIiAgKyBjdXJyZW50O1xuICAgICAgICAgICAgfSwgXCJcIik7XG5cbiAgICAgICAgICAgIHN0YXJ0VGFnU2VhcmNoRGF0YSA9IGZpbmRTdGFydFRhZyhsaW5lc0Fib3ZlU3RyKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmKHN0YXJ0QmxvY2tLZXkgPT09IFwiXCIpIHtcblxuICAgICAgICBsZXQgY29kZUJsb2NrRGF0YSA9IHBhcnNlQ29kZUJsb2NrU3RhcnQobGluZXNBYm92ZUFycmF5KVxuICAgICAgICBpZihjb2RlQmxvY2tEYXRhICE9PSBudWxsKSB7XG4gICAgICAgICAgICBcbiAgICAgICAgICAgIHN0YXJ0QmxvY2tLZXkgPSBjb2RlQmxvY2tEYXRhLmlkO1xuXG4gICAgICAgICAgICBpZihjb2RlQmxvY2tEYXRhLmluZGV4ID4gMCkge1xuICAgICAgICAgICAgICAgIGxpbmVzQWJvdmVBcnJheSA9IGxpbmVzQWJvdmVBcnJheS5zbGljZShjb2RlQmxvY2tEYXRhLmluZGV4ICsgMSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4geyBzdGFydEJsb2NrS2V5LCBsaW5lc0Fib3ZlQXJyYXkgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldFN0YXJ0Q29kZUJsb2NrQWJvdmVMaW5lKGxpbmVzQWJvdmVBcnJheTogc3RyaW5nW10pOiB7IFxuICAgIHN0YXJ0QmxvY2tLZXk6IHN0cmluZywgXG4gICAgbGluZXNBYm92ZUFycmF5OiBzdHJpbmdbXSB9IHwgbnVsbCB7XG4gICAgXG4gICAgbGV0IGxpbmVzQWJvdmVTdHIgPSBsaW5lc0Fib3ZlQXJyYXkucmVkdWNlKChwcmV2LCBjdXJyZW50KSA9PiB7XG4gICAgICAgIHJldHVybiBwcmV2ICsgXCJcXG5cIiAgKyBjdXJyZW50O1xuICAgIH0sIFwiXCIpO1xuXG4gICAgLypcbiAgICAgKiBGaXJzdCB0aGluZyB3ZSBuZWVkIHRvIGRvIGlzIGNoZWNrIGlmIHRoZXJlIGFyZSBhbnkgZW5kIHRhZ3MgaW4gdGhlXG4gICAgICogc2V0IG9mIHN0cmluZ3MgKHdoaWNoIGxvZ2ljYWxseSB3b3VsZCBjbG9zZSBzdGFydCB0YWdzIGFuZCB0aGVyZWZvcmVcbiAgICAgKiB0aGUgc3RhcnQgdGFnIGl0IGNsb3NlcyBpcyBub3Qgd2hhdCB3ZSB3YW50KS4gSWYgdGhlcmUgYXJlIHdlIHdhbnQgdG8gXG4gICAgICogc2xvd2x5IG5hcnJvdyBkb3duIG91ciBzZXQgb2Ygc3RyaW5ncyB1bnRpbCB0aGUgbGFzdCBlbmQgdGFnIGlzIFxuICAgICAqIHJlbW92ZWQuIFRoaXMgbWFrZXMgaXQgZWFzaWVyIHRvIGZpbmQgdGhlIGNsb3Nlc3Qgb3BlbiBzdGFydCB0YWcgXG4gICAgICogaW4gdGhlIGRhdGEuXG4gICAgICovXG4gICAgbGV0IGVuZFRhZ1NlcmFjaERhdGEgPSBmaW5kRW5kVGFnKGxpbmVzQWJvdmVTdHIpO1xuICAgIHdoaWxlKGVuZFRhZ1NlcmFjaERhdGEuZm91bmQgPT09IHRydWUpIHtcblxuICAgICAgICAvLyBHZXQgdGhlIGluZGV4IG9mIHdoZXJlIHRoZSBmaXJzdCByZWdleCBtYXRjaCBpbiB0aGVcbiAgICAgICAgLy8gc3RyaW5nIGlzLiB0aGVuIHdlIHNsaWNlIGZyb20gMCB0byBpbmRleCBvZmYgb2YgdGhlIHN0cmluZ1xuICAgICAgICAvLyBzcGxpdCBpdCBieSBuZXdsaW5lLCBjdXQgb2ZmIHRoZSBmaXJzdCBsaW5lICh3aGljaCBhY3R1YWxseVxuICAgICAgICAvLyBjb250YWlucyB0aGUgcmVnZXgpIHRoZW4gcmVkdWNlIGJhY2sgZG93biB0byBhIHNpbmdsZSBzdHJpbmcuXG4gICAgICAgIGxpbmVzQWJvdmVTdHIgPSBsaW5lc0Fib3ZlU3RyLnNsaWNlKGVuZFRhZ1NlcmFjaERhdGEuZW5kUG9zaXRpb24pO1xuICAgICAgICBlbmRUYWdTZXJhY2hEYXRhID0gZmluZEVuZFRhZyhsaW5lc0Fib3ZlU3RyKTtcbiAgICB9XG5cbiAgICBsZXQgc3RhcnRDb2RlQmxvY2tEYXRhID0gZmluZFN0YXJ0Q29kZWJsb2NrKGxpbmVzQWJvdmVTdHIpO1xuICAgIGxldCBjb2RlQmxvY2tUZXh0ID0gbGluZXNBYm92ZVN0ci5zbGljZShzdGFydENvZGVCbG9ja0RhdGEuc3RhcnRQb3NpdGlvbiwgc3RhcnRDb2RlQmxvY2tEYXRhLmVuZFBvc2l0aW9uKVxuXG4gICAgbGV0IHN0YXJ0QmxvY2tLZXkgPSBcIlwiICAgIFxuICAgIGlmKHN0YXJ0Q29kZUJsb2NrRGF0YS5mb3VuZCA9PT0gZmFsc2UpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIGVsc2Uge1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBOb3cgd2Uga25vdyB0aGVyZSBpcyBhdCBsZWFzdCAxIHN0YXJ0IGtleSBsZWZ0LCBob3dldmVyIHRoZXJlXG4gICAgICAgICAqIG1heSBiZSBtdWx0aXBsZSBzdGFydCBrZXlzIGlmIHRoZSB1c2VyIGlzIG5vdCBjbG9zaW5nIHRoZWlyXG4gICAgICAgICAqIGJsb2Nrcy4gV2UgY3VycmVudGx5IGRvbnQgYWxsb3cgcmVjdXNpdmUgc3BsaXR0aW5nIHNvIHdlIFxuICAgICAgICAgKiB3YW50IHRvIGdldCB0aGUgbGFzdCBrZXkgaW4gb3VyIHJlbWFpbmluZyBzZXQuIFNhbWUgaWRlYSBhc1xuICAgICAgICAgKiBhYm92ZS5cbiAgICAgICAgICovXG4gICAgICAgIHdoaWxlKHN0YXJ0Q29kZUJsb2NrRGF0YS5mb3VuZCA9PT0gdHJ1ZSkge1xuXG4gICAgICAgICAgICAvLyBHZXQgdGhlIGluZGV4IG9mIHdoZXJlIHRoZSBmaXJzdCByZWdleCBtYXRjaCBpbiB0aGVcbiAgICAgICAgICAgIC8vIHN0cmluZyBpcy4gdGhlbiB3ZSBzbGljZSBmcm9tIDAgdG8gaW5kZXggb2ZmIG9mIHRoZSBzdHJpbmdcbiAgICAgICAgICAgIC8vIHNwbGl0IGl0IGJ5IG5ld2xpbmUsIGN1dCBvZmYgdGhlIGZpcnN0IGxpbmUgKHdoaWNoIGFjdHVhbGx5XG4gICAgICAgICAgICAvLyBjb250YWlucyB0aGUgcmVnZXgpIHRoZW4gcmVkdWNlIGJhY2sgZG93biB0byBhIHNpbmdsZSBzdHJpbmcuXG5cbiAgICAgICAgICAgIGNvZGVCbG9ja1RleHQgPSBsaW5lc0Fib3ZlU3RyLnNsaWNlKHN0YXJ0Q29kZUJsb2NrRGF0YS5zdGFydFBvc2l0aW9uLCBzdGFydENvZGVCbG9ja0RhdGEuZW5kUG9zaXRpb24pXG4gICAgICAgICAgICBzdGFydEJsb2NrS2V5ID0gcGFyc2VTdGFydFJlZ2lvbkNvZGVCbG9ja0lEKGNvZGVCbG9ja1RleHQpXG5cbiAgICAgICAgICAgIGxpbmVzQWJvdmVTdHIgPSBsaW5lc0Fib3ZlU3RyLnNsaWNlKHN0YXJ0Q29kZUJsb2NrRGF0YS5lbmRQb3NpdGlvbik7XG4gICAgICAgICAgICBzdGFydENvZGVCbG9ja0RhdGEgPSBmaW5kU3RhcnRDb2RlYmxvY2sobGluZXNBYm92ZVN0cik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBsZXQgcmV0TGluZXNBYm92ZUFycmF5ID0gbGluZXNBYm92ZVN0ci5zcGxpdChcIlxcblwiKTtcbiAgICByZXR1cm4geyBzdGFydEJsb2NrS2V5LCBsaW5lc0Fib3ZlQXJyYXk6IHJldExpbmVzQWJvdmVBcnJheSB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0RW5kQmxvY2tCZWxvdyhsaW5lc0JlbG93OiBzdHJpbmdbXSk6IHN0cmluZ1tdIHtcblxuICAgIC8vIFJlZHVjZSB0aGUgYXJyYXkgZG93biBpbnRvIGEgc2luZ2xlIHN0cmluZyBzbyB0aGF0IHdlIGNhblxuICAgIC8vIGVhc2lseSBSZWdFeCBvdmVyIHRoZSBzdHJpbmcgYW5kIGZpbmQgdGhlIGluZGljaWVzIHdlJ3JlIGxvb2tpbmcgZm9yLlxuICAgIGxldCBsaW5lc0JlbG93U3RyID0gbGluZXNCZWxvdy5yZWR1Y2UoKHByZXYsIGN1cnJlbnQpID0+IHtcbiAgICAgICAgcmV0dXJuIHByZXYgKyBcIlxcblwiICArIGN1cnJlbnQ7XG4gICAgfSwgXCJcIik7XG4gICAgbGV0IGVuZFRhZ1NlcmFjaERhdGEgPSBmaW5kRW5kVGFnKGxpbmVzQmVsb3dTdHIpO1xuICAgIGxldCBzdGFydFRhZ1NlYXJjaERhdGEgPSBmaW5kU3RhcnRUYWcobGluZXNCZWxvd1N0cik7XG5cbiAgICBsZXQgc2xpY2VFbmRJbmRleCA9IC0xOyAvLyBJZiBuZWl0aGVyIHN0YXJ0IG9yIGVuZCBmb3VuZCB3ZSByZXR1cm4gdGhlIGVudGlyZSBhcnJheS5cbiAgICBpZihlbmRUYWdTZXJhY2hEYXRhLmZvdW5kID09PSB0cnVlICYmIHN0YXJ0VGFnU2VhcmNoRGF0YS5mb3VuZCA9PT0gZmFsc2UpIHtcblxuICAgICAgICBzbGljZUVuZEluZGV4ID0gZW5kVGFnU2VyYWNoRGF0YS5zdGFydFBvc2l0aW9uO1xuICAgIH1cbiAgICBlbHNlIGlmKGVuZFRhZ1NlcmFjaERhdGEuZm91bmQgPT09IGZhbHNlICYmIHN0YXJ0VGFnU2VhcmNoRGF0YS5mb3VuZCA9PT0gdHJ1ZSkge1xuXG4gICAgICAgIHNsaWNlRW5kSW5kZXggPSBzdGFydFRhZ1NlYXJjaERhdGEuc3RhcnRQb3NpdGlvbjtcbiAgICB9XG4gICAgZWxzZSBpZihlbmRUYWdTZXJhY2hEYXRhLmZvdW5kID09PSB0cnVlICYmIHN0YXJ0VGFnU2VhcmNoRGF0YS5mb3VuZCA9PT0gdHJ1ZSkge1xuXG4gICAgICAgIHNsaWNlRW5kSW5kZXggPSBlbmRUYWdTZXJhY2hEYXRhLnN0YXJ0UG9zaXRpb247XG4gICAgICAgIGlmKHN0YXJ0VGFnU2VhcmNoRGF0YS5zdGFydFBvc2l0aW9uIDwgZW5kVGFnU2VyYWNoRGF0YS5zdGFydFBvc2l0aW9uKSB7XG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogSWYgd2UgZm91bmQgYSBzdGFydCB0YWcgYmVmb3JlIGFuIGVuZCB0YWcgd2Ugd2FudCB0byB1c2UgdGhlIHN0YXJ0IHRhZ1xuICAgICAgICAgICAgICogb3VyIGN1cnJlbnQgYmxvY2sgaXMgbm90IHByb3Blcmx5IGVuZGVkIGFuZCB3ZSB1c2UgdGhlIG5leHQgc3RhcnQgdGFnIFxuICAgICAgICAgICAgICogYXMgb3VyIGxpbWl0XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIHNsaWNlRW5kSW5kZXggPSBzdGFydFRhZ1NlYXJjaERhdGEuc3RhcnRQb3NpdGlvbjtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBsaW5lc0JlbG93LnNsaWNlKDAsIHNsaWNlRW5kSW5kZXgpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0U3RhcnRUYWdLZXkoc3RhcnRUYWc6IHN0cmluZyk6IHN0cmluZyB8IG51bGwge1xuXG4gICAgbGV0IGtleVNwbGl0ID0gc3RhcnRUYWcuc3BsaXQoXCI6XCIpO1xuICAgIGlmKGtleVNwbGl0Lmxlbmd0aCA+IDEpe1xuICAgICAgICByZXR1cm4ga2V5U3BsaXRbMV0ucmVwbGFjZShcIiBcIiwgXCJcIilcbiAgICB9XG5cbiAgICByZXR1cm4gbnVsbDtcbn1cblxuXG5jb25zdCBUQUJfSEVBREVSX0VORF9SRUdFWF9TVFIgPSBcIl5gYGAkXCI7XG5jb25zdCBUQUJfSEVBREVSX0VORF9SRUdFWDogUmVnRXhwID0gbmV3IFJlZ0V4cChUQUJfSEVBREVSX0VORF9SRUdFWF9TVFIpO1xuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlQ29kZUJsb2NrU3RhcnQoY29kZUJsb2NrTGluZXM6IHN0cmluZ1tdKTogeyBpZDogc3RyaW5nLCBpbmRleDogbnVtYmVyfSB8IG51bGwge1xuXG4gICAgbGV0IGlkID0gbnVsbDtcbiAgICBmb3IobGV0IGkgPSAwOyBpIDwgY29kZUJsb2NrTGluZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgbGV0IGxpbmUgPSBjb2RlQmxvY2tMaW5lc1tpXTtcblxuICAgICAgICBpZihpZCA9PT0gbnVsbCkge1xuICAgICAgICAgICAgbGV0IGtleSA9IGxpbmUuc3BsaXQoXCI6XCIpWzBdO1xuICAgICAgICAgICAgaWYoa2V5LnRvTG93ZXJDYXNlKCkgPT09IFwicmVnaW9uIGlkXCIpIHtcbiAgICAgICAgICAgICAgICBpZCA9IGxpbmUuc3BsaXQoXCI6XCIpWzFdLnRyaW0oKVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgaWYoVEFCX0hFQURFUl9FTkRfUkVHRVgudGVzdChsaW5lKSkge1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHsgaWQ6IGlkLCBpbmRleDogaSB9O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYoaWQgPT09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICByZXR1cm4geyBpZDogaWQsIGluZGV4OiAtMSB9XG4gICAgfVxufVxuY29uc3QgQ09ERUJMT0NLX0VORF9SRUdFWF9TVFIgPSBcImBgYFwiO1xuY29uc3QgQ09ERUJMT0NLX0VORF9SRUdFWDogUmVnRXhwID0gbmV3IFJlZ0V4cChDT0RFQkxPQ0tfRU5EX1JFR0VYX1NUUik7XG5leHBvcnQgZnVuY3Rpb24gZmluZEVuZE9mQ29kZUJsb2NrKHRleHQ6IHN0cmluZyk6IHsgZm91bmQ6IGJvb2xlYW4sIHN0YXJ0UG9zaXRpb246IG51bWJlciwgZW5kUG9zaXRpb246IG51bWJlciwgbWF0Y2hMZW5ndGg6IG51bWJlciB9IHtcblxuICAgIGxldCBmb3VuZCA9IGZhbHNlO1xuICAgIGxldCBzdGFydFBvc2l0aW9uID0gLTE7XG4gICAgbGV0IG1hdGNoTGVuZ3RoID0gMDtcbiAgICBsZXQgZW5kUG9zaXRpb24gPSAtMTtcblxuICAgIGxldCByZWdleERhdGEgPSBDT0RFQkxPQ0tfRU5EX1JFR0VYLmV4ZWModGV4dClcbiAgICBpZihyZWdleERhdGEgIT09IG51bGwgJiYgcmVnZXhEYXRhLmxlbmd0aCA+IDApIHtcbiAgICAgICAgZm91bmQgPSB0cnVlO1xuICAgICAgICBzdGFydFBvc2l0aW9uID0gcmVnZXhEYXRhLmluZGV4XG4gICAgICAgIG1hdGNoTGVuZ3RoID0gcmVnZXhEYXRhWzBdLmxlbmd0aFxuICAgIH1cbiAgICBlbmRQb3NpdGlvbiA9IHN0YXJ0UG9zaXRpb24gKyBtYXRjaExlbmd0aDtcblxuICAgIHJldHVybiB7IGZvdW5kLCBzdGFydFBvc2l0aW9uLCBlbmRQb3NpdGlvbiwgbWF0Y2hMZW5ndGggfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlQ29kZUJsb2NrU2V0dGluZ3MoY29kZUJsb2NrTGluZXM6IHN0cmluZ1tdKTogc3RyaW5nIHtcblxuICAgIGxldCBzZXR0aW5nc0xpbmVzID0gW107XG4gICAgZm9yKGxldCBpID0gMDsgaSA8IGNvZGVCbG9ja0xpbmVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGxldCBsaW5lID0gY29kZUJsb2NrTGluZXNbaV07XG5cbiAgICAgICAgbGV0IGtleSA9IGxpbmUuc3BsaXQoXCI6XCIpWzBdO1xuICAgICAgICBpZihrZXkudG9Mb3dlckNhc2UoKSAhPT0gXCJyZWdpb24gaWRcIikge1xuICAgICAgICAgICAgc2V0dGluZ3NMaW5lcy5wdXNoKGxpbmUpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHNldHRpbmdzTGluZXMuam9pbihcIlxcblwiKTtcbn0iLCIvKlxuICogRmlsZW5hbWU6IG11bHRpLWNvbHVtbi1tYXJrZG93bi9zcmMvdXRpbGl0aWVzL3V0aWxzLnRzXG4gKiBDcmVhdGVkIERhdGU6IFR1ZXNkYXksIEphbnVhcnkgMzB0aCAyMDIyLCA0OjAyOjE5IHBtXG4gKiBBdXRob3I6IENhbWVyb24gUm9iaW5zb25cbiAqIFxuICogQ29weXJpZ2h0IChjKSAyMDIyIENhbWVyb24gUm9iaW5zb25cbiAqL1xuXG5pbXBvcnQgeyBXb3Jrc3BhY2VMZWFmIH0gZnJvbSBcIm9ic2lkaWFuXCI7XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRVSUQobGVuZ3RoOiBudW1iZXIgPSAxMCk6IHN0cmluZyB7XG5cbiAgICBpZihsZW5ndGggPiAxMCkge1xuICAgICAgICBsZW5ndGggPSAxMDtcbiAgICB9XG4gICAgbGV0IFVJRCA9IE1hdGgucmFuZG9tKCkudG9TdHJpbmcoMzYpLnN1YnN0cmluZygyKTtcbiAgICBVSUQgPSBVSUQuc2xpY2UoMCwgbGVuZ3RoKTtcbiAgICBcbiAgICByZXR1cm4gVUlEO1xufVxuXG4vKipcbiAqIEJGUyBvbiB0aGUgY2hpbGQgbm9kZXMgb2YgdGhlIHBhc3NlZCBlbGVtZW50IHNlYXJjaGluZyBmb3IgdGhlIGZpcnN0IGluc3RhbmNlIG9mIHRoZVxuICogbm9kZSB0eXBlIHBhc3NlZC4gUmV0dXJuaW5nIHRoZSBlbGVtZW50IGZvdW5kIG9yIG51bGwgaWYgbm9uZSBmb3VuZC5cbiAqIFxuICogQHBhcmFtIHJvb3QgXG4gKiBAcGFyYW0gbm9kZVR5cGVOYW1lXG4gKiBAcmV0dXJucyBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNlYXJjaENoaWxkcmVuRm9yTm9kZVR5cGUocm9vdDogSFRNTEVsZW1lbnQsIG5vZGVUeXBlTmFtZTogc3RyaW5nKTogSFRNTEVsZW1lbnQgfCBudWxsIHtcblxuICAgIG5vZGVUeXBlTmFtZSA9IG5vZGVUeXBlTmFtZS50b0xvd2VyQ2FzZSgpO1xuICAgIFxuICAgIGxldCBxdWV1ZTogSFRNTEVsZW1lbnRbXSA9IFtyb290XVxuICAgIHdoaWxlKHF1ZXVlLmxlbmd0aCA+IDApe1xuICAgICAgICBcbiAgICAgICAgZm9yKGxldCBpID0gMDsgaSA8IHF1ZXVlLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGxldCBub2RlID0gcXVldWUuc2hpZnQoKVxuXG4gICAgICAgICAgICBsZXQgbm9kZU5hbWUgPSBub2RlLm5vZGVOYW1lLnRvTG93ZXJDYXNlKClcbiAgICAgICAgICAgIGlmKG5vZGVOYW1lID09PSBub2RlVHlwZU5hbWUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbm9kZSBhcyBIVE1MRWxlbWVudDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZm9yKGxldCBpID0gMDsgaSA8IG5vZGUuY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBxdWV1ZS5wdXNoKG5vZGUuY2hpbGRyZW5baV0gYXMgSFRNTEVsZW1lbnQpXG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gbnVsbDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldEZpbGVTb3VyY2VNb2RlKHNvdXJjZVBhdGg6IHN0cmluZyk6IHN0cmluZyB7XG5cbiAgICBsZXQgZmlsZUxlYWYgPSBnZXRGaWxlTGVhZihzb3VyY2VQYXRoKTtcbiAgICBpZihmaWxlTGVhZiA9PT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gXCJcIjtcbiAgICB9XG4gICAgcmV0dXJuIGZpbGVMZWFmLmdldFZpZXdTdGF0ZSgpLnN0YXRlLm1vZGU7XG59XG5leHBvcnQgZnVuY3Rpb24gZ2V0TGVhZlNvdXJjZU1vZGUoZmlsZUxlYWY6IFdvcmtzcGFjZUxlYWYpOiBzdHJpbmcge1xuXG4gICAgcmV0dXJuIGZpbGVMZWFmLmdldFZpZXdTdGF0ZSgpLnN0YXRlLm1vZGU7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBmaWxlU3RpbGxJblZpZXcoc291cmNlUGF0aDogc3RyaW5nKTpib29sZWFuIHtcblxuICAgIGxldCBmaWxlTGVhZiA9IGdldEZpbGVMZWFmKHNvdXJjZVBhdGgpO1xuICAgIGlmKGZpbGVMZWFmID09PSBudWxsKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRGaWxlTGVhZihzb3VyY2VQYXRoOiBzdHJpbmcpOiBXb3Jrc3BhY2VMZWFmIHwgbnVsbCB7XG5cbiAgICBsZXQgbWFya2Rvd25MZWF2ZXMgPSBhcHAud29ya3NwYWNlLmdldExlYXZlc09mVHlwZShcIm1hcmtkb3duXCIpO1xuICAgIGlmKG1hcmtkb3duTGVhdmVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICBmb3IobGV0IGkgPSAwOyBpIDwgbWFya2Rvd25MZWF2ZXMubGVuZ3RoOyBpKyspIHtcblxuICAgICAgICBpZihtYXJrZG93bkxlYXZlc1tpXS5nZXRWaWV3U3RhdGUoKS5zdGF0ZS5maWxlID09PSBzb3VyY2VQYXRoKSB7XG4gICAgICAgICAgICByZXR1cm4gbWFya2Rvd25MZWF2ZXNbaV07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gbnVsbDtcbn0iLCJpbXBvcnQgeyBzZWFyY2hDaGlsZHJlbkZvck5vZGVUeXBlIH0gZnJvbSBcIi4vdXRpbHNcIjtcblxuZXhwb3J0IGVudW0gRWxlbWVudFJlbmRlclR5cGUge1xuICAgIHVuZGVmaW5lZCxcbiAgICBub3JtYWxSZW5kZXIsXG4gICAgc3BlY2lhbFJlbmRlcixcbiAgICBzcGVjaWFsU2luZ2xlRWxlbWVudFJlbmRlcixcbiAgICBjYW52YXNSZW5kZXJFbGVtZW50LFxuICAgIHVuUmVuZGVyZWRcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldEVsZW1lbnRSZW5kZXJUeXBlKGVsZW1lbnQ6IEhUTUxFbGVtZW50KTogRWxlbWVudFJlbmRlclR5cGUge1xuXG4gICAgLyoqXG4gICAgICogVGhlIERhdGF2aWV3IHBsdWdpbiBuZWVkcyB0byBiZSBjb25zdGFudGx5IGNoZWNrZWQgaWYgdGhlIGNsb25lIHNob3VsZCBiZVxuICAgICAqIHVwZGF0ZWQgYnV0IHNob3VsZCBub3QgYWx3YXlzIHVwZGF0ZSB0aGUgXCJkdWFsIHJlbmRlclwiIGFzcGVjdCwgc28gd2UgYWRkXG4gICAgICogYSBzcGVjaWFsIGNhc2UgZm9yIHRoYXQgcGx1Z2luIGFuZCBtYXliZSBvdGhlcnMgaW4gdGhlIGZ1dHVyZS5cbiAgICAgKi9cbiAgICBpZihoYXNEYXRhdmlldyhlbGVtZW50KSA9PT0gdHJ1ZSkge1xuICAgICAgICByZXR1cm4gRWxlbWVudFJlbmRlclR5cGUuc3BlY2lhbFNpbmdsZUVsZW1lbnRSZW5kZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU29tZSB0eXBlcyBvZiBjb250ZW50IGFyZSByZW5kZXJlZCBpbiBjYW52YXNlcyB3aGljaCBhcmUgbm90IHJlbmRlcmVkIHByb3Blcmx5XG4gICAgICogd2hlbiB3ZSBjbG9uZSB0aGUgb3JpZ2luYWwgbm9kZS4gSGVyZSB3ZSBhcmUgZmxhZ2dpbmcgdGhlIGVsZW1lbnQgYXMgYSBjYW52YXNcbiAgICAgKiBlbGVtZW50IHNvIHdlIGNhbiBjbG9uZSB0aGUgY2FudmFzIHRvIGEgY29weSBlbGVtZW50IHdpdGhpbiB0aGUgcmVnaW9uLlxuICAgICAqIFxuICAgICAqL1xuICAgIGlmKCBoYXNEYXRhdmlld0pTKGVsZW1lbnQpID09PSB0cnVlKSB7XG4gICAgICAgIHJldHVybiBFbGVtZW50UmVuZGVyVHlwZS5jYW52YXNSZW5kZXJFbGVtZW50O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIExvb2sgZm9yIHNwZWNpZmljIGtpbmRzIG9mIGVsZW1lbnRzIGJ5IHRoZWlyIENTUyBjbGFzcyBuYW1lcyBoZXJlLiBUaGVzZSBcbiAgICAgKiBhcmUgZ29pbmcgdG8gYmUgYnJpdHRsZSBsaW5rcyBhcyB0aGV5IHJlbHkgb24gb3RoZXIgcGx1Z2luIGRlZmluaXRpb25zIGJ1dFxuICAgICAqIGFzIHRoaXMgaXMgb25seSBhZGRpbmcgaW4gZXh0cmEgY29tcGF0YWJpbGl0eSB0byB0aGUgcGx1Z2lucyBkZWZpbmVkIGhlcmUgXG4gICAgICogaXQgc2hvdWxkIGJlIG9rLlxuICAgICAqIFxuICAgICAqIFRoZXNlIG1heSBiZSBjbGFzc2VzIG9uIG9uZSBvZiB0aGUgc2ltcGxlIGVsZW1lbnRzIChzdWNoIGFzIGEgcGFyYWdyYXBoKVxuICAgICAqIHRoYXQgd2Ugc2VhcmNoIGZvciBiZWxvdyBzbyBuZWVkIHRvIGxvb2sgZm9yIHRoZXNlIGZpcnN0LlxuICAgICAqL1xuICAgIGlmKGhhc0RpY2VSb2xsZXIoZWxlbWVudCkgPT09IHRydWUgfHxcbiAgICAgICBoYXNDb3B5QnV0dG9uKGVsZW1lbnQpID09PSB0cnVlIHx8XG4gICAgICAgaGFzQWRtb25pdGlvbkZvbGQoZWxlbWVudCkgPT09IHRydWUpIHtcblxuICAgICAgICByZXR1cm4gRWxlbWVudFJlbmRlclR5cGUuc3BlY2lhbFJlbmRlclxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoaXMgY2hlY2tzIGZvciBzcGVjaWFsIHR5cGVzIG9mIGVsZW1lbnRzIHRoYXQgc2hvdWxkIGJlIHJlbmRlcmVkIG5vcm1hbGx5LiBJc1xuICAgICAqIHNsaWdodGx5IHJlZHVuZGFudCB3aXRoIG5leHQgY2hlY2sgYnV0IGRpZmZlcmVudGlhdGVzIGJldHdlZW4gdHlwZXMgb2YgZW1lbnRzIFxuICAgICAqIGJlaW5nIGNoZWNrZWQuXG4gICAgICovXG4gICAgaWYoaGFzQWRtb25pdGlvbihlbGVtZW50KSA9PT0gdHJ1ZSB8fFxuICAgICAgIGlzSUZyYW1lKGVsZW1lbnQpID09PSB0cnVlKSB7XG4gICAgICAgIFxuICAgICAgICByZXR1cm4gRWxlbWVudFJlbmRlclR5cGUubm9ybWFsUmVuZGVyXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSWYgd2UgZGlkbnQgZmluZCBhIHNwZWNpYWwgZWxlbWVudCB3ZSB3YW50IHRvIGNoZWNrIGZvciBzaW1wbGUgZWxlbWVudHNcbiAgICAgKiBzdWNoIGFzIHBhcmFncmFwaHMgb3IgbGlzdHMuIEluIHRoZSBjdXJyZW50IGltcGxlbWVudGF0aW9uIHdlIG9ubHkgc2V0IHVwXG4gICAgICogdGhlIHNwZWNpYWwgY2FzZSBmb3IgXCJzcGVjaWFsUmVuZGVyXCIgZWxlbWVudHMgc28gdGhpcyAqc2hvdWxkKiBiZSBzYXZpbmdcbiAgICAgKiBzb21lIHJlbmRlcmluZyB0aW1lIGJ5IHNldHRpbmcgdGhlc2UgdGFncyBwcm9wZXJseS5cbiAgICAgKi9cbiAgICBpZihoYXNQYXJhZ3JhcGgoZWxlbWVudCkgfHwgXG4gICAgICAgaGFzSGVhZGVyKGVsZW1lbnQpICAgIHx8XG4gICAgICAgaGFzTGlzdChlbGVtZW50KSB8fFxuICAgICAgIGlzSG9yaXpvbnRhbFJ1bGUoZWxlbWVudCkgfHxcbiAgICAgICBpc1RhYmxlKGVsZW1lbnQpKSB7XG5cbiAgICAgICAgcmV0dXJuIEVsZW1lbnRSZW5kZXJUeXBlLm5vcm1hbFJlbmRlcjtcbiAgICB9XG5cbiAgICAvLyBJZiBzdGlsbCBub3RoaW5nIGZvdW5kIHdlIHJldHVybiBvdGhlciBhcyB0aGUgZGVmYXVsdCByZXNwb25zZSBpZiBub3RoaW5nIGVsc2UgZm91bmQuXG4gICAgcmV0dXJuIEVsZW1lbnRSZW5kZXJUeXBlLnNwZWNpYWxSZW5kZXI7XG59XG5cbmZ1bmN0aW9uIGhhc1BhcmFncmFwaChlbGVtZW50OiBIVE1MRWxlbWVudCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBlbGVtZW50LmlubmVySFRNTC5zdGFydHNXaXRoKFwiPHBcIik7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBoYXNIZWFkZXIoZWxlbWVudDogSFRNTEVsZW1lbnQpOiBib29sZWFuIHtcblxuICAgIGlmKGVsZW1lbnQuaW5uZXJIVE1MLnN0YXJ0c1dpdGgoXCI8aDFcIikgfHwgXG4gICAgICAgZWxlbWVudC5pbm5lckhUTUwuc3RhcnRzV2l0aChcIjxoMlwiKSB8fCBcbiAgICAgICBlbGVtZW50LmlubmVySFRNTC5zdGFydHNXaXRoKFwiPGgzXCIpIHx8IFxuICAgICAgIGVsZW1lbnQuaW5uZXJIVE1MLnN0YXJ0c1dpdGgoXCI8aDRcIikgfHxcbiAgICAgICBlbGVtZW50LmlubmVySFRNTC5zdGFydHNXaXRoKFwiPGg1XCIpIHx8XG4gICAgICAgZWxlbWVudC5pbm5lckhUTUwuc3RhcnRzV2l0aChcIjxoNlwiKSkge1xuXG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gaGFzTGlzdChlbGVtZW50OiBIVE1MRWxlbWVudCk6IGJvb2xlYW4ge1xuICAgIFxuICAgIGlmKGVsZW1lbnQuaW5uZXJIVE1MLnN0YXJ0c1dpdGgoXCI8dWxcIikgfHwgXG4gICAgICAgZWxlbWVudC5pbm5lckhUTUwuc3RhcnRzV2l0aChcIjxvbFwiKSkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGhhc0NvcHlCdXR0b24oZWxlbWVudDogSFRNTEVsZW1lbnQpOiBib29sZWFuIHtcbiAgICByZXR1cm4gZWxlbWVudC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKFwiY29weS1jb2RlLWJ1dHRvblwiKS5sZW5ndGggIT09IDAgfHwgXG4gICAgICAgICAgICBlbGVtZW50LmdldEVsZW1lbnRzQnlDbGFzc05hbWUoXCJhZG1vbml0aW9uLWNvbnRlbnQtY29weVwiKS5sZW5ndGggIT09IDA7XG59XG5cbmZ1bmN0aW9uIGhhc0RpY2VSb2xsZXIoZWxlbWVudDogSFRNTEVsZW1lbnQpOiBib29sZWFuIHtcbiAgICByZXR1cm4gZWxlbWVudC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKFwiZGljZS1yb2xsZXJcIikubGVuZ3RoICE9PSAwO1xufVxuXG5mdW5jdGlvbiBoYXNBZG1vbml0aW9uKGVsZW1lbnQ6IEhUTUxFbGVtZW50KTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIGVsZW1lbnQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZShcImFkbW9uaXRpb25cIikubGVuZ3RoICE9PSAwO1xufVxuXG5mdW5jdGlvbiBpc0lGcmFtZShlbGVtZW50OiBIVE1MRWxlbWVudCk6IGJvb2xlYW4ge1xuXG4gICAgaWYoZWxlbWVudC5jaGlsZHJlbi5sZW5ndGggPiAwKSB7XG5cbiAgICAgICAgcmV0dXJuIGVsZW1lbnQuZmlyc3RDaGlsZC5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpID09PSBcImlmcmFtZVwiO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZVxufVxuXG5mdW5jdGlvbiBpc0hvcml6b250YWxSdWxlKGVsZW1lbnQ6IEhUTUxFbGVtZW50KTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIGVsZW1lbnQuaW5uZXJIVE1MLnN0YXJ0c1dpdGgoXCI8aHJcIilcbn1cblxuZnVuY3Rpb24gaXNUYWJsZShlbGVtZW50OiBIVE1MRWxlbWVudCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBlbGVtZW50LmlubmVySFRNTC5zdGFydHNXaXRoKFwiPHRhYmxlXCIpXG59XG5cbmZ1bmN0aW9uIGhhc0FkbW9uaXRpb25Gb2xkKGVsZW1lbnQ6IEhUTUxFbGVtZW50KSB7XG4gICAgcmV0dXJuIGVsZW1lbnQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZShcImNhbGxvdXQtZm9sZFwiKS5sZW5ndGggIT09IDA7XG59XG5cbmZ1bmN0aW9uIGhhc0RhdGF2aWV3KGVsZW1lbnQ6IEhUTUxFbGVtZW50KSB7XG5cbiAgICBsZXQgaXNEYXRhdmlldyA9IGVsZW1lbnQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZShcImRhdGF2aWV3XCIpLmxlbmd0aCAhPT0gMDtcbiAgICByZXR1cm4gaXNEYXRhdmlldztcbn1cblxuZnVuY3Rpb24gaGFzRGF0YXZpZXdKUyhlbGVtZW50OiBIVE1MRWxlbWVudCkge1xuXG4gICAgbGV0IGlzRGF0YXZpZXdKUyA9IGVsZW1lbnQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZShcImJsb2NrLWxhbmd1YWdlLWRhdGF2aWV3anNcIikubGVuZ3RoICE9PSAwO1xuICAgIGxldCBjYW52YXMgPSBzZWFyY2hDaGlsZHJlbkZvck5vZGVUeXBlKGVsZW1lbnQsIFwiY2FudmFzXCIpO1xuXG4gICAgLyoqXG4gICAgICogVGhpcyBtZWFucyBvbmx5IGRhdGF2aWV3SlMgY2hhcnQgY2FudmFzIGVsZW1lbnRzIHNob3VsZCBiZSByZW5kZXJlZCBwcm9wZXJseS4gT3RoZXIgY2FudmFzZXMgd2lsbCBcbiAgICAgKiBuZWVkIHRoaWVyIG93biBjYXNlIHB1dCBpbiBvciB0aGUgcmVzdHJpY3Rpb24gcmVtb3ZlZCBhZnRlciB0ZXN0aW5nLlxuICAgICAqL1xuICAgIHJldHVybiBjYW52YXMgIT09IG51bGwgJiYgaXNEYXRhdmlld0pTIFxufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0SGVhZGluZ0NvbGxhcHNlRWxlbWVudChlbGVtZW50OiBIVE1MRWxlbWVudCk6IEVsZW1lbnQgfCBudWxsIHtcblxuICAgIGlmKGVsZW1lbnQgPT09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgbGV0IGNoaWxkRWxlbWVudHMgPSBlbGVtZW50LmdldEVsZW1lbnRzQnlDbGFzc05hbWUoXCJoZWFkaW5nLWNvbGxhcHNlLWluZGljYXRvclwiKVxuICAgIGlmKGNoaWxkRWxlbWVudHMubGVuZ3RoID09PSAxKSB7XG4gICAgICAgIHJldHVybiBjaGlsZEVsZW1lbnRzWzBdO1xuICAgIH1cbiAgICBpZihjaGlsZEVsZW1lbnRzLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgY29uc29sZS5kZWJ1ZyhcIkZvdW5kIG11bHRpcGxlIGhlYWRpbmcgY29sbGFwc2UgaW5kaWNhdG9ycyBpbiBlbGVtZW50LlwiKVxuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbn0iLCIvKlxuICogRmlsZW5hbWU6IG11bHRpLWNvbHVtbi1tYXJrZG93bi9zcmMvZG9tT2JqZWN0LnRzXG4gKiBDcmVhdGVkIERhdGU6IFR1ZXNkYXksIEZlYnJ1YXJ5IDFzdCAyMDIyLCAxMjowNDowMCBwbVxuICogQXV0aG9yOiBDYW1lcm9uIFJvYmluc29uXG4gKiBcbiAqIENvcHlyaWdodCAoYykgMjAyMiBDYW1lcm9uIFJvYmluc29uXG4gKi9cblxuaW1wb3J0IHsgZ2V0VUlEIH0gZnJvbSBcIi4uL3V0aWxpdGllcy91dGlsc1wiO1xuaW1wb3J0IHsgRWxlbWVudFJlbmRlclR5cGUgfSBmcm9tIFwiLi4vdXRpbGl0aWVzL2VsZW1lbnRSZW5kZXJUeXBlUGFyc2VyXCI7XG5pbXBvcnQgeyBjb250YWluc0NvbEVuZFRhZywgY29udGFpbnNDb2xTZXR0aW5nc1RhZywgY29udGFpbnNFbmRUYWcsIGNvbnRhaW5zU3RhcnRUYWcsIGVsSW5uZXJUZXh0Q29udGFpbnNDb2xFbmRUYWcgfSBmcm9tIFwic3JjL3V0aWxpdGllcy90ZXh0UGFyc2VyXCI7XG5cbmV4cG9ydCBlbnVtIERPTU9iamVjdFRhZyB7XG4gICAgbm9uZSxcbiAgICBzdGFydFJlZ2lvbixcbiAgICByZWdpb25TZXR0aW5ncyxcbiAgICBjb2x1bW5CcmVhayxcbiAgICBlbmRSZWdpb25cbn1cblxuZXhwb3J0IGNsYXNzIERPTU9iamVjdCB7XG4gICAgbm9kZUtleTogc3RyaW5nO1xuICAgIG9yaWdpbmFsRWxlbWVudDogSFRNTEVsZW1lbnQ7XG4gICAgY2xvbmVkRWxlbWVudDogSFRNTEVsZW1lbnQgPSBudWxsO1xuICAgIFVJRDogc3RyaW5nO1xuICAgIHRhZzogRE9NT2JqZWN0VGFnO1xuICAgIHVzaW5nT3JpZ2luYWxFbGVtZW50OiBib29sZWFuXG4gICAgZWxlbWVudFR5cGU6IEVsZW1lbnRSZW5kZXJUeXBlID0gRWxlbWVudFJlbmRlclR5cGUudW5kZWZpbmVkO1xuICAgIGVsZW1lbnRDb250YWluZXI6IEhUTUxEaXZFbGVtZW50ID0gbnVsbDtcbiAgICBlbGVtZW50UmVuZGVyZWRIZWlnaHQgPSAwO1xuICAgIGxpbmVzT2ZFbGVtZW50OiBzdHJpbmdbXVxuXG4gICAgY29uc3RydWN0b3IoZWxlbWVudDogSFRNTEVsZW1lbnQsXG4gICAgICAgICAgICAgICAgbGluZXNPZkVsZW1lbnQ6IHN0cmluZ1tdLFxuICAgICAgICAgICAgICAgIHJhbmRvbUlEOnN0cmluZyA9IGdldFVJRCgpLCBcbiAgICAgICAgICAgICAgICB0YWc6IERPTU9iamVjdFRhZyA9IERPTU9iamVjdFRhZy5ub25lICkge1xuICAgICAgICB0aGlzLm5vZGVLZXkgPSBlbGVtZW50LmlubmVyVGV4dC50cmltKCk7XG4gICAgICAgIHRoaXMub3JpZ2luYWxFbGVtZW50ID0gZWxlbWVudDtcbiAgICAgICAgdGhpcy5VSUQgPSByYW5kb21JRDtcbiAgICAgICAgdGhpcy50YWcgPSB0YWc7XG4gICAgICAgIHRoaXMudXNpbmdPcmlnaW5hbEVsZW1lbnQgPSBmYWxzZVxuICAgICAgICB0aGlzLmxpbmVzT2ZFbGVtZW50ID0gbGluZXNPZkVsZW1lbnQ7XG5cbiAgICAgICAgaWYodGhpcy50YWcgPT09IERPTU9iamVjdFRhZy5ub25lKSB7XG4gICAgICAgICAgICB0aGlzLnNldERvbU9iamVjdFRhZygpXG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBzZXRNYWluRE9NRWxlbWVudChkb21FbGVtZW50OiBIVE1MRWxlbWVudCkge1xuICAgICAgICB0aGlzLm9yaWdpbmFsRWxlbWVudCA9IGRvbUVsZW1lbnQ7XG4gICAgICAgIHRoaXMudXNpbmdPcmlnaW5hbEVsZW1lbnQgPSB0cnVlXG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzZXREb21PYmplY3RUYWcoKSB7XG5cbiAgICAgICAgbGV0IGVsZW1lbnRUZXh0U3BhY2VkID0gdGhpcy5saW5lc09mRWxlbWVudC5yZWR1Y2UoKHByZXYsIGN1cnIpID0+IHtcbiAgICAgICAgICAgIHJldHVybiBwcmV2ICsgXCJcXG5cIiArIGN1cnI7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmKGNvbnRhaW5zRW5kVGFnKHRoaXMub3JpZ2luYWxFbGVtZW50LnRleHRDb250ZW50KSA9PT0gdHJ1ZSkge1xuXG4gICAgICAgICAgICB0aGlzLmVsZW1lbnRUeXBlID0gRWxlbWVudFJlbmRlclR5cGUudW5SZW5kZXJlZDtcbiAgICAgICAgICAgIHRoaXMudGFnID0gRE9NT2JqZWN0VGFnLmVuZFJlZ2lvbjtcbiAgICAgICAgICAgIC8vIGVsLmFkZENsYXNzKE11bHRpQ29sdW1uU3R5bGVDU1MuUmVnaW9uRW5kVGFnKVxuICAgICAgICAgICAgLy8gcmVnaW9uYWxNYW5hZ2VyLnVwZGF0ZUVsZW1lbnRUYWcoY3VycmVudE9iamVjdC5VSUQsIERPTU9iamVjdFRhZy5lbmRSZWdpb24pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYoY29udGFpbnNDb2xFbmRUYWcodGhpcy5vcmlnaW5hbEVsZW1lbnQudGV4dENvbnRlbnQpID09PSB0cnVlIHx8IFxuICAgICAgICAodGhpcy5vcmlnaW5hbEVsZW1lbnQuaW5uZXJIVE1MLnN0YXJ0c1dpdGgoXCI8bWFyaz5cIikpICYmIGVsSW5uZXJUZXh0Q29udGFpbnNDb2xFbmRUYWcodGhpcy5vcmlnaW5hbEVsZW1lbnQudGV4dENvbnRlbnQpKSB7XG5cbiAgICAgICAgICAgIHRoaXMuZWxlbWVudFR5cGUgPSBFbGVtZW50UmVuZGVyVHlwZS51blJlbmRlcmVkXG4gICAgICAgICAgICB0aGlzLnRhZyA9IERPTU9iamVjdFRhZy5jb2x1bW5CcmVhaztcbiAgICAgICAgICAgIC8vIGVsLmFkZENsYXNzKE11bHRpQ29sdW1uU3R5bGVDU1MuQ29sdW1uRW5kVGFnKVxuICAgICAgICAgICAgLy8gcmVnaW9uYWxNYW5hZ2VyLnVwZGF0ZUVsZW1lbnRUYWcoY3VycmVudE9iamVjdC5VSUQsIERPTU9iamVjdFRhZy5jb2x1bW5CcmVhayk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZihjb250YWluc1N0YXJ0VGFnKHRoaXMub3JpZ2luYWxFbGVtZW50LnRleHRDb250ZW50KSA9PT0gdHJ1ZSkge1xuXG4gICAgICAgICAgICB0aGlzLmVsZW1lbnRUeXBlID0gRWxlbWVudFJlbmRlclR5cGUudW5SZW5kZXJlZFxuICAgICAgICAgICAgdGhpcy50YWcgPSBET01PYmplY3RUYWcuc3RhcnRSZWdpb247XG4gICAgICAgICAgICAvLyBlbC5hZGRDbGFzcyhNdWx0aUNvbHVtblN0eWxlQ1NTLkNvbHVtbkVuZFRhZylcbiAgICAgICAgICAgIC8vIHJlZ2lvbmFsTWFuYWdlci51cGRhdGVFbGVtZW50VGFnKGN1cnJlbnRPYmplY3QuVUlELCBET01PYmplY3RUYWcuY29sdW1uQnJlYWspO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYoY29udGFpbnNDb2xTZXR0aW5nc1RhZyhlbGVtZW50VGV4dFNwYWNlZCkgPT09IHRydWUpIHtcblxuICAgICAgICAgICAgdGhpcy5lbGVtZW50VHlwZSA9IEVsZW1lbnRSZW5kZXJUeXBlLnVuUmVuZGVyZWRcbiAgICAgICAgICAgIC8vIGVsLmFkZENsYXNzKE11bHRpQ29sdW1uU3R5bGVDU1MuUmVnaW9uU2V0dGluZ3MpXG4gICAgICAgICAgICAvLyByZWdpb25hbE1hbmFnZXIgPSByZWdpb25hbENvbnRhaW5lci5zZXRSZWdpb25TZXR0aW5ncyhlbGVtZW50VGV4dFNwYWNlZClcbiAgICAgICAgICAgIC8vIHJlZ2lvbmFsTWFuYWdlci51cGRhdGVFbGVtZW50VGFnKGN1cnJlbnRPYmplY3QuVUlELCBET01PYmplY3RUYWcucmVnaW9uU2V0dGluZ3MpO1xuICAgICAgICB9XG4gICAgfVxufVxuXG5leHBvcnQgY2xhc3MgRE9NU3RhcnRSZWdpb25PYmplY3QgZXh0ZW5kcyBET01PYmplY3Qge1xuXG4gICAgcmVnaW9uRWxlbWVudDogSFRNTEVsZW1lbnQ7XG5cbiAgICBjb25zdHJ1Y3RvcihiYXNlRE9NT2JqZWN0OiBET01PYmplY3QsIHJlZ2lvbkVsZW1lbnQ6IEhUTUxFbGVtZW50KSB7XG5cbiAgICAgICAgc3VwZXIoYmFzZURPTU9iamVjdC5vcmlnaW5hbEVsZW1lbnQsIGJhc2VET01PYmplY3QubGluZXNPZkVsZW1lbnQsIGJhc2VET01PYmplY3QuVUlELCBET01PYmplY3RUYWcuc3RhcnRSZWdpb24pO1xuICAgICAgICB0aGlzLnJlZ2lvbkVsZW1lbnQgPSByZWdpb25FbGVtZW50O1xuICAgIH1cbn1cblxuZXhwb3J0IGNsYXNzIFRhc2tMaXN0RE9NT2JqZWN0IGV4dGVuZHMgRE9NT2JqZWN0IHtcblxuICAgIG9yaWdpbmFsQ2hlY2tib3hlczogSFRNTEVsZW1lbnRbXSA9IFtdO1xuXG4gICAgY29uc3RydWN0b3IoYmFzZURPTU9iamVjdDogRE9NT2JqZWN0KSB7XG5cbiAgICAgICAgc3VwZXIoYmFzZURPTU9iamVjdC5vcmlnaW5hbEVsZW1lbnQsIGJhc2VET01PYmplY3QubGluZXNPZkVsZW1lbnQsIGJhc2VET01PYmplY3QuVUlELCBET01PYmplY3RUYWcubm9uZSk7XG4gICAgfVxuXG4gICAgY2hlY2tib3hDbGlja2VkKGluZGV4OiBudW1iZXIpIHtcblxuICAgICAgICBpZihpbmRleCA8IHRoaXMub3JpZ2luYWxDaGVja2JveGVzLmxlbmd0aCkge1xuXG4gICAgICAgICAgICBsZXQgb3JpZ2luYWxJbnB1dCA9IHRoaXMub3JpZ2luYWxDaGVja2JveGVzW2luZGV4XS5maXJzdENoaWxkIGFzIEhUTUxJbnB1dEVsZW1lbnQ7XG4gICAgICAgICAgICBvcmlnaW5hbElucHV0LmNsaWNrKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBzdGF0aWMgY2hlY2tGb3JUYXNrTGlzdEVsZW1lbnQoZG9tRWxlbWVudDogRE9NT2JqZWN0KSB7XG5cbiAgICAgICAgaWYoZG9tRWxlbWVudC5vcmlnaW5hbEVsZW1lbnQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZShcInRhc2stbGlzdC1pdGVtXCIpLmxlbmd0aCA+IDAgKSB7XG5cbiAgICAgICAgICAgIHJldHVybiBuZXcgVGFza0xpc3RET01PYmplY3QoZG9tRWxlbWVudCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZG9tRWxlbWVudDtcbiAgICB9XG59IiwiLypcbiAqIEZpbGU6IG11bHRpLWNvbHVtbi1tYXJrZG93bi9zcmMvdXRpbGl0aWVzL2Nzc0RlZmluaXRpb25zLnRzXG4gKiBDcmVhdGVkIERhdGU6IFdlZG5lc2RheSwgRmVicnVhcnkgMTZ0aCAyMDIyLCAxMTowOTowNiBhbVxuICogQXV0aG9yOiBDYW1lcm9uIFJvYmluc29uXG4gKiBcbiAqIENvcHlyaWdodCAoYykgMjAyMiBDYW1lcm9uIFJvYmluc29uXG4gKi9cblxuZXhwb3J0IGVudW0gTXVsdGlDb2x1bW5MYXlvdXRDU1Mge1xuXG4gICAgUmVnaW9uUm9vdENvbnRhaW5lckRpdiA9IFwibWNtLWNvbHVtbi1yb290LWNvbnRhaW5lclwiLFxuICAgIFJlZ2lvbkVycm9yQ29udGFpbmVyRGl2ID0gXCJtY20tY29sdW1uLWVycm9yLXJlZ2lvbi13cmFwcGVyXCIsXG4gICAgUmVnaW9uQ29udGVudENvbnRhaW5lckRpdiA9IFwibWNtLWNvbHVtbi1yZWdpb24td3JhcHBlclwiLFxuICAgIFJlZ2lvbkNvbHVtbkNvbnRhaW5lckRpdiA9IFwibWNtLWNvbHVtbi1wYXJlbnQtY29udGFpbmVyXCIsXG4gICAgQ29sdW1uRHVhbEVsZW1lbnRDb250YWluZXIgPSBcIm1jbS1jb2x1bW4tZWxlbWVudC13cmFwcGVyXCIsXG4gICAgT3JpZ2luYWxFbGVtZW50VHlwZSA9IFwibWNtLW9yaWdpbmFsLWNvbHVtbi1lbGVtZW50XCIsXG4gICAgQ2xvbmVkRWxlbWVudFR5cGUgPSBcIm1jbS1jbG9uZWQtY29sdW1uLWVsZW1lbnRcIixcblxuICAgIENvbnRlbnRPdmVyZmxvd0F1dG9TY3JvbGwgPSBcIm1jbS1jb250ZW50LW92ZXJmbG93LWF1dG8tc2Nyb2xsXCIsXG4gICAgQ29udGVudE92ZXJmbG93SGlkZGVuID0gXCJtY20tY29udGVudC1vdmVyZmxvdy1oaWRkZW5cIixcblxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAvL1xuXG4gICAgU2luZ2xlQ29sdW1uU21hbGwgPSBcIm1jbS1zaW5nbGUtY29sdW1uLXNtYWxsXCIsXG4gICAgU2luZ2xlQ29sdW1uTWVkID0gXCJtY20tc2luZ2xlLWNvbHVtbi1tZWRpdW1cIixcbiAgICBTaW5nbGVDb2x1bW5MYXJnZSA9IFwibWNtLXNpbmdsZS1jb2x1bW4tbGFyZ2VcIixcblxuICAgIFNpbmdsZUNvbHVtbkxlZnRMYXlvdXQgPSBcIm1jbS1zaW5nbGVjb2wtbGF5b3V0LWxlZnRcIixcbiAgICBTaW5nbGVDb2x1bW5DZW50ZXJMYXlvdXQgPSBcIm1jbS1zaW5nbGVjb2wtbGF5b3V0LWNlbnRlclwiLFxuICAgIFNpbmdsZUNvbHVtblJpZ2h0TGF5b3V0ID0gXCJtY20tc2luZ2xlY29sLWxheW91dC1yaWdodFwiLFxuXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIC8vXG5cbiAgICBUd29FcXVhbENvbHVtbnMgPSBcIm1jbS10d28tZXF1YWwtY29sdW1uc1wiLFxuXG4gICAgVHdvQ29sdW1uU21hbGwgPSBcIm1jbS10d28tY29sdW1uLXNtYWxsXCIsXG4gICAgVHdvQ29sdW1uTGFyZ2UgPSBcIm1jbS10d28tY29sdW1uLWxhcmdlXCIsXG5cbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gLy9cblxuICAgIFRocmVlRXF1YWxDb2x1bW5zID0gXCJtY20tdGhyZWUtZXF1YWwtY29sdW1uc1wiLFxuXG4gICAgVGhyZWVDb2x1bW5fTGFyZ2UgPSBcIm1jbS10aHJlZS1jb2x1bW4tbGFyZ2VcIixcbiAgICBUaHJlZUNvbHVtbl9TbWFsbCA9IFwibWNtLXRocmVlLWNvbHVtbi1zbWFsbFwiLFxufVxuXG5leHBvcnQgZW51bSBNdWx0aUNvbHVtblN0eWxlQ1NTIHtcblxuICAgIFJlZ2lvbkVycm9yTWVzc2FnZSA9IFwibWNtLWNvbHVtbi1lcnJvci1tZXNzYWdlXCIsXG4gICAgUmVnaW9uU2V0dGluZ3MgPSBcIm1jbS1jb2x1bW4tc2V0dGluZ3Mtd3JhcHBlclwiLFxuICAgIFJlZ2lvbkNvbnRlbnQgPSBcIm1jbS1jb2x1bW4tY29udGVudC13cmFwcGVyXCIsXG4gICAgUmVnaW9uRW5kVGFnID0gXCJtY20tY29sdW1uLWVuZC10YWctd3JhcHBlclwiLFxuICAgIENvbHVtbkVuZFRhZyA9IFwibWNtLWNvbHVtbi1icmVhay10YWctd3JhcHBlclwiLFxuICAgIFJlZ2lvblNoYWRvdyA9IFwibWNtLXJlZ2lvbi1zaGFkb3dcIixcbiAgICBDb2x1bW5TaGFkb3cgPSBcIm1jbS1jb2x1bW4tc2hhZG93XCIsXG4gICAgQ29sdW1uQm9yZGVyID0gXCJtY20tY29sdW1uLWJvcmRlclwiLFxuICAgIENvbHVtbkNvbnRlbnQgPSBcIm1jbS1jb2x1bW4tZGl2XCJcbn0iLCIvKipcbiAqIEZpbGU6IC9zcmMvZG9tX21hbmFnZXIvcmVnaW9uYWxfbWFuYWdlcnMvUmVnaW9uTWFuYWdlci50cyAgICAgICAgICAgICAgICAgICAqXG4gKiBDcmVhdGVkIERhdGU6IFN1bmRheSwgTWF5IDIybmQgMjAyMiwgNzo0OSBwbSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICogQXV0aG9yOiBDYW1lcm9uIFJvYmluc29uICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpcbiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMjIgQ2FtZXJvbiBSb2JpbnNvbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICovXG5cbmltcG9ydCB7IERPTU9iamVjdCwgRE9NT2JqZWN0VGFnLCBUYXNrTGlzdERPTU9iamVjdCB9IGZyb20gJy4uL2RvbU9iamVjdCc7XG5pbXBvcnQgeyBNdWx0aUNvbHVtblNldHRpbmdzLCBDb2x1bW5MYXlvdXQsIGdldERlZmF1bHRNdWx0aUNvbHVtblNldHRpbmdzIH0gZnJvbSBcIi4uLy4uL3JlZ2lvblNldHRpbmdzXCI7XG5pbXBvcnQgeyBNdWx0aUNvbHVtbkxheW91dENTUywgTXVsdGlDb2x1bW5TdHlsZUNTUyB9IGZyb20gJy4uLy4uL3V0aWxpdGllcy9jc3NEZWZpbml0aW9ucyc7XG5pbXBvcnQgeyBGaWxlRE9NTWFuYWdlciB9IGZyb20gJy4uL2RvbU1hbmFnZXInO1xuaW1wb3J0IHsgRWxlbWVudFJlbmRlclR5cGUsIGdldEVsZW1lbnRSZW5kZXJUeXBlIH0gZnJvbSAnc3JjL3V0aWxpdGllcy9lbGVtZW50UmVuZGVyVHlwZVBhcnNlcic7XG5pbXBvcnQgeyBSZWdpb25NYW5hZ2VyRGF0YSB9IGZyb20gJy4vcmVnaW9uTWFuYWdlckNvbnRhaW5lcic7XG5pbXBvcnQgeyBzZWFyY2hDaGlsZHJlbkZvck5vZGVUeXBlIH0gZnJvbSAnc3JjL3V0aWxpdGllcy91dGlscyc7XG5cbmV4cG9ydCB0eXBlIE11bHRpQ29sdW1uUmVuZGVyRGF0YSA9IHsgXG4gICAgcGFyZW50UmVuZGVyRWxlbWVudDogSFRNTEVsZW1lbnQsIFxuICAgIHBhcmVudFJlbmRlclNldHRpbmdzOiBNdWx0aUNvbHVtblNldHRpbmdzLFxuICAgIGRvbU9iamVjdHM6IERPTU9iamVjdFtdXG59XG5cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBSZWdpb25NYW5hZ2VyIHtcblxuICAgIHByb3RlY3RlZCBkb21MaXN0OiBET01PYmplY3RbXSA9IFtdO1xuICAgIHByb3RlY3RlZCBkb21PYmplY3RNYXA6IE1hcDxzdHJpbmcsIERPTU9iamVjdD4gPSBuZXcgTWFwKCk7XG4gICAgcHJpdmF0ZSBfcmVnaW9uUGFyZW50OiBIVE1MRWxlbWVudDtcbiAgICBwdWJsaWMgZ2V0IHJlZ2lvblBhcmVudCgpOiBIVE1MRWxlbWVudCB7XG4gICAgICAgIHJldHVybiB0aGlzLl9yZWdpb25QYXJlbnQ7XG4gICAgfVxuICAgIHB1YmxpYyBzZXQgcmVnaW9uUGFyZW50KHZhbHVlOiBIVE1MRWxlbWVudCkge1xuICAgICAgICB0aGlzLl9yZWdpb25QYXJlbnQgPSB2YWx1ZTtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgZmlsZU1hbmFnZXI6IEZpbGVET01NYW5hZ2VyO1xuICAgIHByb3RlY3RlZCByZWdpb25hbFNldHRpbmdzOiBNdWx0aUNvbHVtblNldHRpbmdzID0gZ2V0RGVmYXVsdE11bHRpQ29sdW1uU2V0dGluZ3MoKTtcblxuICAgIHByb3RlY3RlZCByZWdpb25LZXk6IHN0cmluZztcblxuICAgIGNvbnN0cnVjdG9yKGRhdGE6IFJlZ2lvbk1hbmFnZXJEYXRhKSB7XG5cbiAgICAgICAgdGhpcy5kb21MaXN0ID0gZGF0YS5kb21MaXN0O1xuICAgICAgICB0aGlzLmRvbU9iamVjdE1hcCA9IGRhdGEuZG9tT2JqZWN0TWFwO1xuICAgICAgICB0aGlzLnJlZ2lvblBhcmVudCA9IGRhdGEucmVnaW9uUGFyZW50O1xuXG4gICAgICAgIHRoaXMuZmlsZU1hbmFnZXIgPSBkYXRhLmZpbGVNYW5hZ2VyO1xuICAgICAgICB0aGlzLnJlZ2lvbmFsU2V0dGluZ3MgPSBkYXRhLnJlZ2lvbmFsU2V0dGluZ3M7XG5cbiAgICAgICAgdGhpcy5yZWdpb25LZXkgPSBkYXRhLnJlZ2lvbktleTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0UmVnaW9uRGF0YSgpOiBSZWdpb25NYW5hZ2VyRGF0YSB7XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGRvbUxpc3Q6IHRoaXMuZG9tTGlzdCxcbiAgICAgICAgICAgIGRvbU9iamVjdE1hcDogdGhpcy5kb21PYmplY3RNYXAsXG4gICAgICAgICAgICByZWdpb25QYXJlbnQ6IHRoaXMucmVnaW9uUGFyZW50LFxuXG4gICAgICAgICAgICBmaWxlTWFuYWdlcjogdGhpcy5maWxlTWFuYWdlcixcbiAgICAgICAgICAgIHJlZ2lvbmFsU2V0dGluZ3M6IHRoaXMucmVnaW9uYWxTZXR0aW5ncyxcblxuICAgICAgICAgICAgcmVnaW9uS2V5OiB0aGlzLnJlZ2lvbktleSxcbiAgICAgICAgICAgIHJvb3RFbGVtZW50OiBudWxsXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgcHVibGljIGFkZE9iamVjdChzaWJsaW5nc0Fib3ZlOiBIVE1MRGl2RWxlbWVudCwgc2libGluZ3NCZWxvdzogSFRNTERpdkVsZW1lbnQsIG9iajogRE9NT2JqZWN0KTogbnVtYmVyIHtcblxuICAgICAgICBsZXQgcHJldk9iaiA9IHNpYmxpbmdzQWJvdmUuY2hpbGRyZW5bc2libGluZ3NBYm92ZS5jaGlsZHJlbi5sZW5ndGggLSAxXSBhcyBIVE1MRWxlbWVudDtcbiAgICAgICAgbGV0IG5leHRPYmogPSBzaWJsaW5nc0JlbG93LmNoaWxkcmVuWzBdIGFzIEhUTUxFbGVtZW50O1xuXG4gICAgICAgIGxldCBhZGRBdEluZGV4ID0gc2libGluZ3NBYm92ZS5jaGlsZHJlbi5sZW5ndGg7XG5cbiAgICAgICAgbGV0IHByZXZPYmpUZXh0ID0gXCJcIjtcbiAgICAgICAgaWYgKHByZXZPYmogIT09IHVuZGVmaW5lZCkge1xuXG4gICAgICAgICAgICBwcmV2T2JqVGV4dCA9IHByZXZPYmouaW5uZXJUZXh0O1xuXG4gICAgICAgICAgICBmb3IgKGxldCBpID0gdGhpcy5kb21MaXN0Lmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuZG9tTGlzdFtpXS5ub2RlS2V5ID09PSBwcmV2T2JqLmlubmVyVGV4dCkge1xuICAgICAgICAgICAgICAgICAgICBhZGRBdEluZGV4ID0gaSArIDE7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBuZXh0RWxJbmRleCA9IGFkZEF0SW5kZXg7XG4gICAgICAgIGxldCBuZXh0T2JqVGV4dCA9IFwiXCI7XG4gICAgICAgIGlmIChuZXh0T2JqICE9PSB1bmRlZmluZWQpIHtcblxuICAgICAgICAgICAgbGV0IGZvdW5kTmV4dCA9IGZhbHNlO1xuICAgICAgICAgICAgbmV4dE9ialRleHQgPSBuZXh0T2JqLmlubmVyVGV4dDtcblxuICAgICAgICAgICAgZm9yIChsZXQgaSA9IGFkZEF0SW5kZXg7IGkgPCB0aGlzLmRvbUxpc3QubGVuZ3RoOyBpKyspIHtcblxuICAgICAgICAgICAgICAgIGlmICh0aGlzLmRvbUxpc3RbaV0ubm9kZUtleSA9PT0gbmV4dE9iai5pbm5lclRleHQudHJpbSgpKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgbmV4dEVsSW5kZXggPSBpO1xuICAgICAgICAgICAgICAgICAgICBmb3VuZE5leHQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBjb25zb2xlLmxvZyhcIiBQcmV2OiBcIiwgc2libGluZ3NBYm92ZS5jaGlsZHJlbltzaWJsaW5nc0Fib3ZlLmNoaWxkcmVuLmxlbmd0aCAtIDFdLCBcIkFkZGluZzogXCIsIG9iai5lbGVtZW50LCBcIiBOZXh0OiBcIiwgc2libGluZ3NCZWxvdy5jaGlsZHJlblswXSwgXCJPdmVyd3JpdGluZzpcIiwgdGhpcy5kb21MaXN0LnNsaWNlKGFkZEF0SW5kZXgsIG5leHRFbEluZGV4KSk7XG4gICAgICAgIHRoaXMuZG9tTGlzdC5zcGxpY2UoYWRkQXRJbmRleCwgbmV4dEVsSW5kZXggLSBhZGRBdEluZGV4LCBvYmopO1xuICAgICAgICB0aGlzLmRvbU9iamVjdE1hcC5zZXQob2JqLlVJRCwgb2JqKTtcblxuICAgICAgICAvLyAvKipcbiAgICAgICAgLy8gICogTWFrZSBhIGNvcHkgb2YgdGhlIGxpc3QgdG8gbG9nLCBvbmx5IGJlY2F1c2VcbiAgICAgICAgLy8gICogY29uc29sZSBsb2cgdXBkYXRlcyBpdHMgcmVmZXJlbmNlcyB3aXRoIHVwZGF0ZXMgaW4gbWVtb3J5LlxuICAgICAgICAvLyAgKi9cbiAgICAgICAgLy8gbGV0IHggPSB0aGlzLmRvbUxpc3Quc2xpY2UoMCk7XG4gICAgICAgIC8vIGNvbnNvbGUubG9nKHgpO1xuICAgICAgICByZXR1cm4gYWRkQXRJbmRleDtcbiAgICB9XG5cbiAgICBwdWJsaWMgcmVtb3ZlT2JqZWN0KG9iamVjdFVJRDogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIC8vIC8qKlxuICAgICAgICAvLyAgKiBNYWtlIGEgY29weSBvZiB0aGUgbGlzdCB0byBsb2dcbiAgICAgICAgLy8gICovXG4gICAgICAgIC8vIGxldCB4ID0gZG9tTGlzdC5zbGljZSgwKTtcbiAgICAgICAgLy8gY29uc29sZS5sb2coeCk7XG4gICAgICAgIC8vIEdldCB0aGUgb2JqZWN0IGJ5IGtleSwgcmVtb3ZlIGl0IGZyb20gdGhlIG1hcCBhbmQgdGhlblxuICAgICAgICAvLyBmcm9tIHRoZSBsaXN0LlxuICAgICAgICBsZXQgb2JqID0gdGhpcy5kb21PYmplY3RNYXAuZ2V0KG9iamVjdFVJRCk7XG4gICAgICAgIHRoaXMuZG9tT2JqZWN0TWFwLmRlbGV0ZShvYmplY3RVSUQpO1xuXG4gICAgICAgIGlmIChvYmogPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuZG9tTGlzdC5jb250YWlucyhvYmopKSB7XG4gICAgICAgICAgICB0aGlzLmRvbUxpc3QucmVtb3ZlKG9iaik7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5kb21MaXN0Lmxlbmd0aCA9PT0gMCAmJiB0aGlzLmZpbGVNYW5hZ2VyICE9PSBudWxsKSB7XG4gICAgICAgICAgICB0aGlzLmZpbGVNYW5hZ2VyLnJlbW92ZVJlZ2lvbih0aGlzLnJlZ2lvbktleSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyB4ID0gZG9tTGlzdC5zbGljZSgwKTtcbiAgICAgICAgLy8gY29uc29sZS5sb2coeCk7XG4gICAgfVxuXG4gICAgcHVibGljIHVwZGF0ZUVsZW1lbnRUYWcob2JqZWN0VUlEOiBzdHJpbmcsIG5ld1RhZzogRE9NT2JqZWN0VGFnKTogdm9pZCB7XG5cbiAgICAgICAgbGV0IG9iaiA9IHRoaXMuZG9tT2JqZWN0TWFwLmdldChvYmplY3RVSUQpO1xuICAgICAgICBsZXQgaW5kZXggPSB0aGlzLmRvbUxpc3QuaW5kZXhPZihvYmopO1xuICAgICAgICBpZiAoaW5kZXggIT09IC0xKSB7XG4gICAgICAgICAgICB0aGlzLmRvbUxpc3RbaW5kZXhdLnRhZyA9IG5ld1RhZztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyBzZXRSZWdpb25hbFNldHRpbmdzKHJlZ2lvblNldHRpbmdzOiBNdWx0aUNvbHVtblNldHRpbmdzKTogdm9pZCB7XG4gICAgICAgIHRoaXMucmVnaW9uYWxTZXR0aW5ncyA9IHJlZ2lvblNldHRpbmdzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gb2JqZWN0IGNvbnRhaW5pbmcgYWxsIG5lY2Vzc2FyeSBpbmZvcm1hdGlvbiBmb3IgdGhlIHJlZ2lvblxuICAgICAqIHRvIGJlIHJlbmRlcmVkIHRvIHRoZSBwcmV2aWV3IHBhbmUuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBhIE11bHRpQ29sdW1uUmVuZGVyRGF0YSBvYmplY3Qgd2l0aCB0aGUgcm9vdCBET00gZWxlbWVudCwgc2V0dGluZ3Mgb2JqZWN0LCBhbmRcbiAgICAgKiBhbGwgY2hpbGQgb2JqZWN0cyBpbiB0aGUgb3JkZXIgdGhleSBzaG91bGQgYmUgcmVuZGVyZWQuXG4gICAgICovXG4gICAgcHVibGljIGdldFJlZ2lvblJlbmRlckRhdGEoKTogTXVsdGlDb2x1bW5SZW5kZXJEYXRhIHtcblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgcGFyZW50UmVuZGVyRWxlbWVudDogdGhpcy5yZWdpb25QYXJlbnQsXG4gICAgICAgICAgICBwYXJlbnRSZW5kZXJTZXR0aW5nczogdGhpcy5yZWdpb25hbFNldHRpbmdzLFxuICAgICAgICAgICAgZG9tT2JqZWN0czogdGhpcy5kb21MaXN0XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBmdWN0aW9uIGlzIGNhbGxlZCB3aGVuIGEgc3RhcnQgdGFnIGlzIHJlbW92ZWQgZnJvbSB2aWV3IG1lYW5pbmdcbiAgICAgKiBvdXIgcGFyZW50IGVsZW1lbnQgc3RvcmluZyB0aGUgbXVsdGktY29sdW1uIHJlZ2lvbiBpcyByZW1vdmVkLiBJdFxuICAgICAqIHJlbW92ZXMgdGhlIENTUyBjbGFzcyBmcm9tIGFsbCBvZiB0aGUgZWxlbWVudHMgc28gdGhleSB3aWxsIGJlXG4gICAgICogcmUtcmVuZGVyZWQgaW4gdGhlIHByZXZpZXcgd2luZG93LlxuICAgICAqL1xuICAgIHB1YmxpYyBkaXNwbGF5T3JpZ2luYWxFbGVtZW50cygpIHtcblxuXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5kb21MaXN0Lmxlbmd0aDsgaSsrKSB7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLmRvbUxpc3RbaV0ub3JpZ2luYWxFbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5kb21MaXN0W2ldLm9yaWdpbmFsRWxlbWVudC5yZW1vdmVDbGFzc2VzKFtNdWx0aUNvbHVtblN0eWxlQ1NTLlJlZ2lvbkVuZFRhZyxcbiAgICAgICAgICAgICAgICBNdWx0aUNvbHVtblN0eWxlQ1NTLkNvbHVtbkVuZFRhZyxcbiAgICAgICAgICAgICAgICBNdWx0aUNvbHVtblN0eWxlQ1NTLlJlZ2lvblNldHRpbmdzLFxuICAgICAgICAgICAgICAgIE11bHRpQ29sdW1uU3R5bGVDU1MuUmVnaW9uQ29udGVudF0pO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmRvbUxpc3RbaV0ub3JpZ2luYWxFbGVtZW50LnBhcmVudEVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kb21MaXN0W2ldLm9yaWdpbmFsRWxlbWVudC5wYXJlbnRFbGVtZW50LnJlbW92ZUNoaWxkKHRoaXMuZG9tTGlzdFtpXS5vcmlnaW5hbEVsZW1lbnQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICBcbiAgICBwdWJsaWMgZ2V0SUQoKTogc3RyaW5nIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucmVnaW9uS2V5O1xuICAgIH1cblxuICAgIHB1YmxpYyB1cGRhdGVSZW5kZXJlZE1hcmtkb3duKCkge1xuICAgICAgICAvKipcbiAgICAgICAgICogVGhpcyBmdW5jdGlvbiBhY3RzIGFzIHRoZSB1cGRhdGUgbG9vcCBmb3IgdGhlIG11bHRpLWNvbHVtbiByZWdpb25zLlxuICAgICAgICAgKiBIZXJlIHdlIGxvb3AgdGhyb3VnaCBhbGwgb2YgdGhlIGVsZW1lbnRzIHdpdGhpbiB0aGUgcmVuZGVyZWQgcmVnaW9uIGFuZFxuICAgICAgICAgKiBwb3RlbnRpYWxseSB1cGRhdGUgaG93IHRoaW5ncyBhcmUgcmVuZGVyZWQuIFdlIG5lZWQgdG8gZG8gdGhpcyBmb3JcbiAgICAgICAgICogY29tcGF0YWJpbGl0eSB3aXRoIG90aGVyIHBsdWdpbnMuXG4gICAgICAgICAqXG4gICAgICAgICAqIElmIHRoZSBtdWx0aS1jb2x1bW4gcmVnaW9uIGlzIHJlbmRlcmVkIGJlZm9yZSBvdGhlciBwbHVnaW5zIHRoYXQgZWZmZWN0XG4gICAgICAgICAqIGNvbnRlbnQgd2l0aGluIHRoZSByZWdpb24gb3VyIHJlbmRlcmVkIGRhdGEgbWF5IG5vdCBwcm9wZXJseSBkaXNwbGF5XG4gICAgICAgICAqIHRoZSBjb250ZW50IGZyb20gdGhlIG90aGVyIHBsdWdpbi4gSGVyZSB3ZSBsb29wIHRocm91Z2ggdGhlIGVsZW1lbnRzXG4gICAgICAgICAqIGFmdGVyIGFsbCBwbHVnaW5zIGhhdmUgaGFkIGEgY2hhbmNlIHRvIHJ1biBhbmQgY2FuIG1ha2UgY2hhbmdlcyB0byB0aGVcbiAgICAgICAgICogRE9NIGF0IHRoaXMgcG9pbnQuXG4gICAgICAgICAqL1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuZG9tTGlzdC5sZW5ndGg7IGkrKykge1xuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIEhlcmUgd2UgY2hlY2sgZm9yIHNwZWNpYWwgY2FzZXNcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgaWYgKHRoaXMuZG9tTGlzdFtpXSBpbnN0YW5jZW9mIFRhc2tMaXN0RE9NT2JqZWN0KSB7XG5cbiAgICAgICAgICAgICAgICB0aGlzLmZpeENsb25lZENoZWNrTGlzdEJ1dHRvbnModGhpcy5kb21MaXN0W2ldIGFzIFRhc2tMaXN0RE9NT2JqZWN0KTtcbiAgICAgICAgICAgIH1cblxuXG4gICAgICAgICAgICBsZXQgZWxlbWVudFR5cGUgPSB0aGlzLmRvbUxpc3RbaV0uZWxlbWVudFR5cGU7XG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogSWYgdGhlIGVsZW1lbnQgaXMgbm90IGN1cnJlbnRseSBhIHNwZWNpYWwgcmVuZGVyIGVsZW1lbnQgd2UgY2hlY2sgYWdhaW5cbiAgICAgICAgICAgICAqIGFzIHRoZSBvcmlnaW5hbCBlbGVtZW50IG1heSBoYXZlIGJlZW4gdXBkYXRlZC5cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiBUT0RPOiBmaW5kIGEgd2F5IHRvIFwiT2ZmaWNpYWxseVwiIG1hcmsgbm9ybWFsIGVsZW1lbnRzIHJhdGhlciB0aGFuXG4gICAgICAgICAgICAgKiBjb250aW51b3VzbHkgc2VhcmNoIGZvciBzcGVjaWFsIHJlbmRlciB0eXBlcy5cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgaWYgKGVsZW1lbnRUeXBlICE9PSBFbGVtZW50UmVuZGVyVHlwZS5zcGVjaWFsUmVuZGVyICYmXG4gICAgICAgICAgICAgICAgZWxlbWVudFR5cGUgIT09IEVsZW1lbnRSZW5kZXJUeXBlLnNwZWNpYWxTaW5nbGVFbGVtZW50UmVuZGVyICYmIFxuICAgICAgICAgICAgICAgIGVsZW1lbnRUeXBlICE9PSBFbGVtZW50UmVuZGVyVHlwZS51blJlbmRlcmVkKSB7XG5cbiAgICAgICAgICAgICAgICAvLyBJZiB0aGUgbmV3IHJlc3VsdCByZXR1cm5zIGFzIGEgc3BlY2lhbCByZW5kZXJlciB3ZSB1cGRhdGUgc29cbiAgICAgICAgICAgICAgICAvLyB0aGlzIHdvbnQgcnVuIGFnYWluIGZvciB0aGlzIGl0ZW0uXG4gICAgICAgICAgICAgICAgZWxlbWVudFR5cGUgPSBnZXRFbGVtZW50UmVuZGVyVHlwZSh0aGlzLmRvbUxpc3RbaV0ub3JpZ2luYWxFbGVtZW50KTtcbiAgICAgICAgICAgICAgICB0aGlzLmRvbUxpc3RbaV0ub3JpZ2luYWxFbGVtZW50LmNsaWVudEhlaWdodDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGVsZW1lbnRUeXBlID09PSBFbGVtZW50UmVuZGVyVHlwZS5zcGVjaWFsUmVuZGVyIHx8XG4gICAgICAgICAgICAgICAgZWxlbWVudFR5cGUgPT09IEVsZW1lbnRSZW5kZXJUeXBlLnNwZWNpYWxTaW5nbGVFbGVtZW50UmVuZGVyIHx8IFxuICAgICAgICAgICAgICAgIGVsZW1lbnRUeXBlID09PSBFbGVtZW50UmVuZGVyVHlwZS5jYW52YXNSZW5kZXJFbGVtZW50KSB7XG5cbiAgICAgICAgICAgICAgICB0aGlzLmRvbUxpc3RbaV0uZWxlbWVudFR5cGUgPSBlbGVtZW50VHlwZTtcbiAgICAgICAgICAgICAgICB0aGlzLnNldFVwRHVhbFJlbmRlcih0aGlzLmRvbUxpc3RbaV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBmdW5jdGlvbiB0YWtlcyBpbiB0aGUgb3JpZ2luYWwgZWxlbWVudCBhbmQgaXRzIGNsb25lIGFuZCBjaGVja3MgaWZcbiAgICAgKiB0aGUgZWxlbWVudCBjb250YWlucyBhIHRhc2stbGlzdC1pdGVtIGNsYXNzLiBJZiBzbyBpdCBsb29wcyB0aHJvdWdoIGFsbFxuICAgICAqIGl0ZW1zIGluIHRoZSBsaXN0IGFuZCBmaXhlcyB0aGVpciBjaGVja2JveGVzIHRvIHByb3Blcmx5IGZpcmUgYW4gZXZlbnQuXG4gICAgICogVGhlIG5ldyBjaGVja2JveCBjYWxscyB0aGUgY2xpY2sgZnVuY3Rpb24gb24gdGhlIG9yaWdpbmFsIGNoZWNrYm94IHNvXG4gICAgICogY29tcGF0YWJpbGl0eSB3aXRoIG90aGVyIHBsdWdpbnMgKnNob3VsZCogcmVtYWluLlxuICAgICAqIEBwYXJhbSBkb21FbGVtZW50XG4gICAgICogQHBhcmFtIGluaXRhbGl6ZUNoZWNrYm94ZXNcbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgZml4Q2xvbmVkQ2hlY2tMaXN0QnV0dG9ucyhkb21FbGVtZW50OiBUYXNrTGlzdERPTU9iamVjdCwgaW5pdGFsaXplQ2hlY2tib3hlczogYm9vbGVhbiA9IGZhbHNlKSB7XG5cbiAgICAgICAgaWYoZG9tRWxlbWVudC5vcmlnaW5hbEVsZW1lbnQgPT09IG51bGwgfHwgZG9tRWxlbWVudC5jbG9uZWRFbGVtZW50ID09PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgZWxlbWVudDogSFRNTEVsZW1lbnQgPSBkb21FbGVtZW50Lm9yaWdpbmFsRWxlbWVudDtcbiAgICAgICAgbGV0IGNsb25lZEVsZW1lbnQ6IEhUTUxFbGVtZW50ID0gZG9tRWxlbWVudC5jbG9uZWRFbGVtZW50O1xuXG4gICAgICAgIGxldCBjbG9uZWRMaXN0Q2hlY2tib3hlcyA9IEFycmF5LmZyb20oY2xvbmVkRWxlbWVudC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKFwidGFzay1saXN0LWl0ZW1cIikpIGFzIEhUTUxFbGVtZW50W107XG4gICAgICAgIGxldCBvcmlnaW5hbExpc3RDaGVja2JveGVzID0gQXJyYXkuZnJvbShlbGVtZW50LmdldEVsZW1lbnRzQnlDbGFzc05hbWUoXCJ0YXNrLWxpc3QtaXRlbVwiKSkgYXMgSFRNTEVsZW1lbnRbXTtcblxuICAgICAgICBpZiAoaW5pdGFsaXplQ2hlY2tib3hlcyA9PT0gdHJ1ZSkge1xuXG4gICAgICAgICAgICAvLyBXaGVuIHdlIGluaXRhbGl6ZSB3ZSByZW1vdmUgdGhlIG9sZCBpbnB1dCBjaGVja2JveCB0aGF0IGNvbnRhaW5zXG4gICAgICAgICAgICAvLyB0aGUgd2VpcmQgY2FsbGJhY2sgc2l0dWF0aW9uIGNhdXNpbmcgdGhlIGJ1Zy4gVGhlbiB3ZSBjcmVhdGUgYSBuZXdcbiAgICAgICAgICAgIC8vIGNoZWNrYm94IHRvIHJlcGxhY2UgaXQgYW5kIHNldCBpdCB1cCB0byBmaXJlIHRoZSBjbGljayBldmVudCBvblxuICAgICAgICAgICAgLy8gdGhlIG9yaWdpbmFsIGNoZWNrYm94IHNvIGZ1bmN0aW9uYWxpdHkgaXMgcmVzdG9yZWQuXG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG9yaWdpbmFsTGlzdENoZWNrYm94ZXMubGVuZ3RoOyBpKyspIHtcblxuICAgICAgICAgICAgICAgIGNvbnN0IGNoZWNrYm94ID0gY3JlYXRlRWwoJ2lucHV0Jyk7XG5cbiAgICAgICAgICAgICAgICBsZXQgb3JpZ2luYWxJbnB1dCA9IG9yaWdpbmFsTGlzdENoZWNrYm94ZXNbaV0uZmlyc3RDaGlsZCBhcyBIVE1MSW5wdXRFbGVtZW50O1xuXG4gICAgICAgICAgICAgICAgY2hlY2tib3guY2hlY2tlZCA9IG9yaWdpbmFsSW5wdXQuY2hlY2tlZDtcbiAgICAgICAgICAgICAgICBjbG9uZWRMaXN0Q2hlY2tib3hlc1tpXS5yZXBsYWNlQ2hpbGQoY2hlY2tib3gsIGNsb25lZExpc3RDaGVja2JveGVzW2ldLmNoaWxkcmVuWzBdKTtcbiAgICAgICAgICAgICAgICBjaGVja2JveC5hZGRDbGFzcygndGFzay1saXN0LWl0ZW0tY2hlY2tib3gnKTtcbiAgICAgICAgICAgICAgICBjaGVja2JveC50eXBlID0gJ2NoZWNrYm94JztcbiAgICAgICAgICAgICAgICBjaGVja2JveC5vbkNsaWNrRXZlbnQoKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBkb21FbGVtZW50LmNoZWNrYm94Q2xpY2tlZChpKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcblxuICAgICAgICAgICAgLy8gV2hlbmV2ZXIgd2UgcmVhY2ggdGhpcyBwb2ludCB3ZSB1cGRhdGUgb3VyIGxpc3Qgb2Ygb3JpZ2luYWwgY2hlY2tib3hlc1xuICAgICAgICAgICAgLy8gdGhhdCBtYXkgYmUgZGlmZmVyZW50IGZyb20gb3VyIGNhY2hlLiBUaGlzIGlzIGR1ZSB0byBob3cgb2JzaWRpYW5cbiAgICAgICAgICAgIC8vIGNoYW5nZXMgdGhlIERPTSB1bmRlcm5lYXRoIHVzIHNvIHdlIG5lZWQgdG8gY29uc3RhbnRseSB1cGRhdGUgb3VyIGNhY2hlLlxuICAgICAgICAgICAgZG9tRWxlbWVudC5vcmlnaW5hbENoZWNrYm94ZXMgPSBvcmlnaW5hbExpc3RDaGVja2JveGVzO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gV2hlbiB0aGUgVGFza3MgcGx1Z2luIGlzIGluc3RhbGxlZCB0aGUgY2xvbmVkIGNvcHkgb2YgdGhlIG9yaWdpbmFsIGVsZW1lbnQgY29udGFpbnNcbiAgICAgICAgLy8gYW4gZXh0cmEgZWxlbWVudCBmb3Igc29tZSByZWFzb24uIElmIHRoaXMgb2NjdXJzIGZvciBvdGhlciByZWFzb25zIGhlcmUgd2UgYWRqdXN0XG4gICAgICAgIC8vIHRoYXQgdG8ga2VlcCB0aGUgY2xvbmUgdGhlIHNhbWUgYXMgdGhlIG9yaWdpbmFsLlxuICAgICAgICBpZiAoY2xvbmVkTGlzdENoZWNrYm94ZXMubGVuZ3RoID4gb3JpZ2luYWxMaXN0Q2hlY2tib3hlcy5sZW5ndGgpIHtcblxuICAgICAgICAgICAgZm9yIChsZXQgaSA9IG9yaWdpbmFsTGlzdENoZWNrYm94ZXMubGVuZ3RoOyBpIDwgY2xvbmVkTGlzdENoZWNrYm94ZXMubGVuZ3RoOyBpKyspIHtcblxuICAgICAgICAgICAgICAgIGRvbUVsZW1lbnQuY2xvbmVkRWxlbWVudC5yZW1vdmVDaGlsZChjbG9uZWRMaXN0Q2hlY2tib3hlc1tpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgc2V0VXBEdWFsUmVuZGVyKGRvbUVsZW1lbnQ6IERPTU9iamVjdCkge1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBJZiBvdXIgZWxlbWVudCBpcyBvZiBcInNwZWNpYWxSZW5kZXJcIiB0eXBlIGl0ICptYXkqIG5lZWQgdG8gYmUgcmVuZGVyZWRcbiAgICAgICAgICogdXNpbmcgdGhlIG9yaWdpbmFsIGVsZW1lbnQgcmF0aGVyIHRoYW4gYSBjb3B5LiBGb3IgZXhhbXBsZSwgYW4gZWxlbWVudFxuICAgICAgICAgKiBtYXkgaGF2ZSBhbiBvbkNsaWNrIGV2ZW50IHRoYXQgd291bGQgbm90IGdldCBjb3BwaWVkIHRvIHRoZSBjbG9uZS5cbiAgICAgICAgICpcbiAgICAgICAgICogSWYgd2UganVzdCBtb3ZlZCB0aGVzZSBlbGVtZW50cyBpbnRvIHRoZSByZWdpb24gaXQgd291bGQgZ2V0XG4gICAgICAgICAqIG1vdmVkIGJhY2sgb3V0IGludG8gdGhlIG9yaWdpbmFsIGxvY2F0aW9uIGluIHRoZSBET00gYnkgb2JzaWRpYW5cbiAgICAgICAgICogd2hlbiBzY3JvbGxpbmcgb3Igd2hlbiB0aGUgZmlsZSBpcyB1cGRhdGVkLiBPbiB0aGUgbmV4dCByZWZyZXNoIGl0XG4gICAgICAgICAqIHdvdWxkIGJlIG1vdmVkIGJhY2sgYnV0IHRoYXQgY2FuIGxlYWQgdG8gYSByZWdpb24ganVtcGluZ1xuICAgICAgICAgKiBhcm91bmQgYXMgdGhlIGl0ZW0gaXMgbW92ZWQgaW4gYW5kIG91dC5cbiAgICAgICAgICpcbiAgICAgICAgICogSGVyZSB3ZSBzZXQgdXAgdGhlIGRpdiB0byBjb250YWluIHRoZSBlbGVtZW50IGFuZCBjcmVhdGVcbiAgICAgICAgICogYSB2aXN1YWwgb25seSBjbG9uZSBvZiBpdC4gVGhlIGNsb25lIHdpbGwgb25seSBiZSB2aXNpYmxlXG4gICAgICAgICAqIHdoZW4gdGhlIG9yaWdpbmFsIGlzIG5vdCBpbiB0aGUgbXVsdGktY29sdW1uIHJlZ2lvbiBzbyBpdFxuICAgICAgICAgKiBzYXZlcyB1cyBmcm9tIHRoZSB2aXN1YWwgbm9pc2Ugb2YgdGhlIHJlZ2lvbiBqdW1waW5nIGFyb3VuZC5cbiAgICAgICAgICovXG5cbiAgICAgICAgIGxldCBvcmlnaW5hbEVsZW1lbnQgPSBkb21FbGVtZW50Lm9yaWdpbmFsRWxlbWVudDtcbiAgICAgICAgIGxldCBjbG9uZWRFbGVtZW50ID0gZG9tRWxlbWVudC5jbG9uZWRFbGVtZW50O1xuICAgICAgICAgbGV0IGNvbnRhaW5lckVsZW1lbnQ6IEhUTUxEaXZFbGVtZW50ID0gZG9tRWxlbWVudC5lbGVtZW50Q29udGFpbmVyO1xuXG4gICAgICAgIC8vIEdldCBoZWlnaHQgb2YgdGhlIG9yaWdpbmFsIGFuZCBjbG9uZWQgZWxlbWVudC4gSWYgdGhlIGVsZW1lbnQgaXMgbm90IGN1cnJlbnRseSByZW5kZXJlZFxuICAgICAgICAvLyBpdCB3aWxsIGhhdmUgMCBoZWlnaHQgc28gd2UgbmVlZCB0byB0ZW1wb3JhcmlseSByZW5kZXIgaXQgdG8gZ2V0IHRoZSBoZWlnaHQuXG4gICAgICAgIGxldCBvcmlnaW5hbEVsZW1lbnRIZWlnaHQgPSBnZXRFbGVtZW50Q2xpZW50SGVpZ2h0KG9yaWdpbmFsRWxlbWVudCwgY29udGFpbmVyRWxlbWVudCk7XG4gICAgICAgIGxldCBjbG9uZWRFbGVtZW50SGVpZ2h0ID0gZ2V0RWxlbWVudENsaWVudEhlaWdodChjbG9uZWRFbGVtZW50LCBjb250YWluZXJFbGVtZW50KTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogV2Ugb25seSB3YW50IHRvIGNsb25lIHRoZSBlbGVtZW50IG9uY2UgdG8gcmVkdWNlIEdDLiBCdXQgaWYgdGhlIGNsb25lZCBcbiAgICAgICAgICogZWxlbWVudCdzIGhlaWdodCBpcyBub3QgZXF1YWwgdG8gdGhlIG9yaWdpbmFsIGVsZW1lbnQsIHRoaXMgbWVhbnMgdGhlXG4gICAgICAgICAqIGl0ZW0gZWxlbWVudCBoYXMgYmVlbiB1cGRhdGVkIHNvbWV3aGVyZSBlbHNlIHdpdGhvdXQgdGhlIGRvbSBiZWluZyBcbiAgICAgICAgICogcmVmcmVzaGVkLiBUaGlzIGNhbiBvY2N1ciB3aGVuIGVsZW1lbnRzIGFyZSB1cGRhdGVkIGJ5IG90aGVyIHBsdWdpbnMsIFxuICAgICAgICAgKiBzdWNoIGFzIERhdGF2aWV3LlxuICAgICAgICAgKi9cbiAgICAgICAgaWYoY2xvbmVkRWxlbWVudCA9PT0gbnVsbCAgfHwgXG4gICAgICAgICAgICBjbG9uZWRFbGVtZW50SGVpZ2h0ICE9PSBvcmlnaW5hbEVsZW1lbnRIZWlnaHQpIHtcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgLy8gVXBkYXRlIGNsb25lIGFuZCByZWZlcmVuY2UuXG4gICAgICAgICAgICBkb21FbGVtZW50LmNsb25lZEVsZW1lbnQgPSBvcmlnaW5hbEVsZW1lbnQuY2xvbmVOb2RlKHRydWUpIGFzIEhUTUxEaXZFbGVtZW50O1xuICAgICAgICAgICAgY2xvbmVkRWxlbWVudCA9IGRvbUVsZW1lbnQuY2xvbmVkRWxlbWVudDtcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBJZiB3ZSB1cGRhdGVkIHRoZSBjbG9uZWQgZWxlbWVudCwgd2Ugd2FudCB0byBhbHNvIHVwZGF0ZSB0aGVcbiAgICAgICAgICAgICAqIGVsZW1lbnQgcmVuZGVyZWQgaW4gdGhlIHBhcmVudCBjb250YWluZXIuXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGZvciAobGV0IGkgPSBjb250YWluZXJFbGVtZW50LmNoaWxkcmVuLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgICAgICAgICAgY29udGFpbmVyRWxlbWVudC5jaGlsZHJlbltpXS5kZXRhY2goKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gVXBkYXRlIENTUywgd2UgYWRkIGNsb25lZCBjbGFzcyBhbmQgcmVtb3ZlIGNsYXNzZXMgZnJvbSBvcmlnaW5hbEVsZW1lbnQgdGhhdCBkbyBub3QgYXBwbHkuXG4gICAgICAgICAgICBjbG9uZWRFbGVtZW50LmFkZENsYXNzKE11bHRpQ29sdW1uTGF5b3V0Q1NTLkNsb25lZEVsZW1lbnRUeXBlKTtcbiAgICAgICAgICAgIGNsb25lZEVsZW1lbnQucmVtb3ZlQ2xhc3NlcyhbTXVsdGlDb2x1bW5TdHlsZUNTUy5SZWdpb25Db250ZW50LCBNdWx0aUNvbHVtbkxheW91dENTUy5PcmlnaW5hbEVsZW1lbnRUeXBlXSk7XG4gICAgICAgICAgICBjb250YWluZXJFbGVtZW50LmFwcGVuZENoaWxkKGNsb25lZEVsZW1lbnQpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoZG9tRWxlbWVudC5lbGVtZW50VHlwZSA9PT0gRWxlbWVudFJlbmRlclR5cGUuY2FudmFzUmVuZGVyRWxlbWVudCkge1xuXG4gICAgICAgICAgICBjb250YWluZXJFbGVtZW50LmFwcGVuZENoaWxkKG9yaWdpbmFsRWxlbWVudCk7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGNsb25lQ2FudmFzKG9yaWdpbmFsQ2FudmFzOiBIVE1MQ2FudmFzRWxlbWVudCk6IEhUTUxDYW52YXNFbGVtZW50IHtcblxuICAgICAgICAgICAgICAgIC8vY3JlYXRlIGEgbmV3IGNhbnZhc1xuICAgICAgICAgICAgICAgIGxldCBjbG9uZWRDYW52YXM6IEhUTUxDYW52YXNFbGVtZW50ID0gb3JpZ2luYWxDYW52YXMuY2xvbmVOb2RlKHRydWUpIGFzIEhUTUxDYW52YXNFbGVtZW50O1xuICAgICAgICAgICAgICAgIGxldCBjb250ZXh0OiBDYW52YXNSZW5kZXJpbmdDb250ZXh0MkQgPSBjbG9uZWRDYW52YXMuZ2V0Q29udGV4dCgnMmQnKTtcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgIC8vc2V0IGRpbWVuc2lvbnNcbiAgICAgICAgICAgICAgICBjbG9uZWRDYW52YXMud2lkdGggPSBvcmlnaW5hbENhbnZhcy53aWR0aDtcbiAgICAgICAgICAgICAgICBjbG9uZWRDYW52YXMuaGVpZ2h0ID0gb3JpZ2luYWxDYW52YXMuaGVpZ2h0O1xuXG4gICAgICAgICAgICAgICAgaWYoY2xvbmVkQ2FudmFzLndpZHRoID09PSAwIHx8IGNsb25lZENhbnZhcy5oZWlnaHQgPT09IDApe1xuICAgICAgICAgICAgICAgICAgICAvLyBEb250IHdhbnQgdG8gcmVuZGVyIGlmIHRoZSB3aWR0aCBpcyAwIGFzIGl0IHRocm93cyBhbiBlcnJvclxuICAgICAgICAgICAgICAgICAgICAvLyB3b3VsZCBoYXBwZW4gaWYgdGhlIG9sZCBjYW52YXMgaGFzbnQgYmVlbiByZW5kZXJlZCB5ZXQuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBjbG9uZWRDYW52YXM7XG4gICAgICAgICAgICAgICAgfSBcblxuICAgICAgICAgICAgICAgIC8vYXBwbHkgdGhlIG9sZCBjYW52YXMgdG8gdGhlIG5ldyBvbmVcbiAgICAgICAgICAgICAgICBjb250ZXh0LmRyYXdJbWFnZShvcmlnaW5hbENhbnZhcywgMCwgMCk7XG4gICAgICAgICAgICBcbiAgICAgICAgICAgICAgICAvL3JldHVybiB0aGUgbmV3IGNhbnZhc1xuICAgICAgICAgICAgICAgIHJldHVybiBjbG9uZWRDYW52YXM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGxldCBjYW52YXMgPSBzZWFyY2hDaGlsZHJlbkZvck5vZGVUeXBlKG9yaWdpbmFsRWxlbWVudCwgXCJjYW52YXNcIik7XG4gICAgICAgICAgICBpZihjYW52YXMgIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gY2xvbmVkRWxlbWVudC5jaGlsZHJlbi5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICAgICAgICAgICAgICBjbG9uZWRFbGVtZW50LmNoaWxkcmVuW2ldLmRldGFjaCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjbG9uZWRFbGVtZW50LmFwcGVuZENoaWxkKGNsb25lQ2FudmFzKGNhbnZhcyBhcyBIVE1MQ2FudmFzRWxlbWVudCkpXG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnRhaW5lckVsZW1lbnQucmVtb3ZlQ2hpbGQob3JpZ2luYWxFbGVtZW50KTtcbiAgICAgICAgfVxuICAgICAgICBcbiAgICAgICAgLyoqIFxuICAgICAgICAgKiBJZiB0aGUgY29udGFpbmVyIGVsZW1lbnQgaGFzIGxlc3MgdGhhbiAyIGNoaWxkcmVuIHdlIG5lZWQgdG8gbW92ZSB0aGVcbiAgICAgICAgICogb3JpZ2luYWwgZWxlbWVudCBiYWNrIGludG8gaXQuIEhvd2V2ZXIgc29tZSBlbGVtZW50cyBjb25zdGFudGx5IGdldCBtb3ZlZFxuICAgICAgICAgKiBpbiBhbmQgb3V0IGNhdXNpbmcgc29tZSB1bndhbnRlZCBiZWhhdmlvci4gVGhvc2UgZWxlbWVudCB3aWxsIGJlIHRhZ2dlZFxuICAgICAgICAgKiBhcyBzcGVjaWFsU2luZ2xlRWxlbWVudFJlbmRlciBzbyB3ZSBpZ25vcmUgdGhvc2UgZWxlbWVudHMgaGVyZS5cbiAgICAgICAgICovXG4gICAgICAgIGlmKGRvbUVsZW1lbnQuZWxlbWVudENvbnRhaW5lci5jaGlsZHJlbi5sZW5ndGggPCAyICYmIFxuICAgICAgICAgICAgZG9tRWxlbWVudC5lbGVtZW50VHlwZSAhPT0gRWxlbWVudFJlbmRlclR5cGUuc3BlY2lhbFNpbmdsZUVsZW1lbnRSZW5kZXIpIHtcblxuICAgICAgICAgICAgLy8gY29uc29sZS5sb2coXCJVcGRhdGluZyBkdWFsIHJlbmRlcmluZy5cIiwgZG9tRWxlbWVudCwgZG9tRWxlbWVudC5vcmlnaW5hbEVsZW1lbnQucGFyZW50RWxlbWVudCwgZG9tRWxlbWVudC5vcmlnaW5hbEVsZW1lbnQucGFyZW50RWxlbWVudD8uY2hpbGRFbGVtZW50Q291bnQpO1xuICAgICAgICAgICAgXG4gICAgICAgICAgICAvLyBNYWtlIHN1cmUgb3VyIENTUyBpcyB1cCB0byBkYXRlLlxuICAgICAgICAgICAgb3JpZ2luYWxFbGVtZW50LmFkZENsYXNzKE11bHRpQ29sdW1uTGF5b3V0Q1NTLk9yaWdpbmFsRWxlbWVudFR5cGUpO1xuICAgICAgICAgICAgY2xvbmVkRWxlbWVudC5hZGRDbGFzcyhNdWx0aUNvbHVtbkxheW91dENTUy5DbG9uZWRFbGVtZW50VHlwZSk7XG4gICAgICAgICAgICBjbG9uZWRFbGVtZW50LnJlbW92ZUNsYXNzZXMoW011bHRpQ29sdW1uU3R5bGVDU1MuUmVnaW9uQ29udGVudCwgTXVsdGlDb2x1bW5MYXlvdXRDU1MuT3JpZ2luYWxFbGVtZW50VHlwZV0pO1xuICAgIFxuICAgICAgICAgICAgZm9yIChsZXQgaSA9IGNvbnRhaW5lckVsZW1lbnQuY2hpbGRyZW4ubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICAgICAgICBjb250YWluZXJFbGVtZW50LmNoaWxkcmVuW2ldLmRldGFjaCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29udGFpbmVyRWxlbWVudC5hcHBlbmRDaGlsZChvcmlnaW5hbEVsZW1lbnQpO1xuICAgICAgICAgICAgY29udGFpbmVyRWxlbWVudC5hcHBlbmRDaGlsZChjbG9uZWRFbGVtZW50KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgdXAgdGhlIENTUyBjbGFzc2VzIGFuZCB0aGUgbnVtYmVyIG9mIGNvbHVtbnMgYmFzZWQgb24gdGhlIHBhc3NlZCBzZXR0aW5ncy5cbiAgICAgKiBAcGFyYW0gc2V0dGluZ3MgVGhlIHVzZXIgZGVmaW5lZCBzZXR0aW5ncyB0aGF0IGRldGVybWluZSB3aGF0IENTUyBpcyBzZXQgaGVyZS5cbiAgICAgKiBAcGFyYW0gbXVsdGlDb2x1bW5QYXJlbnQgVGhlIHBhcmVudCBvYmplY3QgdGhhdCB0aGUgY29sdW1uIGRpdnMgd2lsbCBiZSBjcmVhdGVkIHVuZGVyLlxuICAgICAqIEByZXR1cm5zIFRoZSBsaXN0IG9mIGNvbHVtbiBkaXZzIGNyZWF0ZWQgdW5kZXIgdGhlIHBhc3NlZCBwYXJlbnQgZWxlbWVudC5cbiAgICAgKi9cbiAgICBnZXRDb2x1bW5Db250ZW50RGl2cyhzZXR0aW5nczogTXVsdGlDb2x1bW5TZXR0aW5ncywgbXVsdGlDb2x1bW5QYXJlbnQ6IEhUTUxEaXZFbGVtZW50KTogSFRNTERpdkVsZW1lbnRbXSB7XG5cbiAgICAgICAgbGV0IGNvbHVtbkNvbnRlbnREaXZzOiBIVE1MRGl2RWxlbWVudFtdID0gW11cbiAgICAgICAgbGV0IHN0eWxlU3RyOiBzdHJpbmcgPSBcIlwiXG4gICAgICAgIGlmKHNldHRpbmdzLmNvbHVtblNwYWNpbmcgIT09IFwiXCIpIHtcblxuICAgICAgICAgICAgc3R5bGVTdHIgPSBgbWFyZ2luLWlubGluZTogJHtzZXR0aW5ncy5jb2x1bW5TcGFjaW5nfTtgXG4gICAgICAgIH1cblxuICAgICAgICBpZihzZXR0aW5ncy5udW1iZXJPZkNvbHVtbnMgPT09IDIpIHtcblxuICAgICAgICAgICAgc3dpdGNoKHNldHRpbmdzLmNvbHVtbkxheW91dCkge1xuICAgICAgICAgICAgICAgIGNhc2UoQ29sdW1uTGF5b3V0LnN0YW5kYXJkKTpcbiAgICAgICAgICAgICAgICBjYXNlKENvbHVtbkxheW91dC5taWRkbGUpOlxuICAgICAgICAgICAgICAgIGNhc2UoQ29sdW1uTGF5b3V0LmNlbnRlcik6XG4gICAgICAgICAgICAgICAgY2FzZShDb2x1bW5MYXlvdXQudGhpcmQpOlxuICAgICAgICAgICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2cy5wdXNoKG11bHRpQ29sdW1uUGFyZW50LmNyZWF0ZURpdih7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbHM6IGAke011bHRpQ29sdW1uU3R5bGVDU1MuQ29sdW1uQ29udGVudH0gJHtNdWx0aUNvbHVtbkxheW91dENTUy5Ud29FcXVhbENvbHVtbnN9YFxuICAgICAgICAgICAgICAgICAgICB9KSk7XG4gICAgICAgICAgICAgICAgICAgIG11bHRpQ29sdW1uUGFyZW50LmNyZWF0ZURpdih7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbHM6IGBtY20tY29sdW1uLXNwYWNlcmAsXG4gICAgICAgICAgICAgICAgICAgICAgICBhdHRyOiB7XCJzdHlsZVwiOiBzdHlsZVN0cn1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIGNvbHVtbkNvbnRlbnREaXZzLnB1c2gobXVsdGlDb2x1bW5QYXJlbnQuY3JlYXRlRGl2KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsczogYCR7TXVsdGlDb2x1bW5TdHlsZUNTUy5Db2x1bW5Db250ZW50fSAke011bHRpQ29sdW1uTGF5b3V0Q1NTLlR3b0VxdWFsQ29sdW1uc31gXG4gICAgICAgICAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICBjYXNlKENvbHVtbkxheW91dC5sZWZ0KTpcbiAgICAgICAgICAgICAgICBjYXNlKENvbHVtbkxheW91dC5maXJzdCk6XG4gICAgICAgICAgICAgICAgICAgIGNvbHVtbkNvbnRlbnREaXZzLnB1c2gobXVsdGlDb2x1bW5QYXJlbnQuY3JlYXRlRGl2KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsczogYCR7TXVsdGlDb2x1bW5TdHlsZUNTUy5Db2x1bW5Db250ZW50fSAke011bHRpQ29sdW1uTGF5b3V0Q1NTLlR3b0NvbHVtbkxhcmdlfWBcbiAgICAgICAgICAgICAgICAgICAgfSkpO1xuICAgICAgICAgICAgICAgICAgICBtdWx0aUNvbHVtblBhcmVudC5jcmVhdGVEaXYoe1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xzOiBgbWNtLWNvbHVtbi1zcGFjZXJgLFxuICAgICAgICAgICAgICAgICAgICAgICAgYXR0cjoge1wic3R5bGVcIjogc3R5bGVTdHJ9XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2cy5wdXNoKG11bHRpQ29sdW1uUGFyZW50LmNyZWF0ZURpdih7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbHM6IGAke011bHRpQ29sdW1uU3R5bGVDU1MuQ29sdW1uQ29udGVudH0gJHtNdWx0aUNvbHVtbkxheW91dENTUy5Ud29Db2x1bW5TbWFsbH1gXG4gICAgICAgICAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICBjYXNlKENvbHVtbkxheW91dC5yaWdodCk6XG4gICAgICAgICAgICAgICAgY2FzZShDb2x1bW5MYXlvdXQuc2Vjb25kKTpcbiAgICAgICAgICAgICAgICBjYXNlKENvbHVtbkxheW91dC5sYXN0KTpcbiAgICAgICAgICAgICAgICAgICAgY29sdW1uQ29udGVudERpdnMucHVzaChtdWx0aUNvbHVtblBhcmVudC5jcmVhdGVEaXYoe1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xzOiBgJHtNdWx0aUNvbHVtblN0eWxlQ1NTLkNvbHVtbkNvbnRlbnR9ICR7TXVsdGlDb2x1bW5MYXlvdXRDU1MuVHdvQ29sdW1uU21hbGx9YFxuICAgICAgICAgICAgICAgICAgICB9KSk7XG4gICAgICAgICAgICAgICAgICAgIG11bHRpQ29sdW1uUGFyZW50LmNyZWF0ZURpdih7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbHM6IGBtY20tY29sdW1uLXNwYWNlcmAsXG4gICAgICAgICAgICAgICAgICAgICAgICBhdHRyOiB7XCJzdHlsZVwiOiBzdHlsZVN0cn1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIGNvbHVtbkNvbnRlbnREaXZzLnB1c2gobXVsdGlDb2x1bW5QYXJlbnQuY3JlYXRlRGl2KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsczogYCR7TXVsdGlDb2x1bW5TdHlsZUNTUy5Db2x1bW5Db250ZW50fSAke011bHRpQ29sdW1uTGF5b3V0Q1NTLlR3b0NvbHVtbkxhcmdlfWBcbiAgICAgICAgICAgICAgICAgICAgfSkpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmKHNldHRpbmdzLm51bWJlck9mQ29sdW1ucyA9PT0gMykge1xuXG4gICAgICAgICAgICBzd2l0Y2goc2V0dGluZ3MuY29sdW1uTGF5b3V0KSB7XG4gICAgICAgICAgICAgICAgY2FzZShDb2x1bW5MYXlvdXQuc3RhbmRhcmQpOlxuICAgICAgICAgICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2cy5wdXNoKG11bHRpQ29sdW1uUGFyZW50LmNyZWF0ZURpdih7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbHM6IGAke011bHRpQ29sdW1uU3R5bGVDU1MuQ29sdW1uQ29udGVudH0gJHtNdWx0aUNvbHVtbkxheW91dENTUy5UaHJlZUVxdWFsQ29sdW1uc31gXG4gICAgICAgICAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgICAgICAgICAgbXVsdGlDb2x1bW5QYXJlbnQuY3JlYXRlRGl2KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsczogYG1jbS1jb2x1bW4tc3BhY2VyYCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGF0dHI6IHtcInN0eWxlXCI6IHN0eWxlU3RyfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgY29sdW1uQ29udGVudERpdnMucHVzaChtdWx0aUNvbHVtblBhcmVudC5jcmVhdGVEaXYoe1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xzOiBgJHtNdWx0aUNvbHVtblN0eWxlQ1NTLkNvbHVtbkNvbnRlbnR9ICR7TXVsdGlDb2x1bW5MYXlvdXRDU1MuVGhyZWVFcXVhbENvbHVtbnN9YFxuICAgICAgICAgICAgICAgICAgICB9KSk7XG4gICAgICAgICAgICAgICAgICAgIG11bHRpQ29sdW1uUGFyZW50LmNyZWF0ZURpdih7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbHM6IGBtY20tY29sdW1uLXNwYWNlcmAsXG4gICAgICAgICAgICAgICAgICAgICAgICBhdHRyOiB7XCJzdHlsZVwiOiBzdHlsZVN0cn1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIGNvbHVtbkNvbnRlbnREaXZzLnB1c2gobXVsdGlDb2x1bW5QYXJlbnQuY3JlYXRlRGl2KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsczogYCR7TXVsdGlDb2x1bW5TdHlsZUNTUy5Db2x1bW5Db250ZW50fSAke011bHRpQ29sdW1uTGF5b3V0Q1NTLlRocmVlRXF1YWxDb2x1bW5zfWBcbiAgICAgICAgICAgICAgICAgICAgfSkpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgIGNhc2UoQ29sdW1uTGF5b3V0LmxlZnQpOlxuICAgICAgICAgICAgICAgIGNhc2UoQ29sdW1uTGF5b3V0LmZpcnN0KTpcbiAgICAgICAgICAgICAgICAgICAgY29sdW1uQ29udGVudERpdnMucHVzaChtdWx0aUNvbHVtblBhcmVudC5jcmVhdGVEaXYoe1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xzOiBgJHtNdWx0aUNvbHVtblN0eWxlQ1NTLkNvbHVtbkNvbnRlbnR9ICR7TXVsdGlDb2x1bW5MYXlvdXRDU1MuVGhyZWVDb2x1bW5fTGFyZ2V9YFxuICAgICAgICAgICAgICAgICAgICB9KSk7XG4gICAgICAgICAgICAgICAgICAgIG11bHRpQ29sdW1uUGFyZW50LmNyZWF0ZURpdih7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbHM6IGBtY20tY29sdW1uLXNwYWNlcmAsXG4gICAgICAgICAgICAgICAgICAgICAgICBhdHRyOiB7XCJzdHlsZVwiOiBzdHlsZVN0cn1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIGNvbHVtbkNvbnRlbnREaXZzLnB1c2gobXVsdGlDb2x1bW5QYXJlbnQuY3JlYXRlRGl2KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsczogYCR7TXVsdGlDb2x1bW5TdHlsZUNTUy5Db2x1bW5Db250ZW50fSAke011bHRpQ29sdW1uTGF5b3V0Q1NTLlRocmVlQ29sdW1uX1NtYWxsfWBcbiAgICAgICAgICAgICAgICAgICAgfSkpO1xuICAgICAgICAgICAgICAgICAgICBtdWx0aUNvbHVtblBhcmVudC5jcmVhdGVEaXYoe1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xzOiBgbWNtLWNvbHVtbi1zcGFjZXJgLFxuICAgICAgICAgICAgICAgICAgICAgICAgYXR0cjoge1wic3R5bGVcIjogc3R5bGVTdHJ9XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2cy5wdXNoKG11bHRpQ29sdW1uUGFyZW50LmNyZWF0ZURpdih7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbHM6IGAke011bHRpQ29sdW1uU3R5bGVDU1MuQ29sdW1uQ29udGVudH0gJHtNdWx0aUNvbHVtbkxheW91dENTUy5UaHJlZUNvbHVtbl9TbWFsbH1gXG4gICAgICAgICAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICBjYXNlKENvbHVtbkxheW91dC5taWRkbGUpOlxuICAgICAgICAgICAgICAgIGNhc2UoQ29sdW1uTGF5b3V0LmNlbnRlcik6XG4gICAgICAgICAgICAgICAgY2FzZShDb2x1bW5MYXlvdXQuc2Vjb25kKTpcbiAgICAgICAgICAgICAgICAgICAgY29sdW1uQ29udGVudERpdnMucHVzaChtdWx0aUNvbHVtblBhcmVudC5jcmVhdGVEaXYoe1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xzOiBgJHtNdWx0aUNvbHVtblN0eWxlQ1NTLkNvbHVtbkNvbnRlbnR9ICR7TXVsdGlDb2x1bW5MYXlvdXRDU1MuVGhyZWVDb2x1bW5fU21hbGx9YFxuICAgICAgICAgICAgICAgICAgICB9KSk7XG4gICAgICAgICAgICAgICAgICAgIG11bHRpQ29sdW1uUGFyZW50LmNyZWF0ZURpdih7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbHM6IGBtY20tY29sdW1uLXNwYWNlcmAsXG4gICAgICAgICAgICAgICAgICAgICAgICBhdHRyOiB7XCJzdHlsZVwiOiBzdHlsZVN0cn1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIGNvbHVtbkNvbnRlbnREaXZzLnB1c2gobXVsdGlDb2x1bW5QYXJlbnQuY3JlYXRlRGl2KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsczogYCR7TXVsdGlDb2x1bW5TdHlsZUNTUy5Db2x1bW5Db250ZW50fSAke011bHRpQ29sdW1uTGF5b3V0Q1NTLlRocmVlQ29sdW1uX0xhcmdlfWBcbiAgICAgICAgICAgICAgICAgICAgfSkpO1xuICAgICAgICAgICAgICAgICAgICBtdWx0aUNvbHVtblBhcmVudC5jcmVhdGVEaXYoe1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xzOiBgbWNtLWNvbHVtbi1zcGFjZXJgLFxuICAgICAgICAgICAgICAgICAgICAgICAgYXR0cjoge1wic3R5bGVcIjogc3R5bGVTdHJ9XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2cy5wdXNoKG11bHRpQ29sdW1uUGFyZW50LmNyZWF0ZURpdih7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbHM6IGAke011bHRpQ29sdW1uU3R5bGVDU1MuQ29sdW1uQ29udGVudH0gJHtNdWx0aUNvbHVtbkxheW91dENTUy5UaHJlZUNvbHVtbl9TbWFsbH1gXG4gICAgICAgICAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICBjYXNlKENvbHVtbkxheW91dC5yaWdodCk6XG4gICAgICAgICAgICAgICAgY2FzZShDb2x1bW5MYXlvdXQudGhpcmQpOlxuICAgICAgICAgICAgICAgIGNhc2UoQ29sdW1uTGF5b3V0Lmxhc3QpOlxuICAgICAgICAgICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2cy5wdXNoKG11bHRpQ29sdW1uUGFyZW50LmNyZWF0ZURpdih7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbHM6IGAke011bHRpQ29sdW1uU3R5bGVDU1MuQ29sdW1uQ29udGVudH0gJHtNdWx0aUNvbHVtbkxheW91dENTUy5UaHJlZUNvbHVtbl9TbWFsbH1gXG4gICAgICAgICAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgICAgICAgICAgbXVsdGlDb2x1bW5QYXJlbnQuY3JlYXRlRGl2KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsczogYG1jbS1jb2x1bW4tc3BhY2VyYCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGF0dHI6IHtcInN0eWxlXCI6IHN0eWxlU3RyfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgY29sdW1uQ29udGVudERpdnMucHVzaChtdWx0aUNvbHVtblBhcmVudC5jcmVhdGVEaXYoe1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xzOiBgJHtNdWx0aUNvbHVtblN0eWxlQ1NTLkNvbHVtbkNvbnRlbnR9ICR7TXVsdGlDb2x1bW5MYXlvdXRDU1MuVGhyZWVDb2x1bW5fU21hbGx9YFxuICAgICAgICAgICAgICAgICAgICB9KSk7XG4gICAgICAgICAgICAgICAgICAgIG11bHRpQ29sdW1uUGFyZW50LmNyZWF0ZURpdih7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbHM6IGBtY20tY29sdW1uLXNwYWNlcmAsXG4gICAgICAgICAgICAgICAgICAgICAgICBhdHRyOiB7XCJzdHlsZVwiOiBzdHlsZVN0cn1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIGNvbHVtbkNvbnRlbnREaXZzLnB1c2gobXVsdGlDb2x1bW5QYXJlbnQuY3JlYXRlRGl2KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsczogYCR7TXVsdGlDb2x1bW5TdHlsZUNTUy5Db2x1bW5Db250ZW50fSAke011bHRpQ29sdW1uTGF5b3V0Q1NTLlRocmVlQ29sdW1uX0xhcmdlfWBcbiAgICAgICAgICAgICAgICAgICAgfSkpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBjb2x1bW5Db250ZW50RGl2cztcbiAgICB9XG5cbiAgICBwdWJsaWMgYWJzdHJhY3QgcmVuZGVyUmVnaW9uRWxlbWVudHNUb1NjcmVlbigpOiB2b2lkO1xuICAgIHB1YmxpYyBhYnN0cmFjdCBleHBvcnRSZWdpb25FbGVtZW50c1RvUERGKHBkZlBhcmVudEVsZW1lbnQ6IEhUTUxFbGVtZW50KTogdm9pZDtcbiAgICBwdWJsaWMgYWJzdHJhY3QgcmVuZGVyUmVnaW9uRWxlbWVudHNUb0xpdmVQcmV2aWV3KHBhcmVudEVsZW1lbnQ6IEhUTUxFbGVtZW50KTogdm9pZFxufVxuXG5cbmZ1bmN0aW9uIGdldEVsZW1lbnRDbGllbnRIZWlnaHQoZWxlbWVudDogSFRNTEVsZW1lbnQsIHBhcmVudFJlbmRlckVsZW1lbnQ6IEhUTUxEaXZFbGVtZW50KTogbnVtYmVyIHtcblxuICAgIGxldCBoZWlnaHQgPSBlbGVtZW50LmNsaWVudEhlaWdodDtcbiAgICBpZihoZWlnaHQgPT09IDApIHtcbiAgICAgICAgcGFyZW50UmVuZGVyRWxlbWVudC5hcHBlbmRDaGlsZChlbGVtZW50KTtcbiAgICAgICAgaGVpZ2h0ID0gZWxlbWVudC5jbGllbnRIZWlnaHRcbiAgICAgICAgcGFyZW50UmVuZGVyRWxlbWVudC5yZW1vdmVDaGlsZChlbGVtZW50KTtcbiAgICB9XG4gICAgcmV0dXJuIGhlaWdodFxufSIsIi8qKlxuICogRmlsZTogL3NyYy9kb21fbWFuYWdlci9yZWdpb25hbF9tYW5hZ2Vycy9yZWdpb25ET01NYW5hZ2VyLnRzICAgICAgICAgICAgICAgICpcbiAqIENyZWF0ZWQgRGF0ZTogU3VuZGF5LCBNYXkgMjJuZCAyMDIyLCA3OjQ2IHBtICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gKiBBdXRob3I6IENhbWVyb24gUm9iaW5zb24gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpcbiAqIENvcHlyaWdodCAoYykgMjAyMiBDYW1lcm9uIFJvYmluc29uICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gKi9cblxuaW1wb3J0IHsgRE9NT2JqZWN0LCBET01PYmplY3RUYWcsIFRhc2tMaXN0RE9NT2JqZWN0IH0gZnJvbSAnLi4vZG9tT2JqZWN0JztcbmltcG9ydCB7IE11bHRpQ29sdW1uU2V0dGluZ3MsIENvbnRlbnRPdmVyZmxvd1R5cGUgfSBmcm9tIFwiLi4vLi4vcmVnaW9uU2V0dGluZ3NcIjtcbmltcG9ydCB7IE11bHRpQ29sdW1uTGF5b3V0Q1NTLCBNdWx0aUNvbHVtblN0eWxlQ1NTIH0gZnJvbSAnLi4vLi4vdXRpbGl0aWVzL2Nzc0RlZmluaXRpb25zJztcbmltcG9ydCB7IE1hcmtkb3duUmVuZGVyQ2hpbGQgfSBmcm9tICdvYnNpZGlhbic7XG5pbXBvcnQgeyBSZWdpb25NYW5hZ2VyIH0gZnJvbSAnLi9yZWdpb25NYW5hZ2VyJztcbmltcG9ydCB7IGdldEhlYWRpbmdDb2xsYXBzZUVsZW1lbnQgfSBmcm9tICdzcmMvdXRpbGl0aWVzL2VsZW1lbnRSZW5kZXJUeXBlUGFyc2VyJztcblxuZXhwb3J0IGNsYXNzIFN0YW5kYXJkTXVsdGlDb2x1bW5SZWdpb25NYW5hZ2VyIGV4dGVuZHMgUmVnaW9uTWFuYWdlciB7XG5cblxuICAgIHB1YmxpYyByZW5kZXJSZWdpb25FbGVtZW50c1RvU2NyZWVuKCk6IHZvaWQge1xuXG4gICAgICAgIHRoaXMucmVuZGVyQ29sdW1uTWFya2Rvd24odGhpcy5yZWdpb25QYXJlbnQsIHRoaXMuZG9tTGlzdCwgdGhpcy5yZWdpb25hbFNldHRpbmdzKTtcbiAgICB9XG4gICAgcHVibGljIGV4cG9ydFJlZ2lvbkVsZW1lbnRzVG9QREYocGRmUGFyZW50RWxlbWVudDogSFRNTEVsZW1lbnQpOiB2b2lkIHtcblxuICAgICAgICAvLyBEZWZhdWx0IHNldCBzaGFkb3cgdG8gb2ZmIGZvciBleHBvcnRpbmcgUERGc1xuICAgICAgICBsZXQgcmVuZGVyU2V0dGluZ3MgPSB0aGlzLnJlZ2lvbmFsU2V0dGluZ3M7XG4gICAgICAgIHJlbmRlclNldHRpbmdzLmRyYXdTaGFkb3cgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5yZW5kZXJDb2x1bW5NYXJrZG93bihwZGZQYXJlbnRFbGVtZW50LCB0aGlzLmRvbUxpc3Quc2xpY2UoKSwgcmVuZGVyU2V0dGluZ3MpO1xuICAgIH1cbiAgICBwdWJsaWMgcmVuZGVyUmVnaW9uRWxlbWVudHNUb0xpdmVQcmV2aWV3KHBhcmVudEVsZW1lbnQ6IEhUTUxFbGVtZW50KTogdm9pZCB7XG5cbiAgICAgICAgdGhpcy5yZW5kZXJDb2x1bW5NYXJrZG93bihwYXJlbnRFbGVtZW50LCB0aGlzLmRvbUxpc3QsIHRoaXMucmVnaW9uYWxTZXR0aW5ncyk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFRoaXMgZnVuY3Rpb24gdGFrZXMgaW4gdGhlIGRhdGEgZm9yIHRoZSBtdWx0aS1jb2x1bW4gcmVnaW9uIGFuZCBzZXRzIHVwIHRoZSBcbiAgICAgKiB1c2VyIGRlZmluZWQgbnVtYmVyIG9mIGNoaWxkcmVuIHdpdGggdGhlIHByb3BlciBjc3MgY2xhc3NlcyB0byBiZSByZW5kZXJlZCBwcm9wZXJseS5cbiAgICAgKiBcbiAgICAgKiBAcGFyYW0gcGFyZW50RWxlbWVudCBUaGUgZWxlbWVudCB0aGF0IHRoZSBtdWx0aS1jb2x1bW4gcmVnaW9uIHdpbGwgYmUgcmVuZGVyZWQgdW5kZXIuXG4gICAgICogQHBhcmFtIHJlZ2lvbkVsZW1lbnRzIFRoZSBsaXN0IG9mIERPTSBvYmplY3RzIHRoYXQgd2lsbCBiZSBjb3BwaWVkIHVuZGVyIHRoZSBwYXJlbnQgb2JqZWN0XG4gICAgICogQHBhcmFtIHNldHRpbmdzIFRoZSBzZXR0aW5ncyB0aGUgdXNlciBoYXMgZGVmaW5lZCBmb3IgdGhlIHJlZ2lvbi5cbiAgICAgKi9cbiAgICBwcml2YXRlIHJlbmRlckNvbHVtbk1hcmtkb3duKHBhcmVudEVsZW1lbnQ6IEhUTUxFbGVtZW50LCByZWdpb25FbGVtZW50czogRE9NT2JqZWN0W10sIHNldHRpbmdzOiBNdWx0aUNvbHVtblNldHRpbmdzKSB7XG5cbiAgICAgICAgbGV0IG11bHRpQ29sdW1uUGFyZW50ID0gY3JlYXRlRGl2KHtcbiAgICAgICAgICAgIGNsczogTXVsdGlDb2x1bW5MYXlvdXRDU1MuUmVnaW9uQ29sdW1uQ29udGFpbmVyRGl2LFxuICAgICAgICB9KTtcblxuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBQYXNzIG91ciBwYXJlbnQgZGl2IGFuZCBzZXR0aW5ncyB0byBwYXJzZXIgdG8gY3JlYXRlIHRoZSByZXF1aXJlZFxuICAgICAgICAgKiBjb2x1bW4gZGl2cyBhcyBjaGlsZHJlbiBvZiB0aGUgcGFyZW50LlxuICAgICAgICAgKi9cbiAgICAgICAgbGV0IGNvbHVtbkNvbnRlbnREaXZzID0gdGhpcy5nZXRDb2x1bW5Db250ZW50RGl2cyhzZXR0aW5ncywgbXVsdGlDb2x1bW5QYXJlbnQpO1xuICAgICAgICBpZihzZXR0aW5ncy5kcmF3U2hhZG93ID09PSB0cnVlKSB7XG4gICAgICAgICAgICBtdWx0aUNvbHVtblBhcmVudC5hZGRDbGFzcyhNdWx0aUNvbHVtblN0eWxlQ1NTLlJlZ2lvblNoYWRvdyk7XG4gICAgICAgIH1cbiAgICAgICAgZm9yKGxldCBpID0gMDsgaSA8IGNvbHVtbkNvbnRlbnREaXZzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBpZihzZXR0aW5ncy5kcmF3Qm9yZGVyID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgY29sdW1uQ29udGVudERpdnNbaV0uYWRkQ2xhc3MoTXVsdGlDb2x1bW5TdHlsZUNTUy5Db2x1bW5Cb3JkZXIpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZihzZXR0aW5ncy5kcmF3U2hhZG93ID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgY29sdW1uQ29udGVudERpdnNbaV0uYWRkQ2xhc3MoTXVsdGlDb2x1bW5TdHlsZUNTUy5Db2x1bW5TaGFkb3cpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ3JlYXRlIG1hcmtkb3duIHJlbmRlcmVyIHRvIHBhcnNlIHRoZSBwYXNzZWQgbWFya2Rvd25cbiAgICAgICAgLy8gYmV0d2VlbiB0aGUgdGFncy5cbiAgICAgICAgbGV0IG1hcmtkb3duUmVuZGVyQ2hpbGQgPSBuZXcgTWFya2Rvd25SZW5kZXJDaGlsZChcbiAgICAgICAgICAgIG11bHRpQ29sdW1uUGFyZW50XG4gICAgICAgICk7XG5cbiAgICAgICAgLy8gUmVtb3ZlIGV2ZXJ5IG90aGVyIGNoaWxkIGZyb20gdGhlIHBhcmVudCBzbyBcbiAgICAgICAgLy8gd2UgZG9udCBlbmQgdXAgd2l0aCBtdWx0aXBsZSBzZXRzIG9mIGRhdGEuIFRoaXMgc2hvdWxkXG4gICAgICAgIC8vIHJlYWxseSBvbmx5IG5lZWQgdG8gbG9vcCBvbmNlIGZvciBpID0gMCBidXQgbG9vcCBqdXN0XG4gICAgICAgIC8vIGluIGNhc2UuXG4gICAgICAgIGZvcihsZXQgaSA9IHBhcmVudEVsZW1lbnQuY2hpbGRyZW4ubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICAgIHBhcmVudEVsZW1lbnQuY2hpbGRyZW5baV0uZGV0YWNoKCk7XG4gICAgICAgIH1cbiAgICAgICAgcGFyZW50RWxlbWVudC5hcHBlbmRDaGlsZChtYXJrZG93blJlbmRlckNoaWxkLmNvbnRhaW5lckVsKTtcblxuICAgICAgICB0aGlzLmFwcGVuZEVsZW1lbnRzVG9Db2x1bW5zKHJlZ2lvbkVsZW1lbnRzLCBjb2x1bW5Db250ZW50RGl2cywgc2V0dGluZ3MpO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXBwZW5kRWxlbWVudHNUb0NvbHVtbnMocmVnaW9uRWxlbWVudHM6IERPTU9iamVjdFtdLCBjb2x1bW5Db250ZW50RGl2czogSFRNTERpdkVsZW1lbnRbXSwgc2V0dGluZ3M6IE11bHRpQ29sdW1uU2V0dGluZ3MpIHtcblxuICAgICAgICBsZXQgY29sdW1uSW5kZXggPSAwO1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHJlZ2lvbkVsZW1lbnRzLmxlbmd0aDsgaSsrKSB7XG5cbiAgICAgICAgICAgIGlmIChyZWdpb25FbGVtZW50c1tpXS50YWcgPT09IERPTU9iamVjdFRhZy5ub25lIHx8XG4gICAgICAgICAgICAgICAgcmVnaW9uRWxlbWVudHNbaV0udGFnID09PSBET01PYmplY3RUYWcuY29sdW1uQnJlYWspIHtcblxuICAgICAgICAgICAgICAgIC8vIFdlIHN0b3JlIHRoZSBlbGVtZW50cyBpbiBhIHdyYXBwZXIgY29udGFpbmVyIHVudGlsIHdlIGRldGVybWluZVxuICAgICAgICAgICAgICAgIGxldCBlbGVtZW50ID0gY3JlYXRlRGl2KHtcbiAgICAgICAgICAgICAgICAgICAgY2xzOiBNdWx0aUNvbHVtbkxheW91dENTUy5Db2x1bW5EdWFsRWxlbWVudENvbnRhaW5lcixcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIGlmKHNldHRpbmdzLmNvbnRlbnRPdmVyZmxvdyA9PT0gQ29udGVudE92ZXJmbG93VHlwZS5oaWRkZW4pIHtcbiAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5hZGRDbGFzcyhNdWx0aUNvbHVtbkxheW91dENTUy5Db250ZW50T3ZlcmZsb3dIaWRkZW4pXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBlbGVtZW50LmFkZENsYXNzKE11bHRpQ29sdW1uTGF5b3V0Q1NTLkNvbnRlbnRPdmVyZmxvd0F1dG9TY3JvbGwpXG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmVnaW9uRWxlbWVudHNbaV0uZWxlbWVudENvbnRhaW5lciA9IGVsZW1lbnQ7XG5cbiAgICAgICAgICAgICAgICAvLyBPdGhlcndpc2Ugd2UganVzdCBtYWtlIGEgY29weSBvZiB0aGUgb3JpZ2luYWwgZWxlbWVudCB0byBkaXNwbGF5LlxuICAgICAgICAgICAgICAgIGxldCBjbG9uZWRFbGVtZW50ID0gcmVnaW9uRWxlbWVudHNbaV0ub3JpZ2luYWxFbGVtZW50LmNsb25lTm9kZSh0cnVlKSBhcyBIVE1MRGl2RWxlbWVudDtcbiAgICAgICAgICAgICAgICBsZXQgaGVhZGluZ0NvbGxhcHNlRWxlbWVudCA9IGdldEhlYWRpbmdDb2xsYXBzZUVsZW1lbnQoY2xvbmVkRWxlbWVudCk7XG4gICAgICAgICAgICAgICAgaWYoaGVhZGluZ0NvbGxhcHNlRWxlbWVudCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIHJlbW92ZXMgdGhlIGNvbGxhcHNlIGFycm93IGZyb20gdGhlIHZpZXcgaWYgaXQgZXhpc3RzLlxuICAgICAgICAgICAgICAgICAgICBoZWFkaW5nQ29sbGFwc2VFbGVtZW50LmRldGFjaCgpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJlZ2lvbkVsZW1lbnRzW2ldLmNsb25lZEVsZW1lbnQgPSBjbG9uZWRFbGVtZW50O1xuICAgICAgICAgICAgICAgIGVsZW1lbnQuYXBwZW5kQ2hpbGQoY2xvbmVkRWxlbWVudCk7XG5cbiAgICAgICAgICAgICAgICBpZiAocmVnaW9uRWxlbWVudHNbaV0gaW5zdGFuY2VvZiBUYXNrTGlzdERPTU9iamVjdCkge1xuXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZml4Q2xvbmVkQ2hlY2tMaXN0QnV0dG9ucyhyZWdpb25FbGVtZW50c1tpXSBhcyBUYXNrTGlzdERPTU9iamVjdCwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGVsZW1lbnQgIT09IG51bGwgJiYgcmVnaW9uRWxlbWVudHNbaV0udGFnICE9PSBET01PYmplY3RUYWcuY29sdW1uQnJlYWspIHtcblxuICAgICAgICAgICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2c1tjb2x1bW5JbmRleF0uYXBwZW5kQ2hpbGQoZWxlbWVudCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgICAgICogSWYgdGhlIHRhZyBpcyBhIGNvbHVtbiBicmVhayB3ZSB1cGRhdGUgdGhlIGNvbHVtbiBpbmRleCBhZnRlclxuICAgICAgICAgICAgICAgICAqIGFwcGVuZGluZyB0aGUgaXRlbSB0byB0aGUgY29sdW1uIGRpdi4gVGhpcyBrZWVwcyB0aGUgbWFpbiBET01cbiAgICAgICAgICAgICAgICAgKiBjbGVhbmVyIGJ5IHJlbW92aW5nIG90aGVyIGl0ZW1zIGFuZCBwbGFjaW5nIHRoZW0gYWxsIHdpdGhpblxuICAgICAgICAgICAgICAgICAqIGEgcmVnaW9uIGNvbnRhaW5lci5cbiAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICBpZiAocmVnaW9uRWxlbWVudHNbaV0udGFnID09PSBET01PYmplY3RUYWcuY29sdW1uQnJlYWsgJiZcbiAgICAgICAgICAgICAgICAgICAgKGNvbHVtbkluZGV4ICsgMSkgPCBzZXR0aW5ncy5udW1iZXJPZkNvbHVtbnMpIHtcblxuICAgICAgICAgICAgICAgICAgICBjb2x1bW5JbmRleCsrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbn1cblxuIiwiaW1wb3J0IHsgRE9NT2JqZWN0LCBET01PYmplY3RUYWcsIFRhc2tMaXN0RE9NT2JqZWN0IH0gZnJvbSAnLi4vZG9tT2JqZWN0JztcbmltcG9ydCB7IE11bHRpQ29sdW1uU2V0dGluZ3MsIENvbHVtbkxheW91dCwgU2luZ2xlQ29sdW1uU2l6ZSB9IGZyb20gXCIuLi8uLi9yZWdpb25TZXR0aW5nc1wiO1xuaW1wb3J0IHsgTXVsdGlDb2x1bW5MYXlvdXRDU1MsIE11bHRpQ29sdW1uU3R5bGVDU1MgfSBmcm9tICcuLi8uLi91dGlsaXRpZXMvY3NzRGVmaW5pdGlvbnMnO1xuaW1wb3J0IHsgTWFya2Rvd25SZW5kZXJDaGlsZCB9IGZyb20gJ29ic2lkaWFuJztcbmltcG9ydCB7IFJlZ2lvbk1hbmFnZXIgfSBmcm9tICcuL3JlZ2lvbk1hbmFnZXInO1xuaW1wb3J0IHsgZ2V0SGVhZGluZ0NvbGxhcHNlRWxlbWVudCB9IGZyb20gJ3NyYy91dGlsaXRpZXMvZWxlbWVudFJlbmRlclR5cGVQYXJzZXInO1xuXG5cbmV4cG9ydCBjbGFzcyBTaW5nbGVDb2x1bW5SZWdpb25NYW5hZ2VyIGV4dGVuZHMgUmVnaW9uTWFuYWdlciB7XG5cblxuICAgIHB1YmxpYyByZW5kZXJSZWdpb25FbGVtZW50c1RvU2NyZWVuKCk6IHZvaWQge1xuXG4gICAgICAgIHRoaXMucmVuZGVyQ29sdW1uTWFya2Rvd24odGhpcy5yZWdpb25QYXJlbnQsIHRoaXMuZG9tTGlzdCwgdGhpcy5yZWdpb25hbFNldHRpbmdzKTtcbiAgICB9XG4gICAgcHVibGljIGV4cG9ydFJlZ2lvbkVsZW1lbnRzVG9QREYocGRmUGFyZW50RWxlbWVudDogSFRNTEVsZW1lbnQpOiB2b2lkIHtcblxuICAgICAgICAvLyBEZWZhdWx0IHNldCBzaGFkb3cgdG8gb2ZmIGZvciBleHBvcnRpbmcgUERGc1xuICAgICAgICBsZXQgcmVuZGVyU2V0dGluZ3MgPSB0aGlzLnJlZ2lvbmFsU2V0dGluZ3M7XG4gICAgICAgIHJlbmRlclNldHRpbmdzLmRyYXdTaGFkb3cgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5yZW5kZXJDb2x1bW5NYXJrZG93bihwZGZQYXJlbnRFbGVtZW50LCB0aGlzLmRvbUxpc3Quc2xpY2UoKSwgcmVuZGVyU2V0dGluZ3MpO1xuICAgIH1cbiAgICBwdWJsaWMgcmVuZGVyUmVnaW9uRWxlbWVudHNUb0xpdmVQcmV2aWV3KHBhcmVudEVsZW1lbnQ6IEhUTUxFbGVtZW50KTogdm9pZCB7XG5cbiAgICAgICAgdGhpcy5yZW5kZXJDb2x1bW5NYXJrZG93bihwYXJlbnRFbGVtZW50LCB0aGlzLmRvbUxpc3QsIHRoaXMucmVnaW9uYWxTZXR0aW5ncyk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFRoaXMgZnVuY3Rpb24gdGFrZXMgaW4gdGhlIGRhdGEgZm9yIHRoZSBtdWx0aS1jb2x1bW4gcmVnaW9uIGFuZCBzZXRzIHVwIHRoZVxuICAgICAqIHVzZXIgZGVmaW5lZCBudW1iZXIgb2YgY2hpbGRyZW4gd2l0aCB0aGUgcHJvcGVyIGNzcyBjbGFzc2VzIHRvIGJlIHJlbmRlcmVkIHByb3Blcmx5LlxuICAgICAqXG4gICAgICogQHBhcmFtIHBhcmVudEVsZW1lbnQgVGhlIGVsZW1lbnQgdGhhdCB0aGUgbXVsdGktY29sdW1uIHJlZ2lvbiB3aWxsIGJlIHJlbmRlcmVkIHVuZGVyLlxuICAgICAqIEBwYXJhbSByZWdpb25FbGVtZW50cyBUaGUgbGlzdCBvZiBET00gb2JqZWN0cyB0aGF0IHdpbGwgYmUgY29wcGllZCB1bmRlciB0aGUgcGFyZW50IG9iamVjdFxuICAgICAqIEBwYXJhbSBzZXR0aW5ncyBUaGUgc2V0dGluZ3MgdGhlIHVzZXIgaGFzIGRlZmluZWQgZm9yIHRoZSByZWdpb24uXG4gICAgICovXG4gICAgcHJvdGVjdGVkIHJlbmRlckNvbHVtbk1hcmtkb3duKHBhcmVudEVsZW1lbnQ6IEhUTUxFbGVtZW50LCByZWdpb25FbGVtZW50czogRE9NT2JqZWN0W10sIHNldHRpbmdzOiBNdWx0aUNvbHVtblNldHRpbmdzKSB7XG5cbiAgICAgICAgbGV0IG11bHRpQ29sdW1uUGFyZW50ID0gY3JlYXRlRGl2KHtcbiAgICAgICAgICAgIGNsczogTXVsdGlDb2x1bW5MYXlvdXRDU1MuUmVnaW9uQ29sdW1uQ29udGFpbmVyRGl2LFxuICAgICAgICB9KTtcblxuICAgICAgICBpZihpc0xlZnRMYXlvdXQodGhpcy5yZWdpb25hbFNldHRpbmdzLmNvbHVtblBvc2l0aW9uKSl7XG4gICAgICAgICAgICBtdWx0aUNvbHVtblBhcmVudC5hZGRDbGFzcyhNdWx0aUNvbHVtbkxheW91dENTUy5TaW5nbGVDb2x1bW5MZWZ0TGF5b3V0KVxuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYoaXNSaWdodExheW91dCh0aGlzLnJlZ2lvbmFsU2V0dGluZ3MuY29sdW1uUG9zaXRpb24pKSB7XG4gICAgICAgICAgICBtdWx0aUNvbHVtblBhcmVudC5hZGRDbGFzcyhNdWx0aUNvbHVtbkxheW91dENTUy5TaW5nbGVDb2x1bW5SaWdodExheW91dClcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIG11bHRpQ29sdW1uUGFyZW50LmFkZENsYXNzKE11bHRpQ29sdW1uTGF5b3V0Q1NTLlNpbmdsZUNvbHVtbkNlbnRlckxheW91dClcbiAgICAgICAgfVxuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBQYXNzIG91ciBwYXJlbnQgZGl2IGFuZCBzZXR0aW5ncyB0byBwYXJzZXIgdG8gY3JlYXRlIHRoZSByZXF1aXJlZFxuICAgICAgICAgKiBjb2x1bW4gZGl2cyBhcyBjaGlsZHJlbiBvZiB0aGUgcGFyZW50LlxuICAgICAgICAgKi9cbiAgICAgICAgbGV0IGNvbHVtbkNvbnRlbnREaXYgPSB0aGlzLmNyZWF0ZUNvbHVtbkNvbnRlbnREaXZzKG11bHRpQ29sdW1uUGFyZW50KTtcbiAgICAgICAgaWYgKHNldHRpbmdzLmRyYXdCb3JkZXIgPT09IHRydWUpIHtcbiAgICAgICAgICAgIGNvbHVtbkNvbnRlbnREaXYuYWRkQ2xhc3MoTXVsdGlDb2x1bW5TdHlsZUNTUy5Db2x1bW5Cb3JkZXIpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChzZXR0aW5ncy5kcmF3U2hhZG93ID09PSB0cnVlKSB7XG4gICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2LmFkZENsYXNzKE11bHRpQ29sdW1uU3R5bGVDU1MuQ29sdW1uU2hhZG93KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIENyZWF0ZSBtYXJrZG93biByZW5kZXJlciB0byBwYXJzZSB0aGUgcGFzc2VkIG1hcmtkb3duXG4gICAgICAgIC8vIGJldHdlZW4gdGhlIHRhZ3MuXG4gICAgICAgIGxldCBtYXJrZG93blJlbmRlckNoaWxkID0gbmV3IE1hcmtkb3duUmVuZGVyQ2hpbGQoXG4gICAgICAgICAgICBtdWx0aUNvbHVtblBhcmVudFxuICAgICAgICApO1xuXG4gICAgICAgIC8vIFJlbW92ZSBldmVyeSBvdGhlciBjaGlsZCBmcm9tIHRoZSBwYXJlbnQgc28gXG4gICAgICAgIC8vIHdlIGRvbnQgZW5kIHVwIHdpdGggbXVsdGlwbGUgc2V0cyBvZiBkYXRhLiBUaGlzIHNob3VsZFxuICAgICAgICAvLyByZWFsbHkgb25seSBuZWVkIHRvIGxvb3Agb25jZSBmb3IgaSA9IDAgYnV0IGxvb3AganVzdFxuICAgICAgICAvLyBpbiBjYXNlLlxuICAgICAgICBmb3IgKGxldCBpID0gcGFyZW50RWxlbWVudC5jaGlsZHJlbi5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICAgICAgcGFyZW50RWxlbWVudC5jaGlsZHJlbltpXS5kZXRhY2goKTtcbiAgICAgICAgfVxuICAgICAgICBwYXJlbnRFbGVtZW50LmFwcGVuZENoaWxkKG1hcmtkb3duUmVuZGVyQ2hpbGQuY29udGFpbmVyRWwpO1xuXG4gICAgICAgIHRoaXMuYXBwZW5kRWxlbWVudHNUb0NvbHVtbnMocmVnaW9uRWxlbWVudHMsIGNvbHVtbkNvbnRlbnREaXYsIHNldHRpbmdzKTtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgYXBwZW5kRWxlbWVudHNUb0NvbHVtbnMocmVnaW9uRWxlbWVudHM6IERPTU9iamVjdFtdLCBjb2x1bW5Db250ZW50RGl2OiBIVE1MRGl2RWxlbWVudCwgc2V0dGluZ3M6IE11bHRpQ29sdW1uU2V0dGluZ3MpIHtcblxuXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcmVnaW9uRWxlbWVudHMubGVuZ3RoOyBpKyspIHtcblxuICAgICAgICAgICAgaWYgKHJlZ2lvbkVsZW1lbnRzW2ldLnRhZyA9PT0gRE9NT2JqZWN0VGFnLm5vbmUgfHxcbiAgICAgICAgICAgICAgICByZWdpb25FbGVtZW50c1tpXS50YWcgPT09IERPTU9iamVjdFRhZy5jb2x1bW5CcmVhaykge1xuXG4gICAgICAgICAgICAgICAgLy8gV2Ugc3RvcmUgdGhlIGVsZW1lbnRzIGluIGEgd3JhcHBlciBjb250YWluZXIgdW50aWwgd2UgZGV0ZXJtaW5lXG4gICAgICAgICAgICAgICAgbGV0IGVsZW1lbnQgPSBjcmVhdGVEaXYoe1xuICAgICAgICAgICAgICAgICAgICBjbHM6IE11bHRpQ29sdW1uTGF5b3V0Q1NTLkNvbHVtbkR1YWxFbGVtZW50Q29udGFpbmVyLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHJlZ2lvbkVsZW1lbnRzW2ldLmVsZW1lbnRDb250YWluZXIgPSBlbGVtZW50O1xuXG4gICAgICAgICAgICAgICAgLy8gT3RoZXJ3aXNlIHdlIGp1c3QgbWFrZSBhIGNvcHkgb2YgdGhlIG9yaWdpbmFsIGVsZW1lbnQgdG8gZGlzcGxheS5cbiAgICAgICAgICAgICAgICBsZXQgY2xvbmVkRWxlbWVudCA9IHJlZ2lvbkVsZW1lbnRzW2ldLm9yaWdpbmFsRWxlbWVudC5jbG9uZU5vZGUodHJ1ZSkgYXMgSFRNTERpdkVsZW1lbnQ7XG4gICAgICAgICAgICAgICAgbGV0IGhlYWRpbmdDb2xsYXBzZUVsZW1lbnQgPSBnZXRIZWFkaW5nQ29sbGFwc2VFbGVtZW50KGNsb25lZEVsZW1lbnQpO1xuICAgICAgICAgICAgICAgIGlmKGhlYWRpbmdDb2xsYXBzZUVsZW1lbnQgIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gVGhpcyByZW1vdmVzIHRoZSBjb2xsYXBzZSBhcnJvdyBmcm9tIHRoZSB2aWV3IGlmIGl0IGV4aXN0cy5cbiAgICAgICAgICAgICAgICAgICAgaGVhZGluZ0NvbGxhcHNlRWxlbWVudC5kZXRhY2goKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZWdpb25FbGVtZW50c1tpXS5jbG9uZWRFbGVtZW50ID0gY2xvbmVkRWxlbWVudDtcbiAgICAgICAgICAgICAgICBlbGVtZW50LmFwcGVuZENoaWxkKGNsb25lZEVsZW1lbnQpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHJlZ2lvbkVsZW1lbnRzW2ldIGluc3RhbmNlb2YgVGFza0xpc3RET01PYmplY3QpIHtcblxuICAgICAgICAgICAgICAgICAgICB0aGlzLmZpeENsb25lZENoZWNrTGlzdEJ1dHRvbnMocmVnaW9uRWxlbWVudHNbaV0gYXMgVGFza0xpc3RET01PYmplY3QsIHRydWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChlbGVtZW50ICE9PSBudWxsKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgY29sdW1uQ29udGVudERpdi5hcHBlbmRDaGlsZChlbGVtZW50KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBjcmVhdGVDb2x1bW5Db250ZW50RGl2cyhtdWx0aUNvbHVtblBhcmVudDogSFRNTERpdkVsZW1lbnQpOiBIVE1MRGl2RWxlbWVudCB7XG5cbiAgICAgICAgbGV0IGNvbnRlbnREaXYgPSBtdWx0aUNvbHVtblBhcmVudC5jcmVhdGVEaXYoe1xuICAgICAgICAgICAgY2xzOiBgJHtNdWx0aUNvbHVtblN0eWxlQ1NTLkNvbHVtbkNvbnRlbnR9YFxuICAgICAgICB9KTtcblxuICAgICAgICBpZih0aGlzLnJlZ2lvbmFsU2V0dGluZ3MuY29sdW1uU2l6ZSA9PT0gU2luZ2xlQ29sdW1uU2l6ZS5zbWFsbCkge1xuICAgICAgICAgICAgY29udGVudERpdi5hZGRDbGFzcyhgJHtNdWx0aUNvbHVtbkxheW91dENTUy5TaW5nbGVDb2x1bW5TbWFsbH1gKVxuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYodGhpcy5yZWdpb25hbFNldHRpbmdzLmNvbHVtblNpemUgPT09IFNpbmdsZUNvbHVtblNpemUubGFyZ2UpIHtcbiAgICAgICAgICAgIGNvbnRlbnREaXYuYWRkQ2xhc3MoYCR7TXVsdGlDb2x1bW5MYXlvdXRDU1MuU2luZ2xlQ29sdW1uTGFyZ2V9YClcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGNvbnRlbnREaXYuYWRkQ2xhc3MoYCR7TXVsdGlDb2x1bW5MYXlvdXRDU1MuU2luZ2xlQ29sdW1uTWVkfWApXG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gY29udGVudERpdjtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGlzQ2VudGVyZWQobGF5b3V0OiBDb2x1bW5MYXlvdXQpOiBib29sZWFuIHtcblxuICAgIGlmKGxheW91dCA9PT0gQ29sdW1uTGF5b3V0LnN0YW5kYXJkIHx8XG4gICAgICAgbGF5b3V0ID09PSBDb2x1bW5MYXlvdXQubWlkZGxlICAgfHxcbiAgICAgICBsYXlvdXQgPT09IENvbHVtbkxheW91dC5jZW50ZXIgICB8fFxuICAgICAgIGxheW91dCA9PT0gQ29sdW1uTGF5b3V0LnNlY29uZCAgICApIHtcblxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2Vcbn1cblxuZnVuY3Rpb24gaXNMZWZ0TGF5b3V0KGxheW91dDogQ29sdW1uTGF5b3V0KTogYm9vbGVhbiB7XG5cbiAgICBpZihsYXlvdXQgPT09IENvbHVtbkxheW91dC5sZWZ0IHx8XG4gICAgICAgbGF5b3V0ID09PSBDb2x1bW5MYXlvdXQuZmlyc3QgKSB7XG4gXG4gICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgfVxuIFxuICAgICByZXR1cm4gZmFsc2Vcbn1cblxuZnVuY3Rpb24gaXNSaWdodExheW91dChsYXlvdXQ6IENvbHVtbkxheW91dCk6IGJvb2xlYW4ge1xuXG4gICAgaWYobGF5b3V0ID09PSBDb2x1bW5MYXlvdXQucmlnaHQgfHxcbiAgICAgICBsYXlvdXQgPT09IENvbHVtbkxheW91dC50aGlyZCB8fFxuICAgICAgIGxheW91dCA9PT0gQ29sdW1uTGF5b3V0Lmxhc3QgKSB7XG4gXG4gICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgfVxuIFxuICAgICByZXR1cm4gZmFsc2Vcbn0iLCIvKipcbiAqIEZpbGU6IC9zcmMvZG9tX21hbmFnZXIvcmVnaW9uYWxfbWFuYWdlcnMvYXV0b0xheW91dFJlZ2lvbk1hbmFnZXIudHMgICAgICAgICAqXG4gKiBDcmVhdGVkIERhdGU6IFN1bmRheSwgTWF5IDIybmQgMjAyMiwgMTA6MjMgcG0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICogQXV0aG9yOiBDYW1lcm9uIFJvYmluc29uICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpcbiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMjIgQ2FtZXJvbiBSb2JpbnNvbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICovXG5cbmltcG9ydCB7IERPTU9iamVjdCwgRE9NT2JqZWN0VGFnLCBUYXNrTGlzdERPTU9iamVjdCB9IGZyb20gJy4uL2RvbU9iamVjdCc7XG5pbXBvcnQgeyBNdWx0aUNvbHVtblNldHRpbmdzIH0gZnJvbSBcIi4uLy4uL3JlZ2lvblNldHRpbmdzXCI7XG5pbXBvcnQgeyBNdWx0aUNvbHVtbkxheW91dENTUywgTXVsdGlDb2x1bW5TdHlsZUNTUyB9IGZyb20gJy4uLy4uL3V0aWxpdGllcy9jc3NEZWZpbml0aW9ucyc7XG5pbXBvcnQgeyBSZWdpb25NYW5hZ2VyIH0gZnJvbSAnLi9yZWdpb25NYW5hZ2VyJztcbmltcG9ydCB7IGdldEhlYWRpbmdDb2xsYXBzZUVsZW1lbnQsIGhhc0hlYWRlciB9IGZyb20gJ3NyYy91dGlsaXRpZXMvZWxlbWVudFJlbmRlclR5cGVQYXJzZXInO1xuXG5leHBvcnQgY2xhc3MgQXV0b0xheW91dFJlZ2lvbk1hbmFnZXIgZXh0ZW5kcyBSZWdpb25NYW5hZ2VyIHtcblxuICAgIHByaXZhdGUgcHJldmlvdXNDb2x1bW5IZWlnaHRzOiBudW1iZXJbXSA9IFtdXG5cbiAgICBwcml2YXRlIGNvbHVtblBhcmVudDogSFRNTERpdkVsZW1lbnQ7XG4gICAgcHJpdmF0ZSBjb2x1bW5EaXZzOiBIVE1MRGl2RWxlbWVudFtdO1xuXG4gICAgcHVibGljIHJlbmRlclJlZ2lvbkVsZW1lbnRzVG9TY3JlZW4oKTogdm9pZCB7XG5cbiAgICAgICAgIHRoaXMucmVuZGVyQ29sdW1uTWFya2Rvd24odGhpcy5yZWdpb25QYXJlbnQsIHRoaXMuZG9tTGlzdCwgdGhpcy5yZWdpb25hbFNldHRpbmdzKTtcbiAgICB9XG4gICAgcHVibGljIGV4cG9ydFJlZ2lvbkVsZW1lbnRzVG9QREYocGRmUGFyZW50RWxlbWVudDogSFRNTEVsZW1lbnQpOiB2b2lkIHtcblxuICAgICAgICAvLyBEZWZhdWx0IHNldCBzaGFkb3cgdG8gb2ZmIGZvciBleHBvcnRpbmcgUERGc1xuICAgICAgICBsZXQgcmVuZGVyU2V0dGluZ3MgPSB0aGlzLnJlZ2lvbmFsU2V0dGluZ3M7XG4gICAgICAgIHJlbmRlclNldHRpbmdzLmRyYXdTaGFkb3cgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5yZW5kZXJDb2x1bW5NYXJrZG93bihwZGZQYXJlbnRFbGVtZW50LCB0aGlzLmRvbUxpc3Quc2xpY2UoKSwgcmVuZGVyU2V0dGluZ3MpO1xuICAgIH1cbiAgICBwdWJsaWMgcmVuZGVyUmVnaW9uRWxlbWVudHNUb0xpdmVQcmV2aWV3KHBhcmVudEVsZW1lbnQ6IEhUTUxFbGVtZW50KTogdm9pZCB7XG5cbiAgICAgICAgdGhpcy5yZW5kZXJDb2x1bW5NYXJrZG93bihwYXJlbnRFbGVtZW50LCB0aGlzLmRvbUxpc3QsIHRoaXMucmVnaW9uYWxTZXR0aW5ncyk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFRoaXMgZnVuY3Rpb24gdGFrZXMgaW4gdGhlIGRhdGEgZm9yIHRoZSBtdWx0aS1jb2x1bW4gcmVnaW9uIGFuZCBzZXRzIHVwIHRoZSBcbiAgICAgKiB1c2VyIGRlZmluZWQgbnVtYmVyIG9mIGNoaWxkcmVuIHdpdGggdGhlIHByb3BlciBjc3MgY2xhc3NlcyB0byBiZSByZW5kZXJlZCBwcm9wZXJseS5cbiAgICAgKiBcbiAgICAgKiBAcGFyYW0gcGFyZW50RWxlbWVudCBUaGUgZWxlbWVudCB0aGF0IHRoZSBtdWx0aS1jb2x1bW4gcmVnaW9uIHdpbGwgYmUgcmVuZGVyZWQgdW5kZXIuXG4gICAgICogQHBhcmFtIHJlZ2lvbkVsZW1lbnRzIFRoZSBsaXN0IG9mIERPTSBvYmplY3RzIHRoYXQgd2lsbCBiZSBjb3BwaWVkIHVuZGVyIHRoZSBwYXJlbnQgb2JqZWN0XG4gICAgICogQHBhcmFtIHNldHRpbmdzIFRoZSBzZXR0aW5ncyB0aGUgdXNlciBoYXMgZGVmaW5lZCBmb3IgdGhlIHJlZ2lvbi5cbiAgICAgKi9cbiAgICBwcml2YXRlIHJlbmRlckNvbHVtbk1hcmtkb3duKHBhcmVudEVsZW1lbnQ6IEhUTUxFbGVtZW50LCByZWdpb25FbGVtZW50czogRE9NT2JqZWN0W10sIHNldHRpbmdzOiBNdWx0aUNvbHVtblNldHRpbmdzKSB7XG5cbiAgICAgICAgbGV0IG11bHRpQ29sdW1uUGFyZW50ID0gY3JlYXRlRGl2KHtcbiAgICAgICAgICAgIGNsczogTXVsdGlDb2x1bW5MYXlvdXRDU1MuUmVnaW9uQ29sdW1uQ29udGFpbmVyRGl2LFxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5jb2x1bW5QYXJlbnQgPSBtdWx0aUNvbHVtblBhcmVudDtcblxuICAgICAgICAvKipcbiAgICAgICAgICogUGFzcyBvdXIgcGFyZW50IGRpdiBhbmQgc2V0dGluZ3MgdG8gcGFyc2VyIHRvIGNyZWF0ZSB0aGUgcmVxdWlyZWRcbiAgICAgICAgICogY29sdW1uIGRpdnMgYXMgY2hpbGRyZW4gb2YgdGhlIHBhcmVudC5cbiAgICAgICAgICovXG4gICAgICAgIHRoaXMuY29sdW1uRGl2cyA9IHRoaXMuZ2V0Q29sdW1uQ29udGVudERpdnMoc2V0dGluZ3MsIG11bHRpQ29sdW1uUGFyZW50KTtcblxuICAgICAgICBpZiAoc2V0dGluZ3MuZHJhd1NoYWRvdyA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgbXVsdGlDb2x1bW5QYXJlbnQuYWRkQ2xhc3MoTXVsdGlDb2x1bW5TdHlsZUNTUy5SZWdpb25TaGFkb3cpO1xuICAgICAgICB9XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5jb2x1bW5EaXZzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBpZiAoc2V0dGluZ3MuZHJhd0JvcmRlciA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuY29sdW1uRGl2c1tpXS5hZGRDbGFzcyhNdWx0aUNvbHVtblN0eWxlQ1NTLkNvbHVtbkJvcmRlcik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChzZXR0aW5ncy5kcmF3U2hhZG93ID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jb2x1bW5EaXZzW2ldLmFkZENsYXNzKE11bHRpQ29sdW1uU3R5bGVDU1MuQ29sdW1uU2hhZG93KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFJlbW92ZSBldmVyeSBvdGhlciBjaGlsZCBmcm9tIHRoZSBwYXJlbnQgc28gXG4gICAgICAgIC8vIHdlIGRvbnQgZW5kIHVwIHdpdGggbXVsdGlwbGUgc2V0cyBvZiBkYXRhLiBUaGlzIHNob3VsZFxuICAgICAgICAvLyByZWFsbHkgb25seSBuZWVkIHRvIGxvb3Agb25jZSBmb3IgaSA9IDAgYnV0IGxvb3AganVzdFxuICAgICAgICAvLyBpbiBjYXNlLlxuICAgICAgICBmb3IgKGxldCBpID0gcGFyZW50RWxlbWVudC5jaGlsZHJlbi5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICAgICAgcGFyZW50RWxlbWVudC5jaGlsZHJlbltpXS5kZXRhY2goKTtcbiAgICAgICAgfVxuICAgICAgICBwYXJlbnRFbGVtZW50LmFwcGVuZENoaWxkKG11bHRpQ29sdW1uUGFyZW50KTtcblxuICAgICAgICB0aGlzLmFwcGVuZEVsZW1lbnRzVG9Db2x1bW5zKHJlZ2lvbkVsZW1lbnRzLCB0aGlzLmNvbHVtbkRpdnMsIHNldHRpbmdzKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFwcGVuZEVsZW1lbnRzVG9Db2x1bW5zKHJlZ2lvbkVsZW1lbnRzOiBET01PYmplY3RbXSwgY29sdW1uQ29udGVudERpdnM6IEhUTUxEaXZFbGVtZW50W10sIHNldHRpbmdzOiBNdWx0aUNvbHVtblNldHRpbmdzKSB7XG5cbiAgICAgICAgZnVuY3Rpb24gYmFsYW5jZUVsZW1lbnRzKCkge1xuXG4gICAgICAgICAgICBsZXQgdG90YWxIZWlnaHQgPSByZWdpb25FbGVtZW50cy5tYXAoKGVsOiBET01PYmplY3QsIGluZGV4OiBudW1iZXIpID0+IHsgXG5cbiAgICAgICAgICAgICAgICAvLyBXZSBvbmx5IHdhbnQgdG8gYXR0ZW1wdCB0byB1cGRhdGUgdGhlIGVsZW1lbnRSZW5kZXJlZEhlaWdodCBpZiBpdCBpcyAwIGFuZCBpZiBpdCBpcyBub3QgYW4gdW5yZW5kZXJlZCBlbGVtZW50IHN1Y2ggYXMgYSBlbmRyZWdpb24gdGFnLlxuICAgICAgICAgICAgICAgIGlmKGVsLmVsZW1lbnRSZW5kZXJlZEhlaWdodCA9PT0gMCAmJlxuICAgICAgICAgICAgICAgICAgICBlbC50YWcgIT09IERPTU9iamVjdFRhZy5jb2x1bW5CcmVhayAmJlxuICAgICAgICAgICAgICAgICAgICBlbC50YWcgIT09IERPTU9iamVjdFRhZy5lbmRSZWdpb24gJiZcbiAgICAgICAgICAgICAgICAgICAgZWwudGFnICE9PSBET01PYmplY3RUYWcucmVnaW9uU2V0dGluZ3MgJiZcbiAgICAgICAgICAgICAgICAgICAgZWwudGFnICE9PSBET01PYmplY3RUYWcuc3RhcnRSZWdpb24pIHtcbiAgICBcbiAgICAgICAgICAgICAgICAgICAgLy8gQWRkIGVsZW1lbnQgdG8gcmVuZGVyZWQgZGl2IHNvIHdlIGNhbiBleHRyYWN0IHRoZSByZW5kZXJlZCBoZWlnaHQuXG4gICAgICAgICAgICAgICAgICAgIGNvbHVtbkNvbnRlbnREaXZzWzBdLmFwcGVuZENoaWxkKGVsLm9yaWdpbmFsRWxlbWVudClcbiAgICAgICAgICAgICAgICAgICAgZWwuZWxlbWVudFJlbmRlcmVkSGVpZ2h0ID0gZWwub3JpZ2luYWxFbGVtZW50LmNsaWVudEhlaWdodFxuICAgICAgICAgICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2c1swXS5yZW1vdmVDaGlsZChlbC5vcmlnaW5hbEVsZW1lbnQpXG4gICAgICAgICAgICAgICAgfVxuICAgIFxuICAgICAgICAgICAgICAgIHJldHVybiBlbC5lbGVtZW50UmVuZGVyZWRIZWlnaHQgXG4gICAgICAgICAgICB9KS5yZWR1Y2UoKHByZXY6IG51bWJlciwgY3VycjogbnVtYmVyKSA9PiB7IHJldHVybiBwcmV2ICsgY3VyciB9LCAwKTtcbiAgICAgICAgICAgIGxldCBtYXhDb2x1bW5Db250ZW50SGVpZ2h0ID0gTWF0aC50cnVuYyh0b3RhbEhlaWdodCAvIHNldHRpbmdzLm51bWJlck9mQ29sdW1ucyk7XG5cbiAgICAgICAgICAgIGZvcihsZXQgaSA9IDA7IGkgPCBjb2x1bW5Db250ZW50RGl2cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGogPSBjb2x1bW5Db250ZW50RGl2c1tpXS5jaGlsZHJlbi5sZW5ndGggLSAxOyBqID49IDA7IGotLSkge1xuICAgICAgICAgICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2c1tpXS5jaGlsZHJlbltqXS5kZXRhY2goKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGxldCBjb2x1bW5JbmRleCA9IDA7XG4gICAgICAgICAgICBsZXQgY3VycmVudENvbHVtbkhlaWdodCA9IDA7XG4gICAgICAgICAgICBmdW5jdGlvbiBjaGVja1Nob3VsZFN3aXRjaENvbHVtbnMobmV4dEVsZW1lbnRIZWlnaHQ6IG51bWJlcikge1xuICAgIFxuICAgICAgICAgICAgICAgIGlmIChjdXJyZW50Q29sdW1uSGVpZ2h0ICsgbmV4dEVsZW1lbnRIZWlnaHQgPiBtYXhDb2x1bW5Db250ZW50SGVpZ2h0ICYmXG4gICAgICAgICAgICAgICAgICAgIChjb2x1bW5JbmRleCArIDEpIDwgc2V0dGluZ3MubnVtYmVyT2ZDb2x1bW5zKSB7XG4gICAgXG4gICAgICAgICAgICAgICAgICAgIGNvbHVtbkluZGV4Kys7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRDb2x1bW5IZWlnaHQgPSAwO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCByZWdpb25FbGVtZW50cy5sZW5ndGg7IGkrKykge1xuXG4gICAgICAgICAgICAgICAgaWYgKHJlZ2lvbkVsZW1lbnRzW2ldLnRhZyA9PT0gRE9NT2JqZWN0VGFnLm5vbmUgfHxcbiAgICAgICAgICAgICAgICAgICAgcmVnaW9uRWxlbWVudHNbaV0udGFnID09PSBET01PYmplY3RUYWcuY29sdW1uQnJlYWspIHtcbiAgICBcbiAgICAgICAgICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgICAgICAgICAqIEhlcmUgd2UgY2hlY2sgaWYgd2UgbmVlZCB0byBzd2FwIHRvIHRoZSBuZXh0IGNvbHVtbiBmb3IgdGhlIGN1cnJlbnQgZWxlbWVudC5cbiAgICAgICAgICAgICAgICAgICAgICogSWYgdGhlIHVzZXIgd2FudHMgdG8ga2VlcCBoZWFkaW5ncyB3aXRoIHRoZSBjb250ZW50IGJlbG93IGl0IHdlIGFsc28gbWFrZSBzdXJlXG4gICAgICAgICAgICAgICAgICAgICAqIHRoYXQgdGhlIGxhc3QgaXRlbSBpbiBhIGNvbHVtbiBpcyBub3QgYSBoZWFkZXIgZWxlbWVudCBieSB1c2luZyB0aGUgaGVhZGVyIGFuZFxuICAgICAgICAgICAgICAgICAgICAgKiB0aGUgbmV4dCBlbGVtZW50J3MgaGVpZ2h0IGFzIHRoZSBoZWlnaHQgdmFsdWUuIFxuICAgICAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICAgICAgaWYoaGFzSGVhZGVyKHJlZ2lvbkVsZW1lbnRzW2ldLm9yaWdpbmFsRWxlbWVudCkgPT09IHRydWUpIHsgLy8gVE9ETzogQWRkIHRoaXMgYXMgc2VsZWN0YWJsZSBvcHRpb24uXG4gICAgXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgaGVhZGVyQW5kTmV4dEVsZW1lbnRIZWlnaHQgPSByZWdpb25FbGVtZW50c1tpXS5lbGVtZW50UmVuZGVyZWRIZWlnaHQ7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZihpIDwgcmVnaW9uRWxlbWVudHMubGVuZ3RoIC0gMSkge1xuICAgIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhlYWRlckFuZE5leHRFbGVtZW50SGVpZ2h0ICs9IHJlZ2lvbkVsZW1lbnRzW2kgKyAxXS5lbGVtZW50UmVuZGVyZWRIZWlnaHQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgXG4gICAgICAgICAgICAgICAgICAgICAgICBjaGVja1Nob3VsZFN3aXRjaENvbHVtbnMoaGVhZGVyQW5kTmV4dEVsZW1lbnRIZWlnaHQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgIFxuICAgICAgICAgICAgICAgICAgICAgICAgY2hlY2tTaG91bGRTd2l0Y2hDb2x1bW5zKHJlZ2lvbkVsZW1lbnRzW2ldLmVsZW1lbnRSZW5kZXJlZEhlaWdodCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgY3VycmVudENvbHVtbkhlaWdodCArPSByZWdpb25FbGVtZW50c1tpXS5lbGVtZW50UmVuZGVyZWRIZWlnaHRcbiAgICBcbiAgICBcbiAgICAgICAgICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgICAgICAgICAqIFdlIHN0b3JlIHRoZSBlbGVtZW50cyBpbiBhIHdyYXBwZXIgY29udGFpbmVyIHVudGlsIHdlIGRldGVybWluZSBpZiB3ZSB3YW50IHRvIFxuICAgICAgICAgICAgICAgICAgICAgKiB1c2UgdGhlIG9yaWdpbmFsIGVsZW1lbnQgb3IgYSBjbG9uZSBvZiB0aGUgZWxlbWVudC4gVGhpcyBoZWxwcyB1cyBieSBhbGxvd2luZyBcbiAgICAgICAgICAgICAgICAgICAgICogdXMgdG8gY3JlYXRlIGEgdmlzdWFsIG9ubHkgY2xvbmUgd2hpbGUgdGhlIHVwZGF0ZSBsb29wIG1vdmVzIHRoZSBvcmlnaW5hbCBlbGVtZW50IFxuICAgICAgICAgICAgICAgICAgICAgKiBpbnRvIHRoZSBjb2x1bW5zLlxuICAgICAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICAgICAgbGV0IGVsZW1lbnQgPSBjcmVhdGVEaXYoe1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xzOiBNdWx0aUNvbHVtbkxheW91dENTUy5Db2x1bW5EdWFsRWxlbWVudENvbnRhaW5lcixcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIHJlZ2lvbkVsZW1lbnRzW2ldLmVsZW1lbnRDb250YWluZXIgPSBlbGVtZW50O1xuICAgIFxuICAgICAgICAgICAgICAgICAgICBsZXQgY2xvbmVkRWxlbWVudCA9IHJlZ2lvbkVsZW1lbnRzW2ldLmNsb25lZEVsZW1lbnQ7XG4gICAgICAgICAgICAgICAgICAgIGlmKHJlZ2lvbkVsZW1lbnRzW2ldLmNsb25lZEVsZW1lbnQgPT09IG51bGwpIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgY2xvbmVkRWxlbWVudCA9IHJlZ2lvbkVsZW1lbnRzW2ldLm9yaWdpbmFsRWxlbWVudC5jbG9uZU5vZGUodHJ1ZSkgYXMgSFRNTERpdkVsZW1lbnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgaGVhZGluZ0NvbGxhcHNlRWxlbWVudCA9IGdldEhlYWRpbmdDb2xsYXBzZUVsZW1lbnQoY2xvbmVkRWxlbWVudCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZihoZWFkaW5nQ29sbGFwc2VFbGVtZW50ICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gVGhpcyByZW1vdmVzIHRoZSBjb2xsYXBzZSBhcnJvdyBmcm9tIHRoZSB2aWV3IGlmIGl0IGV4aXN0cy5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoZWFkaW5nQ29sbGFwc2VFbGVtZW50LmRldGFjaCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICBcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlZ2lvbkVsZW1lbnRzW2ldLmNsb25lZEVsZW1lbnQgPSBjbG9uZWRFbGVtZW50O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsZW1lbnQuYXBwZW5kQ2hpbGQoY2xvbmVkRWxlbWVudCk7XG4gICAgXG4gICAgICAgICAgICAgICAgICAgIGlmIChyZWdpb25FbGVtZW50c1tpXSBpbnN0YW5jZW9mIFRhc2tMaXN0RE9NT2JqZWN0KSB7XG4gICAgXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmZpeENsb25lZENoZWNrTGlzdEJ1dHRvbnMocmVnaW9uRWxlbWVudHNbaV0gYXMgVGFza0xpc3RET01PYmplY3QsIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgXG4gICAgICAgICAgICAgICAgICAgIGlmIChlbGVtZW50ICE9PSBudWxsICYmIFxuICAgICAgICAgICAgICAgICAgICAgICAgY29sdW1uQ29udGVudERpdnNbY29sdW1uSW5kZXhdICYmIFxuICAgICAgICAgICAgICAgICAgICAgICAgcmVnaW9uRWxlbWVudHNbaV0udGFnICE9PSBET01PYmplY3RUYWcuY29sdW1uQnJlYWspIHtcbiAgICBcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbHVtbkNvbnRlbnREaXZzW2NvbHVtbkluZGV4XS5hcHBlbmRDaGlsZChlbGVtZW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlZ2lvbkVsZW1lbnRzW2ldLmVsZW1lbnRSZW5kZXJlZEhlaWdodCA9IGVsZW1lbnQuY2xpZW50SGVpZ2h0O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgXG4gICAgICAgICAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICAgICAgICAgKiBJZiB0aGUgdGFnIGlzIGEgY29sdW1uIGJyZWFrIHdlIHVwZGF0ZSB0aGUgY29sdW1uIGluZGV4IGFmdGVyXG4gICAgICAgICAgICAgICAgICAgICAqIGFwcGVuZGluZyB0aGUgaXRlbSB0byB0aGUgY29sdW1uIGRpdi4gVGhpcyBrZWVwcyB0aGUgbWFpbiBET01cbiAgICAgICAgICAgICAgICAgICAgICogY2xlYW5lciBieSByZW1vdmluZyBvdGhlciBpdGVtcyBhbmQgcGxhY2luZyB0aGVtIGFsbCB3aXRoaW5cbiAgICAgICAgICAgICAgICAgICAgICogYSByZWdpb24gY29udGFpbmVyLlxuICAgICAgICAgICAgICAgICAgICAgKiBcbiAgICAgICAgICAgICAgICAgICAgICogUmVtb3ZpbmcgdGhlIGVuZCBjb2x1bW4gdGFnIGFzIGFuIG9wdGlvbiBmb3Igbm93LlxuICAgICAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICAgICAgLy8gaWYgKHJlZ2lvbkVsZW1lbnRzW2ldLnRhZyA9PT0gRE9NT2JqZWN0VGFnLmNvbHVtbkJyZWFrICYmXG4gICAgICAgICAgICAgICAgICAgIC8vICAgIChjb2x1bW5JbmRleCArIDEpIDwgc2V0dGluZ3MubnVtYmVyT2ZDb2x1bW5zKSB7XG4gICAgXG4gICAgICAgICAgICAgICAgICAgIC8vICAgICBjb2x1bW5JbmRleCsrO1xuICAgICAgICAgICAgICAgICAgICAvLyAgICAgY3VycmVudENvbHVtbkhlaWdodCA9IDA7XG4gICAgICAgICAgICAgICAgICAgIC8vIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvKipcbiAgICAgICAgICogQXR0ZW1wdCB0byBiYWxhbmNlZCB0aGUgZWxlbWVudHMuIFdlIG5lZWQgdG8gaXRlcmF0ZSBvdmVyIHRoZSBlbGVtZW50cyBtdWx0aXBsZSB0aW1lcyBiZWNhdXNlXG4gICAgICAgICAqIG91ciBpbml0aWFsIGJhbGFuY2UgZXN0aW1hdGUgbWF5IG5vdCBiZSBwZXJmZWN0bHkgYmFsYW5jZWQgZHVlIHRvIGRpZmZlcmVudCBjb2x1bW4gd2lkdGhzIGNhdXNpbmcgXG4gICAgICAgICAqIGVsZW1lbnRzIHdpdGhpbiB0aGVtIHRvIGJlIG9mIGRpZmZlcmVudCBoZWlnaHRzLiBUaGlzIGNhbiBjYXVzZSB0aGUgZWxlbWVudHMgdG8ganVtcCBhcm91bmQgb24gXG4gICAgICAgICAqIHN1YnNpcXVlbnQgdXBkYXRlIGxvb3BzIHdoaWNoIGlzIG5vdCBpZGVhbC4gSGVyZSB3ZSByZW5kZXIgdGhlIGVsZW1lbnRzIHRvIHRoZSBzY3JlZW4gYW5kIHVwZGF0ZSBcbiAgICAgICAgICogdGhlaXIgaGVpZ2h0IGFmdGVyIGJlaW5nIHJlbmRlcmVkIGludG8gdGhlIGVzdGltYXRlZCBwb3NpdGlvbi4gXG4gICAgICAgICAqIFxuICAgICAgICAgKiBPbmNlIGV2ZXJ5dGhpbmcgaXMgcmVuZGVyZWQgd2UgY2hlY2sgYWxsIG9mIHRoZSBjb2x1bW4gaGVpZ2h0cyBhZ2FpbnN0IG91ciBsYXN0IGl0ZXJhdGlvbiBhbmQgXG4gICAgICAgICAqIGlmIG5vdGhpbmcgaGFzIGNoYW5nZWQgd2Uga25vdyB3ZSBhcmUgYmFsYW5jZWQuXG4gICAgICAgICAqIFxuICAgICAgICAgKiBUaGVyZSBpcyBwcm9iYWJseSBhIGJldHRlciB3YXkgb2YgYWNjb21wbGlzaGluZyB0aGlzIHRhc2sgYnV0IHRoaXMgd29ya3MgZm9yIHRoZSB0aW1lIGJlaW5nLlxuICAgICAgICAgKi9cbiAgICAgICAgZm9yKGxldCBpID0gMDsgaSA8IDU7IGkrKykge1xuICAgICAgICAgICAgXG4gICAgICAgICAgICBiYWxhbmNlRWxlbWVudHMoKVxuXG4gICAgICAgICAgICBsZXQgYmFsYW5jZWQgPSB0cnVlO1xuICAgICAgICAgICAgZm9yKGxldCBqID0gMDsgaiA8IGNvbHVtbkNvbnRlbnREaXZzLmxlbmd0aDsgaisrKSB7XG5cbiAgICAgICAgICAgICAgICAvLyBJZiB0aGUgY29sdW1uIGhlaWdodHMgYXJlIHVuZGVmaW5lZCB3ZSBzZXQgZGVmYXVsdCB0byB6ZXJvIHNvIG5vdCB0byBlbmNvdW50ZXIgYW4gZXJyb3IuXG4gICAgICAgICAgICAgICAgaWYoIXRoaXMucHJldmlvdXNDb2x1bW5IZWlnaHRzW2pdKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucHJldmlvdXNDb2x1bW5IZWlnaHRzLnB1c2goMClcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBpZiB0aGlzIHJlbmRlciBoZWlnaHQgaXMgbm90IHRoZSBzYW1lIGFzIHRoZSBwcmV2aW91cyBoZWlnaHQgd2UgYXJlIHN0aWxsIGJhbGFuY2luZy5cbiAgICAgICAgICAgICAgICBpZih0aGlzLnByZXZpb3VzQ29sdW1uSGVpZ2h0c1tqXSAhPT0gY29sdW1uQ29udGVudERpdnNbal0uY2xpZW50SGVpZ2h0KSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucHJldmlvdXNDb2x1bW5IZWlnaHRzW2pdID0gY29sdW1uQ29udGVudERpdnNbal0uY2xpZW50SGVpZ2h0XG4gICAgICAgICAgICAgICAgICAgIGJhbGFuY2VkID0gZmFsc2VcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIGlmIHdlIG1hZGUgaXQgb3V0IG9mIHRoZSBsb29wIGFuZCBhbGwgb2YgdGhlIGNvbHVtbnMgYXJlIHRoZSBzYW1lIGhlaWdodCBhcyBsYXN0IHVwZGF0ZVxuICAgICAgICAgICAgLy8gd2UncmUgYmFsYW5jZWQgc28gd2UgY2FuIGJyZWFrIG91dCBvZiB0aGUgbG9vcC5cbiAgICAgICAgICAgIGlmKGJhbGFuY2VkID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwdWJsaWMgdXBkYXRlUmVuZGVyZWRNYXJrZG93bigpIHtcblxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuZG9tTGlzdC5sZW5ndGg7IGkrKykge1xuXG4gICAgICAgICAgICBsZXQgZWwgPSB0aGlzLmRvbUxpc3RbaV1cbiAgICAgICAgICAgIGxldCBvcmlnaW5hbENsaWVudEhlaWdodCA9IDA7XG4gICAgICAgICAgICBpZiAoZWwub3JpZ2luYWxFbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgb3JpZ2luYWxDbGllbnRIZWlnaHQgPSBlbC5vcmlnaW5hbEVsZW1lbnQuY2xpZW50SGVpZ2h0XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgY2xvbmVkQ2xpZW50SGVpZ2h0ID0gMDtcbiAgICAgICAgICAgIGlmIChlbC5jbG9uZWRFbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgY2xvbmVkQ2xpZW50SGVpZ2h0ID0gZWwuY2xvbmVkRWxlbWVudC5jbGllbnRIZWlnaHRcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKG9yaWdpbmFsQ2xpZW50SGVpZ2h0IDwgY2xvbmVkQ2xpZW50SGVpZ2h0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5kb21MaXN0W2ldLmVsZW1lbnRSZW5kZXJlZEhlaWdodCA9IGNsb25lZENsaWVudEhlaWdodDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuZG9tTGlzdFtpXS5lbGVtZW50UmVuZGVyZWRIZWlnaHQgPSBvcmlnaW5hbENsaWVudEhlaWdodDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGxldCB2YWxpZENvbHVtbnMgPSB0cnVlO1xuICAgICAgICBpZih0aGlzLmNvbHVtblBhcmVudCAhPT0gbnVsbCAmJiB0aGlzLmNvbHVtbkRpdnMgIT09IG51bGwgJiYgdGhpcy5jb2x1bW5EaXZzICE9PSB1bmRlZmluZWQgJiZcbiAgICAgICAgICAgIHRoaXMuY29sdW1uRGl2cy5sZW5ndGggPT09IHRoaXMucmVnaW9uYWxTZXR0aW5ncy5udW1iZXJPZkNvbHVtbnMpIHtcblxuICAgICAgICAgICAgbGV0IHRvdGFsSGVpZ2h0ID0gdGhpcy5kb21MaXN0Lm1hcCgoZWw6IERPTU9iamVjdCwgaW5kZXg6IG51bWJlcikgPT4geyBcblxuICAgICAgICAgICAgICAgIC8vIFdlIG9ubHkgd2FudCB0byBhdHRlbXB0IHRvIHVwZGF0ZSB0aGUgZWxlbWVudFJlbmRlcmVkSGVpZ2h0IGlmIGl0IGlzIDAgYW5kIGlmIGl0IGlzIG5vdCBhbiB1bnJlbmRlcmVkIGVsZW1lbnQgc3VjaCBhcyBhIGVuZHJlZ2lvbiB0YWcuXG4gICAgICAgICAgICAgICAgaWYoZWwuZWxlbWVudFJlbmRlcmVkSGVpZ2h0ID09PSAwICYmXG4gICAgICAgICAgICAgICAgICAgIGVsLnRhZyAhPT0gRE9NT2JqZWN0VGFnLmNvbHVtbkJyZWFrICYmXG4gICAgICAgICAgICAgICAgICAgIGVsLnRhZyAhPT0gRE9NT2JqZWN0VGFnLmVuZFJlZ2lvbiAmJlxuICAgICAgICAgICAgICAgICAgICBlbC50YWcgIT09IERPTU9iamVjdFRhZy5yZWdpb25TZXR0aW5ncyAmJlxuICAgICAgICAgICAgICAgICAgICBlbC50YWcgIT09IERPTU9iamVjdFRhZy5zdGFydFJlZ2lvbikge1xuICAgIFxuICAgICAgICAgICAgICAgICAgICAvLyBBZGQgZWxlbWVudCB0byByZW5kZXJlZCBkaXYgc28gd2UgY2FuIGV4dHJhY3QgdGhlIHJlbmRlcmVkIGhlaWdodC5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jb2x1bW5QYXJlbnQuYXBwZW5kQ2hpbGQoZWwub3JpZ2luYWxFbGVtZW50KVxuICAgICAgICAgICAgICAgICAgICBlbC5lbGVtZW50UmVuZGVyZWRIZWlnaHQgPSBlbC5vcmlnaW5hbEVsZW1lbnQuY2xpZW50SGVpZ2h0XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY29sdW1uUGFyZW50LnJlbW92ZUNoaWxkKGVsLm9yaWdpbmFsRWxlbWVudClcbiAgICAgICAgICAgICAgICB9XG4gICAgXG4gICAgICAgICAgICAgICAgcmV0dXJuIGVsLmVsZW1lbnRSZW5kZXJlZEhlaWdodCBcbiAgICAgICAgICAgIH0pLnJlZHVjZSgocHJldjogbnVtYmVyLCBjdXJyOiBudW1iZXIpID0+IHsgcmV0dXJuIHByZXYgKyBjdXJyIH0sIDApO1xuICAgICAgICAgICAgbGV0IG1heENvbHVtbkNvbnRlbnRIZWlnaHQgPSBNYXRoLnRydW5jKHRvdGFsSGVpZ2h0IC8gdGhpcy5yZWdpb25hbFNldHRpbmdzLm51bWJlck9mQ29sdW1ucyk7XG5cbiAgICAgICAgICAgIGZvcihsZXQgaSA9IDA7IGkgPCB0aGlzLmNvbHVtbkRpdnMubGVuZ3RoIC0gMTsgaSsrKSB7XG5cbiAgICAgICAgICAgICAgICBsZXQgY29sdW1uSGVpZ2h0ID0gMFxuICAgICAgICAgICAgICAgIGZvcihsZXQgaiA9IDA7IGogPCB0aGlzLmNvbHVtbkRpdnNbaV0uY2hpbGRyZW4ubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgY29sdW1uSGVpZ2h0ICs9IHRoaXMuY29sdW1uRGl2c1tpXS5jaGlsZHJlbltqXS5jbGllbnRIZWlnaHRcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZihjb2x1bW5IZWlnaHQgPiBtYXhDb2x1bW5Db250ZW50SGVpZ2h0KSB7XG4gICAgICAgICAgICAgICAgICAgIHZhbGlkQ29sdW1ucyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZih2YWxpZENvbHVtbnMgPT09IGZhbHNlKSB7XG5cbiAgICAgICAgICAgIHRoaXMucmVuZGVyQ29sdW1uTWFya2Rvd24odGhpcy5yZWdpb25QYXJlbnQsIHRoaXMuZG9tTGlzdCwgdGhpcy5yZWdpb25hbFNldHRpbmdzKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHN1cGVyLnVwZGF0ZVJlbmRlcmVkTWFya2Rvd24oKTtcbiAgICB9XG59XG5cbiIsIi8qKlxuICogRmlsZTogL3NyYy9kb21fbWFuYWdlci9yZWdpb25hbF9tYW5hZ2Vycy9yZWdpb25NYW5hZ2VyQ29udGFpbmVyLnRzICAgICAgICAgICpcbiAqIENyZWF0ZWQgRGF0ZTogU3VuZGF5LCBNYXkgMjJuZCAyMDIyLCA3OjUwIHBtICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gKiBBdXRob3I6IENhbWVyb24gUm9iaW5zb24gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpcbiAqIENvcHlyaWdodCAoYykgMjAyMiBDYW1lcm9uIFJvYmluc29uICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gKi9cblxuaW1wb3J0IHsgcGFyc2VDb2x1bW5TZXR0aW5ncywgcGFyc2VTaW5nbGVDb2x1bW5TZXR0aW5ncyB9IGZyb20gXCIuLi8uLi91dGlsaXRpZXMvc2V0dGluZ3NQYXJzZXJcIjtcbmltcG9ydCB7IERPTU9iamVjdCB9IGZyb20gJy4uL2RvbU9iamVjdCc7XG5pbXBvcnQgeyBNdWx0aUNvbHVtblNldHRpbmdzLCBnZXREZWZhdWx0TXVsdGlDb2x1bW5TZXR0aW5ncyB9IGZyb20gXCIuLi8uLi9yZWdpb25TZXR0aW5nc1wiO1xuaW1wb3J0IHsgRmlsZURPTU1hbmFnZXIgfSBmcm9tICcuLi9kb21NYW5hZ2VyJztcbmltcG9ydCB7IFN0YW5kYXJkTXVsdGlDb2x1bW5SZWdpb25NYW5hZ2VyIGFzIFN0YW5kYXJkTXVsdGlDb2x1bW5SZWdpb25NYW5hZ2VyIH0gZnJvbSAnLi9zdGFuZGFyZE11bHRpQ29sdW1uUmVnaW9uTWFuYWdlcic7XG5pbXBvcnQgeyBTaW5nbGVDb2x1bW5SZWdpb25NYW5hZ2VyIH0gZnJvbSBcIi4vc2luZ2xlQ29sdW1uUmVnaW9uTWFuYWdlclwiO1xuaW1wb3J0IHsgUmVnaW9uTWFuYWdlciB9IGZyb20gXCIuL3JlZ2lvbk1hbmFnZXJcIjtcbmltcG9ydCB7IEF1dG9MYXlvdXRSZWdpb25NYW5hZ2VyIH0gZnJvbSAnLi9hdXRvTGF5b3V0UmVnaW9uTWFuYWdlcic7XG5cbi8qKlxuICogVGhpcyBjbGFzcyBhY3RzIGFzIGFuIGFic3RyYWN0aW9uIGZvciB0aGUgYWN0dWFsIHJlZ2lvbmFsIG1hbmFnZXIuIEl0IGlzIHVzZWQgdG8gdXBkYXRlIHRoZVxuICogc3ViY2xhc3Mgb2YgUmVnaW9uYWxNYW5hZ2VyIGRlcGVuZGluZyBvbiB1c2VyIHByZWZlcmVuY2VzIHRvIG1ha2UgcmVuZGVyaW5nIG1vcmUgc2ltcGxpZmllZC5cbiAqL1xuZXhwb3J0IGNsYXNzIFJlZ2lvbk1hbmFnZXJDb250YWluZXIge1xuXG4gICAgcHJvdGVjdGVkIHJlZ2lvbjogUmVnaW9uTWFuYWdlcjtcbiAgICBjb25zdHJ1Y3RvcihwYXJlbnRGaWxlTWFuYWdlcjogRmlsZURPTU1hbmFnZXIsIHJlZ2lvbktleTogc3RyaW5nLCByb290RWxlbWVudDogSFRNTEVsZW1lbnQsIHJlZ2lvblBhcmVudDogSFRNTEVsZW1lbnQpIHtcbiAgICAgICAgdGhpcy5yZWdpb24gPSBuZXcgU3RhbmRhcmRNdWx0aUNvbHVtblJlZ2lvbk1hbmFnZXIoY3JlYXRlRGVmYXVsdFJlZ2lvbk1hbmFnZXJEYXRhKHJlZ2lvblBhcmVudCwgcGFyZW50RmlsZU1hbmFnZXIsIHJlZ2lvbktleSwgcm9vdEVsZW1lbnQpKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0UmVnaW9uKCk6IFJlZ2lvbk1hbmFnZXIge1xuICAgICAgICByZXR1cm4gdGhpcy5yZWdpb247XG4gICAgfVxuXG4gICAgcHVibGljIHNldFJlZ2lvblNldHRpbmdzKHNldHRpbmdzVGV4dDogc3RyaW5nKTogUmVnaW9uTWFuYWdlciB7XG5cbiAgICAgICAgbGV0IHJlZ2lvbmFsU2V0dGluZ3MgPSBwYXJzZUNvbHVtblNldHRpbmdzKHNldHRpbmdzVGV4dCk7XG4gICAgICAgIGlmIChyZWdpb25hbFNldHRpbmdzLm51bWJlck9mQ29sdW1ucyA9PT0gMSkge1xuXG4gICAgICAgICAgICByZWdpb25hbFNldHRpbmdzID0gcGFyc2VTaW5nbGVDb2x1bW5TZXR0aW5ncyhzZXR0aW5nc1RleHQsIHJlZ2lvbmFsU2V0dGluZ3MpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucmVnaW9uLnNldFJlZ2lvbmFsU2V0dGluZ3MocmVnaW9uYWxTZXR0aW5ncyk7XG5cbiAgICAgICAgaWYgKHJlZ2lvbmFsU2V0dGluZ3MubnVtYmVyT2ZDb2x1bW5zID09PSAxKSB7XG5cbiAgICAgICAgICAgIGlmKHRoaXMucmVnaW9uIGluc3RhbmNlb2YgU2luZ2xlQ29sdW1uUmVnaW9uTWFuYWdlciA9PT0gZmFsc2UpIHtcblxuICAgICAgICAgICAgICAgIGNvbnNvbGUuZGVidWcoXCJDb252ZXJ0aW5nIHJlZ2lvbiB0byBzaW5nbGUgY29sdW1uLlwiKVxuICAgICAgICAgICAgICAgIHRoaXMuY29udmVydFRvU2luZ2xlQ29sdW1uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZihyZWdpb25hbFNldHRpbmdzLmF1dG9MYXlvdXQgPT09IHRydWUpIHtcblxuICAgICAgICAgICAgaWYodGhpcy5yZWdpb24gaW5zdGFuY2VvZiBBdXRvTGF5b3V0UmVnaW9uTWFuYWdlciA9PT0gZmFsc2UpIHtcblxuICAgICAgICAgICAgICAgIGNvbnNvbGUuZGVidWcoXCJDb252ZXJ0aW5nIHJlZ2lvbiB0byBhdXRvIGxheW91dC5cIilcbiAgICAgICAgICAgICAgICB0aGlzLmNvbnZlcnRUb0F1dG9MYXlvdXQoKVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHJlZ2lvbmFsU2V0dGluZ3MubnVtYmVyT2ZDb2x1bW5zID49IDIpIHtcblxuICAgICAgICAgICAgaWYodGhpcy5yZWdpb24gaW5zdGFuY2VvZiBTdGFuZGFyZE11bHRpQ29sdW1uUmVnaW9uTWFuYWdlciA9PT0gZmFsc2UpIHtcblxuICAgICAgICAgICAgICAgIGNvbnNvbGUuZGVidWcoXCJDb252ZXJ0aW5nIHJlZ2lvbiB0byBzdGFuZGFyZCBtdWx0aS1jb2x1bW5cIilcbiAgICAgICAgICAgICAgICB0aGlzLmNvbnZlcnRUb1N0YW5kYXJkTXVsdGlDb2x1bW4oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzLnJlZ2lvbjtcbiAgICB9XG5cbiAgICBwcml2YXRlIGNvbnZlcnRUb1NpbmdsZUNvbHVtbigpOiBTaW5nbGVDb2x1bW5SZWdpb25NYW5hZ2VyIHtcblxuICAgICAgICBsZXQgZGF0YSA9IHRoaXMucmVnaW9uLmdldFJlZ2lvbkRhdGEoKTtcbiAgICAgICAgdGhpcy5yZWdpb24gPSBuZXcgU2luZ2xlQ29sdW1uUmVnaW9uTWFuYWdlcihkYXRhKTtcblxuICAgICAgICByZXR1cm4gdGhpcy5yZWdpb24gYXMgU2luZ2xlQ29sdW1uUmVnaW9uTWFuYWdlcjtcbiAgICB9XG5cbiAgICBwcml2YXRlIGNvbnZlcnRUb1N0YW5kYXJkTXVsdGlDb2x1bW4oKTogU3RhbmRhcmRNdWx0aUNvbHVtblJlZ2lvbk1hbmFnZXIge1xuXG4gICAgICAgIGxldCBkYXRhID0gdGhpcy5yZWdpb24uZ2V0UmVnaW9uRGF0YSgpO1xuICAgICAgICB0aGlzLnJlZ2lvbiA9IG5ldyBTdGFuZGFyZE11bHRpQ29sdW1uUmVnaW9uTWFuYWdlcihkYXRhKTtcblxuICAgICAgICByZXR1cm4gdGhpcy5yZWdpb24gYXMgU3RhbmRhcmRNdWx0aUNvbHVtblJlZ2lvbk1hbmFnZXI7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBjb252ZXJ0VG9BdXRvTGF5b3V0KCk6IEF1dG9MYXlvdXRSZWdpb25NYW5hZ2VyIHtcblxuICAgICAgICBsZXQgZGF0YSA9IHRoaXMucmVnaW9uLmdldFJlZ2lvbkRhdGEoKTtcbiAgICAgICAgdGhpcy5yZWdpb24gPSBuZXcgQXV0b0xheW91dFJlZ2lvbk1hbmFnZXIoZGF0YSk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXMucmVnaW9uIGFzIEF1dG9MYXlvdXRSZWdpb25NYW5hZ2VyO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gY3JlYXRlRGVmYXVsdFJlZ2lvbk1hbmFnZXJEYXRhKHJlZ2lvblBhcmVudDogSFRNTEVsZW1lbnQsIGZpbGVNYW5hZ2VyOiBGaWxlRE9NTWFuYWdlciwgcmVnaW9uS2V5OiBzdHJpbmcsIHJvb3RFbGVtZW50OiBIVE1MRWxlbWVudCk6IFJlZ2lvbk1hbmFnZXJEYXRhIHtcblxuICAgIHJldHVybiB7XG4gICAgICAgIGRvbUxpc3Q6IFtdLFxuICAgICAgICBkb21PYmplY3RNYXA6IG5ldyBNYXAoKSxcbiAgICAgICAgcmVnaW9uUGFyZW50OiByZWdpb25QYXJlbnQsXG4gICAgICAgIGZpbGVNYW5hZ2VyOiBmaWxlTWFuYWdlcixcbiAgICAgICAgcmVnaW9uYWxTZXR0aW5nczogZ2V0RGVmYXVsdE11bHRpQ29sdW1uU2V0dGluZ3MoKSxcbiAgICAgICAgcmVnaW9uS2V5OiByZWdpb25LZXksXG4gICAgICAgIHJvb3RFbGVtZW50OiByb290RWxlbWVudFxuICAgIH07XG59XG5cbmV4cG9ydCB0eXBlIFJlZ2lvbk1hbmFnZXJEYXRhID0ge1xuICAgIGRvbUxpc3Q6IERPTU9iamVjdFtdO1xuICAgIGRvbU9iamVjdE1hcDogTWFwPHN0cmluZywgRE9NT2JqZWN0PjtcbiAgICByZWdpb25QYXJlbnQ6IEhUTUxFbGVtZW50O1xuXG4gICAgZmlsZU1hbmFnZXI6IEZpbGVET01NYW5hZ2VyO1xuICAgIHJlZ2lvbmFsU2V0dGluZ3M6IE11bHRpQ29sdW1uU2V0dGluZ3M7XG5cbiAgICByZWdpb25LZXk6IHN0cmluZztcbiAgICByb290RWxlbWVudDogSFRNTEVsZW1lbnQ7XG59O1xuIiwiLypcbiAqIEZpbGU6IG11bHRpLWNvbHVtbi1tYXJrZG93bi9zcmMvZG9tTWFuYWdlci50c1xuICogQ3JlYXRlZCBEYXRlOiBTYXR1cmRheSwgSmFudWFyeSAzMHRoIDIwMjIsIDM6MTY6MzIgcG1cbiAqIEF1dGhvcjogQ2FtZXJvbiBSb2JpbnNvblxuICogXG4gKiBDb3B5cmlnaHQgKGMpIDIwMjIgQ2FtZXJvbiBSb2JpbnNvblxuICovXG5cbmltcG9ydCB7IFJlZ2lvbk1hbmFnZXIgfSBmcm9tIFwiLi9yZWdpb25hbF9tYW5hZ2Vycy9yZWdpb25NYW5hZ2VyXCI7XG5pbXBvcnQgeyBSZWdpb25NYW5hZ2VyQ29udGFpbmVyIH0gZnJvbSBcIi4vcmVnaW9uYWxfbWFuYWdlcnMvcmVnaW9uTWFuYWdlckNvbnRhaW5lclwiO1xuXG4vKipcbiAqIFRoaXMgY2xhc3MgaGFuZGxlcyB0aGUgZ2xvYmFsIG1hbmFnZXJzIGtlZXBpbmcgdHJhY2sgb2YgYWxsIG9wZW4gZmlsZXMgdGhhdFxuICogY29udGFpbiBNQ00tUmVnaW9ucy5cbiAqL1xuZXhwb3J0IGNsYXNzIEdsb2JhbERPTU1hbmFnZXIge1xuICAgIG1hbmFnZXJzOiBNYXA8c3RyaW5nLCBGaWxlRE9NTWFuYWdlcj47XG5cbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgdGhpcy5tYW5hZ2VycyA9IG5ldyBNYXAoKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgcmVtb3ZlRmlsZU1hbmFnZXJDYWxsYmFjayhrZXk6IHN0cmluZykge1xuICAgICAgICBpZih0aGlzLm1hbmFnZXJzLmhhcyhrZXkpID09PSB0cnVlKSB7XG4gICAgICAgICAgICB0aGlzLm1hbmFnZXJzLmRlbGV0ZShrZXkpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHVibGljIGdldEZpbGVNYW5hZ2VyKGtleTogc3RyaW5nKSB7XG5cbiAgICAgICAgbGV0IGZpbGVNYW5hZ2VyID0gbnVsbDtcbiAgICAgICAgaWYodGhpcy5tYW5hZ2Vycy5oYXMoa2V5KSA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgZmlsZU1hbmFnZXIgPSB0aGlzLm1hbmFnZXJzLmdldChrZXkpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgZmlsZU1hbmFnZXIgPSBjcmVhdGVGaWxlRE9NTWFuYWdlcih0aGlzLCBrZXkpO1xuICAgICAgICAgICAgdGhpcy5tYW5hZ2Vycy5zZXQoa2V5LCBmaWxlTWFuYWdlcik7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZmlsZU1hbmFnZXI7XG4gICAgfVxuXG4gICAgcHVibGljIGdldEFsbEZpbGVNYW5hZ2VycygpIHtcbiAgICAgICAgcmV0dXJuIEFycmF5LmZyb20odGhpcy5tYW5hZ2Vycy52YWx1ZXMoKSk7XG4gICAgfVxufVxuXG5leHBvcnQgdHlwZSBGaWxlRE9NTWFuYWdlciA9IHtcbiAgICByZWdpb25NYXA6IE1hcDxzdHJpbmcsIFJlZ2lvbk1hbmFnZXJDb250YWluZXI+LFxuICAgIGhhc1N0YXJ0VGFnOiBib29sZWFuLFxuICAgIGNyZWF0ZVJlZ2lvbmFsTWFuYWdlcjogKHJlZ2lvbktleTogc3RyaW5nLCByb290RWxlbWVudDogSFRNTEVsZW1lbnQsIGVycm9yRWxlbWVudDogSFRNTEVsZW1lbnQsIHJlbmRlclJlZ2lvbkVsZW1lbnQ6IEhUTUxFbGVtZW50KSA9PiBSZWdpb25NYW5hZ2VyXG4gICAgZ2V0UmVnaW9uYWxDb250YWluZXI6IChyZWdpb25LZXk6IHN0cmluZykgPT4gUmVnaW9uTWFuYWdlckNvbnRhaW5lciB8IG51bGwsXG4gICAgZ2V0QWxsUmVnaW9uYWxNYW5hZ2VyczogKCkgPT4gUmVnaW9uTWFuYWdlcltdLFxuICAgIHJlbW92ZVJlZ2lvbjogKHJlZ2lvbktleTogc3RyaW5nKSA9PiB2b2lkLFxuICAgIHNldEhhc1N0YXJ0VGFnOiAoKSA9PiB2b2lkLFxuICAgIGdldEhhc1N0YXJ0VGFnOiAoKSA9PiBib29sZWFuLFxuICAgIGdldE51bWJlck9mUmVnaW9uczogKCkgPT4gbnVtYmVyLFxuICAgIGNoZWNrS2V5RXhpc3RzOiAoY2hlY2tLZXk6IHN0cmluZykgPT4gYm9vbGVhblxufVxuZnVuY3Rpb24gY3JlYXRlRmlsZURPTU1hbmFnZXIocGFyZW50TWFuYWdlcjogR2xvYmFsRE9NTWFuYWdlciwgZmlsZUtleTogc3RyaW5nKTogRmlsZURPTU1hbmFnZXIge1xuICAgIFxuICAgIGxldCByZWdpb25NYXA6IE1hcDxzdHJpbmcsIFJlZ2lvbk1hbmFnZXJDb250YWluZXI+ID0gbmV3IE1hcCgpO1xuICAgIGxldCBoYXNTdGFydFRhZzogYm9vbGVhbiA9IGZhbHNlO1xuXG4gICAgZnVuY3Rpb24gcmVtb3ZlUmVnaW9uKHJlZ2lvbktleTogc3RyaW5nKTogdm9pZCB7XG5cbiAgICAgICAgbGV0IHJlZ2lvbkNvbnRhaW5lciA9IHJlZ2lvbk1hcC5nZXQocmVnaW9uS2V5KTtcbiAgICAgICAgaWYocmVnaW9uQ29udGFpbmVyKSB7XG4gICAgICAgICAgICBsZXQgcmVnaW9uYWxNYW5hZ2VyID0gcmVnaW9uQ29udGFpbmVyLmdldFJlZ2lvbigpO1xuICAgICAgICAgICAgcmVnaW9uYWxNYW5hZ2VyLmRpc3BsYXlPcmlnaW5hbEVsZW1lbnRzKCk7XG4gICAgICAgIH1cblxuICAgICAgICByZWdpb25NYXAuZGVsZXRlKHJlZ2lvbktleSk7XG4gICAgICAgIFxuICAgICAgICBpZihyZWdpb25NYXAuc2l6ZSA9PT0gMCkge1xuICAgICAgICAgICAgcGFyZW50TWFuYWdlci5yZW1vdmVGaWxlTWFuYWdlckNhbGxiYWNrKGZpbGVLZXkpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY3JlYXRlUmVnaW9uYWxNYW5hZ2VyKHJlZ2lvbktleTogc3RyaW5nLCByb290RWxlbWVudDogSFRNTEVsZW1lbnQsIGVycm9yRWxlbWVudDogSFRNTEVsZW1lbnQsIHJlbmRlclJlZ2lvbkVsZW1lbnQ6IEhUTUxFbGVtZW50KTogUmVnaW9uTWFuYWdlciB7XG5cbiAgICAgICAgLy9UT0RPOiBVc2UgdGhlIGVycm9yIGVsZW1lbnQgd2hlbmV2ZXIgdGhlcmUgaXMgYW4gZXJyb3IuXG5cbiAgICAgICAgbGV0IHJlZ29uYWxDb250YWluZXIgPSBuZXcgUmVnaW9uTWFuYWdlckNvbnRhaW5lcih0aGlzLCByZWdpb25LZXksIHJvb3RFbGVtZW50LCByZW5kZXJSZWdpb25FbGVtZW50KTtcbiAgICAgICAgcmVnaW9uTWFwLnNldChyZWdpb25LZXksIHJlZ29uYWxDb250YWluZXIpO1xuICAgICAgICByZXR1cm4gcmVnb25hbENvbnRhaW5lci5nZXRSZWdpb24oKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBnZXRSZWdpb25hbENvbnRhaW5lcihyZWdpb25LZXk6IHN0cmluZyk6IFJlZ2lvbk1hbmFnZXJDb250YWluZXIgfCBudWxsIHtcblxuICAgICAgICBsZXQgcmVnb25hbE1hbmFnZXIgPSBudWxsO1xuICAgICAgICBpZihyZWdpb25NYXAuaGFzKHJlZ2lvbktleSkgPT09IHRydWUpIHtcbiAgICAgICAgICAgIHJlZ29uYWxNYW5hZ2VyID0gcmVnaW9uTWFwLmdldChyZWdpb25LZXkpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJlZ29uYWxNYW5hZ2VyO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldEFsbFJlZ2lvbmFsTWFuYWdlcnMoKTogUmVnaW9uTWFuYWdlcltdIHtcblxuICAgICAgICBsZXQgY29udGFpbmVycyA9IEFycmF5LmZyb20ocmVnaW9uTWFwLnZhbHVlcygpKVxuICAgICAgICBsZXQgcmVnaW9uczogUmVnaW9uTWFuYWdlcltdID0gY29udGFpbmVycy5tYXAoKGN1cnIpID0+IHsgcmV0dXJuIGN1cnIuZ2V0UmVnaW9uKCkgfSk7XG4gICAgICAgIHJldHVybiByZWdpb25zO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHNldEhhc1N0YXJ0VGFnKCkge1xuICAgICAgICBoYXNTdGFydFRhZyA9IHRydWU7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0SGFzU3RhcnRUYWcoKSB7XG4gICAgICAgIHJldHVybiBoYXNTdGFydFRhZztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBnZXROdW1iZXJPZlJlZ2lvbnMoKSB7XG4gICAgICAgIHJldHVybiByZWdpb25NYXAuc2l6ZVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNoZWNrS2V5RXhpc3RzKGNoZWNrS2V5OiBzdHJpbmcpIHtcbiAgICAgICAgcmV0dXJuIHJlZ2lvbk1hcC5oYXMoY2hlY2tLZXkpO1xuICAgIH1cblxuICAgIHJldHVybiB7IHJlZ2lvbk1hcDogcmVnaW9uTWFwLCBcbiAgICAgICAgaGFzU3RhcnRUYWc6IGhhc1N0YXJ0VGFnLCAgXG4gICAgICAgIGNyZWF0ZVJlZ2lvbmFsTWFuYWdlcjogY3JlYXRlUmVnaW9uYWxNYW5hZ2VyLCBcbiAgICAgICAgZ2V0UmVnaW9uYWxDb250YWluZXI6IGdldFJlZ2lvbmFsQ29udGFpbmVyLFxuICAgICAgICBnZXRBbGxSZWdpb25hbE1hbmFnZXJzOiBnZXRBbGxSZWdpb25hbE1hbmFnZXJzLFxuICAgICAgICByZW1vdmVSZWdpb246IHJlbW92ZVJlZ2lvbiwgXG4gICAgICAgIHNldEhhc1N0YXJ0VGFnOiBzZXRIYXNTdGFydFRhZywgXG4gICAgICAgIGdldEhhc1N0YXJ0VGFnOiBnZXRIYXNTdGFydFRhZyxcbiAgICAgICAgZ2V0TnVtYmVyT2ZSZWdpb25zOiBnZXROdW1iZXJPZlJlZ2lvbnMsXG4gICAgICAgIGNoZWNrS2V5RXhpc3RzOiBjaGVja0tleUV4aXN0c1xuICAgIH1cbn0iLCIvKlxuICogRmlsZW5hbWU6IG11bHRpLWNvbHVtbi1tYXJrZG93bi9zcmMvbGl2ZV9wcmV2aWV3L011bHRpQ29sdW1uTWFya2Rvd25fV2lkZ2V0LnRzXG4gKiBDcmVhdGVkIERhdGU6IFR1ZXNkYXksIEF1Z3VzdCAxNnRoIDIwMjIsIDQ6Mzg6NDMgcG1cbiAqIEF1dGhvcjogQ2FtZXJvbiBSb2JpbnNvblxuICogXG4gKiBDb3B5cmlnaHQgKGMpIDIwMjIgQ2FtZXJvbiBSb2JpbnNvblxuICovXG5cbmltcG9ydCB7IE1hcmtkb3duUmVuZGVyQ2hpbGQsIE1hcmtkb3duUmVuZGVyZXIsIFdvcmtzcGFjZUxlYWYgfSBmcm9tIFwib2JzaWRpYW5cIjtcbmltcG9ydCB7IFdpZGdldFR5cGUgfSBmcm9tIFwiQGNvZGVtaXJyb3Ivdmlld1wiO1xuaW1wb3J0IHsgZ2V0RGVmYXVsdE11bHRpQ29sdW1uU2V0dGluZ3MsIE11bHRpQ29sdW1uU2V0dGluZ3MgfSBmcm9tIFwiLi4vcmVnaW9uU2V0dGluZ3NcIjtcbmltcG9ydCB7IGZpbmRTZXR0aW5nc0NvZGVibG9jaywgZmluZFN0YXJ0Q29kZWJsb2NrIH0gZnJvbSBcIi4uL3V0aWxpdGllcy90ZXh0UGFyc2VyXCI7XG5pbXBvcnQgeyBwYXJzZUNvbHVtblNldHRpbmdzLCBwYXJzZVNpbmdsZUNvbHVtblNldHRpbmdzIH0gZnJvbSBcIi4uL3V0aWxpdGllcy9zZXR0aW5nc1BhcnNlclwiO1xuaW1wb3J0IHsgU3RhbmRhcmRNdWx0aUNvbHVtblJlZ2lvbk1hbmFnZXIgfSBmcm9tIFwiLi4vZG9tX21hbmFnZXIvcmVnaW9uYWxfbWFuYWdlcnMvc3RhbmRhcmRNdWx0aUNvbHVtblJlZ2lvbk1hbmFnZXJcIjtcbmltcG9ydCB7IFJlZ2lvbk1hbmFnZXJEYXRhIH0gZnJvbSBcIi4uL2RvbV9tYW5hZ2VyL3JlZ2lvbmFsX21hbmFnZXJzL3JlZ2lvbk1hbmFnZXJDb250YWluZXJcIjtcbmltcG9ydCB7IGdldFVJRCB9IGZyb20gXCIuLi91dGlsaXRpZXMvdXRpbHNcIjtcbmltcG9ydCB7IERPTU9iamVjdCB9IGZyb20gXCIuLi9kb21fbWFuYWdlci9kb21PYmplY3RcIjtcbmltcG9ydCB7IFJlZ2lvbk1hbmFnZXIgfSBmcm9tIFwiLi4vZG9tX21hbmFnZXIvcmVnaW9uYWxfbWFuYWdlcnMvcmVnaW9uTWFuYWdlclwiO1xuaW1wb3J0IHsgU2luZ2xlQ29sdW1uUmVnaW9uTWFuYWdlciB9IGZyb20gXCIuLi9kb21fbWFuYWdlci9yZWdpb25hbF9tYW5hZ2Vycy9zaW5nbGVDb2x1bW5SZWdpb25NYW5hZ2VyXCI7XG5pbXBvcnQgeyBBdXRvTGF5b3V0UmVnaW9uTWFuYWdlciB9IGZyb20gXCIuLi9kb21fbWFuYWdlci9yZWdpb25hbF9tYW5hZ2Vycy9hdXRvTGF5b3V0UmVnaW9uTWFuYWdlclwiO1xuXG5leHBvcnQgY2xhc3MgTXVsdGlDb2x1bW5NYXJrZG93bl9MaXZlUHJldmlld19XaWRnZXQgZXh0ZW5kcyBXaWRnZXRUeXBlIHtcblxuICAgIGNvbnRlbnREYXRhOiBzdHJpbmc7XG4gICAgdGVtcFBhcmVudDogSFRNTERpdkVsZW1lbnQ7XG4gICAgZG9tTGlzdDogRE9NT2JqZWN0W10gPSBbXTtcbiAgICBzZXR0aW5nc1RleHQ6IHN0cmluZztcbiAgICByZWdpb25TZXR0aW5nczogTXVsdGlDb2x1bW5TZXR0aW5ncyA9IGdldERlZmF1bHRNdWx0aUNvbHVtblNldHRpbmdzKCk7XG4gICAgcmVnaW9uTWFuYWdlcjogUmVnaW9uTWFuYWdlcjtcblxuICAgIGNvbnN0cnVjdG9yKGNvbnRlbnREYXRhOiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIoKTtcbiAgICAgICAgdGhpcy5jb250ZW50RGF0YSA9IGNvbnRlbnREYXRhO1xuXG4gICAgICAgIC8vIEZpbmQgdGhlIHNldHRpbmdzIGRlZmluZWQgaW4gdGhlIGNvbnRlbnQsIGlmIGl0IGV4aXN0cy5cbiAgICAgICAgLy8gSWYgdGhlIHNldHRpbmdzIGNvZGVibG9jayBpc250IGRlZmluZWQgYXR0ZW1wdCB0byBnZXQgdGhlIHJlZ2lvbiBjb2RlYmxvY2sgdHlwZS5cbiAgICAgICAgbGV0IHNldHRpbmdzU3RhcnREYXRhID0gZmluZFNldHRpbmdzQ29kZWJsb2NrKHRoaXMuY29udGVudERhdGEpO1xuICAgICAgICBpZihzZXR0aW5nc1N0YXJ0RGF0YS5mb3VuZCA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgIHNldHRpbmdzU3RhcnREYXRhID0gZmluZFN0YXJ0Q29kZWJsb2NrKHRoaXMuY29udGVudERhdGEpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChzZXR0aW5nc1N0YXJ0RGF0YS5mb3VuZCA9PT0gdHJ1ZSkge1xuXG4gICAgICAgICAgICB0aGlzLnNldHRpbmdzVGV4dCA9IHRoaXMuY29udGVudERhdGEuc2xpY2Uoc2V0dGluZ3NTdGFydERhdGEuc3RhcnRQb3NpdGlvbiwgc2V0dGluZ3NTdGFydERhdGEuZW5kUG9zaXRpb24pO1xuICAgICAgICAgICAgdGhpcy5jb250ZW50RGF0YSA9IHRoaXMuY29udGVudERhdGEucmVwbGFjZSh0aGlzLnNldHRpbmdzVGV4dCwgXCJcIik7XG5cbiAgICAgICAgICAgIC8vIFBhcnNlIHRoZSBzZXR0aW5ncywgdXBkYXRpbmcgdGhlIGRlZmF1bHQgc2V0dGluZ3MuXG4gICAgICAgICAgICB0aGlzLnJlZ2lvblNldHRpbmdzID0gcGFyc2VDb2x1bW5TZXR0aW5ncyh0aGlzLnNldHRpbmdzVGV4dCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBSZW5kZXIgdGhlIG1hcmtkb3duIGNvbnRlbnQgdG8gb3VyIHRlbXAgcGFyZW50IGVsZW1lbnQuXG4gICAgICAgIHRoaXMudGVtcFBhcmVudCA9IGNyZWF0ZURpdigpO1xuICAgICAgICBsZXQgZWxlbWVudE1hcmtkb3duUmVuZGVyZXIgPSBuZXcgTWFya2Rvd25SZW5kZXJDaGlsZCh0aGlzLnRlbXBQYXJlbnQpO1xuICAgICAgICBNYXJrZG93blJlbmRlcmVyLnJlbmRlck1hcmtkb3duKHRoaXMuY29udGVudERhdGEsIHRoaXMudGVtcFBhcmVudCwgXCJcIiwgZWxlbWVudE1hcmtkb3duUmVuZGVyZXIpO1xuXG4gICAgICAgIC8vIHRha2UgYWxsIGVsZW1lbnRzLCBpbiBvcmRlciwgYW5kIGNyZWF0ZSBvdXIgRE9NIGxpc3QuXG4gICAgICAgIGxldCBhcnIgPSBBcnJheS5mcm9tKHRoaXMudGVtcFBhcmVudC5jaGlsZHJlbik7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSB7XG5cbiAgICAgICAgICAgIHRoaXMuZG9tTGlzdC5wdXNoKG5ldyBET01PYmplY3QoYXJyW2ldIGFzIEhUTUxFbGVtZW50LCBbXCJcIl0pKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFNldCB1cCB0aGUgcmVnaW9uIG1hbmFnZXIgZGF0YSBiZWZvcmUgdGhlbiBjcmVhdGluZyBvdXIgcmVnaW9uIG1hbmFnZXIuXG4gICAgICAgIGxldCByZWdpb25EYXRhOiBSZWdpb25NYW5hZ2VyRGF0YSA9IHtcbiAgICAgICAgICAgIGRvbUxpc3Q6IHRoaXMuZG9tTGlzdCxcbiAgICAgICAgICAgIGRvbU9iamVjdE1hcDogbmV3IE1hcDxzdHJpbmcsIERPTU9iamVjdD4oKSxcbiAgICAgICAgICAgIHJlZ2lvblBhcmVudDogY3JlYXRlRGl2KCksXG4gICAgICAgICAgICBmaWxlTWFuYWdlcjogbnVsbCxcbiAgICAgICAgICAgIHJlZ2lvbmFsU2V0dGluZ3M6IHRoaXMucmVnaW9uU2V0dGluZ3MsXG4gICAgICAgICAgICByZWdpb25LZXk6IGdldFVJRCgpLFxuICAgICAgICAgICAgcm9vdEVsZW1lbnQ6IGNyZWF0ZURpdigpXG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gRmluYWxseSBzZXR1cCB0aGUgdHlwZSBvZiByZWdpb24gbWFuYWdlciByZXF1aXJlZC5cbiAgICAgICAgaWYgKHRoaXMucmVnaW9uU2V0dGluZ3MubnVtYmVyT2ZDb2x1bW5zID09PSAxKSB7XG4gICAgICAgICAgICB0aGlzLnJlZ2lvblNldHRpbmdzID0gcGFyc2VTaW5nbGVDb2x1bW5TZXR0aW5ncyh0aGlzLnNldHRpbmdzVGV4dCwgdGhpcy5yZWdpb25TZXR0aW5ncyk7XG4gICAgICAgICAgICB0aGlzLnJlZ2lvbk1hbmFnZXIgPSBuZXcgU2luZ2xlQ29sdW1uUmVnaW9uTWFuYWdlcihyZWdpb25EYXRhKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh0aGlzLnJlZ2lvblNldHRpbmdzLmF1dG9MYXlvdXQgPT09IHRydWUpIHtcbiAgICAgICAgICAgIHRoaXMucmVnaW9uTWFuYWdlciA9IG5ldyBBdXRvTGF5b3V0UmVnaW9uTWFuYWdlcihyZWdpb25EYXRhKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMucmVnaW9uTWFuYWdlciA9IG5ldyBTdGFuZGFyZE11bHRpQ29sdW1uUmVnaW9uTWFuYWdlcihyZWdpb25EYXRhKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHRvRE9NKCkge1xuICAgICAgICAvLyBDcmVhdGUgb3VyIGVsZW1lbnQgdG8gaG9sZCBhbGwgb2YgdGhlIGxpdmUgcHJldmlldyBlbGVtZW50cy5cbiAgICAgICAgbGV0IGVsID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImRpdlwiKTtcbiAgICAgICAgZWwuY2xhc3NOYW1lID0gXCJtY20tY20tcHJldmlld1wiO1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBGb3Igc2l0dWF0aW9ucyB3aGVyZSB3ZSBuZWVkIHRvIGtub3cgdGhlIHJlbmRlcmVkIGhlaWdodCwgQXV0b0xheW91dCwgXG4gICAgICAgICAqIHRoZSBlbGVtZW50IG11c3QgYmUgcmVuZGVyZWQgb250byB0aGUgc2NyZWVuIHRvIGdldCB0aGUgaW5mbywgZXZlbiBpZiBcbiAgICAgICAgICogb25seSBmb3IgYSBtb21lbnQuIEhlcmUgd2UgYXR0ZW1wdCB0byBnZXQgYSBsZWFmIGZyb20gdGhlIGFwcCBzbyB3ZSBcbiAgICAgICAgICogY2FuIGJyaWVmbHkgYXBwZW5kIG91ciBlbGVtZW50LCBjaGVjayBhbnkgZGF0YSBpZiByZXF1aXJlZCwgYW5kIHRoZW5cbiAgICAgICAgICogcmVtb3ZlIGl0LlxuICAgICAgICAgKi9cbiAgICAgICAgbGV0IGxlYWY6IFdvcmtzcGFjZUxlYWYgPSBudWxsO1xuICAgICAgICBpZiAoYXBwKSB7XG4gICAgICAgICAgICBsZXQgbGVhdmVzID0gYXBwLndvcmtzcGFjZS5nZXRMZWF2ZXNPZlR5cGUoXCJtYXJrZG93blwiKTtcbiAgICAgICAgICAgIGlmIChsZWF2ZXMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgIGxlYWYgPSBsZWF2ZXNbMF07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5yZWdpb25NYW5hZ2VyKSB7XG5cbiAgICAgICAgICAgIGlmIChsZWFmKSB7XG4gICAgICAgICAgICAgICAgbGVhZi52aWV3LmNvbnRhaW5lckVsLmFwcGVuZENoaWxkKGVsKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5yZWdpb25NYW5hZ2VyLnJlbmRlclJlZ2lvbkVsZW1lbnRzVG9MaXZlUHJldmlldyhlbCk7XG5cbiAgICAgICAgICAgIGlmIChsZWFmKSB7XG4gICAgICAgICAgICAgICAgbGVhZi52aWV3LmNvbnRhaW5lckVsLnJlbW92ZUNoaWxkKGVsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBlbDtcbiAgICB9XG59XG5cbmV4cG9ydCBjbGFzcyBNdWx0aUNvbHVtbk1hcmtkb3duX0RlZmluZWRTZXR0aW5nc19MaXZlUHJldmlld19XaWRnZXQgZXh0ZW5kcyBXaWRnZXRUeXBlIHtcblxuICAgIGNvbnRlbnREYXRhOiBzdHJpbmc7XG5cbiAgICBjb25zdHJ1Y3Rvcihjb250ZW50RGF0YTogc3RyaW5nKSB7XG4gICAgICAgIHN1cGVyKCk7XG5cbiAgICAgICAgdGhpcy5jb250ZW50RGF0YSA9IGNvbnRlbnREYXRhO1xuICAgIH1cblxuICAgIHRvRE9NKCkge1xuICAgICAgICBjb25zb2xlLmxvZyhcIlJlbmRlcmluZyBzZXR0aW5ncyBibG9ja1wiKVxuICAgICAgICAvLyBDcmVhdGUgb3VyIGVsZW1lbnQgdG8gaG9sZCBhbGwgb2YgdGhlIGxpdmUgcHJldmlldyBlbGVtZW50cy5cbiAgICAgICAgbGV0IGVsID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImRpdlwiKTtcbiAgICAgICAgZWwuY2xhc3NOYW1lID0gXCJtY20tY20tc2V0dGluZ3MtcHJldmlld1wiO1xuXG4gICAgICAgIGxldCBsYWJlbERpdiA9IGVsLmNyZWF0ZURpdigpXG4gICAgICAgIGxldCBsYWJlbCA9IGxhYmVsRGl2LmNyZWF0ZVNwYW4oe1xuICAgICAgICAgICAgY2xzOiBcIm1jbS1jb2wtc2V0dGluZ3MtcHJldmlld1wiXG4gICAgICAgIH0pXG4gICAgICAgIGxhYmVsLnRleHRDb250ZW50ID0gXCJDb2x1bW4gU2V0dGluZ3M6XCI7XG5cbiAgICAgICAgbGV0IGxpc3QgPSBlbC5jcmVhdGVFbChcInVsXCIpXG4gICAgICAgIGxldCBsaW5lcyA9IHRoaXMuY29udGVudERhdGEuc3BsaXQoXCJcXG5cIilcbiAgICAgICAgZm9yKGxldCBpID0gMTsgaSA8IGxpbmVzLmxlbmd0aCAtIDE7IGkrKykge1xuICAgICAgICAgICAgbGV0IGl0ZW0gPSBsaXN0LmNyZWF0ZUVsKFwibGlcIilcbiAgICAgICAgICAgIGl0ZW0udGV4dENvbnRlbnQgPSBsaW5lc1tpXVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGVsO1xuICAgIH1cbn0iLCIvKlxuICogRmlsZW5hbWU6IG11bHRpLWNvbHVtbi1tYXJrZG93bi9zcmMvbGl2ZV9wcmV2aWV3L2NtNl9saXZlUHJldmlldy50c1xuICogQ3JlYXRlZCBEYXRlOiBNb25kYXksIEF1Z3VzdCAxc3QgMjAyMiwgMTo1MToxNiBwbVxuICogQXV0aG9yOiBDYW1lcm9uIFJvYmluc29uXG4gKiBcbiAqIENvcHlyaWdodCAoYykgMjAyMiBDYW1lcm9uIFJvYmluc29uXG4gKi9cblxuaW1wb3J0IHsgRXh0ZW5zaW9uLCBMaW5lLCBSYW5nZVNldEJ1aWxkZXIsIFN0YXRlRmllbGQsIFRyYW5zYWN0aW9uIH0gZnJvbSBcIkBjb2RlbWlycm9yL3N0YXRlXCI7XG5pbXBvcnQgeyBEZWNvcmF0aW9uLCBEZWNvcmF0aW9uU2V0LCBFZGl0b3JWaWV3IH0gZnJvbSBcIkBjb2RlbWlycm9yL3ZpZXdcIjtcbmltcG9ydCB7IHN5bnRheFRyZWUsIHRva2VuQ2xhc3NOb2RlUHJvcCB9IGZyb20gXCJAY29kZW1pcnJvci9sYW5ndWFnZVwiO1xuaW1wb3J0IHsgY29udGFpbnNSZWdpb25TdGFydCwgZmluZEVuZFRhZywgZmluZFNldHRpbmdzQ29kZWJsb2NrLCBmaW5kU3RhcnRDb2RlYmxvY2ssIGZpbmRTdGFydFRhZyB9IGZyb20gXCIuLi91dGlsaXRpZXMvdGV4dFBhcnNlclwiO1xuaW1wb3J0IHsgTXVsdGlDb2x1bW5NYXJrZG93bl9EZWZpbmVkU2V0dGluZ3NfTGl2ZVByZXZpZXdfV2lkZ2V0LCBNdWx0aUNvbHVtbk1hcmtkb3duX0xpdmVQcmV2aWV3X1dpZGdldCB9IGZyb20gXCIuL21jbV9saXZlUHJldmlld193aWRnZXRcIjtcblxuZXhwb3J0IGNvbnN0IG11bHRpQ29sdW1uTWFya2Rvd25fU3RhdGVGaWVsZCA9IFN0YXRlRmllbGQuZGVmaW5lPERlY29yYXRpb25TZXQ+KHtcblx0Y3JlYXRlKHN0YXRlKTogRGVjb3JhdGlvblNldCB7XG5cdFx0cmV0dXJuIERlY29yYXRpb24ubm9uZTtcblx0fSxcblx0dXBkYXRlKG9sZFN0YXRlOiBEZWNvcmF0aW9uU2V0LCB0cmFuc2FjdGlvbjogVHJhbnNhY3Rpb24pOiBEZWNvcmF0aW9uU2V0IHtcblx0XHRjb25zdCBidWlsZGVyID0gbmV3IFJhbmdlU2V0QnVpbGRlcjxEZWNvcmF0aW9uPigpO1xuICAgICAgICBsZXQgZ2VuZXJhdGVkID0gZmFsc2U7XG5cblx0XHRzeW50YXhUcmVlKHRyYW5zYWN0aW9uLnN0YXRlKS5pdGVyYXRlKHtcblx0XHRcdGVudGVyKG5vZGUpIHtcblxuICAgICAgICAgICAgICAgIC8vIFdlIG9ubHkgd2FudCB0byBydW4gdGhlIGdlbmVyYXRpb24gb25jZSBwZXIgc3RhdGUgY2hhbmdlLiBJZlxuICAgICAgICAgICAgICAgIC8vIGEgcHJldmlvdXMgbm9kZSBoYXMgc3VjZXNzZnVsbHkgZ2VuZXJhdGVkIHJlZ2lvbnMgd2UgaWdub3JlIGFsbFxuICAgICAgICAgICAgICAgIC8vIG90aGVyIG5vZGVzIGluIHRoZSBzdGF0ZS5cbiAgICAgICAgICAgICAgICBpZihnZW5lcmF0ZWQgPT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGxldCBtYXJrZG93bkxlYXZlcyA9IGFwcC53b3Jrc3BhY2UuZ2V0TGVhdmVzT2ZUeXBlKFwibWFya2Rvd25cIik7XG4gICAgICAgICAgICAgICAgaWYobWFya2Rvd25MZWF2ZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBUT0RPOiBDaGVjayBvdGhlciB3YXlzIHRvIGdldCBpZiBzb3VyY2UgaXMgbGl2ZSBwcmV2aWV3PyBlZGl0b3JMaXZlUHJldmlld0ZpZWxkXG4gICAgICAgICAgICAgICAgaWYobWFya2Rvd25MZWF2ZXNbMF0uZ2V0Vmlld1N0YXRlKCkuc3RhdGUuc291cmNlID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZGVidWcoXCJVc2VyIGRpc2FibGVkIGxpdmUgcHJldmlldy5cIilcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuXHRcdFx0XHQvLyBXZSB3YW50IHRvIHJ1biBvbiB0aGUgd2hvbGUgZmlsZSBzbyB3ZSBkb250IGp1c3QgbG9vayBmb3IgYSBzaW5nbGUgdG9rZW4uXG5cdFx0XHRcdGNvbnN0IHRva2VuUHJvcHMgPSBub2RlLnR5cGUucHJvcDxzdHJpbmc+KHRva2VuQ2xhc3NOb2RlUHJvcCk7XG5cdFx0XHRcdGlmICh0b2tlblByb3BzICE9PSB1bmRlZmluZWQpIHtcblx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvKipcblx0XHRcdFx0ICogV2hlbiB3ZSBoYXZlIHRoZSB3aGlsZSBmaWxlIHdlIHRoZW4gZ2V0IHRoZSBlbnRpcmUgZG9jIHRleHQgYW5kIGNoZWNrIGlmIGl0IFxuXHRcdFx0XHQgKiBjb250YWlucyBhIE1DTSByZWdpb24gc28gd2Uga25vdyB0byBicmVhayBvciBub3QuXG5cdFx0XHRcdCAqL1xuICAgICAgICAgICAgICAgIGxldCBkb2NMZW5ndGggPSB0cmFuc2FjdGlvbi5zdGF0ZS5kb2MubGVuZ3RoXG4gICAgICAgICAgICAgICAgbGV0IGRvY1RleHQgPSB0cmFuc2FjdGlvbi5zdGF0ZS5kb2Muc2xpY2VTdHJpbmcoMCwgZG9jTGVuZ3RoKTtcblx0XHRcdFx0aWYgKGNvbnRhaW5zUmVnaW9uU3RhcnQoZG9jVGV4dCkgPT09IGZhbHNlKSB7XG5cdFx0XHRcdFx0Y29uc29sZS5kZWJ1ZyhcIk5vIHN0YXJ0IHRhZyBpbiBkb2N1bWVudC5cIilcblx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBXZSB3YW50IHRvIGtub3cgd2hlcmUgdGhlIHVzZXIncyBjdXJzb3IgaXMsIGl0IGNhbiBiZVxuXHRcdFx0XHQvLyBzZWxlY3RpbmcgbXVsdGlwbGUgcmVnaW9ucyBvZiB0ZXh0IGFzIHdlbGwgc28gd2UgbmVlZCB0byBrbm93XG5cdFx0XHRcdC8vIGFsbCBsb2NhdGlvbnMuIFVzZWQgdG8ga25vdyBpZiB3ZSBzaG91bGQgcmVuZGVyIHJlZ2lvbiBhcyB0ZXh0IG9yIGFzIHByZXZpZXcuXG5cdFx0XHRcdGxldCByYW5nZXMgPSBnZXRDdXJzb3JMaW5lTG9jYXRpb25zKCk7XG5cblx0XHRcdFx0Ly8gU2V0dXAgb3VyIGxvb3AgdG8gcmVuZGVyIHRoZSByZWdpb25zIGFzIE1DTS4gXG5cdFx0XHRcdGxldCB3b3JraW5nRmlsZVRleHQgPSBkb2NUZXh0O1xuXHRcdFx0XHRsZXQgc3RhcnRUYWdEYXRhID0gZmluZFN0YXJ0VGFnKHdvcmtpbmdGaWxlVGV4dCk7XG5cdFx0XHRcdGlmKHN0YXJ0VGFnRGF0YS5mb3VuZCA9PT0gZmFsc2UpIHtcblx0XHRcdFx0XHRzdGFydFRhZ0RhdGEgPSBmaW5kU3RhcnRDb2RlYmxvY2sod29ya2luZ0ZpbGVUZXh0KTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGxldCBlbmRUYWdEYXRhID0gZmluZEVuZFRhZyh3b3JraW5nRmlsZVRleHQpO1xuXHRcdFx0XHRsZXQgbG9vcEluZGV4ID0gMDtcblx0XHRcdFx0bGV0IHN0YXJ0SW5kZXhPZmZzZXQgPSAwO1xuXHRcdFx0XHR3aGlsZSAoc3RhcnRUYWdEYXRhLmZvdW5kID09PSB0cnVlICYmIGVuZFRhZ0RhdGEuZm91bmQgPT09IHRydWUpIHtcblxuXHRcdFx0XHRcdC8qKlxuXHRcdFx0XHRcdCAqIEZvciB0aGUgcmVnaW9uIHdlIGZvdW5kIGdldCB0aGUgc3RhcnQgYW5kIGVuZCBwb3NpdGlvbiBvZiB0aGUgdGFncyBzbyB3ZSBcblx0XHRcdFx0XHQgKiBjYW4gc2xpY2UgaXQgb3V0IG9mIHRoZSBkb2N1bWVudC5cblx0XHRcdFx0XHQgKi9cblx0XHRcdFx0XHRsZXQgc3RhcnRJbmRleCA9IHN0YXJ0SW5kZXhPZmZzZXQgKyBzdGFydFRhZ0RhdGEuc3RhcnRQb3NpdGlvblxuXHRcdFx0XHRcdGxldCBlbmRJbmRleCA9IHN0YXJ0SW5kZXhPZmZzZXQgKyBlbmRUYWdEYXRhLnN0YXJ0UG9zaXRpb24gKyBlbmRUYWdEYXRhLm1hdGNoTGVuZ3RoIC8vIFdpdGhvdXQgdGhlIG1hdGNoTGVuZ3RoIHdpbGwgbGVhdmUgdGhlIGVuZCB0YWcgb24gdGhlIHNjcmVlbi5cblxuXHRcdFx0XHRcdC8vIFRoaXMgdGV4dCBpcyB0aGUgZW50aXJlIHJlZ2lvbiBkYXRhIGluY2x1ZGluZyB0aGUgc3RhcnQgYW5kIGVuZCB0YWdzLlxuXHRcdFx0XHRcdGxldCBlbGVtZW50VGV4dCA9IGRvY1RleHQuc2xpY2Uoc3RhcnRJbmRleCwgZW5kSW5kZXgpXG5cblx0XHRcdFx0XHQvKipcblx0XHRcdFx0XHQgKiBVcGRhdGUgb3VyIHN0YXJ0IG9mZnNldCBhbmQgdGhlIHdvcmtpbmcgdGV4dCBvZiB0aGUgZmlsZSBzbyBvdXIgbmV4dCBcblx0XHRcdFx0XHQgKiBpdGVyYXRpb24ga25vd3Mgd2hlcmUgd2UgbGVmdCBvZmZcblx0XHRcdFx0XHQgKi9cblx0XHRcdFx0XHRzdGFydEluZGV4T2Zmc2V0ID0gZW5kSW5kZXhcblx0XHRcdFx0XHR3b3JraW5nRmlsZVRleHQgPSBkb2NUZXh0LnNsaWNlKGVuZEluZGV4KTtcblxuXG5cdFx0XHRcdFx0Ly8gSGVyZSB3ZSBjaGVjayBpZiB0aGUgY3Vyc29yIGlzIGluIHRoaXMgc3BlY2lmaWMgcmVnaW9uLlxuXHRcdFx0XHRcdGxldCBjdXJzb3JJblJlZ2lvbiA9IGNoZWNrQ3Vyc29ySW5SZWdpb24oc3RhcnRJbmRleCwgZW5kSW5kZXgsIHJhbmdlcyk7XG5cdFx0XHRcdFx0aWYoY3Vyc29ySW5SZWdpb24gPT09IHRydWUpIHtcblx0XHRcdFx0XHRcdFxuXHRcdFx0XHRcdFx0Ly8gSWYgdGhlIGN1cnNvciBpcyB3aXRoaW4gdGhlIHJlZ2lvbiB3ZSB0aGVuIG5lZWQgdG8ga25vdyBpZlxuXHRcdFx0XHRcdFx0Ly8gaXQgaXMgd2l0aGluIG91ciBzZXR0aW5ncyBibG9jayAoaWYgaXQgZXhpc3RzLilcblx0XHRcdFx0XHRcdGxldCBzZXR0aW5nc1N0YXJ0RGF0YSA9IGZpbmRTdGFydENvZGVibG9jayhlbGVtZW50VGV4dCk7XG5cdFx0XHRcdFx0XHRpZihzZXR0aW5nc1N0YXJ0RGF0YS5mb3VuZCA9PT0gZmFsc2UpIHtcblx0XHRcdFx0XHRcdFx0c2V0dGluZ3NTdGFydERhdGEgPSBmaW5kU2V0dGluZ3NDb2RlYmxvY2soZWxlbWVudFRleHQpO1xuXHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRpZihzZXR0aW5nc1N0YXJ0RGF0YS5mb3VuZCA9PT0gdHJ1ZSkge1xuXG5cdFx0XHRcdFx0XHRcdC8vIFNpbmNlIHRoZSBzZXR0aW5ncyBibG9jayBleGlzdHMgY2hlY2sgaWYgdGhlIGN1cnNvciBpcyB3aXRoaW4gdGhhdCByZWdpb24uXG5cdFx0XHRcdFx0XHRcdGxldCBjb2RlYmxvY2tTdGFydEluZGV4ID0gc3RhcnRJbmRleCArIHNldHRpbmdzU3RhcnREYXRhLnN0YXJ0UG9zaXRpb247XG5cdFx0XHRcdFx0XHRcdGxldCBjb2RlYmxvY2tFbmRJbmRleCA9IHN0YXJ0SW5kZXggKyBzZXR0aW5nc1N0YXJ0RGF0YS5lbmRQb3NpdGlvbjtcblx0XHRcdFx0XHRcdFx0bGV0IHNldHRpbmdzVGV4dCA9IGRvY1RleHQuc2xpY2UoY29kZWJsb2NrU3RhcnRJbmRleCwgY29kZWJsb2NrRW5kSW5kZXggKVxuXG5cdFx0XHRcdFx0XHRcdGxldCBjdXJzb3JJbkNvZGVibG9jayA9IGNoZWNrQ3Vyc29ySW5SZWdpb24oY29kZWJsb2NrU3RhcnRJbmRleCwgY29kZWJsb2NrRW5kSW5kZXgsIHJhbmdlcyk7XG5cdFx0XHRcdFx0XHRcdGlmKGN1cnNvckluQ29kZWJsb2NrID09PSBmYWxzZSkge1xuXHRcblx0XHRcdFx0XHRcdFx0XHQvLyBJZiB0aGUgY3Vyc29yIGlzIG5vdCB3aXRoaW4gdGhlIHJlZ2lvbiB3ZSBwYXNzIHRoZSBkYXRhIHRvIHRoZVxuXHRcdFx0XHRcdFx0XHRcdC8vIHNldHRpbmdzIHZpZXcgc28gaXQgY2FuIGJlIGRpc3BsYXllZCBpbiB0aGUgcmVnaW9uLlxuXHRcdFx0XHRcdFx0XHRcdGJ1aWxkZXIuYWRkKFxuXHRcdFx0XHRcdFx0XHRcdFx0Y29kZWJsb2NrU3RhcnRJbmRleCxcblx0XHRcdFx0XHRcdFx0XHRcdGNvZGVibG9ja0VuZEluZGV4ICsgMSxcblx0XHRcdFx0XHRcdFx0XHRcdERlY29yYXRpb24ucmVwbGFjZSh7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdHdpZGdldDogbmV3IE11bHRpQ29sdW1uTWFya2Rvd25fRGVmaW5lZFNldHRpbmdzX0xpdmVQcmV2aWV3X1dpZGdldChzZXR0aW5nc1RleHQpLFxuXHRcdFx0XHRcdFx0XHRcdFx0fSlcblx0XHRcdFx0XHRcdFx0XHQpO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9XHRcdFx0XHRcdFx0XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0Ly8gQXQgdGhpcyBwb2ludCBpZiB0aGUgY3Vyc29yIGlzbnQgaW4gdGhlIHJlZ2lvbiB3ZSBwYXNzIHRoZSBkYXRhIHRvIHRoZVxuXHRcdFx0XHRcdC8vIGVsZW1lbnQgdG8gYmUgcmVuZGVyZWQuXG5cdFx0XHRcdFx0aWYoY3Vyc29ySW5SZWdpb24gPT09IGZhbHNlKSB7XG5cdFx0XHRcdFx0XHRidWlsZGVyLmFkZChcblx0XHRcdFx0XHRcdFx0c3RhcnRJbmRleCxcblx0XHRcdFx0XHRcdFx0ZW5kSW5kZXgsXG5cdFx0XHRcdFx0XHRcdERlY29yYXRpb24ucmVwbGFjZSh7XG5cdFx0XHRcdFx0XHRcdFx0d2lkZ2V0OiBuZXcgTXVsdGlDb2x1bW5NYXJrZG93bl9MaXZlUHJldmlld19XaWRnZXQoZWxlbWVudFRleHQpLFxuXHRcdFx0XHRcdFx0XHR9KVxuXHRcdFx0XHRcdFx0KTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0Z2VuZXJhdGVkID0gdHJ1ZTtcblxuXHRcdFx0XHRcdC8vIFJlQ2FsY3VsYXRlIGFkZGl0aW9uYWwgc3RhcnQgdGFncyBpZiB0aGVyZSBhcmUgbW9yZSBpbiBkb2N1bWVudC5cblx0XHRcdFx0XHRzdGFydFRhZ0RhdGEgPSBmaW5kU3RhcnRUYWcod29ya2luZ0ZpbGVUZXh0KTtcblx0XHRcdFx0XHRpZihzdGFydFRhZ0RhdGEuZm91bmQgPT09IGZhbHNlKSB7XG5cdFx0XHRcdFx0XHRzdGFydFRhZ0RhdGEgPSBmaW5kU3RhcnRDb2RlYmxvY2sod29ya2luZ0ZpbGVUZXh0KTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRlbmRUYWdEYXRhID0gZmluZEVuZFRhZyh3b3JraW5nRmlsZVRleHQpO1xuXHRcdFx0XHRcdGxvb3BJbmRleCsrO1xuXHRcdFx0XHRcdGlmKGxvb3BJbmRleCA+IDEwMCkge1xuXHRcdFx0XHRcdFx0Y29uc29sZS53YXJuKFwiUG90ZW50aWFsIGlzc3VlIHdpdGggcmVuZGVyaW5nIE11bHRpLUNvbHVtbiBNYXJrZG93biBsaXZlIHByZXZpZXcgcmVnaW9ucy4gSWYgcHJvYmxlbSBwZXJzaXN0cyBwbGVhc2UgZmlsZSBhIGJ1ZyByZXBvcnQgd2l0aCBkZXZlbG9wZXIuXCIpXG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH0sXG5cdFx0fSk7XG4gXG5cdFx0cmV0dXJuIGJ1aWxkZXIuZmluaXNoKCk7XG5cblx0XHRmdW5jdGlvbiBnZXRDdXJzb3JMaW5lTG9jYXRpb25zKCk6IHsgbGluZTogTGluZSwgcG9zaXRpb246IG51bWJlciB9W10ge1xuXG5cdFx0XHRsZXQgcmFuZ2VzOiB7IGxpbmU6IExpbmUsIHBvc2l0aW9uOiBudW1iZXIgfVtdID0gW107XG5cblx0XHRcdGlmICh0cmFuc2FjdGlvbi5zdGF0ZS5zZWxlY3Rpb24ucmFuZ2VzKSB7XG5cblx0XHRcdFx0cmFuZ2VzID0gdHJhbnNhY3Rpb24uc3RhdGUuc2VsZWN0aW9uLnJhbmdlcy5maWx0ZXIoKHJhbmdlKSA9PiB7XG5cblx0XHRcdFx0XHRyZXR1cm4gcmFuZ2UuZW1wdHk7XG5cdFx0XHRcdH0pLm1hcCgocmFuZ2UpID0+IHtcblxuXHRcdFx0XHRcdGxldCBsaW5lID0gdHJhbnNhY3Rpb24uc3RhdGUuZG9jLmxpbmVBdChyYW5nZS5oZWFkKTtcblx0XHRcdFx0XHRsZXQgdGV4dCA9IGAke2xpbmUubnVtYmVyfToke3JhbmdlLmhlYWQgLSBsaW5lLmZyb219YDtcblxuXHRcdFx0XHRcdHJldHVybiB7XG5cdFx0XHRcdFx0XHRsaW5lOiBsaW5lLFxuXHRcdFx0XHRcdFx0cG9zaXRpb246IHJhbmdlLmhlYWRcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0pO1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gcmFuZ2VzO1xuXHRcdH1cblxuICAgICAgICBmdW5jdGlvbiB2YWx1ZUlzSW5SYW5nZSh2YWx1ZTogbnVtYmVyLCBtaW5WYWw6IG51bWJlciwgbWF4VmFsOiBudW1iZXIsIGluY2x1c2l2ZTogYm9vbGVhbiA9IHRydWUpIHtcblxuICAgICAgICAgICAgaWYoaW5jbHVzaXZlID09PSB0cnVlICYmICh2YWx1ZSA9PT0gbWluVmFsIHx8IHZhbHVlID09PSBtYXhWYWwpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChtaW5WYWwgPCB2YWx1ZSAmJiB2YWx1ZSA8IG1heFZhbCkge1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuXG5cdFx0ZnVuY3Rpb24gY2hlY2tDdXJzb3JJblJlZ2lvbihzdGFydEluZGV4OiBudW1iZXIsXG5cdFx0XHRcdFx0XHRcdFx0ZW5kSW5kZXg6IG51bWJlciwgXG5cdFx0XHRcdFx0XHRcdFx0cmFuZ2VzOiB7IGxpbmU6IExpbmUsIHBvc2l0aW9uOiBudW1iZXIgfVtdICk6IGJvb2xlYW4ge1xuXG5cdFx0XHRsZXQgY3Vyc29ySW5SZWdpb24gPSBmYWxzZTtcblx0XHRcdGZvciAobGV0IGkgPSAwOyBpIDwgcmFuZ2VzLmxlbmd0aDsgaSsrKSB7XG5cblx0XHRcdFx0Ly8gVE9ETzogTWF5YmUgbG9vayBpbnRvIGxpbWl0aW5nIHRoaXMgdG8gdGhlIHNlY29uZCBhbmQgc2Vjb25kIHRvIGxhc3QgbGluZVxuXHRcdFx0XHQvLyBvZiB0aGUgcmVnaW9uIGFzIGNsaWNraW5nIHJpZ2h0IGF0IHRoZSB0b3Agb3IgYm90dG9tIG9mIHRoZSByZWdpb25cblx0XHRcdFx0Ly8gc3dhcHMgaXQgdG8gdW5yZW5kZXJlZC5cblx0XHRcdFx0bGV0IHJhbmdlID0gcmFuZ2VzW2ldO1xuXHRcdFx0XHRpZih2YWx1ZUlzSW5SYW5nZShyYW5nZS5wb3NpdGlvbiwgc3RhcnRJbmRleCwgZW5kSW5kZXgpID09PSB0cnVlKSB7XG5cdFx0XHRcdFx0Y3Vyc29ySW5SZWdpb24gPSB0cnVlO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdGlmKGN1cnNvckluUmVnaW9uID09PSBmYWxzZSAmJiB0cmFuc2FjdGlvbi5zZWxlY3Rpb24pe1xuXHRcdFx0XHRmb3IgKGxldCBpID0gMDsgaSA8IHRyYW5zYWN0aW9uLnNlbGVjdGlvbi5yYW5nZXMubGVuZ3RoOyBpKyspIHtcblxuXHRcdFx0XHRcdGxldCByYW5nZSA9IHRyYW5zYWN0aW9uLnNlbGVjdGlvbi5yYW5nZXNbaV07XG5cblx0XHRcdFx0XHQvLyBJZiBlaXRoZXIgdGhlIHN0YXJ0IG9yIGVuZCBvZiB0aGUgc2VsZWN0aW9uIGlzIHdpdGhpbiB0aGVcblx0XHRcdFx0XHQvLyByZWdpb24gcmFuZ2Ugd2UgZG8gbm90IHJlbmRlciBsaXZlIHByZXZpZXcuXG5cdFx0XHRcdFx0aWYodmFsdWVJc0luUmFuZ2UocmFuZ2UuZnJvbSwgc3RhcnRJbmRleCwgZW5kSW5kZXgpIHx8IFxuXHRcdFx0XHRcdCAgIHZhbHVlSXNJblJhbmdlKHJhbmdlLnRvLCBzdGFydEluZGV4LCBlbmRJbmRleCkpIHtcblx0XHRcdFx0XHRcdGN1cnNvckluUmVnaW9uID0gdHJ1ZTtcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdC8vIE9yIGlmIHRoZSBlbnRpcmUgcmVnaW9uIGlzIHdpdGhpbiB0aGUgc2VsZWN0aW9uIHJhbmdlXG5cdFx0XHRcdFx0Ly8gd2UgZG8gbm90IHJlbmRlciB0aGUgbGl2ZSBwcmV2aWV3LlxuXHRcdFx0XHRcdGlmKHZhbHVlSXNJblJhbmdlKHN0YXJ0SW5kZXgsIHJhbmdlLmZyb20sIHJhbmdlLnRvKSAmJiBcblx0XHRcdFx0XHQgICB2YWx1ZUlzSW5SYW5nZShlbmRJbmRleCwgcmFuZ2UuZnJvbSwgcmFuZ2UudG8pKSB7XG5cdFx0XHRcdFx0XHRjdXJzb3JJblJlZ2lvbiA9IHRydWU7XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIGN1cnNvckluUmVnaW9uO1xuXHRcdH1cblx0fSxcblx0cHJvdmlkZShmaWVsZDogU3RhdGVGaWVsZDxEZWNvcmF0aW9uU2V0Pik6IEV4dGVuc2lvbiB7XG5cdFx0cmV0dXJuIEVkaXRvclZpZXcuZGVjb3JhdGlvbnMuZnJvbShmaWVsZCk7XG5cdH0sXG59KTtcblxuIiwiLypcclxuICogRmlsZTogbXVsdGktY29sdW1uLW1hcmtkb3duL3NyYy9tYWluLnRzXHJcbiAqIENyZWF0ZWQgRGF0ZTogVHVlc2RheSwgT2N0b2JlciA1dGggMjAyMSwgMTowOSBwbVxyXG4gKiBBdXRob3I6IENhbWVyb24gUm9iaW5zb25cclxuICogXHJcbiAqIENvcHlyaWdodCAoYykgMjAyMiBDYW1lcm9uIFJvYmluc29uXHJcbiAqL1xyXG5cclxuaW1wb3J0IHsgTm90aWNlLCBQbHVnaW4sICBNYXJrZG93blJlbmRlckNoaWxkLCBNYXJrZG93blJlbmRlcmVyLCBURmlsZSB9IGZyb20gJ29ic2lkaWFuJztcclxuaW1wb3J0ICogYXMgbXVsdGlDb2x1bW5QYXJzZXIgZnJvbSAnLi91dGlsaXRpZXMvdGV4dFBhcnNlcic7XHJcbmltcG9ydCB7IEZpbGVET01NYW5hZ2VyLCBHbG9iYWxET01NYW5hZ2VyIH0gZnJvbSAnLi9kb21fbWFuYWdlci9kb21NYW5hZ2VyJztcclxuaW1wb3J0IHsgTXVsdGlDb2x1bW5SZW5kZXJEYXRhIH0gZnJvbSBcIi4vZG9tX21hbmFnZXIvcmVnaW9uYWxfbWFuYWdlcnMvcmVnaW9uTWFuYWdlclwiO1xyXG5pbXBvcnQgeyBSZWdpb25NYW5hZ2VyIH0gZnJvbSBcIi4vZG9tX21hbmFnZXIvcmVnaW9uYWxfbWFuYWdlcnMvcmVnaW9uTWFuYWdlclwiO1xyXG5pbXBvcnQgeyBSZWdpb25NYW5hZ2VyQ29udGFpbmVyIH0gZnJvbSBcIi4vZG9tX21hbmFnZXIvcmVnaW9uYWxfbWFuYWdlcnMvcmVnaW9uTWFuYWdlckNvbnRhaW5lclwiO1xyXG5pbXBvcnQgeyBET01PYmplY3QsIERPTU9iamVjdFRhZywgVGFza0xpc3RET01PYmplY3QgfSBmcm9tICcuL2RvbV9tYW5hZ2VyL2RvbU9iamVjdCc7XHJcbmltcG9ydCB7IGZpbGVTdGlsbEluVmlldywgZ2V0RmlsZUxlYWYsIGdldExlYWZTb3VyY2VNb2RlLCBnZXRVSUQgfSBmcm9tICcuL3V0aWxpdGllcy91dGlscyc7XHJcbmltcG9ydCB7IE11bHRpQ29sdW1uTGF5b3V0Q1NTLCBNdWx0aUNvbHVtblN0eWxlQ1NTIH0gZnJvbSAnLi91dGlsaXRpZXMvY3NzRGVmaW5pdGlvbnMnO1xyXG5pbXBvcnQgeyBFbGVtZW50UmVuZGVyVHlwZSB9IGZyb20gJy4vdXRpbGl0aWVzL2VsZW1lbnRSZW5kZXJUeXBlUGFyc2VyJztcclxuaW1wb3J0IHsgbXVsdGlDb2x1bW5NYXJrZG93bl9TdGF0ZUZpZWxkIH0gZnJvbSAnLi9saXZlX3ByZXZpZXcvY202X2xpdmVQcmV2aWV3JztcclxuaW1wb3J0IHsgcGFyc2VTdGFydFJlZ2lvbkNvZGVCbG9ja0lEIH0gZnJvbSAnLi91dGlsaXRpZXMvc2V0dGluZ3NQYXJzZXInO1xyXG5cclxuY29uc3QgQ09ERUJMT0NLX1NUQVJUX1NUUlMgPSBbXHJcbiAgICBcInN0YXJ0LW11bHRpLWNvbHVtblwiLFxyXG4gICAgXCJtdWx0aS1jb2x1bW4tc3RhcnRcIlxyXG5dXHJcbmV4cG9ydCBkZWZhdWx0IGNsYXNzIE11bHRpQ29sdW1uTWFya2Rvd24gZXh0ZW5kcyBQbHVnaW4ge1xyXG5cclxuICAgIGdsb2JhbE1hbmFnZXI6IEdsb2JhbERPTU1hbmFnZXIgPSBuZXcgR2xvYmFsRE9NTWFuYWdlcigpO1xyXG5cclxuXHRhc3luYyBvbmxvYWQoKSB7XHJcblxyXG4gICAgICAgIGNvbnNvbGUubG9nKFwiTG9hZGluZyBtdWx0aS1jb2x1bW4gbWFya2Rvd25cIik7XHJcbiAgICAgICAgdGhpcy5nbG9iYWxNYW5hZ2VyID0gbmV3IEdsb2JhbERPTU1hbmFnZXIoKTtcclxuXHJcbiAgICAgICAgdGhpcy5yZWdpc3RlckVkaXRvckV4dGVuc2lvbihtdWx0aUNvbHVtbk1hcmtkb3duX1N0YXRlRmllbGQpXHJcblxyXG4gICAgICAgIGZvcihsZXQgaSA9IDA7IGkgPCBDT0RFQkxPQ0tfU1RBUlRfU1RSUy5sZW5ndGg7IGkrKykge1xyXG5cclxuICAgICAgICAgICAgbGV0IHN0YXJ0U3RyID0gQ09ERUJMT0NLX1NUQVJUX1NUUlNbaV1cclxuICAgICAgICAgICAgdGhpcy5zZXR1cE1hcmtkb3duQ29kZWJsb2NrUG9zdFByb2Nlc3NvcihzdGFydFN0cik7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHRoaXMuc2V0dXBNYXJrZG93blBvc3RQcm9jZXNzb3IoKTtcclxuXHJcbiAgICAgICAgLy9UT0RPOiBTZXQgdXAgdGhpcyBhcyBhIG1vZGFsIHRvIHNldCBzZXR0aW5ncyBhdXRvbWF0aWNhbGx5XHJcbiAgICAgICAgdGhpcy5hZGRDb21tYW5kKHsgICAgICAgICAgICBcclxuICAgICAgICAgICAgaWQ6IGBpbnNlcnQtbXVsdGktY29sdW1uLXJlZ2lvbmAsXHJcbiAgICAgICAgICAgIG5hbWU6IGBJbnNlcnQgTXVsdGktQ29sdW1uIFJlZ2lvbmAsXHJcbiAgICAgICAgICAgIGVkaXRvckNhbGxiYWNrOiAoZWRpdG9yLCB2aWV3KSA9PiB7XHJcblxyXG4gICAgICAgICAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgICAgICAgICBsZXQgY3Vyc29yU3RhcnRQb3NpdGlvbiA9IGVkaXRvci5nZXRDdXJzb3IoXCJmcm9tXCIpO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICBlZGl0b3IuZ2V0RG9jKCkucmVwbGFjZVNlbGVjdGlvbihcclxuYFxyXG5cXGBcXGBcXGBzdGFydC1tdWx0aS1jb2x1bW5cclxuSUQ6IElEXyR7Z2V0VUlEKDQpfVxyXG5OdW1iZXIgb2YgQ29sdW1uczogMlxyXG5MYXJnZXN0IENvbHVtbjogc3RhbmRhcmRcclxuXFxgXFxgXFxgXHJcblxyXG5cclxuXHJcbi0tLSBjb2x1bW4tZW5kIC0tLVxyXG5cclxuXHJcblxyXG49PT0gZW5kLW11bHRpLWNvbHVtblxyXG5cclxuJHtlZGl0b3IuZ2V0RG9jKCkuZ2V0U2VsZWN0aW9uKCl9YFxyXG4gICAgICAgICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgICAgICAgICAgXHJcbiAgICAgICAgICAgICAgICAgICAgY3Vyc29yU3RhcnRQb3NpdGlvbi5saW5lID0gY3Vyc29yU3RhcnRQb3NpdGlvbi5saW5lICsgN1xyXG4gICAgICAgICAgICAgICAgICAgIGN1cnNvclN0YXJ0UG9zaXRpb24uY2ggPSAwO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICBlZGl0b3Iuc2V0Q3Vyc29yKGN1cnNvclN0YXJ0UG9zaXRpb24pO1xyXG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xyXG4gICAgICAgICAgICAgICAgICAgIG5ldyBOb3RpY2UoXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIFwiRW5jb3VudGVyZWQgYW4gZXJyb3IgaW5zZXJ0aW5nIGEgbXVsdGktY29sdW1uIHJlZ2lvbi4gUGxlYXNlIHRyeSBhZ2FpbiBsYXRlci5cIlxyXG4gICAgICAgICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgdGhpcy5hZGRDb21tYW5kKHsgICAgICAgICAgICBcclxuICAgICAgICAgICAgaWQ6IGBhZGQtSURzLVRvLW11bHRpLWNvbHVtbi1yZWdpb25gLFxyXG4gICAgICAgICAgICBuYW1lOiBgRml4IE1pc3NpbmcgSURzIGZvciBNdWx0aS1Db2x1bW4gUmVnaW9uc2AsXHJcbiAgICAgICAgICAgIGVkaXRvckNhbGxiYWNrOiAoZWRpdG9yLCB2aWV3KSA9PiB7XHJcblxyXG4gICAgICAgICAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgICAgICAgICAvKipcclxuICAgICAgICAgICAgICAgICAgICAgKiBOb3Qgc3VyZSBpZiB0aGVyZSBpcyBhbiBlYXNpZXIgd2F5IHRvIGRvIHRoaXMuXHJcbiAgICAgICAgICAgICAgICAgICAgICogXHJcbiAgICAgICAgICAgICAgICAgICAgICogR2V0IGFsbCBvZiB0aGUgbGluZXMgb2YgdGhlIGRvY3VtZW50IHNwbGl0IGJ5IG5ld2xpbmVzLlxyXG4gICAgICAgICAgICAgICAgICAgICAqL1xyXG4gICAgICAgICAgICAgICAgICAgIGxldCBkb2NUZXh0ID0gZWRpdG9yLmdldFJhbmdlKHsgbGluZTogMCwgY2g6IDAgfSwgeyBsaW5lOiBlZGl0b3IuZ2V0RG9jKCkubGluZUNvdW50KCksIGNoOiAwfSk7XHJcbiAgICAgICAgICAgICAgICAgICAgbGV0IGxpbmVzID0gZG9jVGV4dC5zcGxpdChcIlxcblwiKTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgbGV0IHN0YXJ0Q29kZWJsb2NrID0gbXVsdGlDb2x1bW5QYXJzZXIuZmluZFN0YXJ0Q29kZWJsb2NrKGRvY1RleHQpO1xyXG4gICAgICAgICAgICAgICAgICAgIGxldCBsaW5lT2Zmc2V0ID0gMDtcclxuICAgICAgICAgICAgICAgICAgICBsZXQgbnVtQ29kZWJsb2Nrc1VwZGF0ZWQgPSAwO1xyXG4gICAgICAgICAgICAgICAgICAgIHdoaWxlKHN0YXJ0Q29kZWJsb2NrLmZvdW5kID09PSB0cnVlKSB7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgc3RhcnRSZXBsYWNlTGluZXMgPSAoZG9jVGV4dC5zbGljZSgwLCBzdGFydENvZGVibG9jay5zdGFydFBvc2l0aW9uKS5zcGxpdChcIlxcblwiKS5sZW5ndGggLSAxKSArIGxpbmVPZmZzZXQ7IC8vIC0xIHRvIFplcm8gaW5kZXggdGhlIHJlcGxhY2UgbGluZVxyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHNldHRpbmdzVGV4dCA9IGRvY1RleHQuc2xpY2Uoc3RhcnRDb2RlYmxvY2suc3RhcnRQb3NpdGlvbiwgc3RhcnRDb2RlYmxvY2suZW5kUG9zaXRpb24pO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgc2V0dGluZ3NJRCA9IHBhcnNlU3RhcnRSZWdpb25Db2RlQmxvY2tJRChzZXR0aW5nc1RleHQpO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYoc2V0dGluZ3NJRCA9PT0gXCJcIikge1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCByZXBsYWNlbWVudFRleHQgPSBlZGl0b3IuZ2V0UmFuZ2UoeyBsaW5lOiBzdGFydFJlcGxhY2VMaW5lcywgY2g6IDAgfSwgeyBsaW5lOiBzdGFydFJlcGxhY2VMaW5lcywgY2g6IHN0YXJ0Q29kZWJsb2NrLm1hdGNoTGVuZ3RofSkgKyBgXFxuSUQ6IElEXyR7Z2V0VUlEKDQpfWBcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVkaXRvci5yZXBsYWNlUmFuZ2UocmVwbGFjZW1lbnRUZXh0LCB7IGxpbmU6IHN0YXJ0UmVwbGFjZUxpbmVzLCBjaDogMCB9LCBcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7IGxpbmU6IHN0YXJ0UmVwbGFjZUxpbmVzLCBjaDogc3RhcnRDb2RlYmxvY2subWF0Y2hMZW5ndGh9KTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGFydFJlcGxhY2VMaW5lcyArPSAxOyAvLyB3ZSBhZGRlZCBhIGxpbmUgdG8gdGhlIGRvYyBzbyB1cGRhdGUgb3VyIG9mZnNldC5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG51bUNvZGVibG9ja3NVcGRhdGVkICs9IDE7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgbGluZU9mZnNldCA9IHN0YXJ0UmVwbGFjZUxpbmVzXHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBkb2NUZXh0ID0gZG9jVGV4dC5zbGljZShzdGFydENvZGVibG9jay5zdGFydFBvc2l0aW9uICsgc3RhcnRDb2RlYmxvY2subWF0Y2hMZW5ndGgpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBzdGFydENvZGVibG9jayA9IG11bHRpQ29sdW1uUGFyc2VyLmZpbmRTdGFydENvZGVibG9jayhkb2NUZXh0KTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIC8qKlxyXG4gICAgICAgICAgICAgICAgICAgICAqIExvb3AgdGhyb3VnaCBhbGwgb2YgdGhlIGxpbmVzIGNoZWNraW5nIGlmIHRoZSBsaW5lIGlzIGEgXHJcbiAgICAgICAgICAgICAgICAgICAgICogc3RhcnQgdGFnIGFuZCBpZiBzbyBpcyBpdCBtaXNzaW5nIGFuIElELlxyXG4gICAgICAgICAgICAgICAgICAgICAqL1xyXG4gICAgICAgICAgICAgICAgICAgIGxldCBsaW5lc1dpdGhvdXRJRHMgPSBbXVxyXG4gICAgICAgICAgICAgICAgICAgIGxldCB0ZXh0V2l0aG91dElEcyA9IFtdXHJcbiAgICAgICAgICAgICAgICAgICAgZm9yKGxldCBpID0gMDsgaSA8IGxpbmVzLmxlbmd0aDsgaSsrKSB7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgZGF0YSA9IG11bHRpQ29sdW1uUGFyc2VyLmlzU3RhcnRUYWdXaXRoSUQobGluZXNbaV0pO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZihkYXRhLmlzU3RhcnRUYWcgPT09IHRydWUgJiYgZGF0YS5oYXNLZXkgPT09IGZhbHNlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5lc1dpdGhvdXRJRHMucHVzaChpKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRleHRXaXRob3V0SURzLnB1c2gobGluZXNbaV0pXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICB9ICAgICAgICAgICAgICAgICAgICBcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgaWYobGluZXNXaXRob3V0SURzLmxlbmd0aCA9PT0gMCAmJiBudW1Db2RlYmxvY2tzVXBkYXRlZCA9PT0gMCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBuZXcgTm90aWNlIChcIkZvdW5kIDAgbWlzc2luZyBJRHMgaW4gdGhlIGN1cnJlbnQgZG9jdW1lbnQuXCIpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICAvKipcclxuICAgICAgICAgICAgICAgICAgICAgKiBOb3cgbG9vcCB0aHJvdWdoIGVhY2ggbGluZSB0aGF0IGlzIG1pc3NpbmcgYW4gSUQgYW5kXHJcbiAgICAgICAgICAgICAgICAgICAgICogZ2VuZXJhdGUgYSByYW5kb20gSUQgYW5kIHJlcGxhY2UgdGhlIG9yaWdpbmFsIHRleHQuXHJcbiAgICAgICAgICAgICAgICAgICAgICovXHJcbiAgICAgICAgICAgICAgICAgICAgZm9yKGxldCBpID0gMDsgaSA8IGxpbmVzV2l0aG91dElEcy5sZW5ndGg7IGkrKykge1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IG9yaWdpbmFsVGV4dCA9IHRleHRXaXRob3V0SURzW2ldXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCB0ZXh0ID0gb3JpZ2luYWxUZXh0O1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB0ZXh0ID0gdGV4dC50cmltRW5kKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKHRleHQuY2hhckF0KHRleHQubGVuZ3RoIC0gMSkgPT09IFwiOlwiKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXh0ID0gdGV4dC5zbGljZSgwLCB0ZXh0Lmxlbmd0aC0xKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICB0ZXh0ID0gYCR7dGV4dH06IElEXyR7Z2V0VUlEKDQpfWA7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBlZGl0b3IucmVwbGFjZVJhbmdlKHRleHQsIHsgbGluZTogbGluZXNXaXRob3V0SURzW2ldLCBjaDogMCB9LCBcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7IGxpbmU6IGxpbmVzV2l0aG91dElEc1tpXSwgY2g6IG9yaWdpbmFsVGV4dC5sZW5ndGh9KTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIG5ldyBOb3RpY2UgKGBSZXBsYWNlZCAke2xpbmVzV2l0aG91dElEcy5sZW5ndGggKyBudW1Db2RlYmxvY2tzVXBkYXRlZH0gbWlzc2luZyBJRChzKSBpbiB0aGUgY3VycmVudCBkb2N1bWVudC5gKTtcclxuICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcclxuICAgICAgICAgICAgICAgICAgICBuZXcgTm90aWNlKFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBcIkVuY291bnRlcmVkIGFuIGVycm9yIGFkZGlnbiBJRHMgdG8gbXVsdGktY29sdW1uIHJlZ2lvbnMuIFBsZWFzZSB0cnkgYWdhaW4gbGF0ZXIuXCJcclxuICAgICAgICAgICAgICAgICAgICApO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfSk7XHJcblxyXG4gICAgICAgIHRoaXMucmVnaXN0ZXJJbnRlcnZhbCh3aW5kb3cuc2V0SW50ZXJ2YWwoKCkgPT4ge1xyXG4gICAgICAgICAgICBcclxuICAgICAgICAgICAgdGhpcy5VcGRhdGVPcGVuRmlsZVByZXZpZXdzKCk7XHJcbiAgICAgICAgfSwgNTAwKSk7XHJcbiAgICB9XHJcblxyXG4gICAgVXBkYXRlT3BlbkZpbGVQcmV2aWV3cygpIHtcclxuXHJcbiAgICAgICAgbGV0IGZpbGVNYW5hZ2VycyA9IHRoaXMuZ2xvYmFsTWFuYWdlci5nZXRBbGxGaWxlTWFuYWdlcnMoKTtcclxuICAgICAgICBmaWxlTWFuYWdlcnMuZm9yRWFjaChlbGVtZW50ID0+IHtcclxuICAgICAgICAgICAgXHJcbiAgICAgICAgICAgIGxldCByZWdpb25hbE1hbmFnZXJzID0gZWxlbWVudC5nZXRBbGxSZWdpb25hbE1hbmFnZXJzKCk7XHJcbiAgICAgICAgICAgIHJlZ2lvbmFsTWFuYWdlcnMuZm9yRWFjaChyZWdpb25NYW5hZ2VyID0+IHtcclxuICAgICAgICAgICAgICAgIFxyXG4gICAgICAgICAgICAgICAgcmVnaW9uTWFuYWdlci51cGRhdGVSZW5kZXJlZE1hcmtkb3duKClcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgc2V0dXBNYXJrZG93blBvc3RQcm9jZXNzb3IoKSB7XHJcbiAgICAgICAgdGhpcy5yZWdpc3Rlck1hcmtkb3duUG9zdFByb2Nlc3Nvcihhc3luYyAoZWwsIGN0eCkgPT4ge1xyXG5cclxuICAgICAgICAgICAgY29uc3Qgc291cmNlUGF0aCA9IGN0eC5zb3VyY2VQYXRoO1xyXG5cclxuICAgICAgICAgICAgbGV0IGZpbGVET01NYW5hZ2VyID0gdGhpcy5nbG9iYWxNYW5hZ2VyLmdldEZpbGVNYW5hZ2VyKHNvdXJjZVBhdGgpO1xyXG4gICAgICAgICAgICBpZihmaWxlRE9NTWFuYWdlciA9PT0gbnVsbCkge1xyXG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coXCJGb3VuZCBudWxsIERPTSBtYW5hZ2VyLiBDb3VsZCBub3QgcHJvY2VzcyBtdWx0aS1jb2x1bW4gbWFya2Rvd24uXCIpXHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIC8qKlxyXG4gICAgICAgICAgICAgKiBIZXJlIHdlIGNoZWNrIGlmIHRoZSBleHBvcnQgXCJwcmludFwiIGZsYWcgaXMgaW4gdGhlIERPTSBzbyB3ZSBjYW4gZGV0ZXJtaW5lIGlmIHdlXHJcbiAgICAgICAgICAgICAqIGFyZSBleHBvcnRpbmcgYW5kIGhhbmRsZSB0aGF0IGNhc2UuXHJcbiAgICAgICAgICAgICAqL1xyXG4gICAgICAgICAgICBpZih0aGlzLmNoZWNrRXhwb3J0aW5nKGVsKSkge1xyXG5cclxuICAgICAgICAgICAgICAgIHRoaXMuZXhwb3J0RG9jdW1lbnRUb1BERihlbCwgZmlsZURPTU1hbmFnZXIsIHNvdXJjZVBhdGgpO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAvLyBHZXQgdGhlIGluZm8gZm9yIG91ciBjdXJyZW50IGNvbnRleHQgYW5kIHRoZW4gY2hlY2tcclxuICAgICAgICAgICAgLy8gaWYgdGhlIGVudGlyZSB0ZXh0IGNvbnRhaW5zIGEgc3RhcnQgdGFnLiBJZiB0aGVyZSBpc1xyXG4gICAgICAgICAgICAvLyBubyBzdGFydCB0YWcgaW4gdGhlIGRvY3VtZW50IHdlIGNhbiBqdXN0IHJldHVybiBhbmRcclxuICAgICAgICAgICAgLy8gaWdub3JlIHRoZSByZXN0IG9mIHRoZSBwYXJzaW5nLlxyXG4gICAgICAgICAgICBsZXQgaW5mbyA9IGN0eC5nZXRTZWN0aW9uSW5mbyhlbCk7XHJcblxyXG4gICAgICAgICAgICAvKipcclxuICAgICAgICAgICAgICogV2UgbmVlZCB0aGUgY29udGV4dCBpbmZvIHRvIHByb3Blcmx5IHBhcnNlIHNvIHJldHVybmluZyBoZXJlIFxyXG4gICAgICAgICAgICAgKiBpbmZvIGlzIG51bGwuIFRPRE86IFNldCBlcnJvciBpbiB2aWV3IGlmIHRoaXMgb2NjdXJzLlxyXG4gICAgICAgICAgICAgKi9cclxuICAgICAgICAgICAgaWYoIWluZm8pIHtcclxuXHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGxldCBkb2NTdHJpbmcgPSBpbmZvLnRleHQ7XHJcbiAgICAgICAgICAgIGxldCBkb2NMaW5lcyA9IGRvY1N0cmluZy5zcGxpdChcIlxcblwiKTtcclxuXHJcbiAgICAgICAgICAgIC8qKlxyXG4gICAgICAgICAgICAgKiBJZiB3ZSBlbmNvdW50ZXIgYSBzdGFydCB0YWcgb24gdGhlIGRvY3VtZW50IHdlIHNldCB0aGUgZmxhZyB0byBzdGFydFxyXG4gICAgICAgICAgICAgKiBwYXJzaW5nIHRoZSByZXN0IG9mIHRoZSBkb2N1bWVudC5cclxuICAgICAgICAgICAgICovXHJcbiAgICAgICAgICAgIGlmKG11bHRpQ29sdW1uUGFyc2VyLmNvbnRhaW5zU3RhcnRUYWcoZWwudGV4dENvbnRlbnQpIHx8IFxyXG4gICAgICAgICAgICAgICBtdWx0aUNvbHVtblBhcnNlci5jb250YWluc1N0YXJ0Q29kZUJsb2NrKGRvY1N0cmluZykpIHtcclxuXHJcbiAgICAgICAgICAgICAgICBmaWxlRE9NTWFuYWdlci5zZXRIYXNTdGFydFRhZygpO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAvKiogXHJcbiAgICAgICAgICAgICAqIElmIHRoZSBkb2N1bWVudCBkb2VzIG5vdCBjb250YWluIGFueSBzdGFydCB0YWdzIHdlIGlnbm9yZSB0aGVcclxuICAgICAgICAgICAgICogcmVzdCBvZiB0aGUgcGFyc2luZy4gVGhpcyBpcyBvbmx5IHNldCB0byB0cnVlIG9uY2UgdGhlIGZpcnN0XHJcbiAgICAgICAgICAgICAqIHN0YXJ0IHRhZyBlbGVtZW50IGlzIHBhcnNlZCBhYm92ZS5cclxuICAgICAgICAgICAgICovXHJcbiAgICAgICAgICAgIGlmKGZpbGVET01NYW5hZ2VyLmdldEhhc1N0YXJ0VGFnKCkgPT09IGZhbHNlKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIC8qKlxyXG4gICAgICAgICAgICAgKiBUYWtlIHRoZSBpbmZvIHByb3ZpZGVkIGFuZCBnZW5lcmF0ZSB0aGUgcmVxdWlyZWQgdmFyaWFibGVzIGZyb20gXHJcbiAgICAgICAgICAgICAqIHRoZSBsaW5lIHN0YXJ0IGFuZCBlbmQgdmFsdWVzLlxyXG4gICAgICAgICAgICAgKi9cclxuICAgICAgICAgICAgbGV0IGxpbmVzQWJvdmVBcnJheSA9IGRvY0xpbmVzLnNsaWNlKDAsIGluZm8ubGluZVN0YXJ0KVxyXG4gICAgICAgICAgICBsZXQgbGluZXNPZkVsZW1lbnQgPSBkb2NMaW5lcy5zbGljZShpbmZvLmxpbmVTdGFydCwgaW5mby5saW5lRW5kICsgMSk7XHJcbiAgICAgICAgICAgIGxldCB0ZXh0T2ZFbGVtZW50ID0gbGluZXNPZkVsZW1lbnQuam9pbihcIlxcblwiKVxyXG4gICAgICAgICAgICBsZXQgbGluZXNCZWxvd0FycmF5ID0gZG9jTGluZXMuc2xpY2UoaW5mby5saW5lRW5kICsgMSlcclxuXHJcbiAgICAgICAgICAgIC8vI3JlZ2lvbiBEZXByZWNpYXRlZCBTdGFydCBUYWdcclxuICAgICAgICAgICAgLyoqXHJcbiAgICAgICAgICAgICAqIElmIHRoZSBjdXJyZW50IGxpbmUgaXMgYSBzdGFydCB0YWcgd2Ugd2FudCB0byBzZXQgdXAgdGhlXHJcbiAgICAgICAgICAgICAqIHJlZ2lvbiBtYW5hZ2VyLiBUaGUgcmVnaW9uYWwgbWFuYWdlciB0YWtlcyBjYXJlXHJcbiAgICAgICAgICAgICAqIG9mIGFsbCBpdGVtcyBiZXR3ZWVuIGl0J3Mgc3RhcnQgYW5kIGVuZCB0YWdzIHdoaWxlIHRoZVxyXG4gICAgICAgICAgICAgKiBmaWxlIG1hbmFnZXIgd2UgZ290IGFib3ZlIGFib3ZlIHRha2VzIGNhcmUgb2YgYWxsIHJlZ2lvbmFsIFxyXG4gICAgICAgICAgICAgKiBtYW5hZ2VycyBpbiBlYWNoIGZpbGUuXHJcbiAgICAgICAgICAgICAqL1xyXG4gICAgICAgICAgICBpZihtdWx0aUNvbHVtblBhcnNlci5jb250YWluc1N0YXJ0VGFnKHRleHRPZkVsZW1lbnQpKSB7XHJcblxyXG4gICAgICAgICAgICAgICAgLyoqIFxyXG4gICAgICAgICAgICAgICAgICogU2V0IHVwIHRoZSBjdXJyZW50IGVsZW1lbnQgdG8gYWN0IGFzIHRoZSBwYXJlbnQgZm9yIHRoZSBcclxuICAgICAgICAgICAgICAgICAqIG11bHRpLWNvbHVtbiByZWdpb24uXHJcbiAgICAgICAgICAgICAgICAgKi9cclxuICAgICAgICAgICAgICAgIGVsLmNoaWxkcmVuWzBdLmRldGFjaCgpO1xyXG4gICAgICAgICAgICAgICAgZWwuY2xhc3NMaXN0LmFkZChNdWx0aUNvbHVtbkxheW91dENTUy5SZWdpb25Sb290Q29udGFpbmVyRGl2KVxyXG4gICAgICAgICAgICAgICAgbGV0IHJlbmRlckVycm9yUmVnaW9uID0gZWwuY3JlYXRlRGl2KHtcclxuICAgICAgICAgICAgICAgICAgICBjbHM6IGAke011bHRpQ29sdW1uTGF5b3V0Q1NTLlJlZ2lvbkVycm9yQ29udGFpbmVyRGl2fSAke011bHRpQ29sdW1uU3R5bGVDU1MuUmVnaW9uRXJyb3JNZXNzYWdlfWAsXHJcbiAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICAgIGxldCByZW5kZXJDb2x1bW5SZWdpb24gPSBlbC5jcmVhdGVEaXYoe1xyXG4gICAgICAgICAgICAgICAgICAgIGNsczogTXVsdGlDb2x1bW5MYXlvdXRDU1MuUmVnaW9uQ29udGVudENvbnRhaW5lckRpdlxyXG4gICAgICAgICAgICAgICAgfSlcclxuXHJcbiAgICAgICAgICAgICAgICBsZXQgc3RhcnRCbG9ja0RhdGEgPSBtdWx0aUNvbHVtblBhcnNlci5nZXRTdGFydEJsb2NrQWJvdmVMaW5lKGxpbmVzT2ZFbGVtZW50KVxyXG4gICAgICAgICAgICAgICAgaWYoc3RhcnRCbG9ja0RhdGEgPT09IG51bGwpIHtcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBcclxuICAgICAgICAgICAgICAgIGxldCByZWdpb25LZXkgPSBzdGFydEJsb2NrRGF0YS5zdGFydEJsb2NrS2V5O1xyXG4gICAgICAgICAgICAgICAgaWYoZmlsZURPTU1hbmFnZXIuY2hlY2tLZXlFeGlzdHMocmVnaW9uS2V5KSA9PT0gdHJ1ZSkge1xyXG5cclxuICAgICAgICAgICAgICAgICAgICBsZXQgeyBudW1iZXJPZlRhZ3MsIGtleXMgfSA9IG11bHRpQ29sdW1uUGFyc2VyLmNvdW50U3RhcnRUYWdzKGluZm8udGV4dCk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIGxldCBudW1NYXRjaGVzID0gMDtcclxuICAgICAgICAgICAgICAgICAgICBmb3IobGV0IGkgPSAwOyBpIDwgbnVtYmVyT2ZUYWdzOyBpKyspIHtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEJlY2F1c2Ugd2UgY2hlY2tlZCBpZiBrZXkgZXhpc3RzIG9uZSBvZiB0aGVzZSBoYXMgdG8gbWF0Y2guXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKGtleXNbaV0gPT09IHJlZ2lvbktleSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbnVtTWF0Y2hlcysrO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICAvLyBXZSBvbmx5IHdhbnQgdG8gZGlzcGxheSBhbiBlcnJvciBpZiB0aGVyZSBhcmUgbW9yZSB0aGFuIDIgb2YgdGhlIHNhbWUgaWQgYWNyb3NzXHJcbiAgICAgICAgICAgICAgICAgICAgLy8gdGhlIHdob2xlIGRvY3VtZW50LiBUaGlzIHByZXZlbnRzIGVycm9zIHdoZW4gb2JzaWRpYW4gcmVsb2FkcyB0aGUgd2hvbGUgZG9jdW1lbnRcclxuICAgICAgICAgICAgICAgICAgICAvLyBhbmQgdGhlcmUgYXJlIHR3byBvZiB0aGUgc2FtZSBrZXkgaW4gdGhlIG1hcC5cclxuICAgICAgICAgICAgICAgICAgICBpZihudW1NYXRjaGVzID49IDIpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYocmVnaW9uS2V5ID09PSBcIlwiKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW5kZXJFcnJvclJlZ2lvbi5pbm5lclRleHQgPSBcIkZvdW5kIG11bHRpcGxlIHJlZ2lvbnMgd2l0aCBlbXB0eSBJRHMuIFBsZWFzZSBzZXQgYSB1bmlxdWUgSUQgYWZ0ZXIgZWFjaCBzdGFydCB0YWcuXFxuRUc6ICc9PT0gbXVsdGktY29sdW1uLXN0YXJ0OiByYW5kb21JRCdcXG5PciB1c2UgJ0ZpeCBNaXNzaW5nIElEcycgaW4gdGhlIGNvbW1hbmQgcGFsZXR0ZSBhbmQgcmVsb2FkIHRoZSBkb2N1bWVudC5cIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVuZGVyRXJyb3JSZWdpb24uaW5uZXJUZXh0ID0gXCJSZWdpb24gSUQgYWxyZWFkeSBleGlzdHMgaW4gZG9jdW1lbnQsIHBsZWFzZSBzZXQgYSB1bmlxdWUgSUQuXFxuRUc6ICc9PT0gbXVsdGktY29sdW1uLXN0YXJ0OiByYW5kb21JRCdcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBlbC5pZCA9IGBNdWx0aUNvbHVtbklEOiR7cmVnaW9uS2V5fWBcclxuXHJcbiAgICAgICAgICAgICAgICBsZXQgZWxlbWVudE1hcmtkb3duUmVuZGVyZXIgPSBuZXcgTWFya2Rvd25SZW5kZXJDaGlsZChlbCk7XHJcbiAgICAgICAgICAgICAgICBmaWxlRE9NTWFuYWdlci5jcmVhdGVSZWdpb25hbE1hbmFnZXIocmVnaW9uS2V5LCBlbCwgcmVuZGVyRXJyb3JSZWdpb24sIHJlbmRlckNvbHVtblJlZ2lvbik7XHJcbiAgICAgICAgICAgICAgICBlbGVtZW50TWFya2Rvd25SZW5kZXJlci5vbnVubG9hZCA9ICgpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICBpZihmaWxlRE9NTWFuYWdlcikge1xyXG4gICAgXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGZpbGVET01NYW5hZ2VyLnJlbW92ZVJlZ2lvbihzdGFydEJsb2NrRGF0YS5zdGFydEJsb2NrS2V5KTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9O1xyXG4gICAgICAgICAgICAgICAgY3R4LmFkZENoaWxkKGVsZW1lbnRNYXJrZG93blJlbmRlcmVyKTtcclxuXHJcbiAgICAgICAgICAgICAgICAvKipcclxuICAgICAgICAgICAgICAgICAqIE5vdyB3ZSBoYXZlIGNyZWF0ZWQgb3VyIHJlZ2lvbmFsIG1hbmFnZXIgYW5kIGRlZmluZWQgd2hhdCBlbGVtZW50cyBcclxuICAgICAgICAgICAgICAgICAqIG5lZWQgdG8gYmUgcmVuZGVyZWQgaW50by4gU28gd2UgY2FuIHJldHVybiB3aXRob3V0IGFueSBtb3JlIHByb2Nlc3NpbmcuXHJcbiAgICAgICAgICAgICAgICAgKi9cclxuICAgICAgICAgICAgICAgIHJldHVyblxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIC8vI2VuZHJlZ2lvbiBEZXByZWNpYXRlZCBTdGFydCBUYWdcclxuXHJcbiAgICAgICAgICAgIC8qKlxyXG4gICAgICAgICAgICAgKiBDaGVjayBpZiBhbnkgb2YgdGhlIGxpbmVzIGFib3ZlIHVzIGNvbnRhaW4gYSBzdGFydCBibG9jaywgYW5kIGlmXHJcbiAgICAgICAgICAgICAqIHNvIGdldCB0aGUgbGluZXMgZnJvbSBvdXIgY3VycmVudCBlbGVtZW50IHRvIHRoZSBzdGFydCBibG9jay5cclxuICAgICAgICAgICAgICovXHJcbiAgICAgICAgICAgIGxldCBzdGFydEJvY2tBYm92ZSA9IG11bHRpQ29sdW1uUGFyc2VyLmdldFN0YXJ0QmxvY2tPckNvZGVibG9ja0Fib3ZlTGluZShsaW5lc0Fib3ZlQXJyYXkpO1xyXG4gICAgICAgICAgICBpZihzdGFydEJvY2tBYm92ZSA9PT0gbnVsbCkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIC8qKlxyXG4gICAgICAgICAgICAgKiBXZSBub3cga25vdyB3ZSdyZSB3aXRoaW4gYSBtdWx0aS1jb2x1bW4gcmVnaW9uLCBzbyB3ZSB1cGRhdGUgb3VyXHJcbiAgICAgICAgICAgICAqIGxpc3Qgb2YgbGluZXMgYWJvdmUgdG8ganVzdCBiZSB0aGUgaXRlbXMgd2l0aGluIHRoaXMgcmVnaW9uLlxyXG4gICAgICAgICAgICAgKi9cclxuICAgICAgICAgICAgbGluZXNBYm92ZUFycmF5ID0gc3RhcnRCb2NrQWJvdmUubGluZXNBYm92ZUFycmF5O1xyXG5cclxuICAgICAgICAgICAgLyoqXHJcbiAgICAgICAgICAgICAqIFdlIHVzZSB0aGUgc3RhcnQgYmxvY2sncyBrZXkgdG8gZ2V0IG91ciByZWdpb25hbCBtYW5hZ2VyLiBJZiB0aGlzXHJcbiAgICAgICAgICAgICAqIGxvb2t1cCBmYWlscyB3ZSBjYW4gbm90IGNvbnRpbnVlIHByb2Nlc3NpbmcgdGhpcyBlbGVtZW50LlxyXG4gICAgICAgICAgICAgKi9cclxuICAgICAgICAgICAgbGV0IHJlZ2lvbmFsQ29udGFpbmVyOiBSZWdpb25NYW5hZ2VyQ29udGFpbmVyID0gZmlsZURPTU1hbmFnZXIuZ2V0UmVnaW9uYWxDb250YWluZXIoc3RhcnRCb2NrQWJvdmUuc3RhcnRCbG9ja0tleSk7XHJcbiAgICAgICAgICAgIGlmKHJlZ2lvbmFsQ29udGFpbmVyID09PSBudWxsKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm5cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBsZXQgcmVnaW9uYWxNYW5hZ2VyOiBSZWdpb25NYW5hZ2VyID0gcmVnaW9uYWxDb250YWluZXIuZ2V0UmVnaW9uKCk7XHJcblxyXG4gICAgICAgICAgICAvKipcclxuICAgICAgICAgICAgICogVG8gbWFrZSBzdXJlIHdlJ3JlIHBsYWNpbmcgdGhlIGl0ZW0gaW4gdGhlIHJpZ2h0IGxvY2F0aW9uIChhbmQgXHJcbiAgICAgICAgICAgICAqIG92ZXJ3cml0ZSBlbGVtZW50cyB0aGF0IGFyZSBub3cgZ29uZSkgd2Ugbm93IHdhbnQgYWxsIG9mIHRoZVxyXG4gICAgICAgICAgICAgKiBsaW5lcyBhZnRlciB0aGlzIGVsZW1lbnQgdXAgdG8gdGhlIGVuZCB0YWcuXHJcbiAgICAgICAgICAgICAqL1xyXG4gICAgICAgICAgICBsaW5lc0JlbG93QXJyYXkgPSAgbXVsdGlDb2x1bW5QYXJzZXIuZ2V0RW5kQmxvY2tCZWxvdyhsaW5lc0JlbG93QXJyYXkpO1xyXG5cclxuICAgICAgICAgICAgLyoqXHJcbiAgICAgICAgICAgICAqIE5vdyB3ZSB0YWtlIHRoZSBsaW5lcyBhYm92ZSBvdXIgY3VycmVudCBlbGVtZW50IHVwIHVudGlsIHRoZVxyXG4gICAgICAgICAgICAgKiBzdGFydCByZWdpb24gdGFnIGFuZCByZW5kZXIgdGhhdCBpbnRvIGFuIEhUTUwgZWxlbWVudC4gV2Ugd2lsbCBcclxuICAgICAgICAgICAgICogdXNlIHRoZXNlIGVsZW1lbnRzIHRvIGRldGVybWluZSB3aGVyZSB0byBwbGFjZSBvdXIgY3VycmVudCBlbGVtZW50LlxyXG4gICAgICAgICAgICAgKi9cclxuICAgICAgICAgICAgbGV0IHNpYmxpbmdzQWJvdmU6IEhUTUxEaXZFbGVtZW50ID0gcmVuZGVyTWFya2Rvd25Gcm9tTGluZXMobGluZXNBYm92ZUFycmF5LCBzb3VyY2VQYXRoKTtcclxuXHJcbiAgICAgICAgICAgIGxldCBzaWJsaW5nc0JlbG93OiBIVE1MRGl2RWxlbWVudCA9IHJlbmRlck1hcmtkb3duRnJvbUxpbmVzKGxpbmVzQmVsb3dBcnJheSwgc291cmNlUGF0aCk7XHJcblxyXG4gICAgICAgICAgICAvKipcclxuICAgICAgICAgICAgICogU2V0IHVwIG91ciBkb20gb2JqZWN0IHRvIGJlIGFkZGVkIHRvIHRoZSBtYW5hZ2VyLlxyXG4gICAgICAgICAgICAgKi9cclxuICAgICAgICAgICAgbGV0IGN1cnJlbnRPYmplY3Q6IERPTU9iamVjdCA9IG5ldyBET01PYmplY3QoZWwsIGxpbmVzT2ZFbGVtZW50KVxyXG4gICAgICAgICAgICBlbC5pZCA9IGN1cnJlbnRPYmplY3QuVUlEO1xyXG5cclxuICAgICAgICAgICAgY3VycmVudE9iamVjdCA9IFRhc2tMaXN0RE9NT2JqZWN0LmNoZWNrRm9yVGFza0xpc3RFbGVtZW50KGN1cnJlbnRPYmplY3QpXHJcblxyXG4gICAgICAgICAgICAvKipcclxuICAgICAgICAgICAgICogTm93IHdlIGFkZCB0aGUgb2JqZWN0IHRvIHRoZSBtYW5hZ2VyIGFuZCB0aGVuIHNldHVwIHRoZVxyXG4gICAgICAgICAgICAgKiBjYWxsYmFjayBmb3Igd2hlbiB0aGUgb2JqZWN0IGlzIHJlbW92ZWQgZnJvbSB2aWV3IHRoYXQgd2lsbCByZW1vdmUgXHJcbiAgICAgICAgICAgICAqIHRoZSBpdGVtIGZyb20gdGhlIG1hbmFnZXIuXHJcbiAgICAgICAgICAgICAqL1xyXG4gICAgICAgICAgICByZWdpb25hbE1hbmFnZXIuYWRkT2JqZWN0KHNpYmxpbmdzQWJvdmUsIHNpYmxpbmdzQmVsb3csIGN1cnJlbnRPYmplY3QpO1xyXG5cclxuICAgICAgICAgICAgbGV0IGVsZW1lbnRNYXJrZG93blJlbmRlcmVyID0gbmV3IE1hcmtkb3duUmVuZGVyQ2hpbGQoZWwpO1xyXG4gICAgICAgICAgICBlbGVtZW50TWFya2Rvd25SZW5kZXJlci5vbnVubG9hZCA9ICgpID0+IHtcclxuXHJcbiAgICAgICAgICAgICAgICBpZihyZWdpb25hbENvbnRhaW5lciA9PT0gbnVsbCkge1xyXG4gICAgICAgICAgICAgICAgICAgIHJldHVyblxyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgXHJcbiAgICAgICAgICAgICAgICBsZXQgcmVnaW9uYWxNYW5hZ2VyOiBSZWdpb25NYW5hZ2VyID0gcmVnaW9uYWxDb250YWluZXIuZ2V0UmVnaW9uKCk7XHJcbiAgICAgICAgICAgICAgICBpZihyZWdpb25hbE1hbmFnZXIpIHtcclxuICAgICAgICAgICAgICAgICAgICBcclxuICAgICAgICAgICAgICAgICAgICAvLyBXZSBjYW4gYXR0ZW1wdCB0byB1cGRhdGUgdGhlIHZpZXcgaGVyZSBhZnRlciB0aGUgaXRlbSBpcyByZW1vdmVkXHJcbiAgICAgICAgICAgICAgICAgICAgLy8gYnV0IG5lZWQgdG8gZ2V0IHRoZSBpdGVtJ3MgcGFyZW50IGVsZW1lbnQgYmVmb3JlIHJlbW92aW5nIG9iamVjdCBmcm9tIG1hbmFnZXIuXHJcbiAgICAgICAgICAgICAgICAgICAgbGV0IHJlZ2lvblJlbmRlckRhdGE6IE11bHRpQ29sdW1uUmVuZGVyRGF0YSA9IHJlZ2lvbmFsTWFuYWdlci5nZXRSZWdpb25SZW5kZXJEYXRhKCk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIHJlZ2lvbmFsTWFuYWdlci5yZW1vdmVPYmplY3QoY3VycmVudE9iamVjdC5VSUQpO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAvKipcclxuICAgICAgICAgICAgICAgICAgICAgKiBOZWVkIHRvIGNoZWNrIGhlcmUgaWYgZWxlbWVudCBpcyBudWxsIGFzIHRoaXMgY2xvc3VyZSB3aWxsIGJlIGNhbGxlZFxyXG4gICAgICAgICAgICAgICAgICAgICAqIHJlcGVhdGVkbHkgb24gZmlsZSBjaGFuZ2UuXHJcbiAgICAgICAgICAgICAgICAgICAgICovXHJcbiAgICAgICAgICAgICAgICAgICAgaWYocmVnaW9uUmVuZGVyRGF0YS5wYXJlbnRSZW5kZXJFbGVtZW50ID09PSBudWxsKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgcmVnaW9uYWxNYW5hZ2VyLnJlbmRlclJlZ2lvbkVsZW1lbnRzVG9TY3JlZW4oKVxyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9O1xyXG4gICAgICAgICAgICBjdHguYWRkQ2hpbGQoZWxlbWVudE1hcmtkb3duUmVuZGVyZXIpO1xyXG5cclxuICAgICAgICAgICAgbGV0IGVsZW1lbnRUZXh0U3BhY2VkID0gbGluZXNPZkVsZW1lbnQucmVkdWNlKChwcmV2LCBjdXJyKSA9PiB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gcHJldiArIFwiXFxuXCIgKyBjdXJyO1xyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgLyoqXHJcbiAgICAgICAgICAgICAqIE5vdyB3ZSBjaGVjayBpZiBvdXIgY3VycmVudCBlbGVtZW50IGlzIGEgc3BlY2lhbCBmbGFnIHNvIHdlIGNhblxyXG4gICAgICAgICAgICAgKiBwcm9wZXJseSBzZXQgdGhlIGVsZW1lbnQgdGFnIHdpdGhpbiB0aGUgcmVnaW9uYWwgbWFuYWdlci5cclxuICAgICAgICAgICAgICovXHJcbiAgICAgICAgICAgIGlmKG11bHRpQ29sdW1uUGFyc2VyLmNvbnRhaW5zRW5kVGFnKGVsLnRleHRDb250ZW50KSA9PT0gdHJ1ZSkge1xyXG5cclxuICAgICAgICAgICAgICAgIGN1cnJlbnRPYmplY3QuZWxlbWVudFR5cGUgPSBFbGVtZW50UmVuZGVyVHlwZS51blJlbmRlcmVkXHJcbiAgICAgICAgICAgICAgICBlbC5hZGRDbGFzcyhNdWx0aUNvbHVtblN0eWxlQ1NTLlJlZ2lvbkVuZFRhZylcclxuICAgICAgICAgICAgICAgIHJlZ2lvbmFsTWFuYWdlci51cGRhdGVFbGVtZW50VGFnKGN1cnJlbnRPYmplY3QuVUlELCBET01PYmplY3RUYWcuZW5kUmVnaW9uKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBlbHNlIGlmKG11bHRpQ29sdW1uUGFyc2VyLmNvbnRhaW5zQ29sRW5kVGFnKGVsZW1lbnRUZXh0U3BhY2VkKSA9PT0gdHJ1ZSkge1xyXG5cclxuICAgICAgICAgICAgICAgIGN1cnJlbnRPYmplY3QuZWxlbWVudFR5cGUgPSBFbGVtZW50UmVuZGVyVHlwZS51blJlbmRlcmVkXHJcbiAgICAgICAgICAgICAgICBlbC5hZGRDbGFzcyhNdWx0aUNvbHVtblN0eWxlQ1NTLkNvbHVtbkVuZFRhZylcclxuICAgICAgICAgICAgICAgIHJlZ2lvbmFsTWFuYWdlci51cGRhdGVFbGVtZW50VGFnKGN1cnJlbnRPYmplY3QuVUlELCBET01PYmplY3RUYWcuY29sdW1uQnJlYWspO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGVsc2UgaWYobXVsdGlDb2x1bW5QYXJzZXIuY29udGFpbnNDb2xTZXR0aW5nc1RhZyhlbGVtZW50VGV4dFNwYWNlZCkgPT09IHRydWUpIHtcclxuXHJcbiAgICAgICAgICAgICAgICBjdXJyZW50T2JqZWN0LmVsZW1lbnRUeXBlID0gRWxlbWVudFJlbmRlclR5cGUudW5SZW5kZXJlZFxyXG4gICAgICAgICAgICAgICAgZWwuYWRkQ2xhc3MoTXVsdGlDb2x1bW5TdHlsZUNTUy5SZWdpb25TZXR0aW5ncylcclxuICAgICAgICAgICAgICAgIHJlZ2lvbmFsTWFuYWdlciA9IHJlZ2lvbmFsQ29udGFpbmVyLnNldFJlZ2lvblNldHRpbmdzKGVsZW1lbnRUZXh0U3BhY2VkKVxyXG4gICAgICAgICAgICAgICAgcmVnaW9uYWxNYW5hZ2VyLnVwZGF0ZUVsZW1lbnRUYWcoY3VycmVudE9iamVjdC5VSUQsIERPTU9iamVjdFRhZy5yZWdpb25TZXR0aW5ncyk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgICAgICBlbC5hZGRDbGFzcyhNdWx0aUNvbHVtblN0eWxlQ1NTLlJlZ2lvbkNvbnRlbnQpXHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgXHJcbiAgICAgICAgICAgIHJlZ2lvbmFsTWFuYWdlci5yZW5kZXJSZWdpb25FbGVtZW50c1RvU2NyZWVuKClcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgaXNTdGFydENvZGVibG9ja0luRXhwb3J0KG5vZGU6IEhUTUxFbGVtZW50KTogYm9vbGVhbiB7XHJcblxyXG4gICAgICAgIGZvcihsZXQgaSA9IDA7IGkgPCBDT0RFQkxPQ0tfU1RBUlRfU1RSUy5sZW5ndGg7IGkrKykge1xyXG5cclxuICAgICAgICAgICAgaWYobm9kZS5oYXNDbGFzcyhgYmxvY2stbGFuZ3VhZ2UtJHtDT0RFQkxPQ0tfU1RBUlRfU1RSU1tpXX1gKSkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgYXN5bmMgZXhwb3J0RG9jdW1lbnRUb1BERihlbDogSFRNTEVsZW1lbnQsIGZpbGVET01NYW5hZ2VyOiBGaWxlRE9NTWFuYWdlciwgc291cmNlUGF0aDogc3RyaW5nKSB7XHJcblxyXG4gICAgICAgIC8vIEEgdHJ1ZSBleHBvcnQgd2lsbCBiZSBwYXNzZWQgYW4gZWxlbWVudCB3aXRoIGFsbCBvdGhlciBpdGVtcyBpbiB0aGUgZG9jIGFzIGNoaWxkcmVuLiBcclxuICAgICAgICAvLyBTbyBpZiB0aGVyZSBhcmUgbm8gY2hpbGRyZW4gd2UgY2FuIGp1c3QgcmV0dXJuXHJcbiAgICAgICAgbGV0IGRvY0NoaWxkcmVuID0gQXJyYXkuZnJvbShlbC5jaGlsZE5vZGVzKTtcclxuICAgICAgICBpZihkb2NDaGlsZHJlbi5sZW5ndGggPT09IDApIHtcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgbGV0IGNoaWxkcmVuVG9SZW1vdmUgPSBbXTtcclxuICAgICAgICBcclxuICAgICAgICAvLyBUbyBleHBvcnQgY29kZWJsb2NrcyB3ZSBuZWVkIHRvIGdldCB0aGUgSURzIHNvIHdlIGNhbiBnZXQgdGhlIGRhdGEgZnJvbSBvdXIgbWFuYWdlcnMuXHJcbiAgICAgICAgLy8gaG93ZXZlciBzaW5jZSB0aGUgSUQgaXNudCBiZWluZyBzdG9yZWQgaW4gdGhlIGVsZW1lbnQgeWV0IHRoaXMgbWVhbnMgd2UgbmVlZCB0byByZWFkXHJcbiAgICAgICAgLy8gYWxsIG9mIHRoZSBJRHMgb3V0IG9mIHRoZSBmdWxsIGRvY3VtZW50LlxyXG4gICAgICAgIGxldCBjb2RlYmxvY2tTdGFydEJsb2NrcyA9IFtdXHJcbiAgICAgICAgbGV0IGFGaWxlID0gdGhpcy5hcHAudmF1bHQuZ2V0QWJzdHJhY3RGaWxlQnlQYXRoKHNvdXJjZVBhdGgpO1xyXG4gICAgICAgIGlmKGFGaWxlIGluc3RhbmNlb2YgVEZpbGUpIHtcclxuXHJcbiAgICAgICAgICAgIGxldCBmaWxlID0gYUZpbGUgYXMgVEZpbGVcclxuICAgICAgICAgICAgbGV0IGZpbGVUZXh0ID0gYXdhaXQgdGhpcy5hcHAudmF1bHQuY2FjaGVkUmVhZChmaWxlKSAvLyBJcyBjYWNoZWQgcmVhZCBPayBoZXJlPyBJdCBzaG91bGQgYmUuXHJcblxyXG4gICAgICAgICAgICAvLyBPbmNlIHdlIGhhdmUgb3VyIGRhdGEgd2Ugc2VhcmNoIHRoZSB0ZXh0IGZvciBhbGwgY29kZWJsb2NrIHN0YXJ0IHZhbHVlcy5cclxuICAgICAgICAgICAgLy8gc3RvcmluZyB0aGVtIGludG8gb3VyIHF1ZXVlLlxyXG4gICAgICAgICAgICBsZXQgY29kZUJsb2NrRGF0YSA9IG11bHRpQ29sdW1uUGFyc2VyLmZpbmRTdGFydENvZGVibG9jayhmaWxlVGV4dCk7XHJcbiAgICAgICAgICAgIHdoaWxlKGNvZGVCbG9ja0RhdGEuZm91bmQgPT09IHRydWUpIHtcclxuXHJcbiAgICAgICAgICAgICAgICBsZXQgY29kZWJsb2NrVGV4dCA9IGZpbGVUZXh0LnNsaWNlKGNvZGVCbG9ja0RhdGEuc3RhcnRQb3NpdGlvbiwgY29kZUJsb2NrRGF0YS5lbmRQb3NpdGlvbik7XHJcbiAgICAgICAgICAgICAgICBmaWxlVGV4dCA9IGZpbGVUZXh0LnNsaWNlKGNvZGVCbG9ja0RhdGEuZW5kUG9zaXRpb24pO1xyXG4gICAgICAgICAgICAgICAgY29kZWJsb2NrU3RhcnRCbG9ja3MucHVzaChjb2RlYmxvY2tUZXh0KTtcclxuXHJcbiAgICAgICAgICAgICAgICBjb2RlQmxvY2tEYXRhID0gbXVsdGlDb2x1bW5QYXJzZXIuZmluZFN0YXJ0Q29kZWJsb2NrKGZpbGVUZXh0KTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0gIFxyXG5cclxuICAgICAgICBsZXQgaW5CbG9jayA9IGZhbHNlO1xyXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZG9jQ2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcclxuXHJcbiAgICAgICAgICAgIGxldCBjaGlsZCA9IGRvY0NoaWxkcmVuW2ldO1xyXG4gICAgICAgICAgICBpZiAoY2hpbGQgaW5zdGFuY2VvZiBIVE1MRWxlbWVudCkge1xyXG4gICAgICAgICAgICAgICAgbGV0IGNoaWxkRWwgPSBjaGlsZCBhcyBIVE1MRWxlbWVudDtcclxuICAgICAgICAgICAgICAgIGlmIChpbkJsb2NrID09PSBmYWxzZSkge1xyXG4gICAgICAgICAgICAgICAgICAgIFxyXG4gICAgICAgICAgICAgICAgICAgIGxldCBmb3VuZEJsb2NrRGF0YSA9IGZhbHNlO1xyXG4gICAgICAgICAgICAgICAgICAgIGxldCByZWdpb25LZXkgPSBcIlwiO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICBsZXQgYmxvY2tEYXRhID0gbXVsdGlDb2x1bW5QYXJzZXIuaXNTdGFydFRhZ1dpdGhJRChjaGlsZC50ZXh0Q29udGVudCk7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKGJsb2NrRGF0YS5pc1N0YXJ0VGFnID09PSB0cnVlKSB7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBmb3VuZEJsb2NrRGF0YSA9IHRydWU7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChibG9ja0RhdGEuaGFzS2V5ID09PSB0cnVlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgZm91bmRLZXkgPSBtdWx0aUNvbHVtblBhcnNlci5nZXRTdGFydFRhZ0tleShjaGlsZC50ZXh0Q29udGVudCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZm91bmRLZXkgIT09IG51bGwpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWdpb25LZXkgPSBmb3VuZEtleTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICBlbHNlIGlmKGJsb2NrRGF0YS5pc1N0YXJ0VGFnID09PSBmYWxzZSAmJiB0aGlzLmlzU3RhcnRDb2RlYmxvY2tJbkV4cG9ydChjaGlsZCkpIHtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIElmIHRoZSBzdGFydCB0YWcgZnJvbSB0aGUgb2xkIHZlcnNpb24gaXMgbnVsbCB3ZSB0aGVuIGNoZWNrIHRvIHNlZSBpZiB0aGUgZWxlbWVudCBpc1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBhIGNvZGVibG9jayBzdGFydC4gSWYgaXQgaXMgd2UgdXNlIHRoZSBuZXh0IGF2YWlsYWJsZSBjb2RlYmxvY2sgZGF0YSB0byByZXRyaWV2ZSBvdXIgSUQuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBjb2RlYmxvY2tUZXh0ID0gY29kZWJsb2NrU3RhcnRCbG9ja3Muc2hpZnQoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYoY29kZWJsb2NrVGV4dCA9PT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKFwiRm91bmQgdW5kZWZpbmVkIGNvZGVibG9jayBkYXRhIHdoZW4gZXhwb3J0aW5nLlwiKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgaWQgPSBwYXJzZVN0YXJ0UmVnaW9uQ29kZUJsb2NrSUQoY29kZWJsb2NrVGV4dCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKGlkICE9PSBcIlwiKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3VuZEJsb2NrRGF0YSA9IHRydWU7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWdpb25LZXkgPSBpZDtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgaWYoZm91bmRCbG9ja0RhdGEgPT09IHRydWUgJiYgcmVnaW9uS2V5ICE9PSBcIlwiKSB7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBpbkJsb2NrID0gdHJ1ZTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSBjaGlsZC5jaGlsZHJlbi5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGQuY2hpbGRyZW5baV0uZGV0YWNoKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGQuaW5uZXJUZXh0ID0gXCJcIjtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkLmNsYXNzTGlzdC5hZGQoTXVsdGlDb2x1bW5MYXlvdXRDU1MuUmVnaW9uUm9vdENvbnRhaW5lckRpdik7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCByZW5kZXJFcnJvclJlZ2lvbiA9IGNoaWxkLmNyZWF0ZURpdih7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbHM6IGAke011bHRpQ29sdW1uTGF5b3V0Q1NTLlJlZ2lvbkVycm9yQ29udGFpbmVyRGl2fSwgJHtNdWx0aUNvbHVtblN0eWxlQ1NTLlJlZ2lvbkVycm9yTWVzc2FnZX1gLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHJlbmRlckNvbHVtblJlZ2lvbiA9IGNoaWxkLmNyZWF0ZURpdih7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbHM6IE11bHRpQ29sdW1uTGF5b3V0Q1NTLlJlZ2lvbkNvbnRlbnRDb250YWluZXJEaXZcclxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XHJcblxyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHJlZ2lvbmFsQ29udGFpbmVyOiBSZWdpb25NYW5hZ2VyQ29udGFpbmVyID0gZmlsZURPTU1hbmFnZXIuZ2V0UmVnaW9uYWxDb250YWluZXIocmVnaW9uS2V5KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJlZ2lvbmFsQ29udGFpbmVyID09PSBudWxsKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW5kZXJFcnJvclJlZ2lvbi5pbm5lclRleHQgPSBcIkVycm9yIHJlbmRlcmluZyBtdWx0aS1jb2x1bW4gcmVnaW9uLlxcblBsZWFzZSBjbG9zZSBhbmQgcmVvcGVuIHRoZSBmaWxlLCB0aGVuIG1ha2Ugc3VyZSB5b3UgYXJlIGluIHJlYWRpbmcgbW9kZSBiZWZvcmUgZXhwb3J0aW5nLlwiO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHJlZ2lvbmFsTWFuYWdlcjogUmVnaW9uTWFuYWdlciA9IHJlZ2lvbmFsQ29udGFpbmVyLmdldFJlZ2lvbigpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVnaW9uYWxNYW5hZ2VyLmV4cG9ydFJlZ2lvbkVsZW1lbnRzVG9QREYocmVuZGVyQ29sdW1uUmVnaW9uKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGVsc2Uge1xyXG5cclxuICAgICAgICAgICAgICAgICAgICBpZiAobXVsdGlDb2x1bW5QYXJzZXIuY29udGFpbnNFbmRUYWcoY2hpbGQudGV4dENvbnRlbnQpID09PSB0cnVlKSB7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBpbkJsb2NrID0gZmFsc2U7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICBjaGlsZHJlblRvUmVtb3ZlLnB1c2goY2hpbGQpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjaGlsZHJlblRvUmVtb3ZlLmZvckVhY2goY2hpbGQgPT4ge1xyXG4gICAgICAgICAgICBlbC5yZW1vdmVDaGlsZChjaGlsZCk7XHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgY2hlY2tFeHBvcnRpbmcoZWxlbWVudDogSFRNTEVsZW1lbnQpOiBib29sZWFuIHtcclxuXHJcbiAgICAgICAgaWYoZWxlbWVudCA9PT0gbnVsbCkge1xyXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZihlbGVtZW50LmNsYXNzTGlzdC5jb250YWlucyhcInByaW50XCIpKSB7XHJcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYoZWxlbWVudC5wYXJlbnROb2RlICE9PSBudWxsKSB7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNoZWNrRXhwb3J0aW5nKGVsZW1lbnQucGFyZW50RWxlbWVudCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICB9XHJcblxyXG4gICAgc2V0dXBNYXJrZG93bkNvZGVibG9ja1Bvc3RQcm9jZXNzb3Ioc3RhcnRTdHI6IHN0cmluZykge1xyXG5cclxuICAgICAgICB0aGlzLnJlZ2lzdGVyTWFya2Rvd25Db2RlQmxvY2tQcm9jZXNzb3Ioc3RhcnRTdHIsIChzb3VyY2UsIGVsLCBjdHgpID0+IHtcclxuXHJcbiAgICAgICAgICAgIGNvbnN0IHNvdXJjZVBhdGggPSBjdHguc291cmNlUGF0aDtcclxuICAgICAgICBcclxuICAgICAgICAgICAgLy8gU2V0IHVwIG91ciBDU1Mgc28gdGhhdCB0aGUgY29kZWJsb2NrIG9ubHkgcmVuZGVycyB0aGlzIGRhdGEgaW4gcmVhZGluZyBtb2RlXHJcbiAgICAgICAgICAgIC8vIHNvdXJjZS9saXZlIHByZXZpZXcgbW9kZSBpcyBoYW5kbGVkIGJ5IHRoZSBDTTYgaW1wbGVtZW50YXRpb24uXHJcbiAgICAgICAgICAgIGVsLnBhcmVudEVsZW1lbnQ/LmFkZENsYXNzKFwicHJlaXZldy1tY20tc3RhcnQtYmxvY2tcIik7XHJcbiAgICAgICAgXHJcbiAgICAgICAgICAgIC8vIFRvIGRldGVybWluZSB3aGF0IGtpbmQgb2YgdmlldyB3ZSBhcmUgcmVuZGVyaW5nIGluIHdlIG5lZWQgYSBtYXJrZG93biBsZWFmLlxyXG4gICAgICAgICAgICAvLyBSZWFsbHkgdGhpcyBzaG91bGQgbmV2ZXIgcmV0dXJuIGhlcmUgc2luY2UgcmVuZGVyaW5nIGlzIG9ubHkgZG9uZSBpbiBtYXJrZG93biBsZWF2ZXMuXHJcbiAgICAgICAgICAgIGxldCBtYXJrZG93bkxlYXZlcyA9IGFwcC53b3Jrc3BhY2UuZ2V0TGVhdmVzT2ZUeXBlKFwibWFya2Rvd25cIik7XHJcbiAgICAgICAgICAgIGlmKG1hcmtkb3duTGVhdmVzLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgXHJcbiAgICAgICAgICAgIC8vIENoZWNrIHRoZSB0eXBlIG9mIHRoZSBsZWFmXHJcbiAgICAgICAgICAgIGxldCBmb3VuZEZpbGVMZWFmID0gZmFsc2U7XHJcbiAgICAgICAgICAgIGZvcihsZXQgaSA9IDA7IGkgPCBtYXJrZG93bkxlYXZlcy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgIFxyXG4gICAgICAgICAgICAgICAgbGV0IGZpbGVMZWFmID0gZ2V0RmlsZUxlYWYoc291cmNlUGF0aCk7XHJcbiAgICAgICAgICAgICAgICBpZihmaWxlTGVhZiA9PT0gbnVsbCkge1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgZm91bmRGaWxlTGVhZiA9IHRydWU7XHJcbiAgICAgICAgXHJcbiAgICAgICAgICAgICAgICBpZihnZXRMZWFmU291cmNlTW9kZShmaWxlTGVhZikgPT09IFwic291cmNlXCIpIHtcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICBcclxuICAgICAgICAgICAgaWYodGhpcy5nbG9iYWxNYW5hZ2VyID09PSBudWxsIHx8IHRoaXMuZ2xvYmFsTWFuYWdlciA9PT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcIkdsb2JhbCBtYW5hZ2VyIGlzIHVuZGVmaW5lZD9cIik7XHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGxldCBmaWxlRE9NTWFuYWdlciA9IHRoaXMuZ2xvYmFsTWFuYWdlci5nZXRGaWxlTWFuYWdlcihzb3VyY2VQYXRoKTtcclxuICAgICAgICAgICAgaWYoZmlsZURPTU1hbmFnZXIgPT09IG51bGwpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBcclxuICAgICAgICAgICAgLy8gU2V0IGZpbGUgdG8gaGF2ZSBzdGFydCB0YWcuXHJcbiAgICAgICAgICAgIGZpbGVET01NYW5hZ2VyLnNldEhhc1N0YXJ0VGFnKCk7XHJcbiAgICAgICAgXHJcbiAgICAgICAgICAgIC8vIEdldCB0aGUgaW5mbyBmb3Igb3VyIGN1cnJlbnQgY29udGV4dCBhbmQgdGhlbiBjaGVja1xyXG4gICAgICAgICAgICAvLyBpZiB0aGUgZW50aXJlIHRleHQgY29udGFpbnMgYSBzdGFydCB0YWcuIElmIHRoZXJlIGlzXHJcbiAgICAgICAgICAgIC8vIG5vIHN0YXJ0IHRhZyBpbiB0aGUgZG9jdW1lbnQgd2UgY2FuIGp1c3QgcmV0dXJuIGFuZFxyXG4gICAgICAgICAgICAvLyBpZ25vcmUgdGhlIHJlc3Qgb2YgdGhlIHBhcnNpbmcuXHJcbiAgICAgICAgICAgIGxldCBpbmZvID0gY3R4LmdldFNlY3Rpb25JbmZvKGVsKTtcclxuICAgICAgICBcclxuICAgICAgICAgICAgLyoqXHJcbiAgICAgICAgICAgICAqIFdlIG5lZWQgdGhlIGNvbnRleHQgaW5mbyB0byBwcm9wZXJseSBwYXJzZSBzbyByZXR1cm5pbmcgaGVyZSBcclxuICAgICAgICAgICAgICogaW5mbyBpcyBudWxsLiBUT0RPOiBTZXQgZXJyb3IgaW4gdmlldyBpZiB0aGlzIG9jY3Vycy5cclxuICAgICAgICAgICAgICovXHJcbiAgICAgICAgICAgIGlmKCFpbmZvKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICBcclxuICAgICAgICAgICAgLyoqIFxyXG4gICAgICAgICAgICAgKiBTZXQgdXAgdGhlIGN1cnJlbnQgZWxlbWVudCB0byBhY3QgYXMgdGhlIHBhcmVudCBmb3IgdGhlIFxyXG4gICAgICAgICAgICAgKiBtdWx0aS1jb2x1bW4gcmVnaW9uLlxyXG4gICAgICAgICAgICAgKi9cclxuICAgICAgICAgICAgZWwuY2xhc3NMaXN0LmFkZChNdWx0aUNvbHVtbkxheW91dENTUy5SZWdpb25Sb290Q29udGFpbmVyRGl2KVxyXG4gICAgICAgICAgICBsZXQgcmVuZGVyRXJyb3JSZWdpb24gPSBlbC5jcmVhdGVEaXYoe1xyXG4gICAgICAgICAgICAgICAgY2xzOiBgJHtNdWx0aUNvbHVtbkxheW91dENTUy5SZWdpb25FcnJvckNvbnRhaW5lckRpdn0gJHtNdWx0aUNvbHVtblN0eWxlQ1NTLlJlZ2lvbkVycm9yTWVzc2FnZX1gLFxyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgbGV0IHJlbmRlckNvbHVtblJlZ2lvbiA9IGVsLmNyZWF0ZURpdih7XHJcbiAgICAgICAgICAgICAgICBjbHM6IE11bHRpQ29sdW1uTGF5b3V0Q1NTLlJlZ2lvbkNvbnRlbnRDb250YWluZXJEaXZcclxuICAgICAgICAgICAgfSlcclxuICAgICAgICBcclxuICAgICAgICAgICAgbGV0IHJlZ2lvbktleSA9IHBhcnNlU3RhcnRSZWdpb25Db2RlQmxvY2tJRChzb3VyY2UpO1xyXG4gICAgICAgIFxyXG4gICAgICAgICAgICBsZXQgY3JlYXRlTmV3UmVnaW9uTWFuYWdlciA9IHRydWU7XHJcbiAgICAgICAgICAgIGlmKGZpbGVET01NYW5hZ2VyLmNoZWNrS2V5RXhpc3RzKHJlZ2lvbktleSkgPT09IHRydWUpIHtcclxuICAgICAgICAgICAgICAgIFxyXG4gICAgICAgICAgICAgICAgY3JlYXRlTmV3UmVnaW9uTWFuYWdlciA9IGZhbHNlO1xyXG4gICAgICAgICAgICAgICAgbGV0IHsgbnVtYmVyT2ZUYWdzLCBrZXlzIH0gPSBtdWx0aUNvbHVtblBhcnNlci5jb3VudFN0YXJ0VGFncyhpbmZvLnRleHQpO1xyXG4gICAgICAgIFxyXG4gICAgICAgICAgICAgICAgbGV0IG51bU1hdGNoZXMgPSAwO1xyXG4gICAgICAgICAgICAgICAgZm9yKGxldCBpID0gMDsgaSA8IG51bWJlck9mVGFnczsgaSsrKSB7XHJcbiAgICAgICAgXHJcbiAgICAgICAgICAgICAgICAgICAgLy8gQmVjYXVzZSB3ZSBjaGVja2VkIGlmIGtleSBleGlzdHMgb25lIG9mIHRoZXNlIGhhcyB0byBtYXRjaC5cclxuICAgICAgICAgICAgICAgICAgICBpZihrZXlzW2ldID09PSByZWdpb25LZXkpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgbnVtTWF0Y2hlcysrO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICBcclxuICAgICAgICAgICAgICAgIC8vIFdlIG9ubHkgd2FudCB0byBkaXNwbGF5IGFuIGVycm9yIGlmIHRoZXJlIGFyZSBtb3JlIHRoYW4gMiBvZiB0aGUgc2FtZSBpZCBhY3Jvc3NcclxuICAgICAgICAgICAgICAgIC8vIHRoZSB3aG9sZSBkb2N1bWVudC4gVGhpcyBwcmV2ZW50cyBlcnJvcyB3aGVuIG9ic2lkaWFuIHJlbG9hZHMgdGhlIHdob2xlIGRvY3VtZW50XHJcbiAgICAgICAgICAgICAgICAvLyBhbmQgdGhlcmUgYXJlIHR3byBvZiB0aGUgc2FtZSBrZXkgaW4gdGhlIG1hcC5cclxuICAgICAgICAgICAgICAgIGlmKG51bU1hdGNoZXMgPj0gMikge1xyXG4gICAgICAgICAgICAgICAgICAgIGlmKHJlZ2lvbktleSA9PT0gXCJcIikge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICByZW5kZXJFcnJvclJlZ2lvbi5pbm5lclRleHQgPSBcIkZvdW5kIG11bHRpcGxlIHJlZ2lvbnMgd2l0aCBlbXB0eSBJRHMuIFBsZWFzZSBzZXQgYSB1bmlxdWUgSUQgYWZ0ZXIgZWFjaCBzdGFydCB0YWcuXFxuRUc6ICc9PT0gbXVsdGktY29sdW1uLXN0YXJ0OiByYW5kb21JRCdcXG5PciB1c2UgJ0ZpeCBNaXNzaW5nIElEcycgaW4gdGhlIGNvbW1hbmQgcGFsZXR0ZSBhbmQgcmVsb2FkIHRoZSBkb2N1bWVudC5cIlxyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgcmVuZGVyRXJyb3JSZWdpb24uaW5uZXJUZXh0ID0gXCJSZWdpb24gSUQgYWxyZWFkeSBleGlzdHMgaW4gZG9jdW1lbnQsIHBsZWFzZSBzZXQgYSB1bmlxdWUgSUQuXFxuRUc6ICc9PT0gbXVsdGktY29sdW1uLXN0YXJ0OiByYW5kb21JRCdcIlxyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgZWwuaWQgPSBgTXVsdGlDb2x1bW5JRDoke3JlZ2lvbktleX1gXHJcbiAgICAgICAgXHJcbiAgICAgICAgICAgIC8vIElmIHNvbWV0aGluZyBjaGFuZ2VzIGluIHRoZSBjb2RlYmxvY2sgd2UgZG9udCBuZWNlc3NhcmlseSB3YW50IHRvIHVwZGF0ZSBvdXJcclxuICAgICAgICAgICAgLy8gb2xkIHJlZmVyZW5jZSB0byB0aGUgcmVnaW9uIG1hbmFnZXIuIFRoaXMgY291bGQgYmUgYSBwb3RlbnRpYWwgYnVnIGFyZWEuXHJcbiAgICAgICAgICAgIGlmKGNyZWF0ZU5ld1JlZ2lvbk1hbmFnZXIgPT09IHRydWUpIHtcclxuICAgICAgICBcclxuICAgICAgICAgICAgICAgIC8vIENyZWF0ZSBhIG5ldyByZWdpb25hbCBtYW5hZ2VyLlxyXG4gICAgICAgICAgICAgICAgbGV0IGVsZW1lbnRNYXJrZG93blJlbmRlcmVyID0gbmV3IE1hcmtkb3duUmVuZGVyQ2hpbGQoZWwpO1xyXG4gICAgICAgICAgICAgICAgZmlsZURPTU1hbmFnZXIuY3JlYXRlUmVnaW9uYWxNYW5hZ2VyKHJlZ2lvbktleSwgZWwsIHJlbmRlckVycm9yUmVnaW9uLCByZW5kZXJDb2x1bW5SZWdpb24pO1xyXG4gICAgICAgIFxyXG4gICAgICAgICAgICAgICAgLy8gU2V0IHVwIHRoZSBvbiB1bmxvYWQgY2FsbGJhY2suIFRoaXMgY2FuIGJlIGNhbGxlZCBpZiB0aGUgdXNlciBjaGFuZ2VzXHJcbiAgICAgICAgICAgICAgICAvLyB0aGUgc3RhcnQvc2V0dGluZ3MgY29kZWJsb2NrIGluIGFueSB3YXkuIFdlIG9ubHkgd2FudCB0byB1bmxvYWRcclxuICAgICAgICAgICAgICAgIC8vIGlmIHRoZSBmaWxlIGlzIGJlaW5nIHJlbW92ZWQgZnJvbSB2aWV3LlxyXG4gICAgICAgICAgICAgICAgZWxlbWVudE1hcmtkb3duUmVuZGVyZXIub251bmxvYWQgPSAoKSA9PiB7XHJcbiAgICAgICAgXHJcbiAgICAgICAgICAgICAgICAgICAgaWYoZmlsZURPTU1hbmFnZXIgJiYgZmlsZVN0aWxsSW5WaWV3KHNvdXJjZVBhdGgpID09PSBmYWxzZSkge1xyXG4gICAgICAgIFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmRlYnVnKFwiRmlsZSBub3QgaW4gYW55IG1hcmtkb3duIGxlYWYuIFJlbW92aW5nIHJlZ2lvbiBmcm9tIGRvbSBtYW5hZ2VyLlwiKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICBmaWxlRE9NTWFuYWdlci5yZW1vdmVSZWdpb24ocmVnaW9uS2V5KTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9O1xyXG4gICAgICAgICAgICAgICAgY3R4LmFkZENoaWxkKGVsZW1lbnRNYXJrZG93blJlbmRlcmVyKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIFxyXG4gICAgICAgICAgICBsZXQgcmVnaW9uYWxNYW5hZ2VyQ29udGFpbmVyID0gZmlsZURPTU1hbmFnZXIuZ2V0UmVnaW9uYWxDb250YWluZXIocmVnaW9uS2V5KTtcclxuICAgICAgICAgICAgaWYocmVnaW9uYWxNYW5hZ2VyQ29udGFpbmVyICE9PSBudWxsKSB7XHJcbiAgICAgICAgXHJcbiAgICAgICAgICAgICAgICBsZXQgcmVnaW9uYWxNYW5hZ2VyID0gcmVnaW9uYWxNYW5hZ2VyQ29udGFpbmVyLnNldFJlZ2lvblNldHRpbmdzKHNvdXJjZSk7XHJcbiAgICAgICAgICAgICAgICByZWdpb25hbE1hbmFnZXIucmVnaW9uUGFyZW50ID0gZWw7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9KVxyXG4gICAgfVxyXG59XHJcblxyXG5cclxuZXhwb3J0IHR5cGUgbmVhcmJ5U2libGluZ3MgPSB7IFxyXG4gICAgc2libGluZ3NBYm92ZTogSFRNTERpdkVsZW1lbnQsXHJcbiAgICBjdXJyZW50T2JqZWN0OiBET01PYmplY3QsIFxyXG59XHJcbmZ1bmN0aW9uIHJlbmRlck1hcmtkb3duRnJvbUxpbmVzKG1kTGluZXM6IHN0cmluZ1tdLCBzb3VyY2VQYXRoOiBzdHJpbmcpOiBIVE1MRGl2RWxlbWVudCB7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBXZSByZS1yZW5kZXIgYWxsIG9mIHRoZSBpdGVtcyBhYm92ZSBvdXIgZWxlbWVudCwgdW50aWwgdGhlIHN0YXJ0IHRhZywgXHJcbiAgICAgKiBzbyB3ZSBjYW4gZGV0ZXJtaW5lIHdoZXJlIHRvIHBsYWNlIHRoZSBuZXcgaXRlbSBpbiB0aGUgbWFuYWdlci5cclxuICAgICAqIFxyXG4gICAgICogVE9ETzogQ2FuIHJlZHVjZSB0aGUgYW1vdW50IG5lZWRpbmcgdG8gYmUgcmVuZGVyZWQgYnkgb25seSByZW5kZXJpbmcgdG9cclxuICAgICAqIHRoZSBzdGFydCB0YWcgb3IgYSBjb2x1bW4tYnJlYWsgd2hpY2hldmVyIGlzIGNsb3Nlci5cclxuICAgICAqL1xyXG4gICAgbGV0IHNpYmxpbmdzID0gY3JlYXRlRGl2KCk7XHJcbiAgICBsZXQgbWFya2Rvd25SZW5kZXJDaGlsZCA9IG5ldyBNYXJrZG93blJlbmRlckNoaWxkKFxyXG4gICAgICAgIHNpYmxpbmdzXHJcbiAgICApO1xyXG4gICAgTWFya2Rvd25SZW5kZXJlci5yZW5kZXJNYXJrZG93bihcclxuICAgICAgICBtZExpbmVzLnJlZHVjZSgocHJldiwgY3VycmVudCkgPT4ge1xyXG4gICAgICAgICAgICByZXR1cm4gcHJldiArIFwiXFxuXCIgICsgY3VycmVudDtcclxuICAgICAgICB9LCBcIlwiKSxcclxuICAgICAgICBzaWJsaW5ncyxcclxuICAgICAgICBzb3VyY2VQYXRoLFxyXG4gICAgICAgIG1hcmtkb3duUmVuZGVyQ2hpbGRcclxuICAgICk7XHJcblxyXG4gICAgcmV0dXJuIHNpYmxpbmdzO1xyXG59XHJcbiJdLCJuYW1lcyI6WyJNYXJrZG93blJlbmRlckNoaWxkIiwiV2lkZ2V0VHlwZSIsIk1hcmtkb3duUmVuZGVyZXIiLCJTdGF0ZUZpZWxkIiwiRGVjb3JhdGlvbiIsIlJhbmdlU2V0QnVpbGRlciIsInN5bnRheFRyZWUiLCJ0b2tlbkNsYXNzTm9kZVByb3AiLCJFZGl0b3JWaWV3IiwiUGx1Z2luIiwiTm90aWNlIiwibXVsdGlDb2x1bW5QYXJzZXIuZmluZFN0YXJ0Q29kZWJsb2NrIiwibXVsdGlDb2x1bW5QYXJzZXIuaXNTdGFydFRhZ1dpdGhJRCIsIm11bHRpQ29sdW1uUGFyc2VyLmNvbnRhaW5zU3RhcnRUYWciLCJtdWx0aUNvbHVtblBhcnNlci5jb250YWluc1N0YXJ0Q29kZUJsb2NrIiwibXVsdGlDb2x1bW5QYXJzZXIuZ2V0U3RhcnRCbG9ja0Fib3ZlTGluZSIsIm11bHRpQ29sdW1uUGFyc2VyLmNvdW50U3RhcnRUYWdzIiwibXVsdGlDb2x1bW5QYXJzZXIuZ2V0U3RhcnRCbG9ja09yQ29kZWJsb2NrQWJvdmVMaW5lIiwibXVsdGlDb2x1bW5QYXJzZXIuZ2V0RW5kQmxvY2tCZWxvdyIsIm11bHRpQ29sdW1uUGFyc2VyLmNvbnRhaW5zRW5kVGFnIiwibXVsdGlDb2x1bW5QYXJzZXIuY29udGFpbnNDb2xFbmRUYWciLCJtdWx0aUNvbHVtblBhcnNlci5jb250YWluc0NvbFNldHRpbmdzVGFnIiwiVEZpbGUiLCJtdWx0aUNvbHVtblBhcnNlci5nZXRTdGFydFRhZ0tleSJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7O0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQXVEQTtBQUNPLFNBQVMsU0FBUyxDQUFDLE9BQU8sRUFBRSxVQUFVLEVBQUUsQ0FBQyxFQUFFLFNBQVMsRUFBRTtBQUM3RCxJQUFJLFNBQVMsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLE9BQU8sS0FBSyxZQUFZLENBQUMsR0FBRyxLQUFLLEdBQUcsSUFBSSxDQUFDLENBQUMsVUFBVSxPQUFPLEVBQUUsRUFBRSxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRTtBQUNoSCxJQUFJLE9BQU8sS0FBSyxDQUFDLEtBQUssQ0FBQyxHQUFHLE9BQU8sQ0FBQyxFQUFFLFVBQVUsT0FBTyxFQUFFLE1BQU0sRUFBRTtBQUMvRCxRQUFRLFNBQVMsU0FBUyxDQUFDLEtBQUssRUFBRSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxPQUFPLENBQUMsRUFBRSxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUU7QUFDbkcsUUFBUSxTQUFTLFFBQVEsQ0FBQyxLQUFLLEVBQUUsRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxPQUFPLENBQUMsRUFBRSxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUU7QUFDdEcsUUFBUSxTQUFTLElBQUksQ0FBQyxNQUFNLEVBQUUsRUFBRSxNQUFNLENBQUMsSUFBSSxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEdBQUcsS0FBSyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLFFBQVEsQ0FBQyxDQUFDLEVBQUU7QUFDdEgsUUFBUSxJQUFJLENBQUMsQ0FBQyxTQUFTLEdBQUcsU0FBUyxDQUFDLEtBQUssQ0FBQyxPQUFPLEVBQUUsVUFBVSxJQUFJLEVBQUUsQ0FBQyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7QUFDOUUsS0FBSyxDQUFDLENBQUM7QUFDUDs7QUM3RUE7Ozs7OztBQU1HO0FBRUgsSUFBWSxZQU9YLENBQUE7QUFQRCxDQUFBLFVBQVksWUFBWSxFQUFBO0FBQ3BCLElBQUEsWUFBQSxDQUFBLFlBQUEsQ0FBQSxTQUFBLENBQUEsR0FBQSxDQUFBLENBQUEsR0FBQSxTQUFPLENBQUE7QUFDUCxJQUFBLFlBQUEsQ0FBQSxZQUFBLENBQUEsSUFBQSxDQUFBLEdBQUEsQ0FBQSxDQUFBLEdBQUEsSUFBRSxDQUFBO0FBQ0YsSUFBQSxZQUFBLENBQUEsWUFBQSxDQUFBLE1BQUEsQ0FBQSxHQUFBLENBQUEsQ0FBQSxHQUFBLE1BQUksQ0FBQTtBQUNKLElBQUEsWUFBQSxDQUFBLFlBQUEsQ0FBQSxVQUFBLENBQUEsR0FBQSxDQUFBLENBQUEsR0FBQSxVQUFRLENBQUE7QUFDUixJQUFBLFlBQUEsQ0FBQSxZQUFBLENBQUEsS0FBQSxDQUFBLEdBQUEsQ0FBQSxDQUFBLEdBQUEsS0FBRyxDQUFBO0FBQ0gsSUFBQSxZQUFBLENBQUEsWUFBQSxDQUFBLE9BQUEsQ0FBQSxHQUFBLENBQUEsQ0FBQSxHQUFBLE9BQUssQ0FBQTtBQUNULENBQUMsRUFQVyxZQUFZLEtBQVosWUFBWSxHQU92QixFQUFBLENBQUEsQ0FBQSxDQUFBO0FBRUQsSUFBWSxZQU9YLENBQUE7QUFQRCxDQUFBLFVBQVksWUFBWSxFQUFBO0FBQ3BCLElBQUEsWUFBQSxDQUFBLFlBQUEsQ0FBQSxTQUFBLENBQUEsR0FBQSxDQUFBLENBQUEsR0FBQSxTQUFPLENBQUE7QUFDUCxJQUFBLFlBQUEsQ0FBQSxZQUFBLENBQUEsSUFBQSxDQUFBLEdBQUEsQ0FBQSxDQUFBLEdBQUEsSUFBRSxDQUFBO0FBQ0YsSUFBQSxZQUFBLENBQUEsWUFBQSxDQUFBLE1BQUEsQ0FBQSxHQUFBLENBQUEsQ0FBQSxHQUFBLE1BQUksQ0FBQTtBQUNKLElBQUEsWUFBQSxDQUFBLFlBQUEsQ0FBQSxVQUFBLENBQUEsR0FBQSxDQUFBLENBQUEsR0FBQSxVQUFRLENBQUE7QUFDUixJQUFBLFlBQUEsQ0FBQSxZQUFBLENBQUEsS0FBQSxDQUFBLEdBQUEsQ0FBQSxDQUFBLEdBQUEsS0FBRyxDQUFBO0FBQ0gsSUFBQSxZQUFBLENBQUEsWUFBQSxDQUFBLE9BQUEsQ0FBQSxHQUFBLENBQUEsQ0FBQSxHQUFBLE9BQUssQ0FBQTtBQUNULENBQUMs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
|