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.

3320 lines
516 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["full"] = 3] = "full";
})(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;
case "full":
case "full size":
return SingleColumnSize.full;
}
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) {
// We want to find the first end tag in the text.
// So here we loop backwards, slicing off the tail until
// there are no more end tags available
let lastValidData = getEndTagData(text);
let workingRegexData = lastValidData;
while (workingRegexData.found === true) {
lastValidData = workingRegexData;
text = text.slice(0, workingRegexData.startPosition);
workingRegexData = getEndTagData(text);
}
return lastValidData;
}
function containsEndTag(text) {
return findEndTag(text).found;
}
function getEndTagData(text) {
let found = false;
let startPosition = -1;
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 };
}
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 *="];
const COL_ELEMENT_INNER_TEXT_REGEX_ARR = [];
for (let i = 0; i < COL_ELEMENT_INNER_TEXT_REGEX_STRS.length; i++) {
COL_ELEMENT_INNER_TEXT_REGEX_ARR.push(new RegExp(COL_ELEMENT_INNER_TEXT_REGEX_STRS[i]));
}
function elInnerTextContainsColEndTag(text) {
let found = false;
for (let i = 0; i < COL_ELEMENT_INNER_TEXT_REGEX_ARR.length; i++) {
if (COL_ELEMENT_INNER_TEXT_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
*/
const UPDATE_TIMES = [250, 20000];
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.canvasElementUpdateTime = Date.now();
this.canvasTimerIndex = 0;
this.lastClonedElementUpdateTime = Date.now();
this.updateTimerIndex = 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;
}
clonedElementReadyForUpdate() {
let deltaTime = Date.now() - this.lastClonedElementUpdateTime;
if (deltaTime > UPDATE_TIMES[this.updateTimerIndex]) {
return true;
}
return false;
}
canvasReadyForUpdate() {
let deltaTime = Date.now() - this.canvasElementUpdateTime;
if (deltaTime > UPDATE_TIMES[this.canvasTimerIndex]) {
this.canvasElementUpdateTime = Date.now();
this.canvasTimerIndex = Math.clamp(this.canvasTimerIndex + 1, 0, UPDATE_TIMES.length - 1);
return true;
}
return false;
}
updateClonedElement(newClonedElement) {
this.clonedElement = newClonedElement;
this.lastClonedElementUpdateTime = Date.now();
this.updateTimerIndex = Math.clamp(this.updateTimerIndex + 1, 0, UPDATE_TIMES.length - 1);
}
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["SingleColumnFull"] = "mcm-single-column-full";
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 nextObj = siblingsBelow.children[0];
let addAtIndex = siblingsAbove.children.length;
if (siblingsAbove.children.length > 0) {
/**
* We want to find the first sibling withouth "" for an inner text so we can use that to anchor our
* element into the domList. For most items the first element before our new element will have the proper
* innerText. Sometimes other elements are empty and were causing issues.
*
* Now we loop back through the previous siblings looking for the first one with a valid inner text and using that
* as the anchor and offsetting our addAtIndex by the number of empty string elements we found.
*/
let prevSiblingInnerText = "";
let prevSiblingOffset = 0;
for (let i = siblingsAbove.children.length - 1; i >= 0; i--) {
let obj = siblingsAbove.children[i];
if (obj.innerText !== "") {
prevSiblingInnerText = obj.innerText;
break;
}
prevSiblingOffset++;
}
for (let i = this.domList.length - 1; i >= 0; i--) {
if (this.domList[i].nodeKey === prevSiblingInnerText) {
addAtIndex = i + 1 + prevSiblingOffset;
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: ", Array.from(siblingsAbove.children).slice(-3), "Adding: ", obj.originalElement, " 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 ||
Math.abs(clonedElementHeight - originalElementHeight) > 10 ||
domElement.clonedElementReadyForUpdate() === true) &&
domElement.elementType !== ElementRenderType.canvasRenderElement) {
// console.log("Updating Cloned Element.", clonedElementHeight, originalElementHeight)
// Update clone and reference.
cloneElement();
}
if (domElement.elementType === ElementRenderType.canvasRenderElement &&
domElement.canvasReadyForUpdate()) {
// console.log("Updating canvas re-render")
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) {
domElement.updateClonedElement(originalElement.cloneNode(true));
clonedElement = domElement.clonedElement;
clonedElement.addClass(MultiColumnLayoutCSS.ClonedElementType);
clonedElement.removeClasses([MultiColumnStyleCSS.RegionContent, MultiColumnLayoutCSS.OriginalElementType]);
containerElement.appendChild(clonedElement);
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 &&
domElement.elementType !== ElementRenderType.canvasRenderElement) {
// 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);
}
function cloneElement() {
domElement.updateClonedElement(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);
}
}
/**
* 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 if (this.regionalSettings.columnSize === SingleColumnSize.full) {
contentDiv.addClass(`${MultiColumnLayoutCSS.SingleColumnFull}`);
}
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++) {
let el = this.fixElementRender(arr[i]);
this.domList.push(new DOMObject(el, [""]));
}
// 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);
}
}
fixElementRender(el) {
let fixedEl = fixImageRender(el);
return fixedEl;
}
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() {
// 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;
}
}
function fixImageRender(el) {
let fixedEl = el;
let items = el.getElementsByClassName("internal-embed");
if (items.length === 1) {
let embed = items[0];
let alt = embed.getAttr("alt");
let src = embed.getAttr("src");
let aTFiles = app.vault.getAllLoadedFiles();
let resourcePath = "";
for (let i = 0; i < aTFiles.length; i++) {
let abstractFile = aTFiles[i];
if (abstractFile instanceof obsidian.TFile === false) {
continue;
}
let file = abstractFile;
if (file.name === src && hasImageExtension(file.extension) === true) {
resourcePath = app.vault.getResourcePath(file);
break;
}
}
if (alt === src && resourcePath !== "") {
fixedEl = createDiv({
cls: "internal-embed image-embed is-loaded",
});
fixedEl.setAttr("alt", alt);
let image = fixedEl.createEl("img");
image.setAttr("src", resourcePath);
}
}
return fixedEl;
}
function hasImageExtension(extension) {
extension = extension.toLowerCase();
switch (extension) {
case "png":
case "jpg":
case "jpeg":
case "gif":
case "bmp":
case "svg":
return true;
}
return false;
}
/*
* 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;
}
if (isEditorInLivePreview(transaction.state) === 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 loopIndex = 0;
let startIndexOffset = 0;
while (true) {
// If there are multiple kinds of start blocks, the old way of parsing would cause issues.
// Now search for both kinds and determine what to do after search.
let startTagData_codeblockStart = findStartCodeblock(workingFileText);
let startTagData_depreciatedStart = findStartTag(workingFileText);
// Default to codeblock Style. Then check, if codeblock was not found and depreciated Start was, set startTag to depreciated.
let startTagData = startTagData_codeblockStart;
if (startTagData_codeblockStart.found === false && startTagData_depreciatedStart.found === true) {
startTagData = startTagData_depreciatedStart;
}
else if (startTagData_codeblockStart.found === true && startTagData_depreciatedStart.found === true) {
// If both kinds were found we want to start with the one closer to the top of the document as CM6 requires we work in order.
if (startTagData_codeblockStart.startPosition > startTagData_depreciatedStart.startPosition) {
startTagData = startTagData_depreciatedStart;
}
}
if (startTagData.found === false) {
break;
}
// Search for the first end tag after a start block. (No recursive columns.)
let endTagData = findEndTag(workingFileText.slice(startTagData.startPosition));
if (endTagData.found === false) {
break;
}
/**
* 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 = startIndex + 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),
}));
}
}
}
else {
// At this point if the cursor isnt in the region we pass the data to the
// element to be rendered.
builder.add(startIndex, endIndex, view.Decoration.replace({
widget: new MultiColumnMarkdown_LivePreview_Widget(elementText),
}));
}
generated = true;
// Infinite loop protection.
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) {
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) {
return true;
}
}
if (transaction.state.selection) {
for (let i = 0; i < transaction.state.selection.ranges.length; i++) {
let range = transaction.state.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)) {
return true;
}
// // 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)) {
return true;
}
}
}
return false;
}
},
provide(field) {
return view.EditorView.decorations.from(field);
},
});
function isEditorInLivePreview(state) {
let mdView = state.field(obsidian.editorViewField);
let viewState = mdView.leaf.getViewState();
let stateData = null;
if (viewState.state) {
stateData = viewState.state;
}
return (stateData && stateData.mode == "source" && stateData.source == true);
}
/*
* 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 => {
if (child.parentElement === el) {
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/IHJlY2VpdmVyICE9PSBzdGF0ZSB8fCAhZiA6ICFzdGF0ZS5oYXMocmVjZWl2ZXIpKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IHdyaXRlIHByaXZhdGUgbWVtYmVyIHRvIGFuIG9iamVjdCB3aG9zZSBjbGFzcyBkaWQgbm90IGRlY2xhcmUgaXRcIik7XHJcbiAgICByZXR1cm4gKGtpbmQgPT09IFwiYVwiID8gZi5jYWxsKHJlY2VpdmVyLCB2YWx1ZSkgOiBmID8gZi52YWx1ZSA9IHZhbHVlIDogc3RhdGUuc2V0KHJlY2VpdmVyLCB2YWx1ZSkpLCB2YWx1ZTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fY2xhc3NQcml2YXRlRmllbGRJbihzdGF0ZSwgcmVjZWl2ZXIpIHtcclxuICAgIGlmIChyZWNlaXZlciA9PT0gbnVsbCB8fCAodHlwZW9mIHJlY2VpdmVyICE9PSBcIm9iamVjdFwiICYmIHR5cGVvZiByZWNlaXZlciAhPT0gXCJmdW5jdGlvblwiKSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCB1c2UgJ2luJyBvcGVyYXRvciBvbiBub24tb2JqZWN0XCIpO1xyXG4gICAgcmV0dXJuIHR5cGVvZiBzdGF0ZSA9PT0gXCJmdW5jdGlvblwiID8gcmVjZWl2ZXIgPT09IHN0YXRlIDogc3RhdGUuaGFzKHJlY2VpdmVyKTtcclxufVxyXG4iLCIvKlxuICogRmlsZW5hbWU6IG11bHRpLWNvbHVtbi1tYXJrZG93bi9zcmMvcmVnaW9uU2V0dGluZ3MudHNcbiAqIENyZWF0ZWQgRGF0ZTogVHVlc2RheSwgRmVicnVhcnkgMXN0IDIwMjIsIDEyOjIzOjUzIHBtXG4gKiBBdXRob3I6IENhbWVyb24gUm9iaW5zb25cbiAqIFxuICogQ29weXJpZ2h0IChjKSAyMDIyIENhbWVyb24gUm9iaW5zb25cbiAqL1xuXG5leHBvcnQgZW51bSBCb3JkZXJPcHRpb24ge1xuICAgIGVuYWJsZWQsXG4gICAgb24sXG4gICAgdHJ1ZSxcbiAgICBkaXNhYmxlZCxcbiAgICBvZmYsXG4gICAgZmFsc2Vcbn1cblxuZXhwb3J0IGVudW0gU2hhZG93T3B0aW9uIHtcbiAgICBlbmFibGVkLFxuICAgIG9uLFxuICAgIHRydWUsXG4gICAgZGlzYWJsZWQsXG4gICAgb2ZmLFxuICAgIGZhbHNlXG59XG5cbmV4cG9ydCBlbnVtIENvbHVtbkxheW91dCB7IFxuICAgIHN0YW5kYXJkLFxuICAgIGxlZnQsXG4gICAgZmlyc3QsXG4gICAgY2VudGVyLFxuICAgIG1pZGRsZSxcbiAgICBzZWNvbmQsXG4gICAgcmlnaHQsXG4gICAgdGhpcmQsXG4gICAgbGFzdFxufTtcblxuZXhwb3J0IGVudW0gU2luZ2xlQ29sdW1uU2l6ZSB7XG4gICAgc21hbGwsXG4gICAgbWVkaXVtLFxuICAgIGxhcmdlLFxuICAgIGZ1bGxcbn1cblxuZXhwb3J0IGVudW0gQ29udGVudE92ZXJmbG93VHlwZSB7XG4gICAgc2Nyb2xsLFxuICAgIGhpZGRlblxufVxuXG5leHBvcnQgdHlwZSBNdWx0aUNvbHVtblNldHRpbmdzID0ge1xuICAgIG51bWJlck9mQ29sdW1uczogbnVtYmVyLFxuICAgIGNvbHVtbkxheW91dDogQ29sdW1uTGF5b3V0LFxuICAgIGRyYXdCb3JkZXI6IGJvb2xlYW4sXG4gICAgZHJhd1NoYWRvdzogYm9vbGVhbixcbiAgICBhdXRvTGF5b3V0OiBib29sZWFuXG4gICAgY29sdW1uU2l6ZTogU2luZ2xlQ29sdW1uU2l6ZSxcbiAgICBjb2x1bW5Qb3NpdGlvbjogQ29sdW1uTGF5b3V0LFxuICAgIGNvbHVtblNwYWNpbmc6IHN0cmluZyxcbiAgICBjb250ZW50T3ZlcmZsb3c6IENvbnRlbnRPdmVyZmxvd1R5cGVcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldERlZmF1bHRNdWx0aUNvbHVtblNldHRpbmdzKCk6IE11bHRpQ29sdW1uU2V0dGluZ3Mge1xuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgbnVtYmVyT2ZDb2x1bW5zOiAyLFxuICAgICAgICBjb2x1bW5MYXlvdXQ6IENvbHVtbkxheW91dC5zdGFuZGFyZCxcbiAgICAgICAgZHJhd0JvcmRlcjogdHJ1ZSxcbiAgICAgICAgZHJhd1NoYWRvdzogdHJ1ZSxcbiAgICAgICAgYXV0b0xheW91dDogZmFsc2UsXG4gICAgICAgIGNvbHVtblNpemU6IFNpbmdsZUNvbHVtblNpemUubWVkaXVtLFxuICAgICAgICBjb2x1bW5Qb3NpdGlvbjogQ29sdW1uTGF5b3V0LnN0YW5kYXJkLFxuICAgICAgICBjb2x1bW5TcGFjaW5nOiBcIlwiLFxuICAgICAgICBjb250ZW50T3ZlcmZsb3c6IENvbnRlbnRPdmVyZmxvd1R5cGUuc2Nyb2xsXG4gICAgfVxufSIsIi8qKlxuICogRmlsZTogL3NyYy91dGlsaXRpZXMvc2V0dGluZ3NQYXJzZXIudHMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICogQ3JlYXRlZCBEYXRlOiBGcmlkYXksIEp1bmUgM3JkIDIwMjIsIDg6MTYgcG0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICogQXV0aG9yOiBDYW1lcm9uIFJvYmluc29uICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICogQ29weXJpZ2h0IChjKSAyMDIyIENhbWVyb24gUm9iaW5zb24gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICovXG5cbmltcG9ydCB7IE11bHRpQ29sdW1uU2V0dGluZ3MsIENvbHVtbkxheW91dCwgQm9yZGVyT3B0aW9uLCBTaGFkb3dPcHRpb24sIGdldERlZmF1bHRNdWx0aUNvbHVtblNldHRpbmdzLCBTaW5nbGVDb2x1bW5TaXplLCBDb250ZW50T3ZlcmZsb3dUeXBlIH0gZnJvbSBcIi4uL3JlZ2lvblNldHRpbmdzXCI7XG5cbi8qKlxuICogSGVyZSB3ZSBkZWZpbmUgYWxsIG9mIHRoZSB2YWxpZCBzZXR0aW5ncyBzdHJpbmdzIHRoYXQgdGhlIHVzZXIgY2FuIGVudGVyIGZvciBlYWNoIHNldHRpbmcgdHlwZS5cbiAqIFRoZSBzdHJpbmdzIGFyZSB0aGVuIG1hcHBlZCB0d2ljZSwgZmlyc3QgdG8gYSB2YWxpZCByZWdleCBzdHJpbmcgdGhhdCBzZWFyY2hlcyBmb3IgdGhlIHNldHRpbmdcbiAqIG5hbWUsIGlnbm9yaW5nIGFsbCBleHRyYSBzcGFjZXMgYW5kIGxldHRlciBjYXNlLCBhbmQgdGhlbiBtYXBlZCB0byBhIFJlZ0V4IG9iamVjdCB0byBiZSB1c2VkIFxuICogd2hlbiBwYXJzaW5nLlxuICovXG5jb25zdCBDT0xfUE9TSVRJT05fT1BUSU9OX1NUUlM6IHN0cmluZ1tdID0gW1xuICAgIFwiY29sdW1uIHBvc2l0aW9uXCIsXG4gICAgXCJjb2wgcG9zaXRpb25cIixcbiAgICBcImNvbHVtbiBsb2NhdGlvblwiLFxuICAgIFwiY29sIGxvY2F0aW9uXCIsXG4gICAgXCJzaW5nbGUgY29sdW1uIGxvY2F0aW9uXCIsXG4gICAgXCJzaW5nbGUgY29sdW1uIHBvc2l0aW9uXCIsXG5dO1xuY29uc3QgQ09MX1BPU0lUSU9OX1JFR0VYX0FSUjogUmVnRXhwW10gPSBDT0xfUE9TSVRJT05fT1BUSU9OX1NUUlMubWFwKGNvbnZlcnRTdHJpbmdUb1NldHRpbmdzUmVnZXgpLm1hcCgodmFsdWUpID0+IHtcbiAgICByZXR1cm4gbmV3IFJlZ0V4cCh2YWx1ZSwgXCJpXCIpO1xufSk7XG5cbmNvbnN0IENPTF9TSVpFX09QVElPTl9TVFJTOiBzdHJpbmdbXSA9IFtcbiAgICBcImNvbHVtbiBzaXplXCIsXG4gICAgXCJjb2x1bW4gd2lkdGhcIixcbiAgICBcImNvbCBzaXplXCIsXG4gICAgXCJjb2wgd2lkdGhcIixcbiAgICBcInNpbmdsZSBjb2x1bW4gc2l6ZVwiLFxuICAgIFwic2luZ2xlIGNvbCBzaXplXCIsXG4gICAgXCJzaW5nbGUgY29sdW1uIHdpZHRoXCIsXG4gICAgXCJzaW5nbGUgY29sIHdpZHRoXCJcbl07XG5jb25zdCBDT0xfU0laRV9PUFRJT05fUkVHRVhfQVJSOiBSZWdFeHBbXSA9IENPTF9TSVpFX09QVElPTl9TVFJTLm1hcChjb252ZXJ0U3RyaW5nVG9TZXR0aW5nc1JlZ2V4KS5tYXAoKHZhbHVlKSA9PiB7XG4gICAgcmV0dXJuIG5ldyBSZWdFeHAodmFsdWUsIFwiaVwiKTtcbn0pO1xuXG5jb25zdCBOVU1CRVJfT0ZfQ09MVU1OU19TVFJTID0gW1xuICAgIFwibnVtYmVyIG9mIGNvbHVtbnNcIlxuXVxuY29uc3QgTlVNQkVSX09GX0NPTFVNTlNfUkVHRVhfQVJSOiBSZWdFeHBbXSA9IE5VTUJFUl9PRl9DT0xVTU5TX1NUUlMubWFwKGNvbnZlcnRTdHJpbmdUb1NldHRpbmdzUmVnZXgpLm1hcCgodmFsdWUpID0+IHtcbiAgICByZXR1cm4gbmV3IFJlZ0V4cCh2YWx1ZSwgXCJpXCIpO1xufSk7XG5cbmNvbnN0IExBUkdFU1RfQ09MVU1OX1NUUlMgPSBbXG4gICAgXCJsYXJnZXN0IGNvbHVtblwiXG5dXG5jb25zdCBMQVJHRVNUX0NPTFVNTl9SRUdFWF9BUlI6IFJlZ0V4cFtdID0gTEFSR0VTVF9DT0xVTU5fU1RSUy5tYXAoY29udmVydFN0cmluZ1RvU2V0dGluZ3NSZWdleCkubWFwKCh2YWx1ZSkgPT4ge1xuICAgIHJldHVybiBuZXcgUmVnRXhwKHZhbHVlLCBcImlcIik7XG59KTtcblxuY29uc3QgRFJBV19CT1JERVJfU1RSUyA9IFtcbiAgICBcImJvcmRlclwiXG5dXG5jb25zdCBEUkFXX0JPUkRFUl9SRUdFWF9BUlI6IFJlZ0V4cFtdID0gRFJBV19CT1JERVJfU1RSUy5tYXAoY29udmVydFN0cmluZ1RvU2V0dGluZ3NSZWdleCkubWFwKCh2YWx1ZSkgPT4ge1xuICAgIHJldHVybiBuZXcgUmVnRXhwKHZhbHVlLCBcImlcIik7XG59KTtcblxuY29uc3QgRFJBV19TSEFET1dfU1RSUyA9IFtcbiAgICBcInNoYWRvd1wiXG5dXG5jb25zdCBEUkFXX1NIQURPV19SRUdFWF9BUlI6IFJlZ0V4cFtdID0gRFJBV19TSEFET1dfU1RSUy5tYXAoY29udmVydFN0cmluZ1RvU2V0dGluZ3NSZWdleCkubWFwKCh2YWx1ZSkgPT4ge1xuICAgIHJldHVybiBuZXcgUmVnRXhwKHZhbHVlLCBcImlcIik7XG59KTtcblxuY29uc3QgQVVUT19MQVlPVVRfU0VUVElOR19TVFJTID0gW1xuICAgIFwiYXV0byBsYXlvdXRcIlxuXVxuY29uc3QgQVVUT19MQVlPVVRfUkVHRVhfQVJSOiBSZWdFeHBbXSA9IEFVVE9fTEFZT1VUX1NFVFRJTkdfU1RSUy5tYXAoY29udmVydFN0cmluZ1RvU2V0dGluZ3NSZWdleCkubWFwKCh2YWx1ZSkgPT4ge1xuICAgIHJldHVybiBuZXcgUmVnRXhwKHZhbHVlLCBcImlcIik7XG59KTtcblxuY29uc3QgQ09MVU1OX1NQQUNJTkdfUkVHRVhfQVJSOiBSZWdFeHBbXSA9IFtcbiAgICBcImNvbHVtbiBzcGFjaW5nXCIsXG5dLm1hcCgodmFsdWUpID0+IHtcbiAgICByZXR1cm4gbmV3IFJlZ0V4cChjb252ZXJ0U3RyaW5nVG9TZXR0aW5nc1JlZ2V4KHZhbHVlKSwgXCJpXCIpO1xufSk7XG5cbmNvbnN0IENPTlRFTlRfT1ZFUkZMT1dfUkVHRVhfQVJSOiBSZWdFeHBbXSA9IFtcbiAgICBcIm92ZXJmbG93XCIsXG4gICAgXCJjb250ZW50IG92ZXJmbG93XCJcbl0ubWFwKCh2YWx1ZSkgPT4ge1xuICAgIHJldHVybiBuZXcgUmVnRXhwKGNvbnZlcnRTdHJpbmdUb1NldHRpbmdzUmVnZXgodmFsdWUpLCBcImlcIilcbn0pXG5cbi8qKlxuICogVGhpcyBmdW5jdGlvbiBzZWFyY2hlcyB0aGUgc2V0dGluZ3Mgc3RyaW5nIHRocm91Z2ggZWFjaCByZWdleCBvcHRpb24uIElmIG9uZSBvZiB0aGUgcmVnZXhcbiAqIHZhbHVlcyBtYXRjaCwgaXQgcmV0dXJucyB0aGUgZmlyc3QgZ3JvdXAgZm91bmQgYnkgdGhlIHJlZ2V4LiBUaGlzIGlzIGRlcGVuZGVkIG9uIHByb3BlclxuICogcmVnZXggZm9ybWF0dGluZyB3aGljaCBpcyBkb25lIGJ5IHRoZSBjb252ZXJ0U3RyaW5nVG9TZXR0aW5nc1JlZ2V4IGZ1bmN0aW9uIGRlZmluZWQgYmVsb3cuXG4gKiBcbiAqIEBwYXJhbSBzZXR0aW5nc1N0cmluZyBUaGUgdmFsdWUgdGhhdCBtYXkgbWF0Y2ggb25lIG9mIHRoZSBzZXR0aW5nIG9wdGlvbnMuXG4gKiBAcGFyYW0gdmFsaWRTZXR0aW5nRm9ybWF0UmVnRXggVGhlIHNldHRpbmdzIG9wdGlvbnMgdGhyb3VnaCB3aGljaCB0byBjaGVjayBhbGwgb3B0aW9ucy4gSWYgb25lIG9mIHRoZXNlIHJlZ2V4IFxuICogdmFsdWVzIG1hdGNoIG9uIHRoZSBzdHJpbmcgd2UgYnJlYWsgZnJvbSB0aGUgbG9vcCByZXR1cm5pbmcgdGhlIGZvdW5kIHZhbHVlLlxuICogXG4gKiBAcmV0dXJucyB0aGUgdXNlciBlbnRlcmVkIGRhdGEgaWYgdGhlIHNldHRpbmcgaXMgYSBtYXRjaCwgb3IgbnVsbCBpZiBub24gb2YgdGhlIG9wdGlvbnMgbWF0Y2hlZC5cbiAqL1xuZnVuY3Rpb24gZ2V0U2V0dGluZ3NEYXRhRnJvbUtleXMoc2V0dGluZ3NTdHJpbmc6IHN0cmluZywgdmFsaWRTZXR0aW5nRm9ybWF0UmVnRXg6IFJlZ0V4cFtdKTogc3RyaW5nIHwgbnVsbCB7XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHZhbGlkU2V0dGluZ0Zvcm1hdFJlZ0V4Lmxlbmd0aDsgaSsrKSB7XG5cbiAgICAgICAgbGV0IHJlZ2V4U2VhcmNoRGF0YSA9IHZhbGlkU2V0dGluZ0Zvcm1hdFJlZ0V4W2ldLmV4ZWMoc2V0dGluZ3NTdHJpbmcpXG4gICAgICAgIGlmKHJlZ2V4U2VhcmNoRGF0YSAhPT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuIHJlZ2V4U2VhcmNoRGF0YVsxXS50cmltKClcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBudWxsO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VTaW5nbGVDb2x1bW5TZXR0aW5ncyhzZXR0aW5nc1N0cjogc3RyaW5nLCBvcmlnaW5hbFNldHRpbmdzOiBNdWx0aUNvbHVtblNldHRpbmdzKTogTXVsdGlDb2x1bW5TZXR0aW5ncyB7XG5cbiAgICBsZXQgc2V0dGluZ3NMaW5lcyA9IHNldHRpbmdzU3RyLnNwbGl0KFwiXFxuXCIpO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2V0dGluZ3NMaW5lcy5sZW5ndGg7IGkrKykge1xuXG4gICAgICAgIGxldCBzZXR0aW5nc0xpbmUgPSBzZXR0aW5nc0xpbmVzW2ldO1xuICAgICAgICBsZXQgc2V0dGluZ3NEYXRhID0gZ2V0U2V0dGluZ3NEYXRhRnJvbUtleXMoc2V0dGluZ3NMaW5lLCBDT0xfUE9TSVRJT05fUkVHRVhfQVJSKTtcbiAgICAgICAgaWYgKHNldHRpbmdzRGF0YSAhPT0gbnVsbCkge1xuXG4gICAgICAgICAgICBvcmlnaW5hbFNldHRpbmdzLmNvbHVtblBvc2l0aW9uID0gcGFyc2VGb3JTaW5nbGVDb2x1bW5Mb2NhdGlvbihzZXR0aW5nc0RhdGEpO1xuICAgICAgICB9XG5cbiAgICAgICAgc2V0dGluZ3NEYXRhID0gZ2V0U2V0dGluZ3NEYXRhRnJvbUtleXMoc2V0dGluZ3NMaW5lLCBDT0xfU0laRV9PUFRJT05fUkVHRVhfQVJSKTtcbiAgICAgICAgaWYgKHNldHRpbmdzRGF0YSAhPT0gbnVsbCkge1xuXG4gICAgICAgICAgICBvcmlnaW5hbFNldHRpbmdzLmNvbHVtblNpemUgPSBwYXJzZUZvclNpbmdsZUNvbHVtblNpemUoc2V0dGluZ3NEYXRhKVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG9yaWdpbmFsU2V0dGluZ3M7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZUNvbHVtblNldHRpbmdzKHNldHRpbmdzU3RyOiBzdHJpbmcpOiBNdWx0aUNvbHVtblNldHRpbmdzIHtcblxuICAgIGxldCBwYXJzZWRTZXR0aW5ncyA9IGdldERlZmF1bHRNdWx0aUNvbHVtblNldHRpbmdzKCk7XG5cbiAgICBsZXQgc2V0dGluZ3NMaW5lcyA9IHNldHRpbmdzU3RyLnNwbGl0KFwiXFxuXCIpO1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzZXR0aW5nc0xpbmVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGxldCBzZXR0aW5nc0xpbmUgPSBzZXR0aW5nc0xpbmVzW2ldO1xuXG4gICAgICAgIGxldCBzZXR0aW5nc0RhdGEgPSBnZXRTZXR0aW5nc0RhdGFGcm9tS2V5cyhzZXR0aW5nc0xpbmUsIE5VTUJFUl9PRl9DT0xVTU5TX1JFR0VYX0FSUik7XG4gICAgICAgIGlmIChzZXR0aW5nc0RhdGEgIT09IG51bGwpIHtcblxuICAgICAgICAgICAgbGV0IG51bU9mQ29scyA9IHBhcnNlSW50KHNldHRpbmdzRGF0YSlcbiAgICAgICAgICAgIGlmIChOdW1iZXIuaXNOYU4obnVtT2ZDb2xzKSA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgICAgICBpZiAobnVtT2ZDb2xzID49IDEgJiYgbnVtT2ZDb2xzIDw9IDMpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyc2VkU2V0dGluZ3MubnVtYmVyT2ZDb2x1bW5zID0gbnVtT2ZDb2xzO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHNldHRpbmdzRGF0YSA9IGdldFNldHRpbmdzRGF0YUZyb21LZXlzKHNldHRpbmdzTGluZSwgTEFSR0VTVF9DT0xVTU5fUkVHRVhfQVJSKVxuICAgICAgICBpZiAoc2V0dGluZ3NEYXRhICE9PSBudWxsKSB7XG5cbiAgICAgICAgICAgIGxldCB1c2VyRGVmTGF5b3V0OiBDb2x1bW5MYXlvdXQgPSAoPGFueT5Db2x1bW5MYXlvdXQpW3NldHRpbmdzRGF0YV07XG4gICAgICAgICAgICBpZiAodXNlckRlZkxheW91dCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgcGFyc2VkU2V0dGluZ3MuY29sdW1uTGF5b3V0ID0gdXNlckRlZkxheW91dDtcbiAgICAgICAgICAgICAgICBwYXJzZWRTZXR0aW5ncy5jb2x1bW5Qb3NpdGlvbiA9IHVzZXJEZWZMYXlvdXQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBzZXR0aW5nc0RhdGEgPSBnZXRTZXR0aW5nc0RhdGFGcm9tS2V5cyhzZXR0aW5nc0xpbmUsIERSQVdfQk9SREVSX1JFR0VYX0FSUilcbiAgICAgICAgaWYgKHNldHRpbmdzRGF0YSAhPT0gbnVsbCkge1xuXG4gICAgICAgICAgICBsZXQgaXNCb3JkZXJEcmF3bjogQm9yZGVyT3B0aW9uID0gKDxhbnk+Qm9yZGVyT3B0aW9uKVtzZXR0aW5nc0RhdGFdO1xuICAgICAgICAgICAgaWYgKGlzQm9yZGVyRHJhd24gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIHN3aXRjaCAoaXNCb3JkZXJEcmF3bikge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIChCb3JkZXJPcHRpb24uZGlzYWJsZWQpOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIChCb3JkZXJPcHRpb24ub2ZmKTpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAoQm9yZGVyT3B0aW9uLmZhbHNlKTpcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhcnNlZFNldHRpbmdzLmRyYXdCb3JkZXIgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHNldHRpbmdzRGF0YSA9IGdldFNldHRpbmdzRGF0YUZyb21LZXlzKHNldHRpbmdzTGluZSwgRFJBV19TSEFET1dfUkVHRVhfQVJSKVxuICAgICAgICBpZiAoc2V0dGluZ3NEYXRhICE9PSBudWxsKSB7XG5cbiAgICAgICAgICAgIGxldCBpc1NoYWRvd0RyYXduOiBTaGFkb3dPcHRpb24gPSAoPGFueT5TaGFkb3dPcHRpb24pW3NldHRpbmdzRGF0YV07XG4gICAgICAgICAgICBpZiAoaXNTaGFkb3dEcmF3biAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgc3dpdGNoIChpc1NoYWRvd0RyYXduKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgKFNoYWRvd09wdGlvbi5kaXNhYmxlZCk6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgKFNoYWRvd09wdGlvbi5vZmYpOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIChTaGFkb3dPcHRpb24uZmFsc2UpOlxuICAgICAgICAgICAgICAgICAgICAgICAgcGFyc2VkU2V0dGluZ3MuZHJhd1NoYWRvdyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgc2V0dGluZ3NEYXRhID0gZ2V0U2V0dGluZ3NEYXRhRnJvbUtleXMoc2V0dGluZ3NMaW5lLCBBVVRPX0xBWU9VVF9SRUdFWF9BUlIpXG4gICAgICAgIGlmIChzZXR0aW5nc0RhdGEgIT09IG51bGwpIHtcblxuICAgICAgICAgICAgaWYoc2V0dGluZ3NEYXRhID09PSBcInRydWVcIikge1xuICAgICAgICAgICAgICAgIHBhcnNlZFNldHRpbmdzLmF1dG9MYXlvdXQgPSB0cnVlXG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBzZXR0aW5nc0RhdGEgPSBnZXRTZXR0aW5nc0RhdGFGcm9tS2V5cyhzZXR0aW5nc0xpbmUsIENPTFVNTl9TUEFDSU5HX1JFR0VYX0FSUik7XG4gICAgICAgIGlmKHNldHRpbmdzRGF0YSAhPT0gbnVsbCkge1xuXG4gICAgICAgICAgICBsZXQgcGFyc2VkID0gZ2V0TGVuZ3RoVW5pdChzZXR0aW5nc0RhdGEudHJpbSgpKTtcbiAgICAgICAgICAgIGxldCBzcGFjaW5nU3RyID0gXCJcIjtcblxuICAgICAgICAgICAgaWYocGFyc2VkLmlzVmFsaWQpIHtcblxuICAgICAgICAgICAgICAgIGxldCBub1VuaXRzU3RyID0gc2V0dGluZ3NEYXRhLnJlcGxhY2UocGFyc2VkLnVuaXRTdHIsIFwiXCIpLnRyaW0oKTtcbiAgICAgICAgICAgICAgICBsZXQgbm9Vbml0c051bSA9IHBhcnNlSW50KG5vVW5pdHNTdHIpO1xuICAgICAgICAgICAgICAgIGlmKGlzTmFOKG5vVW5pdHNOdW0pID09PSBmYWxzZSkge1xuXG4gICAgICAgICAgICAgICAgICAgIHNwYWNpbmdTdHIgPSBgJHtub1VuaXRzU3RyfSR7cGFyc2VkLnVuaXRTdHJ9YFxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgIGxldCBub1VuaXRzTnVtID0gcGFyc2VJbnQoc2V0dGluZ3NEYXRhLnRyaW0oKSk7XG4gICAgICAgICAgICAgICAgaWYoaXNOYU4obm9Vbml0c051bSkgPT09IGZhbHNlKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgc3BhY2luZ1N0ciA9IGAke25vVW5pdHNOdW19cHRgXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBwYXJzZWRTZXR0aW5ncy5jb2x1bW5TcGFjaW5nID0gc3BhY2luZ1N0cjtcbiAgICAgICAgfVxuXG4gICAgICAgIHNldHRpbmdzRGF0YSA9IGdldFNldHRpbmdzRGF0YUZyb21LZXlzKHNldHRpbmdzTGluZSwgQ09OVEVOVF9PVkVSRkxPV19SRUdFWF9BUlIpO1xuICAgICAgICBpZihzZXR0aW5nc0RhdGEgIT09IG51bGwpIHtcblxuICAgICAgICAgICAgbGV0IG92ZXJmbG93VHlwZSA9IENvbnRlbnRPdmVyZmxvd1R5cGUuc2Nyb2xsO1xuXG4gICAgICAgICAgICBzZXR0aW5nc0RhdGEgPSBzZXR0aW5nc0RhdGEudG9Mb3dlckNhc2UoKS50cmltKCk7XG4gICAgICAgICAgICBpZihzZXR0aW5nc0RhdGEgPT09IFwiaGlkZGVuXCIpIHtcbiAgICAgICAgICAgICAgICBvdmVyZmxvd1R5cGUgPSBDb250ZW50T3ZlcmZsb3dUeXBlLmhpZGRlbjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcGFyc2VkU2V0dGluZ3MuY29udGVudE92ZXJmbG93ID0gb3ZlcmZsb3dUeXBlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHBhcnNlZFNldHRpbmdzO1xufVxuXG5mdW5jdGlvbiBnZXRMZW5ndGhVbml0KGxlbmd0aFN0cjogc3RyaW5nKTogeyBpc1ZhbGlkOiBib29sZWFuLCB1bml0U3RyOiBzdHJpbmcgfSB7XG5cbiAgICBsZXQgbGFzdENoYXIgPSBsZW5ndGhTdHIuc2xpY2UobGVuZ3RoU3RyLmxlbmd0aCAtIDEpO1xuICAgIGxldCBsYXN0VHdvQ2hhcnMgPSBsZW5ndGhTdHIuc2xpY2UobGVuZ3RoU3RyLmxlbmd0aCAtIDIpO1xuXG4gICAgbGV0IHVuaXRTdHIgPSBcIlwiXG4gICAgbGV0IGlzVmFsaWQgPSBmYWxzZTtcbiAgICBpZihsYXN0Q2hhciA9PT0gXCIlXCIpIHtcbiAgICAgICAgdW5pdFN0ciA9IGxhc3RDaGFyO1xuICAgICAgICBpc1ZhbGlkID0gdHJ1ZTtcbiAgICB9XG4gICAgZWxzZSBpZihsYXN0VHdvQ2hhcnMgPT09IFwiY21cIiB8fFxuICAgICAgICAgICAgbGFzdFR3b0NoYXJzID09PSBcIm1tXCIgfHxcbiAgICAgICAgICAgIGxhc3RUd29DaGFycyA9PT0gXCJpblwiIHx8XG4gICAgICAgICAgICBsYXN0VHdvQ2hhcnMgPT09IFwicHhcIiB8fFxuICAgICAgICAgICAgbGFzdFR3b0NoYXJzID09PSBcInB0XCIgfHxcbiAgICAgICAgICAgIGxhc3RUd29DaGFycyA9PT0gXCJwY1wiIHx8XG4gICAgICAgICAgICBsYXN0VHdvQ2hhcnMgPT09IFwiZW1cIiB8fFxuICAgICAgICAgICAgbGFzdFR3b0NoYXJzID09PSBcImV4XCIgfHxcbiAgICAgICAgICAgIGxhc3RUd29DaGFycyA9PT0gXCJjaFwiIHx8XG4gICAgICAgICAgICBsYXN0VHdvQ2hhcnMgPT09IFwidndcIiB8fFxuICAgICAgICAgICAgbGFzdFR3b0NoYXJzID09PSBcInZoXCIgKSB7XG4gICAgICAgIHVuaXRTdHIgPSBsYXN0VHdvQ2hhcnM7XG4gICAgICAgIGlzVmFsaWQgPSB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiB7IGlzVmFsaWQ6IGlzVmFsaWQsIHVuaXRTdHI6IHVuaXRTdHIgfVxufVxuXG5jb25zdCBDT0RFQkxPQ0tfUkVHSU9OX0lEX1JFR0VYX1NUUlMgPSBbXG4gICAgXCJpZFwiLFxuICAgIFwicmVnaW9uIGlkXCJcbl1cbmNvbnN0IENPREVCTE9DS19SRUdJT05fSURfUkVHRVhfQVJSOiBSZWdFeHBbXSA9IENPREVCTE9DS19SRUdJT05fSURfUkVHRVhfU1RSUy5tYXAoY29udmVydFN0cmluZ1RvU2V0dGluZ3NSZWdleCkubWFwKCh2YWx1ZSkgPT4ge1xuICAgIHJldHVybiBuZXcgUmVnRXhwKHZhbHVlLCBcImlcIik7XG59KTtcbmV4cG9ydCBmdW5jdGlvbiBwYXJzZVN0YXJ0UmVnaW9uQ29kZUJsb2NrSUQoc2V0dGluZ3NTdHI6IHN0cmluZyk6IHN0cmluZyB7XG5cbiAgICBsZXQgY29kZUJsb2NrUmVnaW9uSUQgPSBcIlwiXG4gICAgbGV0IHNldHRpbmdzTGluZXMgPSBzZXR0aW5nc1N0ci5zcGxpdChcIlxcblwiKTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2V0dGluZ3NMaW5lcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBsZXQgc2V0dGluZ3NMaW5lID0gc2V0dGluZ3NMaW5lc1tpXTtcblxuICAgICAgICBsZXQgc2V0dGluZ3NEYXRhID0gZ2V0U2V0dGluZ3NEYXRhRnJvbUtleXMoc2V0dGluZ3NMaW5lLCBDT0RFQkxPQ0tfUkVHSU9OX0lEX1JFR0VYX0FSUik7XG4gICAgICAgIGlmIChzZXR0aW5nc0RhdGEgIT09IG51bGwpIHtcblxuICAgICAgICAgICAgY29kZUJsb2NrUmVnaW9uSUQgPSBzZXR0aW5nc0RhdGFcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjb2RlQmxvY2tSZWdpb25JRDtcbn1cblxuZnVuY3Rpb24gcGFyc2VGb3JTaW5nbGVDb2x1bW5Mb2NhdGlvbihsb2NhdGlvblN0cmluZzogc3RyaW5nKTogQ29sdW1uTGF5b3V0e1xuXG4gICAgc3dpdGNoIChsb2NhdGlvblN0cmluZy50b0xvd2VyQ2FzZSgpLnRyaW0oKS5yZXBsYWNlKFwiIFwiLCBcIlwiKSkge1xuICAgICAgICBjYXNlIFwibGVmdFwiOlxuICAgICAgICBjYXNlIFwibGVmdHNpZGVcIjpcbiAgICAgICAgY2FzZSBcImxlZnRtYXJnaW5cIjpcbiAgICAgICAgY2FzZSBcImxlZnRhbGlnblwiOlxuICAgICAgICBjYXNlIFwibGVmdGFsaWduZWRcIjpcbiAgICAgICAgY2FzZSBcImxlZnRhbGlnbmVtZW50XCI6XG4gICAgICAgIGNhc2UgXCJmaXJzdFwiOlxuICAgICAgICBjYXNlIFwic3RhcnRcIjpcbiAgICAgICAgY2FzZSBcImJlZ2lubmluZ1wiOlxuICAgICAgICAgICAgcmV0dXJuIENvbHVtbkxheW91dC5sZWZ0XG4gICAgICAgIGNhc2UgXCJtaWRkbGVcIjpcbiAgICAgICAgY2FzZSBcIm1pZGRsZWFsaWduZWRcIjpcbiAgICAgICAgY2FzZSBcIm1pZGRsZWFsaWdubWVudFwiOlxuICAgICAgICBjYXNlIFwiY2VudGVyXCI6XG4gICAgICAgIGNhc2UgXCJjZW50ZXJhbGlnbmVkXCI6XG4gICAgICAgIGNhc2UgXCJjZW50ZXJhbGlnbm1lbnRcIjpcbiAgICAgICAgY2FzZSBcImNlbnRlcmVkXCI6XG4gICAgICAgIGNhc2UgXCJzdGFuZGFyZFwiOlxuICAgICAgICAgICAgcmV0dXJuIENvbHVtbkxheW91dC5jZW50ZXJcbiAgICAgICAgY2FzZSBcInJpZ2h0XCI6XG4gICAgICAgIGNhc2UgXCJyaWdodHNpZGVcIjpcbiAgICAgICAgY2FzZSBcInJpZ2h0bWFyZ2luXCI6XG4gICAgICAgIGNhc2UgXCJyaWdodGFsaWduXCI6XG4gICAgICAgIGNhc2UgXCJyaWdodGFsaWduZWRcIjpcbiAgICAgICAgY2FzZSBcInJpZ2h0YWxpZ25tZW50XCI6XG4gICAgICAgIGNhc2UgXCJsYXN0XCI6XG4gICAgICAgIGNhc2UgXCJlbmRcIjpcbiAgICAgICAgICAgIHJldHVybiBDb2x1bW5MYXlvdXQucmlnaHRcbiAgICB9XG5cbiAgICByZXR1cm4gQ29sdW1uTGF5b3V0LmNlbnRlclxufVxuXG5mdW5jdGlvbiBwYXJzZUZvclNpbmdsZUNvbHVtblNpemUoc2l6ZVN0cmluZzogc3RyaW5nKTogU2luZ2xlQ29sdW1uU2l6ZSB7XG5cbiAgICBzd2l0Y2ggKHNpemVTdHJpbmcgPSBzaXplU3RyaW5nLnRvTG93ZXJDYXNlKCkudHJpbSgpLnJlcGxhY2UoXCIgXCIsIFwiXCIpKSB7XG4gICAgICAgIGNhc2UgXCJzbWFsbFwiOlxuICAgICAgICBjYXNlIFwic21cIjpcbiAgICAgICAgICAgIHJldHVybiBTaW5nbGVDb2x1bW5TaXplLnNtYWxsO1xuICAgICAgICBjYXNlIFwibWVkaXVtXCI6XG4gICAgICAgIGNhc2UgXCJtZWRcIjpcbiAgICAgICAgICAgIHJldHVybiBTaW5nbGVDb2x1bW5TaXplLm1lZGl1bTtcbiAgICAgICAgY2FzZSBcImxhcmdlXCI6XG4gICAgICAgIGNhc2UgXCJsZ1wiOlxuICAgICAgICAgICAgcmV0dXJuIFNpbmdsZUNvbHVtblNpemUubGFyZ2U7XG4gICAgICAgIGNhc2UgXCJmdWxsXCI6XG4gICAgICAgIGNhc2UgXCJmdWxsIHNpemVcIjpcbiAgICAgICAgICAgIHJldHVybiBTaW5nbGVDb2x1bW5TaXplLmZ1bGw7XG4gICAgfVxuXG4gICAgcmV0dXJuIFNpbmdsZUNvbHVtblNpemUubWVkaXVtXG59XG5cbmZ1bmN0aW9uIGNvbnZlcnRTdHJpbmdUb1NldHRpbmdzUmVnZXgob3JpZ2luYWxTdHJpbmc6IFN0cmluZyk6IHN0cmluZyB7XG5cbiAgICBvcmlnaW5hbFN0cmluZyA9IG9yaWdpbmFsU3RyaW5nLnJlcGxhY2UoXCIgXCIsIFwiICpcIik7XG4gICAgXG4gICAgbGV0IHJlZ2V4U3RyaW5nID0gYCg/OiR7b3JpZ2luYWxTdHJpbmd9ICo6ICopKC4qKWA7XG4gICAgcmV0dXJuIHJlZ2V4U3RyaW5nO1xufSIsIi8qXG4gKiBGaWxlOiBtdWx0aS1jb2x1bW4tbWFya2Rvd24vc3JjL011bHRpQ29sdW1uUGFyc2VyLnRzXG4gKiBDcmVhdGVkIERhdGU6IFNhdHVyZGF5LCBKYW51YXJ5IDIybmQgMjAyMiwgNjowMjo0NiBwbVxuICogQXV0aG9yOiBDYW1lcm9uIFJvYmluc29uXG4gKiBcbiAqIENvcHlyaWdodCAoYykgMjAyMiBDYW1lcm9uIFJvYmluc29uXG4gKi9cblxuaW1wb3J0IHsgcGFyc2VTdGFydFJlZ2lvbkNvZGVCbG9ja0lEIH0gZnJvbSBcIi4vc2V0dGluZ3NQYXJzZXJcIjtcblxuY29uc3QgU1RBUlRfUkVHRVhfU1RSUyA9IFtcIj09PSAqc3RhcnQtbXVsdGktY29sdW1uKDo/W2EtekEtWjAtOS1fXFxcXHNdKik/XCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIFwiPT09ICptdWx0aS1jb2x1bW4tc3RhcnQoOj9bYS16QS1aMC05LV9cXFxcc10qKT9cIl1cbmNvbnN0IFNUQVJUX1JFR0VYX0FSUjogUmVnRXhwW10gPSBbXTtcbmZvcihsZXQgaSA9IDA7IGkgPCBTVEFSVF9SRUdFWF9TVFJTLmxlbmd0aDsgaSsrKSB7XG4gICAgU1RBUlRfUkVHRVhfQVJSLnB1c2gobmV3IFJlZ0V4cChTVEFSVF9SRUdFWF9TVFJTW2ldKSk7XG59XG5cbmNvbnN0IFNUQVJUX1JFR0VYX1NUUlNfV0hPTEVfTElORSA9IFtcIl49PT0gKnN0YXJ0LW11bHRpLWNvbHVtbig6P1thLXpBLVowLTktX1xcXFxzXSopPyRcIixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIl49PT0gKm11bHRpLWNvbHVtbi1zdGFydCg6P1thLXpBLVowLTktX1xcXFxzXSopPyRcIl1cbmNvbnN0IFNUQVJUX1JFR0VYX0FSUl9XSE9MRV9MSU5FOiBSZWdFeHBbXSA9IFtdO1xuZm9yKGxldCBpID0gMDsgaSA8IFNUQVJUX1JFR0VYX1NUUlNfV0hPTEVfTElORS5sZW5ndGg7IGkrKykge1xuICAgIFNUQVJUX1JFR0VYX0FSUl9XSE9MRV9MSU5FLnB1c2gobmV3IFJlZ0V4cChTVEFSVF9SRUdFWF9TVFJTX1dIT0xFX0xJTkVbaV0pKTtcbn1cblxuXG5leHBvcnQgZnVuY3Rpb24gZmluZFN0YXJ0VGFnKHRleHQ6IHN0cmluZyk6IHsgZm91bmQ6IGJvb2xlYW4sIHN0YXJ0UG9zaXRpb246IG51bWJlciwgZW5kUG9zaXRpb246IG51bWJlciwgbWF0Y2hMZW5ndGg6IG51bWJlciB9IHtcblxuICAgIGxldCBmb3VuZCA9IGZhbHNlO1xuICAgIGxldCBzdGFydFBvc2l0aW9uID0gLTE7XG4gICAgbGV0IG1hdGNoTGVuZ3RoID0gMDtcbiAgICBmb3IobGV0IGkgPSAwOyBpPCBTVEFSVF9SRUdFWF9BUlIubGVuZ3RoOyBpKyspIHtcblxuICAgICAgICBsZXQgcmVnZXhEYXRhID0gU1RBUlRfUkVHRVhfQVJSW2ldLmV4ZWModGV4dClcbiAgICAgICAgaWYocmVnZXhEYXRhICE9PSBudWxsICYmIHJlZ2V4RGF0YS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBzdGFydFBvc2l0aW9uID0gcmVnZXhEYXRhLmluZGV4XG4gICAgICAgICAgICBtYXRjaExlbmd0aCA9IHJlZ2V4RGF0YVswXS5sZW5ndGg7XG5cbiAgICAgICAgICAgIGxldCBsaW5lID0gdGV4dC5zbGljZShzdGFydFBvc2l0aW9uLCBzdGFydFBvc2l0aW9uICsgbWF0Y2hMZW5ndGgpO1xuICAgICAgICAgICAgaWYoU1RBUlRfUkVHRVhfQVJSX1dIT0xFX0xJTkVbaV0udGVzdChsaW5lKSkge1xuICAgICAgICAgICAgICAgIGZvdW5kID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICBsZXQgZW5kUG9zaXRpb24gPSBzdGFydFBvc2l0aW9uICsgbWF0Y2hMZW5ndGg7XG5cbiAgICByZXR1cm4geyBmb3VuZCwgc3RhcnRQb3NpdGlvbiwgZW5kUG9zaXRpb24sIG1hdGNoTGVuZ3RoIH07XG59XG5leHBvcnQgZnVuY3Rpb24gY29udGFpbnNTdGFydFRhZyh0ZXh0OiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gZmluZFN0YXJ0VGFnKHRleHQpLmZvdW5kXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc1N0YXJ0VGFnV2l0aElEKHRleHQ6IHN0cmluZyk6IHtpc1N0YXJ0VGFnOiBib29sZWFuLCBoYXNLZXk6IGJvb2xlYW59IHtcblxuICAgIGxldCBzdGFydFRhZ0RhdGEgPSBmaW5kU3RhcnRUYWcodGV4dCk7XG4gICAgaWYoc3RhcnRUYWdEYXRhLmZvdW5kID09PSB0cnVlKSB7XG5cbiAgICAgICAgbGV0IGtleSA9IGdldFN0YXJ0VGFnS2V5KHRleHQpXG4gICAgICAgIGlmKGtleSA9PT0gbnVsbCB8fCBrZXkgPT09IFwiXCIpIHtcbiAgICAgICAgICAgIHJldHVybiB7aXNTdGFydFRhZzogdHJ1ZSwgaGFzS2V5OiBmYWxzZX07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHtpc1N0YXJ0VGFnOiB0cnVlLCBoYXNLZXk6IHRydWV9O1xuICAgIH1cblxuICAgIHJldHVybiB7aXNTdGFydFRhZzogZmFsc2UsIGhhc0tleTogZmFsc2V9O1xufVxuXG5jb25zdCBFTkRfUkVHRVhfU1RSUyA9IFtcIj09PSAqZW5kLW11bHRpLWNvbHVtblwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgXCI9PT0gKm11bHRpLWNvbHVtbi1lbmRcIl1cbmNvbnN0IEVORF9SRUdFWF9BUlI6IFJlZ0V4cFtdID0gW107XG5mb3IobGV0IGkgPSAwOyBpIDwgRU5EX1JFR0VYX1NUUlMubGVuZ3RoOyBpKyspIHtcbiAgICBFTkRfUkVHRVhfQVJSLnB1c2gobmV3IFJlZ0V4cChFTkRfUkVHRVhfU1RSU1tpXSkpO1xufVxuXG50eXBlIFRhZ1Bvc2l0aW9uaW5nRGF0YSA9IHtcbiAgICBmb3VuZDogYm9vbGVhbjtcbiAgICBzdGFydFBvc2l0aW9uOiBudW1iZXI7XG4gICAgZW5kUG9zaXRpb246IG51bWJlcjtcbiAgICBtYXRjaExlbmd0aDogbnVtYmVyO1xufTtcblxuZXhwb3J0IGZ1bmN0aW9uIGZpbmRFbmRUYWcodGV4dDogc3RyaW5nKTogVGFnUG9zaXRpb25pbmdEYXRhIHtcblxuICAgIC8vIFdlIHdhbnQgdG8gZmluZCB0aGUgZmlyc3QgZW5kIHRhZyBpbiB0aGUgdGV4dC5cbiAgICAvLyBTbyBoZXJlIHdlIGxvb3AgYmFja3dhcmRzLCBzbGljaW5nIG9mZiB0aGUgdGFpbCB1bnRpbFxuICAgIC8vIHRoZXJlIGFyZSBubyBtb3JlIGVuZCB0YWdzIGF2YWlsYWJsZVxuICAgIGxldCBsYXN0VmFsaWREYXRhID0gZ2V0RW5kVGFnRGF0YSh0ZXh0KTtcbiAgICBsZXQgd29ya2luZ1JlZ2V4RGF0YSA9IGxhc3RWYWxpZERhdGE7XG4gICAgd2hpbGUod29ya2luZ1JlZ2V4RGF0YS5mb3VuZCA9PT0gdHJ1ZSkge1xuXG4gICAgICAgIGxhc3RWYWxpZERhdGEgPSB3b3JraW5nUmVnZXhEYXRhO1xuICAgICAgICB0ZXh0ID0gdGV4dC5zbGljZSgwLCB3b3JraW5nUmVnZXhEYXRhLnN0YXJ0UG9zaXRpb24pO1xuICAgICAgICB3b3JraW5nUmVnZXhEYXRhID0gZ2V0RW5kVGFnRGF0YSh0ZXh0KTtcbiAgICB9XG5cbiAgICByZXR1cm4gbGFzdFZhbGlkRGF0YTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBjb250YWluc0VuZFRhZyh0ZXh0OiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gZmluZEVuZFRhZyh0ZXh0KS5mb3VuZFxufVxuXG5mdW5jdGlvbiBnZXRFbmRUYWdEYXRhKHRleHQ6IHN0cmluZykge1xuXG4gICAgbGV0IGZvdW5kID0gZmFsc2U7XG4gICAgbGV0IHN0YXJ0UG9zaXRpb24gPSAtMTtcbiAgICBsZXQgZW5kUG9zaXRpb24gPSAtMVxuICAgIGxldCBtYXRjaExlbmd0aCA9IDA7XG4gICAgZm9yKGxldCBpID0gMDsgaTwgRU5EX1JFR0VYX0FSUi5sZW5ndGg7IGkrKykge1xuXG4gICAgICAgIGxldCByZWdleERhdGEgPSBFTkRfUkVHRVhfQVJSW2ldLmV4ZWModGV4dClcbiAgICAgICAgaWYocmVnZXhEYXRhICE9PSBudWxsICYmIHJlZ2V4RGF0YS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBmb3VuZCA9IHRydWU7XG4gICAgICAgICAgICBzdGFydFBvc2l0aW9uID0gcmVnZXhEYXRhLmluZGV4XG4gICAgICAgICAgICBtYXRjaExlbmd0aCA9IHJlZ2V4RGF0YVswXS5sZW5ndGg7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgIH1cbiAgICBlbmRQb3NpdGlvbiA9IHN0YXJ0UG9zaXRpb24gKyBtYXRjaExlbmd0aDtcblxuICAgIHJldHVybiB7IGZvdW5kLCBzdGFydFBvc2l0aW9uLCBlbmRQb3NpdGlvbiwgbWF0Y2hMZW5ndGggfTtcbn1cblxuY29uc3QgQ09MX1JFR0VYX1NUUlM6IHN0cmluZ1tdID0gW1wiPT09ICpjb2x1bW4tZW5kICo9PT1cIixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIj09PSAqZW5kLWNvbHVtbiAqPT09XCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCI9PT0gKmNvbHVtbi1icmVhayAqPT09XCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCI9PT0gKmJyZWFrLWNvbHVtbiAqPT09XCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCItLS0gKmNvbHVtbi1lbmQgKi0tLVwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiLS0tICplbmQtY29sdW1uICotLS1cIixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIi0tLSAqY29sdW1uLWJyZWFrICotLS1cIixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIi0tLSAqYnJlYWstY29sdW1uICotLS1cIl07XG5jb25zdCBDT0xfUkVHRVhfQVJSOiBSZWdFeHBbXSA9IFtdO1xuZm9yKGxldCBpID0gMDsgaSA8IENPTF9SRUdFWF9TVFJTLmxlbmd0aDsgaSsrKSB7XG4gICAgQ09MX1JFR0VYX0FSUi5wdXNoKG5ldyBSZWdFeHAoQ09MX1JFR0VYX1NUUlNbaV0pKTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBjb250YWluc0NvbEVuZFRhZyh0ZXh0OiBzdHJpbmcpOiBib29sZWFuIHtcblxuICAgIGxldCBmb3VuZCA9IGZhbHNlO1xuICAgIGZvcihsZXQgaSA9IDA7IGk8IENPTF9SRUdFWF9BUlIubGVuZ3RoOyBpKyspIHtcblxuICAgICAgICBpZihDT0xfUkVHRVhfQVJSW2ldLnRlc3QodGV4dCkpIHtcbiAgICAgICAgICAgIGZvdW5kID0gdHJ1ZTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGZvdW5kO1xufVxuXG5jb25zdCBDT0xfRUxFTUVOVF9JTk5FUl9URVhUX1JFR0VYX1NUUlM6IHN0cmluZ1tdID0gW1wiPSAqY29sdW1uLWVuZCAqPVwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiPSAqZW5kLWNvbHVtbiAqPVwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiPSAqY29sdW1uLWJyZWFrICo9XCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCI9ICpicmVhay1jb2x1bW4gKj1cIl1cbmNvbnN0IENPTF9FTEVNRU5UX0lOTkVSX1RFWFRfUkVHRVhfQVJSOiBSZWdFeHBbXSA9IFtdO1xuZm9yKGxldCBpID0gMDsgaSA8IENPTF9FTEVNRU5UX0lOTkVSX1RFWFRfUkVHRVhfU1RSUy5sZW5ndGg7IGkrKykge1xuICAgIENPTF9FTEVNRU5UX0lOTkVSX1RFWFRfUkVHRVhfQVJSLnB1c2gobmV3IFJlZ0V4cChDT0xfRUxFTUVOVF9JTk5FUl9URVhUX1JFR0VYX1NUUlNbaV0pKTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBlbElubmVyVGV4dENvbnRhaW5zQ29sRW5kVGFnKHRleHQ6IHN0cmluZyk6IGJvb2xlYW4ge1xuXG4gICAgbGV0IGZvdW5kID0gZmFsc2U7XG4gICAgZm9yKGxldCBpID0gMDsgaTwgQ09MX0VMRU1FTlRfSU5ORVJfVEVYVF9SRUdFWF9BUlIubGVuZ3RoOyBpKyspIHtcblxuICAgICAgICBpZihDT0xfRUxFTUVOVF9JTk5FUl9URVhUX1JFR0VYX0FSUltpXS50ZXN0KHRleHQpKSB7XG4gICAgICAgICAgICBmb3VuZCA9IHRydWU7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBmb3VuZDtcbn1cblxuY29uc3QgQ09MX1NFVFRJTkdTX1JFR0VYX1NUUlMgPSBbXCJgYGBzZXR0aW5nc1wiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJgYGBjb2x1bW4tc2V0dGluZ3NcIixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiYGBgbXVsdGktY29sdW1uLXNldHRpbmdzXCJdO1xuY29uc3QgQ09MX1NFVFRJTkdTX1JFR0VYX0FSUjogUmVnRXhwW10gPSBbXTtcbmZvcihsZXQgaSA9IDA7IGkgPCBDT0xfU0VUVElOR1NfUkVHRVhfU1RSUy5sZW5ndGg7IGkrKykge1xuICAgIENPTF9TRVRUSU5HU19SRUdFWF9BUlIucHVzaChuZXcgUmVnRXhwKENPTF9TRVRUSU5HU19SRUdFWF9TVFJTW2ldKSk7XG59XG5leHBvcnQgZnVuY3Rpb24gY29udGFpbnNDb2xTZXR0aW5nc1RhZyh0ZXh0OiBzdHJpbmcpOiBib29sZWFuIHtcblxuICAgIGxldCBmb3VuZCA9IGZhbHNlO1xuICAgIGZvcihsZXQgaSA9IDA7IGk8IENPTF9TRVRUSU5HU19SRUdFWF9BUlIubGVuZ3RoOyBpKyspIHtcblxuICAgICAgICBpZihDT0xfU0VUVElOR1NfUkVHRVhfQVJSW2ldLnRlc3QodGV4dCkpIHtcbiAgICAgICAgICAgIGZvdW5kID0gdHJ1ZTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGZvdW5kO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZmluZFNldHRpbmdzQ29kZWJsb2NrKHRleHQ6IHN0cmluZyk6IHsgZm91bmQ6IGJvb2xlYW4sIHN0YXJ0UG9zaXRpb246IG51bWJlciwgZW5kUG9zaXRpb246IG51bWJlciwgbWF0Y2hMZW5ndGg6IG51bWJlciB9IHtcblxuICAgIGxldCBmb3VuZCA9IGZhbHNlO1xuICAgIGxldCBzdGFydFBvc2l0aW9uID0gLTE7XG4gICAgbGV0IGVuZFBvc2l0aW9uID0gLTFcbiAgICBsZXQgbWF0Y2hMZW5ndGggPSAwO1xuICAgIGZvcihsZXQgaSA9IDA7IGk8IENPTF9TRVRUSU5HU19SRUdFWF9BUlIubGVuZ3RoOyBpKyspIHtcblxuICAgICAgICBsZXQgcmVnZXhEYXRhID0gQ09MX1NFVFRJTkdTX1JFR0VYX0FSUltpXS5leGVjKHRleHQpXG4gICAgICAgIGlmKHJlZ2V4RGF0YSAhPT0gbnVsbCAmJiByZWdleERhdGEubGVuZ3RoID4gMCkge1xuXG4gICAgICAgICAgICBmb3VuZCA9IHRydWU7XG4gICAgICAgICAgICBzdGFydFBvc2l0aW9uID0gcmVnZXhEYXRhLmluZGV4XG4gICAgICAgICAgICBtYXRjaExlbmd0aCA9IHJlZ2V4RGF0YVswXS5sZW5ndGg7XG4gICAgICAgICAgICBlbmRQb3NpdGlvbiA9IHN0YXJ0UG9zaXRpb24gKyBtYXRjaExlbmd0aDtcblxuICAgICAgICAgICAgbGV0IHJlbWFpbmluZ1RleHQgPSB0ZXh0LnNsaWNlKGVuZFBvc2l0aW9uKVxuICAgICAgICAgICAgcmVnZXhEYXRhID0gQ09ERUJMT0NLX0VORF9SRUdFWC5leGVjKHJlbWFpbmluZ1RleHQpXG4gICAgICAgICAgICBpZihyZWdleERhdGEgIT09IG51bGwgJiYgcmVnZXhEYXRhLmxlbmd0aCA+IDApIHtcblxuICAgICAgICAgICAgICAgIGZvdW5kID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBlbmRQb3NpdGlvbiArPSByZWdleERhdGEuaW5kZXggKyByZWdleERhdGFbMF0ubGVuZ3RoIFxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4geyBmb3VuZCwgc3RhcnRQb3NpdGlvbiwgZW5kUG9zaXRpb24sIG1hdGNoTGVuZ3RoIH07XG59XG5cbmNvbnN0IFNUQVJUX0NPREVCTE9DS19SRUdFWF9BUlI6IFJlZ0V4cFtdID0gW1xuXCJgYGBtdWx0aS1jb2x1bW4tc3RhcnRcIixcblwiYGBgc3RhcnQtbXVsdGktY29sdW1uXCJcbl0ubWFwKCh2YWwpID0+IHtcbiAgICByZXR1cm4gbmV3IFJlZ0V4cCh2YWwpO1xufSlcbmV4cG9ydCBmdW5jdGlvbiBmaW5kU3RhcnRDb2RlYmxvY2sodGV4dDogc3RyaW5nKTogeyBmb3VuZDogYm9vbGVhbiwgc3RhcnRQb3NpdGlvbjogbnVtYmVyLCBlbmRQb3NpdGlvbjogbnVtYmVyLCBtYXRjaExlbmd0aDogbnVtYmVyIH0ge1xuXG4gICAgbGV0IGZvdW5kID0gZmFsc2U7XG4gICAgbGV0IHN0YXJ0UG9zaXRpb24gPSAtMTtcbiAgICBsZXQgZW5kUG9zaXRpb24gPSAtMVxuICAgIGxldCBtYXRjaExlbmd0aCA9IDA7XG4gICAgZm9yKGxldCBpID0gMDsgaTwgU1RBUlRfQ09ERUJMT0NLX1JFR0VYX0FSUi5sZW5ndGg7IGkrKykge1xuXG4gICAgICAgIGxldCByZWdleERhdGEgPSBTVEFSVF9DT0RFQkxPQ0tfUkVHRVhfQVJSW2ldLmV4ZWModGV4dClcbiAgICAgICAgaWYocmVnZXhEYXRhICE9PSBudWxsICYmIHJlZ2V4RGF0YS5sZW5ndGggPiAwKSB7XG5cbiAgICAgICAgICAgIGZvdW5kID0gdHJ1ZTtcbiAgICAgICAgICAgIHN0YXJ0UG9zaXRpb24gPSByZWdleERhdGEuaW5kZXhcbiAgICAgICAgICAgIG1hdGNoTGVuZ3RoID0gcmVnZXhEYXRhWzBdLmxlbmd0aDtcbiAgICAgICAgICAgIGVuZFBvc2l0aW9uID0gc3RhcnRQb3NpdGlvbiArIG1hdGNoTGVuZ3RoO1xuXG4gICAgICAgICAgICBsZXQgcmVtYWluaW5nVGV4dCA9IHRleHQuc2xpY2UoZW5kUG9zaXRpb24pXG4gICAgICAgICAgICByZWdleERhdGEgPSBDT0RFQkxPQ0tfRU5EX1JFR0VYLmV4ZWMocmVtYWluaW5nVGV4dClcbiAgICAgICAgICAgIGlmKHJlZ2V4RGF0YSAhPT0gbnVsbCAmJiByZWdleERhdGEubGVuZ3RoID4gMCkge1xuXG4gICAgICAgICAgICAgICAgZm91bmQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIGVuZFBvc2l0aW9uICs9IHJlZ2V4RGF0YS5pbmRleCArIHJlZ2V4RGF0YVswXS5sZW5ndGggXG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHsgZm91bmQsIHN0YXJ0UG9zaXRpb24sIGVuZFBvc2l0aW9uLCBtYXRjaExlbmd0aCB9O1xufVxuZXhwb3J0IGZ1bmN0aW9uIGNvbnRhaW5zU3RhcnRDb2RlQmxvY2sodGV4dDogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIGZpbmRTdGFydENvZGVibG9jayh0ZXh0KS5mb3VuZFxufVxuXG5leHBvcnQgZnVuY3Rpb24gY29udGFpbnNSZWdpb25TdGFydCh0ZXh0OiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gY29udGFpbnNTdGFydENvZGVCbG9jayh0ZXh0KSB8fCBjb250YWluc1N0YXJ0VGFnKHRleHQpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY291bnRTdGFydFRhZ3MoaW5pdGlhbFRleHQ6IHN0cmluZyk6IHsgbnVtYmVyT2ZUYWdzOiBudW1iZXIsIGtleXM6IHN0cmluZ1tdIH0ge1xuXG4gICAgbGV0IGtleXM6IHN0cmluZ1tdID0gW107XG4gICAgbGV0IHRleHQgPSBpbml0aWFsVGV4dFxuICAgIGxldCBzdGFydFRhZ0RhdGEgPSBmaW5kU3RhcnRUYWcodGV4dCk7XG4gICAgd2hpbGUoc3RhcnRUYWdEYXRhLmZvdW5kKSB7XG4gICAgICAgIFxuICAgICAgICAvLyBTbGljZSBvZmYgZXZlcnl0aGluZyBiZWZvcmUgdGhlIHRhZ1xuICAgICAgICB0ZXh0ID0gdGV4dC5zbGljZShzdGFydFRhZ0RhdGEuc3RhcnRQb3NpdGlvbik7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEdldCBqdXN0IHRoZSBzdGFydCB0YWcgbGluZSBhbmQgdGhlbiBzZXQgdGV4dCB0byBldmVyeXRoaW5nIGp1c3RcbiAgICAgICAgICogYWZ0ZXIgdGhlIHN0YXJ0IHRhZy5cbiAgICAgICAgICovXG4gICAgICAgIGxldCB0YWcgPSB0ZXh0LnNwbGl0KFwiXFxuXCIpWzBdO1xuICAgICAgICB0ZXh0ID0gdGV4dC5zbGljZSgxKTsgLy8gVGhpcyBtb3ZlcyB0aGUgdGV4dCAxIGNoYXJhY3RlciBzbyB3ZSBkb250IG1hdGNoIHRoZSBzYW1lIHRhZy5cblxuICAgICAgICAvLyBQYXJzZSBvdXQgdGhlIGtleSBhbmQgYXBwZW5kIHRvIHRoZSBsaXN0LlxuICAgICAgICBsZXQga2V5ID0gZ2V0U3RhcnRUYWdLZXkodGFnKTtcbiAgICAgICAgaWYoa2V5ID09PSBudWxsKSB7XG4gICAgICAgICAgICBrZXkgPSBcIlwiXG4gICAgICAgIH1cbiAgICAgICAga2V5cy5wdXNoKGtleSk7XG5cbiAgICAgICAgLy8gU2VhcmNoIGFnYWluIGZvciBhbm90aGVyIHRhZyBiZWZvcmUgbG9vcGluZy5cbiAgICAgICAgc3RhcnRUYWdEYXRhID0gZmluZFN0YXJ0VGFnKHRleHQpO1xuICAgIH1cblxuICAgIHRleHQgPSBpbml0aWFsVGV4dDtcbiAgICBzdGFydFRhZ0RhdGEgPSBmaW5kU3RhcnRDb2RlYmxvY2sodGV4dCk7XG4gICAgd2hpbGUoc3RhcnRUYWdEYXRhLmZvdW5kKSB7XG4gICAgICAgIFxuICAgICAgICBsZXQgc2V0dGluZ3NUZXh0ID0gdGV4dC5zbGljZShzdGFydFRhZ0RhdGEuc3RhcnRQb3NpdGlvbiwgc3RhcnRUYWdEYXRhLmVuZFBvc2l0aW9uKTtcbiAgICAgICAgdGV4dCA9IHRleHQuc2xpY2Uoc3RhcnRUYWdEYXRhLmVuZFBvc2l0aW9uKTtcblxuICAgICAgICBsZXQga2V5ID0gcGFyc2VTdGFydFJlZ2lvbkNvZGVCbG9ja0lEKHNldHRpbmdzVGV4dCk7XG4gICAgICAgIGlmKGtleSA9PT0gbnVsbCkge1xuICAgICAgICAgICAga2V5ID0gXCJcIlxuICAgICAgICB9XG4gICAgICAgIGtleXMucHVzaChrZXkpO1xuXG4gICAgICAgIC8vIFNlYXJjaCBhZ2FpbiBmb3IgYW5vdGhlciB0YWcgYmVmb3JlIGxvb3BpbmcuXG4gICAgICAgIHN0YXJ0VGFnRGF0YSA9IGZpbmRTdGFydENvZGVibG9jayh0ZXh0KTtcbiAgICB9XG5cbiAgICByZXR1cm4geyBudW1iZXJPZlRhZ3M6IGtleXMubGVuZ3RoLCBrZXlzIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRTdGFydEJsb2NrT3JDb2RlYmxvY2tBYm92ZUxpbmUobGluZXNBYm92ZUFycmF5OiBzdHJpbmdbXSk6IHsgXG5zdGFydEJsb2NrS2V5OiBzdHJpbmcsIFxubGluZXNBYm92ZUFycmF5OiBzdHJpbmdbXSB9IHwgbnVsbCB7XG5cbiAgICBsZXQgc3RhcnRCbG9jayA9IGdldFN0YXJ0QmxvY2tBYm92ZUxpbmUobGluZXNBYm92ZUFycmF5KTtcbiAgICBpZihzdGFydEJsb2NrICE9PSBudWxsKSB7XG4gICAgICAgIHJldHVybiBzdGFydEJsb2NrO1xuICAgIH1cblxuICAgIGxldCBjb2RlQmxvY2sgPSBnZXRTdGFydENvZGVCbG9ja0Fib3ZlTGluZShsaW5lc0Fib3ZlQXJyYXkpXG4gICAgaWYoY29kZUJsb2NrICE9PSBudWxsKSB7XG4gICAgICAgIHJldHVybiBjb2RlQmxvY2s7XG4gICAgfVxuICAgIHJldHVybiBudWxsXG59XG5cbi8qKlxuICogVGhpcyBmdW5jdGlvbiB3aWxsIGZpbHRlciBhIHNldCBvZiBzdHJpbmdzLCByZXR1cm5pbmcgYWxsIGl0ZW1zIHN0YXJ0aW5nXG4gKiBmcm9tIHRoZSBjbG9zZXN0IG9wZW4gc3RhcnQgdGFnIHRocm91Z2ggdGhlIGxhc3QgaXRlbSBpbiB0aGUgc2V0LiBcbiAqIFxuICogVGhlIGZ1bmN0aW9uIGZpbHRlcnMgb3V0IGFsbCBlbmQgdGFncyB0byBtYWtlIHN1cmUgdGhhdCB0aGUgc3RhcnQgdGFnIHdlIFxuICogZmluZCBpcyB0aGUgcHJvcGVyIHN0YXJ0IHRhZyBmb3IgdGhlIGxpc3Qgc2VudC4gXG4gKiBAcGFyYW0gbGluZXNBYm92ZUFycmF5IFxuICogQHJldHVybnMgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRTdGFydEJsb2NrQWJvdmVMaW5lKGxpbmVzQWJvdmVBcnJheTogc3RyaW5nW10pOiB7IHN0YXJ0QmxvY2tLZXk6IHN0cmluZywgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmVzQWJvdmVBcnJheTogc3RyaW5nW10gfSB8IG51bGwge1xuXG4gICAgLy8gUmVkdWNlIHRoZSBhcnJheSBkb3duIGludG8gYSBzaW5nbGUgc3RyaW5nIHNvIHRoYXQgd2UgY2FuXG4gICAgLy8gZWFzaWx5IFJlZ0V4IG92ZXIgdGhlIHN0cmluZyBhbmQgZmluZCB0aGUgaW5kaWNpZXMgd2UncmUgbG9va2luZyBmb3IuXG4gICAgbGV0IGxpbmVzQWJvdmVTdHIgPSBsaW5lc0Fib3ZlQXJyYXkucmVkdWNlKChwcmV2LCBjdXJyZW50KSA9PiB7XG4gICAgICAgIHJldHVybiBwcmV2ICsgXCJcXG5cIiAgKyBjdXJyZW50O1xuICAgIH0sIFwiXCIpO1xuXG4gICAgLypcbiAgICAgICAgKiBGaXJzdCB0aGluZyB3ZSBuZWVkIHRvIGRvIGlzIGNoZWNrIGlmIHRoZXJlIGFyZSBhbnkgZW5kIHRhZ3MgaW4gdGhlXG4gICAgICAgICogc2V0IG9mIHN0cmluZ3MgKHdoaWNoIGxvZ2ljYWxseSB3b3VsZCBjbG9zZSBzdGFydCB0YWdzIGFuZCB0aGVyZWZvcmVcbiAgICAgICAgKiB0aGUgc3RhcnQgdGFnIGl0IGNsb3NlcyBpcyBub3Qgd2hhdCB3ZSB3YW50KS4gSWYgdGhlcmUgYXJlIHdlIHdhbnQgdG8gXG4gICAgICAgICogc2xvd2x5IG5hcnJvdyBkb3duIG91ciBzZXQgb2Ygc3RyaW5ncyB1bnRpbCB0aGUgbGFzdCBlbmQgdGFnIGlzIFxuICAgICAgICAqIHJlbW92ZWQuIFRoaXMgbWFrZXMgaXQgZWFzaWVyIHRvIGZpbmQgdGhlIGNsb3Nlc3Qgb3BlbiBzdGFydCB0YWcgXG4gICAgICAgICogaW4gdGhlIGRhdGEuXG4gICAgICAgICovXG4gICAgbGV0IGVuZFRhZ1NlcmFjaERhdGEgPSBmaW5kRW5kVGFnKGxpbmVzQWJvdmVTdHIpO1xuICAgIHdoaWxlKGVuZFRhZ1NlcmFjaERhdGEuZm91bmQgPT09IHRydWUpIHtcblxuICAgICAgICAvLyBHZXQgdGhlIGluZGV4IG9mIHdoZXJlIHRoZSBmaXJzdCByZWdleCBtYXRjaCBpbiB0aGVcbiAgICAgICAgLy8gc3RyaW5nIGlzLiB0aGVuIHdlIHNsaWNlIGZyb20gMCB0byBpbmRleCBvZmYgb2YgdGhlIHN0cmluZ1xuICAgICAgICAvLyBzcGxpdCBpdCBieSBuZXdsaW5lLCBjdXQgb2ZmIHRoZSBmaXJzdCBsaW5lICh3aGljaCBhY3R1YWxseVxuICAgICAgICAvLyBjb250YWlucyB0aGUgcmVnZXgpIHRoZW4gcmVkdWNlIGJhY2sgZG93biB0byBhIHNpbmdsZSBzdHJpbmcuXG4gICAgICAgIC8vXG4gICAgICAgIC8vIFRPRE86IFRoaXMgY291bGQgYmUgc2ltcGxpZmllZCBpZiB3ZSBqdXN0IHNsaWNlIHRoZSB0ZXh0IGFmdGVyXG4gICAgICAgIC8vIHRoZSBlbmQgdGFnIGluc3RlYWQgb2YgdGhlIGJlZ2luaW5nLlxuICAgICAgICBsZXQgaW5kZXhPZlJlZ2V4ID0gZW5kVGFnU2VyYWNoRGF0YS5zdGFydFBvc2l0aW9uO1xuICAgICAgICBsaW5lc0Fib3ZlQXJyYXkgPSBsaW5lc0Fib3ZlU3RyLnNsaWNlKGluZGV4T2ZSZWdleCkuc3BsaXQoXCJcXG5cIikuc3BsaWNlKDEpXG4gICAgICAgIGxpbmVzQWJvdmVTdHIgPSBsaW5lc0Fib3ZlQXJyYXkucmVkdWNlKChwcmV2LCBjdXJyZW50KSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gcHJldiArIFwiXFxuXCIgICsgY3VycmVudDtcbiAgICAgICAgfSwgXCJcIik7XG4gICAgICAgIGVuZFRhZ1NlcmFjaERhdGEgPSBmaW5kRW5kVGFnKGxpbmVzQWJvdmVTdHIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE5vdyB3ZSBoYXZlIHRoZSBzZXQgb2YgbGluZXMgYWZ0ZXIgYWxsIG90aGVyIGVuZCB0YWdzLiBXZSBub3dcbiAgICAgKiBuZWVkIHRvIGNoZWNrIGlmIHRoZXJlIGlzIHN0aWxsIGEgc3RhcnQgdGFnIGxlZnQgaW4gdGhlIGRhdGEuIElmIFxuICAgICAqIHRoZXJlIGlzIG5vIHN0YXJ0IHRhZyB0aGVuIHdlIHdhbnQgdG8gcmV0dXJuIGFuIGVtcHR5IGFycmF5IGFuZCBlbXB0eSBcbiAgICAgKiBrZXkuXG4gICAgICovIFxuICAgIGxldCBzdGFydEJsb2NrS2V5ID0gXCJcIjtcbiAgICBsZXQgc3RhcnRUYWdTZWFyY2hEYXRhID0gZmluZFN0YXJ0VGFnKGxpbmVzQWJvdmVTdHIpO1xuICAgIGlmKHN0YXJ0VGFnU2VhcmNoRGF0YS5mb3VuZCA9PT0gZmFsc2UpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIGVsc2Uge1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBOb3cgd2Uga25vdyB0aGVyZSBpcyBhdCBsZWFzdCAxIHN0YXJ0IGtleSBsZWZ0LCBob3dldmVyIHRoZXJlXG4gICAgICAgICAqIG1heSBiZSBtdWx0aXBsZSBzdGFydCBrZXlzIGlmIHRoZSB1c2VyIGlzIG5vdCBjbG9zaW5nIHRoZWlyXG4gICAgICAgICAqIGJsb2Nrcy4gV2UgY3VycmVudGx5IGRvbnQgYWxsb3cgcmVjdXNpdmUgc3BsaXR0aW5nIHNvIHdlIFxuICAgICAgICAgKiB3YW50IHRvIGdldCB0aGUgbGFzdCBrZXkgaW4gb3VyIHJlbWFpbmluZyBzZXQuIFNhbWUgaWRlYSBhc1xuICAgICAgICAgKiBhYm92ZS5cbiAgICAgICAgICovXG4gICAgICAgIHdoaWxlKHN0YXJ0VGFnU2VhcmNoRGF0YS5mb3VuZCA9PT0gdHJ1ZSkge1xuXG4gICAgICAgICAgICAvLyBHZXQgdGhlIGluZGV4IG9mIHdoZXJlIHRoZSBmaXJzdCByZWdleCBtYXRjaCBpbiB0aGVcbiAgICAgICAgICAgIC8vIHN0cmluZyBpcy4gdGhlbiB3ZSBzbGljZSBmcm9tIDAgdG8gaW5kZXggb2ZmIG9mIHRoZSBzdHJpbmdcbiAgICAgICAgICAgIC8vIHNwbGl0IGl0IGJ5IG5ld2xpbmUsIGN1dCBvZmYgdGhlIGZpcnN0IGxpbmUgKHdoaWNoIGFjdHVhbGx5XG4gICAgICAgICAgICAvLyBjb250YWlucyB0aGUgcmVnZXgpIHRoZW4gcmVkdWNlIGJhY2sgZG93biB0byBhIHNpbmdsZSBzdHJpbmcuXG4gICAgICAgICAgICAvL1xuICAgICAgICAgICAgLy8gVE9ETzogVGhpcyBjb3VsZCBiZSBzaW1wbGlmaWVkIGlmIHdlIGp1c3Qgc2xpY2UgdGhlIHRleHQgYWZ0ZXJcbiAgICAgICAgICAgIC8vIHRoZSBlbmQgdGFnIGluc3RlYWQgb2YgdGhlIGJlZ2luaW5nLlxuICAgICAgICAgICAgbGV0IHN0YXJ0SW5kZXggPSBzdGFydFRhZ1NlYXJjaERhdGEuc3RhcnRQb3NpdGlvbjtcblxuICAgICAgICAgICAgbGluZXNBYm92ZUFycmF5ID0gbGluZXNBYm92ZVN0ci5zbGljZShzdGFydEluZGV4KS5zcGxpdChcIlxcblwiKVxuICAgICAgICAgICAgXG4gICAgICAgICAgICBsZXQgc3RhcnRUYWcgPSBsaW5lc0Fib3ZlQXJyYXlbMF07XG4gICAgICAgICAgICBsZXQga2V5ID0gZ2V0U3RhcnRUYWdLZXkoc3RhcnRUYWcpO1xuICAgICAgICAgICAgaWYoa2V5ICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgc3RhcnRCbG9ja0tleSA9IGtleTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbGluZXNBYm92ZUFycmF5ID0gbGluZXNBYm92ZUFycmF5LnNwbGljZSgxKVxuICAgICAgICAgICAgbGluZXNBYm92ZVN0ciA9IGxpbmVzQWJvdmVBcnJheS5yZWR1Y2UoKHByZXYsIGN1cnJlbnQpID0+IHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcHJldiArIFwiXFxuXCIgICsgY3VycmVudDtcbiAgICAgICAgICAgIH0sIFwiXCIpO1xuXG4gICAgICAgICAgICBzdGFydFRhZ1NlYXJjaERhdGEgPSBmaW5kU3RhcnRUYWcobGluZXNBYm92ZVN0cik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZihzdGFydEJsb2NrS2V5ID09PSBcIlwiKSB7XG5cbiAgICAgICAgbGV0IGNvZGVCbG9ja0RhdGEgPSBwYXJzZUNvZGVCbG9ja1N0YXJ0KGxpbmVzQWJvdmVBcnJheSlcbiAgICAgICAgaWYoY29kZUJsb2NrRGF0YSAhPT0gbnVsbCkge1xuICAgICAgICAgICAgXG4gICAgICAgICAgICBzdGFydEJsb2NrS2V5ID0gY29kZUJsb2NrRGF0YS5pZDtcblxuICAgICAgICAgICAgaWYoY29kZUJsb2NrRGF0YS5pbmRleCA+IDApIHtcbiAgICAgICAgICAgICAgICBsaW5lc0Fib3ZlQXJyYXkgPSBsaW5lc0Fib3ZlQXJyYXkuc2xpY2UoY29kZUJsb2NrRGF0YS5pbmRleCArIDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHsgc3RhcnRCbG9ja0tleSwgbGluZXNBYm92ZUFycmF5IH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRTdGFydENvZGVCbG9ja0Fib3ZlTGluZShsaW5lc0Fib3ZlQXJyYXk6IHN0cmluZ1tdKTogeyBcbiAgICBzdGFydEJsb2NrS2V5OiBzdHJpbmcsIFxuICAgIGxpbmVzQWJvdmVBcnJheTogc3RyaW5nW10gfSB8IG51bGwge1xuICAgIFxuICAgIGxldCBsaW5lc0Fib3ZlU3RyID0gbGluZXNBYm92ZUFycmF5LnJlZHVjZSgocHJldiwgY3VycmVudCkgPT4ge1xuICAgICAgICByZXR1cm4gcHJldiArIFwiXFxuXCIgICsgY3VycmVudDtcbiAgICB9LCBcIlwiKTtcblxuICAgIC8qXG4gICAgICogRmlyc3QgdGhpbmcgd2UgbmVlZCB0byBkbyBpcyBjaGVjayBpZiB0aGVyZSBhcmUgYW55IGVuZCB0YWdzIGluIHRoZVxuICAgICAqIHNldCBvZiBzdHJpbmdzICh3aGljaCBsb2dpY2FsbHkgd291bGQgY2xvc2Ugc3RhcnQgdGFncyBhbmQgdGhlcmVmb3JlXG4gICAgICogdGhlIHN0YXJ0IHRhZyBpdCBjbG9zZXMgaXMgbm90IHdoYXQgd2Ugd2FudCkuIElmIHRoZXJlIGFyZSB3ZSB3YW50IHRvIFxuICAgICAqIHNsb3dseSBuYXJyb3cgZG93biBvdXIgc2V0IG9mIHN0cmluZ3MgdW50aWwgdGhlIGxhc3QgZW5kIHRhZyBpcyBcbiAgICAgKiByZW1vdmVkLiBUaGlzIG1ha2VzIGl0IGVhc2llciB0byBmaW5kIHRoZSBjbG9zZXN0IG9wZW4gc3RhcnQgdGFnIFxuICAgICAqIGluIHRoZSBkYXRhLlxuICAgICAqL1xuICAgIGxldCBlbmRUYWdTZXJhY2hEYXRhID0gZmluZEVuZFRhZyhsaW5lc0Fib3ZlU3RyKTtcbiAgICB3aGlsZShlbmRUYWdTZXJhY2hEYXRhLmZvdW5kID09PSB0cnVlKSB7XG5cbiAgICAgICAgLy8gR2V0IHRoZSBpbmRleCBvZiB3aGVyZSB0aGUgZmlyc3QgcmVnZXggbWF0Y2ggaW4gdGhlXG4gICAgICAgIC8vIHN0cmluZyBpcy4gdGhlbiB3ZSBzbGljZSBmcm9tIDAgdG8gaW5kZXggb2ZmIG9mIHRoZSBzdHJpbmdcbiAgICAgICAgLy8gc3BsaXQgaXQgYnkgbmV3bGluZSwgY3V0IG9mZiB0aGUgZmlyc3QgbGluZSAod2hpY2ggYWN0dWFsbHlcbiAgICAgICAgLy8gY29udGFpbnMgdGhlIHJlZ2V4KSB0aGVuIHJlZHVjZSBiYWNrIGRvd24gdG8gYSBzaW5nbGUgc3RyaW5nLlxuICAgICAgICBsaW5lc0Fib3ZlU3RyID0gbGluZXNBYm92ZVN0ci5zbGljZShlbmRUYWdTZXJhY2hEYXRhLmVuZFBvc2l0aW9uKTtcbiAgICAgICAgZW5kVGFnU2VyYWNoRGF0YSA9IGZpbmRFbmRUYWcobGluZXNBYm92ZVN0cik7XG4gICAgfVxuXG4gICAgbGV0IHN0YXJ0Q29kZUJsb2NrRGF0YSA9IGZpbmRTdGFydENvZGVibG9jayhsaW5lc0Fib3ZlU3RyKTtcbiAgICBsZXQgY29kZUJsb2NrVGV4dCA9IGxpbmVzQWJvdmVTdHIuc2xpY2Uoc3RhcnRDb2RlQmxvY2tEYXRhLnN0YXJ0UG9zaXRpb24sIHN0YXJ0Q29kZUJsb2NrRGF0YS5lbmRQb3NpdGlvbilcblxuICAgIGxldCBzdGFydEJsb2NrS2V5ID0gXCJcIiAgICBcbiAgICBpZihzdGFydENvZGVCbG9ja0RhdGEuZm91bmQgPT09IGZhbHNlKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICBlbHNlIHtcblxuICAgICAgICAvKipcbiAgICAgICAgICogTm93IHdlIGtub3cgdGhlcmUgaXMgYXQgbGVhc3QgMSBzdGFydCBrZXkgbGVmdCwgaG93ZXZlciB0aGVyZVxuICAgICAgICAgKiBtYXkgYmUgbXVsdGlwbGUgc3RhcnQga2V5cyBpZiB0aGUgdXNlciBpcyBub3QgY2xvc2luZyB0aGVpclxuICAgICAgICAgKiBibG9ja3MuIFdlIGN1cnJlbnRseSBkb250IGFsbG93IHJlY3VzaXZlIHNwbGl0dGluZyBzbyB3ZSBcbiAgICAgICAgICogd2FudCB0byBnZXQgdGhlIGxhc3Qga2V5IGluIG91ciByZW1haW5pbmcgc2V0LiBTYW1lIGlkZWEgYXNcbiAgICAgICAgICogYWJvdmUuXG4gICAgICAgICAqL1xuICAgICAgICB3aGlsZShzdGFydENvZGVCbG9ja0RhdGEuZm91bmQgPT09IHRydWUpIHtcblxuICAgICAgICAgICAgLy8gR2V0IHRoZSBpbmRleCBvZiB3aGVyZSB0aGUgZmlyc3QgcmVnZXggbWF0Y2ggaW4gdGhlXG4gICAgICAgICAgICAvLyBzdHJpbmcgaXMuIHRoZW4gd2Ugc2xpY2UgZnJvbSAwIHRvIGluZGV4IG9mZiBvZiB0aGUgc3RyaW5nXG4gICAgICAgICAgICAvLyBzcGxpdCBpdCBieSBuZXdsaW5lLCBjdXQgb2ZmIHRoZSBmaXJzdCBsaW5lICh3aGljaCBhY3R1YWxseVxuICAgICAgICAgICAgLy8gY29udGFpbnMgdGhlIHJlZ2V4KSB0aGVuIHJlZHVjZSBiYWNrIGRvd24gdG8gYSBzaW5nbGUgc3RyaW5nLlxuXG4gICAgICAgICAgICBjb2RlQmxvY2tUZXh0ID0gbGluZXNBYm92ZVN0ci5zbGljZShzdGFydENvZGVCbG9ja0RhdGEuc3RhcnRQb3NpdGlvbiwgc3RhcnRDb2RlQmxvY2tEYXRhLmVuZFBvc2l0aW9uKVxuICAgICAgICAgICAgc3RhcnRCbG9ja0tleSA9IHBhcnNlU3RhcnRSZWdpb25Db2RlQmxvY2tJRChjb2RlQmxvY2tUZXh0KVxuXG4gICAgICAgICAgICBsaW5lc0Fib3ZlU3RyID0gbGluZXNBYm92ZVN0ci5zbGljZShzdGFydENvZGVCbG9ja0RhdGEuZW5kUG9zaXRpb24pO1xuICAgICAgICAgICAgc3RhcnRDb2RlQmxvY2tEYXRhID0gZmluZFN0YXJ0Q29kZWJsb2NrKGxpbmVzQWJvdmVTdHIpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgbGV0IHJldExpbmVzQWJvdmVBcnJheSA9IGxpbmVzQWJvdmVTdHIuc3BsaXQoXCJcXG5cIik7XG4gICAgcmV0dXJuIHsgc3RhcnRCbG9ja0tleSwgbGluZXNBYm92ZUFycmF5OiByZXRMaW5lc0Fib3ZlQXJyYXkgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldEVuZEJsb2NrQmVsb3cobGluZXNCZWxvdzogc3RyaW5nW10pOiBzdHJpbmdbXSB7XG5cbiAgICAvLyBSZWR1Y2UgdGhlIGFycmF5IGRvd24gaW50byBhIHNpbmdsZSBzdHJpbmcgc28gdGhhdCB3ZSBjYW5cbiAgICAvLyBlYXNpbHkgUmVnRXggb3ZlciB0aGUgc3RyaW5nIGFuZCBmaW5kIHRoZSBpbmRpY2llcyB3ZSdyZSBsb29raW5nIGZvci5cbiAgICBsZXQgbGluZXNCZWxvd1N0ciA9IGxpbmVzQmVsb3cucmVkdWNlKChwcmV2LCBjdXJyZW50KSA9PiB7XG4gICAgICAgIHJldHVybiBwcmV2ICsgXCJcXG5cIiAgKyBjdXJyZW50O1xuICAgIH0sIFwiXCIpO1xuICAgIGxldCBlbmRUYWdTZXJhY2hEYXRhID0gZmluZEVuZFRhZyhsaW5lc0JlbG93U3RyKTtcbiAgICBsZXQgc3RhcnRUYWdTZWFyY2hEYXRhID0gZmluZFN0YXJ0VGFnKGxpbmVzQmVsb3dTdHIpO1xuXG4gICAgbGV0IHNsaWNlRW5kSW5kZXggPSAtMTsgLy8gSWYgbmVpdGhlciBzdGFydCBvciBlbmQgZm91bmQgd2UgcmV0dXJuIHRoZSBlbnRpcmUgYXJyYXkuXG4gICAgaWYoZW5kVGFnU2VyYWNoRGF0YS5mb3VuZCA9PT0gdHJ1ZSAmJiBzdGFydFRhZ1NlYXJjaERhdGEuZm91bmQgPT09IGZhbHNlKSB7XG5cbiAgICAgICAgc2xpY2VFbmRJbmRleCA9IGVuZFRhZ1NlcmFjaERhdGEuc3RhcnRQb3NpdGlvbjtcbiAgICB9XG4gICAgZWxzZSBpZihlbmRUYWdTZXJhY2hEYXRhLmZvdW5kID09PSBmYWxzZSAmJiBzdGFydFRhZ1NlYXJjaERhdGEuZm91bmQgPT09IHRydWUpIHtcblxuICAgICAgICBzbGljZUVuZEluZGV4ID0gc3RhcnRUYWdTZWFyY2hEYXRhLnN0YXJ0UG9zaXRpb247XG4gICAgfVxuICAgIGVsc2UgaWYoZW5kVGFnU2VyYWNoRGF0YS5mb3VuZCA9PT0gdHJ1ZSAmJiBzdGFydFRhZ1NlYXJjaERhdGEuZm91bmQgPT09IHRydWUpIHtcblxuICAgICAgICBzbGljZUVuZEluZGV4ID0gZW5kVGFnU2VyYWNoRGF0YS5zdGFydFBvc2l0aW9uO1xuICAgICAgICBpZihzdGFydFRhZ1NlYXJjaERhdGEuc3RhcnRQb3NpdGlvbiA8IGVuZFRhZ1NlcmFjaERhdGEuc3RhcnRQb3NpdGlvbikge1xuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIElmIHdlIGZvdW5kIGEgc3RhcnQgdGFnIGJlZm9yZSBhbiBlbmQgdGFnIHdlIHdhbnQgdG8gdXNlIHRoZSBzdGFydCB0YWdcbiAgICAgICAgICAgICAqIG91ciBjdXJyZW50IGJsb2NrIGlzIG5vdCBwcm9wZXJseSBlbmRlZCBhbmQgd2UgdXNlIHRoZSBuZXh0IHN0YXJ0IHRhZyBcbiAgICAgICAgICAgICAqIGFzIG91ciBsaW1pdFxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBzbGljZUVuZEluZGV4ID0gc3RhcnRUYWdTZWFyY2hEYXRhLnN0YXJ0UG9zaXRpb247XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gbGluZXNCZWxvdy5zbGljZSgwLCBzbGljZUVuZEluZGV4KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldFN0YXJ0VGFnS2V5KHN0YXJ0VGFnOiBzdHJpbmcpOiBzdHJpbmcgfCBudWxsIHtcblxuICAgIGxldCBrZXlTcGxpdCA9IHN0YXJ0VGFnLnNwbGl0KFwiOlwiKTtcbiAgICBpZihrZXlTcGxpdC5sZW5ndGggPiAxKXtcbiAgICAgICAgcmV0dXJuIGtleVNwbGl0WzFdLnJlcGxhY2UoXCIgXCIsIFwiXCIpXG4gICAgfVxuXG4gICAgcmV0dXJuIG51bGw7XG59XG5cblxuY29uc3QgVEFCX0hFQURFUl9FTkRfUkVHRVhfU1RSID0gXCJeYGBgJFwiO1xuY29uc3QgVEFCX0hFQURFUl9FTkRfUkVHRVg6IFJlZ0V4cCA9IG5ldyBSZWdFeHAoVEFCX0hFQURFUl9FTkRfUkVHRVhfU1RSKTtcbmV4cG9ydCBmdW5jdGlvbiBwYXJzZUNvZGVCbG9ja1N0YXJ0KGNvZGVCbG9ja0xpbmVzOiBzdHJpbmdbXSk6IHsgaWQ6IHN0cmluZywgaW5kZXg6IG51bWJlcn0gfCBudWxsIHtcblxuICAgIGxldCBpZCA9IG51bGw7XG4gICAgZm9yKGxldCBpID0gMDsgaSA8IGNvZGVCbG9ja0xpbmVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGxldCBsaW5lID0gY29kZUJsb2NrTGluZXNbaV07XG5cbiAgICAgICAgaWYoaWQgPT09IG51bGwpIHtcbiAgICAgICAgICAgIGxldCBrZXkgPSBsaW5lLnNwbGl0KFwiOlwiKVswXTtcbiAgICAgICAgICAgIGlmKGtleS50b0xvd2VyQ2FzZSgpID09PSBcInJlZ2lvbiBpZFwiKSB7XG4gICAgICAgICAgICAgICAgaWQgPSBsaW5lLnNwbGl0KFwiOlwiKVsxXS50cmltKClcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGlmKFRBQl9IRUFERVJfRU5EX1JFR0VYLnRlc3QobGluZSkpIHtcblxuICAgICAgICAgICAgICAgIHJldHVybiB7IGlkOiBpZCwgaW5kZXg6IGkgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmKGlkID09PSBudWxsKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgcmV0dXJuIHsgaWQ6IGlkLCBpbmRleDogLTEgfVxuICAgIH1cbn1cbmNvbnN0IENPREVCTE9DS19FTkRfUkVHRVhfU1RSID0gXCJgYGBcIjtcbmNvbnN0IENPREVCTE9DS19FTkRfUkVHRVg6IFJlZ0V4cCA9IG5ldyBSZWdFeHAoQ09ERUJMT0NLX0VORF9SRUdFWF9TVFIpO1xuZXhwb3J0IGZ1bmN0aW9uIGZpbmRFbmRPZkNvZGVCbG9jayh0ZXh0OiBzdHJpbmcpOiB7IGZvdW5kOiBib29sZWFuLCBzdGFydFBvc2l0aW9uOiBudW1iZXIsIGVuZFBvc2l0aW9uOiBudW1iZXIsIG1hdGNoTGVuZ3RoOiBudW1iZXIgfSB7XG5cbiAgICBsZXQgZm91bmQgPSBmYWxzZTtcbiAgICBsZXQgc3RhcnRQb3NpdGlvbiA9IC0xO1xuICAgIGxldCBtYXRjaExlbmd0aCA9IDA7XG4gICAgbGV0IGVuZFBvc2l0aW9uID0gLTE7XG5cbiAgICBsZXQgcmVnZXhEYXRhID0gQ09ERUJMT0NLX0VORF9SRUdFWC5leGVjKHRleHQpXG4gICAgaWYocmVnZXhEYXRhICE9PSBudWxsICYmIHJlZ2V4RGF0YS5sZW5ndGggPiAwKSB7XG4gICAgICAgIGZvdW5kID0gdHJ1ZTtcbiAgICAgICAgc3RhcnRQb3NpdGlvbiA9IHJlZ2V4RGF0YS5pbmRleFxuICAgICAgICBtYXRjaExlbmd0aCA9IHJlZ2V4RGF0YVswXS5sZW5ndGhcbiAgICB9XG4gICAgZW5kUG9zaXRpb24gPSBzdGFydFBvc2l0aW9uICsgbWF0Y2hMZW5ndGg7XG5cbiAgICByZXR1cm4geyBmb3VuZCwgc3RhcnRQb3NpdGlvbiwgZW5kUG9zaXRpb24sIG1hdGNoTGVuZ3RoIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZUNvZGVCbG9ja1NldHRpbmdzKGNvZGVCbG9ja0xpbmVzOiBzdHJpbmdbXSk6IHN0cmluZyB7XG5cbiAgICBsZXQgc2V0dGluZ3NMaW5lcyA9IFtdO1xuICAgIGZvcihsZXQgaSA9IDA7IGkgPCBjb2RlQmxvY2tMaW5lcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBsZXQgbGluZSA9IGNvZGVCbG9ja0xpbmVzW2ldO1xuXG4gICAgICAgIGxldCBrZXkgPSBsaW5lLnNwbGl0KFwiOlwiKVswXTtcbiAgICAgICAgaWYoa2V5LnRvTG93ZXJDYXNlKCkgIT09IFwicmVnaW9uIGlkXCIpIHtcbiAgICAgICAgICAgIHNldHRpbmdzTGluZXMucHVzaChsaW5lKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBzZXR0aW5nc0xpbmVzLmpvaW4oXCJcXG5cIik7XG59IiwiLypcbiAqIEZpbGVuYW1lOiBtdWx0aS1jb2x1bW4tbWFya2Rvd24vc3JjL3V0aWxpdGllcy91dGlscy50c1xuICogQ3JlYXRlZCBEYXRlOiBUdWVzZGF5LCBKYW51YXJ5IDMwdGggMjAyMiwgNDowMjoxOSBwbVxuICogQXV0aG9yOiBDYW1lcm9uIFJvYmluc29uXG4gKiBcbiAqIENvcHlyaWdodCAoYykgMjAyMiBDYW1lcm9uIFJvYmluc29uXG4gKi9cblxuaW1wb3J0IHsgV29ya3NwYWNlTGVhZiB9IGZyb20gXCJvYnNpZGlhblwiO1xuXG5leHBvcnQgZnVuY3Rpb24gZ2V0VUlEKGxlbmd0aDogbnVtYmVyID0gMTApOiBzdHJpbmcge1xuXG4gICAgaWYobGVuZ3RoID4gMTApIHtcbiAgICAgICAgbGVuZ3RoID0gMTA7XG4gICAgfVxuICAgIGxldCBVSUQgPSBNYXRoLnJhbmRvbSgpLnRvU3RyaW5nKDM2KS5zdWJzdHJpbmcoMik7XG4gICAgVUlEID0gVUlELnNsaWNlKDAsIGxlbmd0aCk7XG4gICAgXG4gICAgcmV0dXJuIFVJRDtcbn1cblxuLyoqXG4gKiBCRlMgb24gdGhlIGNoaWxkIG5vZGVzIG9mIHRoZSBwYXNzZWQgZWxlbWVudCBzZWFyY2hpbmcgZm9yIHRoZSBmaXJzdCBpbnN0YW5jZSBvZiB0aGVcbiAqIG5vZGUgdHlwZSBwYXNzZWQuIFJldHVybmluZyB0aGUgZWxlbWVudCBmb3VuZCBvciBudWxsIGlmIG5vbmUgZm91bmQuXG4gKiBcbiAqIEBwYXJhbSByb290IFxuICogQHBhcmFtIG5vZGVUeXBlTmFtZVxuICogQHJldHVybnMgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZWFyY2hDaGlsZHJlbkZvck5vZGVUeXBlKHJvb3Q6IEhUTUxFbGVtZW50LCBub2RlVHlwZU5hbWU6IHN0cmluZyk6IEhUTUxFbGVtZW50IHwgbnVsbCB7XG5cbiAgICBub2RlVHlwZU5hbWUgPSBub2RlVHlwZU5hbWUudG9Mb3dlckNhc2UoKTtcbiAgICBcbiAgICBsZXQgcXVldWU6IEhUTUxFbGVtZW50W10gPSBbcm9vdF1cbiAgICB3aGlsZShxdWV1ZS5sZW5ndGggPiAwKXtcbiAgICAgICAgXG4gICAgICAgIGZvcihsZXQgaSA9IDA7IGkgPCBxdWV1ZS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgXG4gICAgICAgICAgICBsZXQgbm9kZSA9IHF1ZXVlLnNoaWZ0KClcblxuICAgICAgICAgICAgbGV0IG5vZGVOYW1lID0gbm9kZS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpXG4gICAgICAgICAgICBpZihub2RlTmFtZSA9PT0gbm9kZVR5cGVOYW1lKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG5vZGUgYXMgSFRNTEVsZW1lbnQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZvcihsZXQgaSA9IDA7IGkgPCBub2RlLmNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgcXVldWUucHVzaChub2RlLmNoaWxkcmVuW2ldIGFzIEhUTUxFbGVtZW50KVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG51bGw7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRGaWxlU291cmNlTW9kZShzb3VyY2VQYXRoOiBzdHJpbmcpOiBzdHJpbmcge1xuXG4gICAgbGV0IGZpbGVMZWFmID0gZ2V0RmlsZUxlYWYoc291cmNlUGF0aCk7XG4gICAgaWYoZmlsZUxlYWYgPT09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIFwiXCI7XG4gICAgfVxuICAgIHJldHVybiBmaWxlTGVhZi5nZXRWaWV3U3RhdGUoKS5zdGF0ZS5tb2RlO1xufVxuZXhwb3J0IGZ1bmN0aW9uIGdldExlYWZTb3VyY2VNb2RlKGZpbGVMZWFmOiBXb3Jrc3BhY2VMZWFmKTogc3RyaW5nIHtcblxuICAgIHJldHVybiBmaWxlTGVhZi5nZXRWaWV3U3RhdGUoKS5zdGF0ZS5tb2RlO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZmlsZVN0aWxsSW5WaWV3KHNvdXJjZVBhdGg6IHN0cmluZyk6Ym9vbGVhbiB7XG5cbiAgICBsZXQgZmlsZUxlYWYgPSBnZXRGaWxlTGVhZihzb3VyY2VQYXRoKTtcbiAgICBpZihmaWxlTGVhZiA9PT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0RmlsZUxlYWYoc291cmNlUGF0aDogc3RyaW5nKTogV29ya3NwYWNlTGVhZiB8IG51bGwge1xuXG4gICAgbGV0IG1hcmtkb3duTGVhdmVzID0gYXBwLndvcmtzcGFjZS5nZXRMZWF2ZXNPZlR5cGUoXCJtYXJrZG93blwiKTtcbiAgICBpZihtYXJrZG93bkxlYXZlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgZm9yKGxldCBpID0gMDsgaSA8IG1hcmtkb3duTGVhdmVzLmxlbmd0aDsgaSsrKSB7XG5cbiAgICAgICAgaWYobWFya2Rvd25MZWF2ZXNbaV0uZ2V0Vmlld1N0YXRlKCkuc3RhdGUuZmlsZSA9PT0gc291cmNlUGF0aCkge1xuICAgICAgICAgICAgcmV0dXJuIG1hcmtkb3duTGVhdmVzW2ldO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG51bGw7XG59IiwiaW1wb3J0IHsgc2VhcmNoQ2hpbGRyZW5Gb3JOb2RlVHlwZSB9IGZyb20gXCIuL3V0aWxzXCI7XG5cbmV4cG9ydCBlbnVtIEVsZW1lbnRSZW5kZXJUeXBlIHtcbiAgICB1bmRlZmluZWQsXG4gICAgbm9ybWFsUmVuZGVyLFxuICAgIHNwZWNpYWxSZW5kZXIsXG4gICAgc3BlY2lhbFNpbmdsZUVsZW1lbnRSZW5kZXIsXG4gICAgY2FudmFzUmVuZGVyRWxlbWVudCxcbiAgICB1blJlbmRlcmVkXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRFbGVtZW50UmVuZGVyVHlwZShlbGVtZW50OiBIVE1MRWxlbWVudCk6IEVsZW1lbnRSZW5kZXJUeXBlIHtcblxuICAgIC8qKlxuICAgICAqIFRoZSBEYXRhdmlldyBwbHVnaW4gbmVlZHMgdG8gYmUgY29uc3RhbnRseSBjaGVja2VkIGlmIHRoZSBjbG9uZSBzaG91bGQgYmVcbiAgICAgKiB1cGRhdGVkIGJ1dCBzaG91bGQgbm90IGFsd2F5cyB1cGRhdGUgdGhlIFwiZHVhbCByZW5kZXJcIiBhc3BlY3QsIHNvIHdlIGFkZFxuICAgICAqIGEgc3BlY2lhbCBjYXNlIGZvciB0aGF0IHBsdWdpbiBhbmQgbWF5YmUgb3RoZXJzIGluIHRoZSBmdXR1cmUuXG4gICAgICovXG4gICAgaWYoaGFzRGF0YXZpZXcoZWxlbWVudCkgPT09IHRydWUpIHtcbiAgICAgICAgcmV0dXJuIEVsZW1lbnRSZW5kZXJUeXBlLnNwZWNpYWxTaW5nbGVFbGVtZW50UmVuZGVyO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNvbWUgdHlwZXMgb2YgY29udGVudCBhcmUgcmVuZGVyZWQgaW4gY2FudmFzZXMgd2hpY2ggYXJlIG5vdCByZW5kZXJlZCBwcm9wZXJseVxuICAgICAqIHdoZW4gd2UgY2xvbmUgdGhlIG9yaWdpbmFsIG5vZGUuIEhlcmUgd2UgYXJlIGZsYWdnaW5nIHRoZSBlbGVtZW50IGFzIGEgY2FudmFzXG4gICAgICogZWxlbWVudCBzbyB3ZSBjYW4gY2xvbmUgdGhlIGNhbnZhcyB0byBhIGNvcHkgZWxlbWVudCB3aXRoaW4gdGhlIHJlZ2lvbi5cbiAgICAgKiBcbiAgICAgKi9cbiAgICBpZiggaGFzRGF0YXZpZXdKUyhlbGVtZW50KSA9PT0gdHJ1ZSkge1xuICAgICAgICByZXR1cm4gRWxlbWVudFJlbmRlclR5cGUuY2FudmFzUmVuZGVyRWxlbWVudDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBMb29rIGZvciBzcGVjaWZpYyBraW5kcyBvZiBlbGVtZW50cyBieSB0aGVpciBDU1MgY2xhc3MgbmFtZXMgaGVyZS4gVGhlc2UgXG4gICAgICogYXJlIGdvaW5nIHRvIGJlIGJyaXR0bGUgbGlua3MgYXMgdGhleSByZWx5IG9uIG90aGVyIHBsdWdpbiBkZWZpbml0aW9ucyBidXRcbiAgICAgKiBhcyB0aGlzIGlzIG9ubHkgYWRkaW5nIGluIGV4dHJhIGNvbXBhdGFiaWxpdHkgdG8gdGhlIHBsdWdpbnMgZGVmaW5lZCBoZXJlIFxuICAgICAqIGl0IHNob3VsZCBiZSBvay5cbiAgICAgKiBcbiAgICAgKiBUaGVzZSBtYXkgYmUgY2xhc3NlcyBvbiBvbmUgb2YgdGhlIHNpbXBsZSBlbGVtZW50cyAoc3VjaCBhcyBhIHBhcmFncmFwaClcbiAgICAgKiB0aGF0IHdlIHNlYXJjaCBmb3IgYmVsb3cgc28gbmVlZCB0byBsb29rIGZvciB0aGVzZSBmaXJzdC5cbiAgICAgKi9cbiAgICBpZihoYXNEaWNlUm9sbGVyKGVsZW1lbnQpID09PSB0cnVlIHx8XG4gICAgICAgaGFzQ29weUJ1dHRvbihlbGVtZW50KSA9PT0gdHJ1ZSB8fFxuICAgICAgIGhhc0FkbW9uaXRpb25Gb2xkKGVsZW1lbnQpID09PSB0cnVlKSB7XG5cbiAgICAgICAgcmV0dXJuIEVsZW1lbnRSZW5kZXJUeXBlLnNwZWNpYWxSZW5kZXJcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIGNoZWNrcyBmb3Igc3BlY2lhbCB0eXBlcyBvZiBlbGVtZW50cyB0aGF0IHNob3VsZCBiZSByZW5kZXJlZCBub3JtYWxseS4gSXNcbiAgICAgKiBzbGlnaHRseSByZWR1bmRhbnQgd2l0aCBuZXh0IGNoZWNrIGJ1dCBkaWZmZXJlbnRpYXRlcyBiZXR3ZWVuIHR5cGVzIG9mIGVtZW50cyBcbiAgICAgKiBiZWluZyBjaGVja2VkLlxuICAgICAqL1xuICAgIGlmKGhhc0FkbW9uaXRpb24oZWxlbWVudCkgPT09IHRydWUgfHxcbiAgICAgICBpc0lGcmFtZShlbGVtZW50KSA9PT0gdHJ1ZSkge1xuICAgICAgICBcbiAgICAgICAgcmV0dXJuIEVsZW1lbnRSZW5kZXJUeXBlLm5vcm1hbFJlbmRlclxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIElmIHdlIGRpZG50IGZpbmQgYSBzcGVjaWFsIGVsZW1lbnQgd2Ugd2FudCB0byBjaGVjayBmb3Igc2ltcGxlIGVsZW1lbnRzXG4gICAgICogc3VjaCBhcyBwYXJhZ3JhcGhzIG9yIGxpc3RzLiBJbiB0aGUgY3VycmVudCBpbXBsZW1lbnRhdGlvbiB3ZSBvbmx5IHNldCB1cFxuICAgICAqIHRoZSBzcGVjaWFsIGNhc2UgZm9yIFwic3BlY2lhbFJlbmRlclwiIGVsZW1lbnRzIHNvIHRoaXMgKnNob3VsZCogYmUgc2F2aW5nXG4gICAgICogc29tZSByZW5kZXJpbmcgdGltZSBieSBzZXR0aW5nIHRoZXNlIHRhZ3MgcHJvcGVybHkuXG4gICAgICovXG4gICAgaWYoaGFzUGFyYWdyYXBoKGVsZW1lbnQpIHx8IFxuICAgICAgIGhhc0hlYWRlcihlbGVtZW50KSAgICB8fFxuICAgICAgIGhhc0xpc3QoZWxlbWVudCkgfHxcbiAgICAgICBpc0hvcml6b250YWxSdWxlKGVsZW1lbnQpIHx8XG4gICAgICAgaXNUYWJsZShlbGVtZW50KSkge1xuXG4gICAgICAgIHJldHVybiBFbGVtZW50UmVuZGVyVHlwZS5ub3JtYWxSZW5kZXI7XG4gICAgfVxuXG4gICAgLy8gSWYgc3RpbGwgbm90aGluZyBmb3VuZCB3ZSByZXR1cm4gb3RoZXIgYXMgdGhlIGRlZmF1bHQgcmVzcG9uc2UgaWYgbm90aGluZyBlbHNlIGZvdW5kLlxuICAgIHJldHVybiBFbGVtZW50UmVuZGVyVHlwZS5zcGVjaWFsUmVuZGVyO1xufVxuXG5mdW5jdGlvbiBoYXNQYXJhZ3JhcGgoZWxlbWVudDogSFRNTEVsZW1lbnQpOiBib29sZWFuIHtcbiAgICByZXR1cm4gZWxlbWVudC5pbm5lckhUTUwuc3RhcnRzV2l0aChcIjxwXCIpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaGFzSGVhZGVyKGVsZW1lbnQ6IEhUTUxFbGVtZW50KTogYm9vbGVhbiB7XG5cbiAgICBpZihlbGVtZW50LmlubmVySFRNTC5zdGFydHNXaXRoKFwiPGgxXCIpIHx8IFxuICAgICAgIGVsZW1lbnQuaW5uZXJIVE1MLnN0YXJ0c1dpdGgoXCI8aDJcIikgfHwgXG4gICAgICAgZWxlbWVudC5pbm5lckhUTUwuc3RhcnRzV2l0aChcIjxoM1wiKSB8fCBcbiAgICAgICBlbGVtZW50LmlubmVySFRNTC5zdGFydHNXaXRoKFwiPGg0XCIpIHx8XG4gICAgICAgZWxlbWVudC5pbm5lckhUTUwuc3RhcnRzV2l0aChcIjxoNVwiKSB8fFxuICAgICAgIGVsZW1lbnQuaW5uZXJIVE1MLnN0YXJ0c1dpdGgoXCI8aDZcIikpIHtcblxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGhhc0xpc3QoZWxlbWVudDogSFRNTEVsZW1lbnQpOiBib29sZWFuIHtcbiAgICBcbiAgICBpZihlbGVtZW50LmlubmVySFRNTC5zdGFydHNXaXRoKFwiPHVsXCIpIHx8IFxuICAgICAgIGVsZW1lbnQuaW5uZXJIVE1MLnN0YXJ0c1dpdGgoXCI8b2xcIikpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBoYXNDb3B5QnV0dG9uKGVsZW1lbnQ6IEhUTUxFbGVtZW50KTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIGVsZW1lbnQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZShcImNvcHktY29kZS1idXR0b25cIikubGVuZ3RoICE9PSAwIHx8IFxuICAgICAgICAgICAgZWxlbWVudC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKFwiYWRtb25pdGlvbi1jb250ZW50LWNvcHlcIikubGVuZ3RoICE9PSAwO1xufVxuXG5mdW5jdGlvbiBoYXNEaWNlUm9sbGVyKGVsZW1lbnQ6IEhUTUxFbGVtZW50KTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIGVsZW1lbnQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZShcImRpY2Utcm9sbGVyXCIpLmxlbmd0aCAhPT0gMDtcbn1cblxuZnVuY3Rpb24gaGFzQWRtb25pdGlvbihlbGVtZW50OiBIVE1MRWxlbWVudCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBlbGVtZW50LmdldEVsZW1lbnRzQnlDbGFzc05hbWUoXCJhZG1vbml0aW9uXCIpLmxlbmd0aCAhPT0gMDtcbn1cblxuZnVuY3Rpb24gaXNJRnJhbWUoZWxlbWVudDogSFRNTEVsZW1lbnQpOiBib29sZWFuIHtcblxuICAgIGlmKGVsZW1lbnQuY2hpbGRyZW4ubGVuZ3RoID4gMCkge1xuXG4gICAgICAgIHJldHVybiBlbGVtZW50LmZpcnN0Q2hpbGQubm9kZU5hbWUudG9Mb3dlckNhc2UoKSA9PT0gXCJpZnJhbWVcIjtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2Vcbn1cblxuZnVuY3Rpb24gaXNIb3Jpem9udGFsUnVsZShlbGVtZW50OiBIVE1MRWxlbWVudCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBlbGVtZW50LmlubmVySFRNTC5zdGFydHNXaXRoKFwiPGhyXCIpXG59XG5cbmZ1bmN0aW9uIGlzVGFibGUoZWxlbWVudDogSFRNTEVsZW1lbnQpOiBib29sZWFuIHtcbiAgICByZXR1cm4gZWxlbWVudC5pbm5lckhUTUwuc3RhcnRzV2l0aChcIjx0YWJsZVwiKVxufVxuXG5mdW5jdGlvbiBoYXNBZG1vbml0aW9uRm9sZChlbGVtZW50OiBIVE1MRWxlbWVudCkge1xuICAgIHJldHVybiBlbGVtZW50LmdldEVsZW1lbnRzQnlDbGFzc05hbWUoXCJjYWxsb3V0LWZvbGRcIikubGVuZ3RoICE9PSAwO1xufVxuXG5mdW5jdGlvbiBoYXNEYXRhdmlldyhlbGVtZW50OiBIVE1MRWxlbWVudCkge1xuXG4gICAgbGV0IGlzRGF0YXZpZXcgPSBlbGVtZW50LmdldEVsZW1lbnRzQnlDbGFzc05hbWUoXCJkYXRhdmlld1wiKS5sZW5ndGggIT09IDA7XG4gICAgcmV0dXJuIGlzRGF0YXZpZXc7XG59XG5cbmZ1bmN0aW9uIGhhc0RhdGF2aWV3SlMoZWxlbWVudDogSFRNTEVsZW1lbnQpIHtcblxuICAgIGxldCBpc0RhdGF2aWV3SlMgPSBlbGVtZW50LmdldEVsZW1lbnRzQnlDbGFzc05hbWUoXCJibG9jay1sYW5ndWFnZS1kYXRhdmlld2pzXCIpLmxlbmd0aCAhPT0gMDtcbiAgICBsZXQgY2FudmFzID0gc2VhcmNoQ2hpbGRyZW5Gb3JOb2RlVHlwZShlbGVtZW50LCBcImNhbnZhc1wiKTtcblxuICAgIC8qKlxuICAgICAqIFRoaXMgbWVhbnMgb25seSBkYXRhdmlld0pTIGNoYXJ0IGNhbnZhcyBlbGVtZW50cyBzaG91bGQgYmUgcmVuZGVyZWQgcHJvcGVybHkuIE90aGVyIGNhbnZhc2VzIHdpbGwgXG4gICAgICogbmVlZCB0aGllciBvd24gY2FzZSBwdXQgaW4gb3IgdGhlIHJlc3RyaWN0aW9uIHJlbW92ZWQgYWZ0ZXIgdGVzdGluZy5cbiAgICAgKi9cbiAgICByZXR1cm4gY2FudmFzICE9PSBudWxsICYmIGlzRGF0YXZpZXdKUyBcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldEhlYWRpbmdDb2xsYXBzZUVsZW1lbnQoZWxlbWVudDogSFRNTEVsZW1lbnQpOiBFbGVtZW50IHwgbnVsbCB7XG5cbiAgICBpZihlbGVtZW50ID09PSBudWxsKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIGxldCBjaGlsZEVsZW1lbnRzID0gZWxlbWVudC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKFwiaGVhZGluZy1jb2xsYXBzZS1pbmRpY2F0b3JcIilcbiAgICBpZihjaGlsZEVsZW1lbnRzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICByZXR1cm4gY2hpbGRFbGVtZW50c1swXTtcbiAgICB9XG4gICAgaWYoY2hpbGRFbGVtZW50cy5sZW5ndGggPiAxKSB7XG4gICAgICAgIGNvbnNvbGUuZGVidWcoXCJGb3VuZCBtdWx0aXBsZSBoZWFkaW5nIGNvbGxhcHNlIGluZGljYXRvcnMgaW4gZWxlbWVudC5cIilcbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG59IiwiLypcbiAqIEZpbGVuYW1lOiBtdWx0aS1jb2x1bW4tbWFya2Rvd24vc3JjL2RvbU9iamVjdC50c1xuICogQ3JlYXRlZCBEYXRlOiBUdWVzZGF5LCBGZWJydWFyeSAxc3QgMjAyMiwgMTI6MDQ6MDAgcG1cbiAqIEF1dGhvcjogQ2FtZXJvbiBSb2JpbnNvblxuICogXG4gKiBDb3B5cmlnaHQgKGMpIDIwMjIgQ2FtZXJvbiBSb2JpbnNvblxuICovXG5cbmltcG9ydCB7IGdldFVJRCB9IGZyb20gXCIuLi91dGlsaXRpZXMvdXRpbHNcIjtcbmltcG9ydCB7IEVsZW1lbnRSZW5kZXJUeXBlIH0gZnJvbSBcIi4uL3V0aWxpdGllcy9lbGVtZW50UmVuZGVyVHlwZVBhcnNlclwiO1xuaW1wb3J0IHsgY29udGFpbnNDb2xFbmRUYWcsIGNvbnRhaW5zQ29sU2V0dGluZ3NUYWcsIGNvbnRhaW5zRW5kVGFnLCBjb250YWluc1N0YXJ0VGFnLCBlbElubmVyVGV4dENvbnRhaW5zQ29sRW5kVGFnIH0gZnJvbSBcInNyYy91dGlsaXRpZXMvdGV4dFBhcnNlclwiO1xuXG5jb25zdCBVUERBVEVfVElNRVM6IG51bWJlcltdID0gWzI1MCwgMjAwMDBdO1xuXG5leHBvcnQgZW51bSBET01PYmplY3RUYWcge1xuICAgIG5vbmUsXG4gICAgc3RhcnRSZWdpb24sXG4gICAgcmVnaW9uU2V0dGluZ3MsXG4gICAgY29sdW1uQnJlYWssXG4gICAgZW5kUmVnaW9uXG59XG5cbmV4cG9ydCBjbGFzcyBET01PYmplY3Qge1xuICAgIG5vZGVLZXk6IHN0cmluZztcbiAgICBvcmlnaW5hbEVsZW1lbnQ6IEhUTUxFbGVtZW50O1xuICAgIGNsb25lZEVsZW1lbnQ6IEhUTUxFbGVtZW50ID0gbnVsbDtcbiAgICBVSUQ6IHN0cmluZztcbiAgICB0YWc6IERPTU9iamVjdFRhZztcbiAgICB1c2luZ09yaWdpbmFsRWxlbWVudDogYm9vbGVhblxuICAgIGVsZW1lbnRUeXBlOiBFbGVtZW50UmVuZGVyVHlwZSA9IEVsZW1lbnRSZW5kZXJUeXBlLnVuZGVmaW5lZDtcbiAgICBlbGVtZW50Q29udGFpbmVyOiBIVE1MRGl2RWxlbWVudCA9IG51bGw7XG4gICAgZWxlbWVudFJlbmRlcmVkSGVpZ2h0ID0gMDtcbiAgICBsaW5lc09mRWxlbWVudDogc3RyaW5nW11cblxuICAgIGNhbnZhc0VsZW1lbnRVcGRhdGVUaW1lOiBudW1iZXIgPSBEYXRlLm5vdygpO1xuICAgIGNhbnZhc1RpbWVySW5kZXggPSAwO1xuXG4gICAgbGFzdENsb25lZEVsZW1lbnRVcGRhdGVUaW1lOiBudW1iZXIgPSBEYXRlLm5vdygpO1xuICAgIHVwZGF0ZVRpbWVySW5kZXggPSAwO1xuXG4gICAgY29uc3RydWN0b3IoZWxlbWVudDogSFRNTEVsZW1lbnQsXG4gICAgICAgICAgICAgICAgbGluZXNPZkVsZW1lbnQ6IHN0cmluZ1tdLFxuICAgICAgICAgICAgICAgIHJhbmRvbUlEOnN0cmluZyA9IGdldFVJRCgpLCBcbiAgICAgICAgICAgICAgICB0YWc6IERPTU9iamVjdFRhZyA9IERPTU9iamVjdFRhZy5ub25lICkge1xuICAgICAgICB0aGlzLm5vZGVLZXkgPSBlbGVtZW50LmlubmVyVGV4dC50cmltKCk7XG4gICAgICAgIHRoaXMub3JpZ2luYWxFbGVtZW50ID0gZWxlbWVudDtcbiAgICAgICAgdGhpcy5VSUQgPSByYW5kb21JRDtcbiAgICAgICAgdGhpcy50YWcgPSB0YWc7XG4gICAgICAgIHRoaXMudXNpbmdPcmlnaW5hbEVsZW1lbnQgPSBmYWxzZVxuICAgICAgICB0aGlzLmxpbmVzT2ZFbGVtZW50ID0gbGluZXNPZkVsZW1lbnQ7XG5cbiAgICAgICAgaWYodGhpcy50YWcgPT09IERPTU9iamVjdFRhZy5ub25lKSB7XG4gICAgICAgICAgICB0aGlzLnNldERvbU9iamVjdFRhZygpXG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBzZXRNYWluRE9NRWxlbWVudChkb21FbGVtZW50OiBIVE1MRWxlbWVudCkge1xuICAgICAgICB0aGlzLm9yaWdpbmFsRWxlbWVudCA9IGRvbUVsZW1lbnQ7XG4gICAgICAgIHRoaXMudXNpbmdPcmlnaW5hbEVsZW1lbnQgPSB0cnVlXG4gICAgfVxuXG4gICAgY2xvbmVkRWxlbWVudFJlYWR5Rm9yVXBkYXRlKCk6IGJvb2xlYW4ge1xuXG4gICAgICAgIGxldCBkZWx0YVRpbWUgPSBEYXRlLm5vdygpIC0gdGhpcy5sYXN0Q2xvbmVkRWxlbWVudFVwZGF0ZVRpbWU7XG4gICAgICAgIGlmKGRlbHRhVGltZSA+IFVQREFURV9USU1FU1t0aGlzLnVwZGF0ZVRpbWVySW5kZXhdKSB7XG5cbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGNhbnZhc1JlYWR5Rm9yVXBkYXRlKCk6IGJvb2xlYW4ge1xuXG4gICAgICAgIGxldCBkZWx0YVRpbWUgPSBEYXRlLm5vdygpIC0gdGhpcy5jYW52YXNFbGVtZW50VXBkYXRlVGltZVxuICAgICAgICBpZihkZWx0YVRpbWUgPiBVUERBVEVfVElNRVNbdGhpcy5jYW52YXNUaW1lckluZGV4XSkge1xuXG4gICAgICAgICAgICB0aGlzLmNhbnZhc0VsZW1lbnRVcGRhdGVUaW1lID0gRGF0ZS5ub3coKTtcbiAgICAgICAgICAgIHRoaXMuY2FudmFzVGltZXJJbmRleCA9IE1hdGguY2xhbXAodGhpcy5jYW52YXNUaW1lckluZGV4ICsgMSwgMCwgVVBEQVRFX1RJTUVTLmxlbmd0aCAtIDEpO1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgdXBkYXRlQ2xvbmVkRWxlbWVudChuZXdDbG9uZWRFbGVtZW50OiBIVE1MRWxlbWVudCkge1xuXG4gICAgICAgIHRoaXMuY2xvbmVkRWxlbWVudCA9IG5ld0Nsb25lZEVsZW1lbnQ7XG5cbiAgICAgICAgdGhpcy5sYXN0Q2xvbmVkRWxlbWVudFVwZGF0ZVRpbWUgPSBEYXRlLm5vdygpO1xuICAgICAgICB0aGlzLnVwZGF0ZVRpbWVySW5kZXggPSBNYXRoLmNsYW1wKHRoaXMudXBkYXRlVGltZXJJbmRleCArIDEsIDAsIFVQREFURV9USU1FUy5sZW5ndGggLSAxKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHNldERvbU9iamVjdFRhZygpIHtcblxuICAgICAgICBsZXQgZWxlbWVudFRleHRTcGFjZWQgPSB0aGlzLmxpbmVzT2ZFbGVtZW50LnJlZHVjZSgocHJldiwgY3VycikgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIHByZXYgKyBcIlxcblwiICsgY3VycjtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYoY29udGFpbnNFbmRUYWcodGhpcy5vcmlnaW5hbEVsZW1lbnQudGV4dENvbnRlbnQpID09PSB0cnVlKSB7XG5cbiAgICAgICAgICAgIHRoaXMuZWxlbWVudFR5cGUgPSBFbGVtZW50UmVuZGVyVHlwZS51blJlbmRlcmVkO1xuICAgICAgICAgICAgdGhpcy50YWcgPSBET01PYmplY3RUYWcuZW5kUmVnaW9uO1xuICAgICAgICAgICAgLy8gZWwuYWRkQ2xhc3MoTXVsdGlDb2x1bW5TdHlsZUNTUy5SZWdpb25FbmRUYWcpXG4gICAgICAgICAgICAvLyByZWdpb25hbE1hbmFnZXIudXBkYXRlRWxlbWVudFRhZyhjdXJyZW50T2JqZWN0LlVJRCwgRE9NT2JqZWN0VGFnLmVuZFJlZ2lvbik7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZihjb250YWluc0NvbEVuZFRhZyh0aGlzLm9yaWdpbmFsRWxlbWVudC50ZXh0Q29udGVudCkgPT09IHRydWUgfHwgXG4gICAgICAgICh0aGlzLm9yaWdpbmFsRWxlbWVudC5pbm5lckhUTUwuc3RhcnRzV2l0aChcIjxtYXJrPlwiKSkgJiYgZWxJbm5lclRleHRDb250YWluc0NvbEVuZFRhZyh0aGlzLm9yaWdpbmFsRWxlbWVudC50ZXh0Q29udGVudCkpIHtcblxuICAgICAgICAgICAgdGhpcy5lbGVtZW50VHlwZSA9IEVsZW1lbnRSZW5kZXJUeXBlLnVuUmVuZGVyZWRcbiAgICAgICAgICAgIHRoaXMudGFnID0gRE9NT2JqZWN0VGFnLmNvbHVtbkJyZWFrO1xuICAgICAgICAgICAgLy8gZWwuYWRkQ2xhc3MoTXVsdGlDb2x1bW5TdHlsZUNTUy5Db2x1bW5FbmRUYWcpXG4gICAgICAgICAgICAvLyByZWdpb25hbE1hbmFnZXIudXBkYXRlRWxlbWVudFRhZyhjdXJyZW50T2JqZWN0LlVJRCwgRE9NT2JqZWN0VGFnLmNvbHVtbkJyZWFrKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmKGNvbnRhaW5zU3RhcnRUYWcodGhpcy5vcmlnaW5hbEVsZW1lbnQudGV4dENvbnRlbnQpID09PSB0cnVlKSB7XG5cbiAgICAgICAgICAgIHRoaXMuZWxlbWVudFR5cGUgPSBFbGVtZW50UmVuZGVyVHlwZS51blJlbmRlcmVkXG4gICAgICAgICAgICB0aGlzLnRhZyA9IERPTU9iamVjdFRhZy5zdGFydFJlZ2lvbjtcbiAgICAgICAgICAgIC8vIGVsLmFkZENsYXNzKE11bHRpQ29sdW1uU3R5bGVDU1MuQ29sdW1uRW5kVGFnKVxuICAgICAgICAgICAgLy8gcmVnaW9uYWxNYW5hZ2VyLnVwZGF0ZUVsZW1lbnRUYWcoY3VycmVudE9iamVjdC5VSUQsIERPTU9iamVjdFRhZy5jb2x1bW5CcmVhayk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZihjb250YWluc0NvbFNldHRpbmdzVGFnKGVsZW1lbnRUZXh0U3BhY2VkKSA9PT0gdHJ1ZSkge1xuXG4gICAgICAgICAgICB0aGlzLmVsZW1lbnRUeXBlID0gRWxlbWVudFJlbmRlclR5cGUudW5SZW5kZXJlZFxuICAgICAgICAgICAgLy8gZWwuYWRkQ2xhc3MoTXVsdGlDb2x1bW5TdHlsZUNTUy5SZWdpb25TZXR0aW5ncylcbiAgICAgICAgICAgIC8vIHJlZ2lvbmFsTWFuYWdlciA9IHJlZ2lvbmFsQ29udGFpbmVyLnNldFJlZ2lvblNldHRpbmdzKGVsZW1lbnRUZXh0U3BhY2VkKVxuICAgICAgICAgICAgLy8gcmVnaW9uYWxNYW5hZ2VyLnVwZGF0ZUVsZW1lbnRUYWcoY3VycmVudE9iamVjdC5VSUQsIERPTU9iamVjdFRhZy5yZWdpb25TZXR0aW5ncyk7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbmV4cG9ydCBjbGFzcyBET01TdGFydFJlZ2lvbk9iamVjdCBleHRlbmRzIERPTU9iamVjdCB7XG5cbiAgICByZWdpb25FbGVtZW50OiBIVE1MRWxlbWVudDtcblxuICAgIGNvbnN0cnVjdG9yKGJhc2VET01PYmplY3Q6IERPTU9iamVjdCwgcmVnaW9uRWxlbWVudDogSFRNTEVsZW1lbnQpIHtcblxuICAgICAgICBzdXBlcihiYXNlRE9NT2JqZWN0Lm9yaWdpbmFsRWxlbWVudCwgYmFzZURPTU9iamVjdC5saW5lc09mRWxlbWVudCwgYmFzZURPTU9iamVjdC5VSUQsIERPTU9iamVjdFRhZy5zdGFydFJlZ2lvbik7XG4gICAgICAgIHRoaXMucmVnaW9uRWxlbWVudCA9IHJlZ2lvbkVsZW1lbnQ7XG4gICAgfVxufVxuXG5leHBvcnQgY2xhc3MgVGFza0xpc3RET01PYmplY3QgZXh0ZW5kcyBET01PYmplY3Qge1xuXG4gICAgb3JpZ2luYWxDaGVja2JveGVzOiBIVE1MRWxlbWVudFtdID0gW107XG5cbiAgICBjb25zdHJ1Y3RvcihiYXNlRE9NT2JqZWN0OiBET01PYmplY3QpIHtcblxuICAgICAgICBzdXBlcihiYXNlRE9NT2JqZWN0Lm9yaWdpbmFsRWxlbWVudCwgYmFzZURPTU9iamVjdC5saW5lc09mRWxlbWVudCwgYmFzZURPTU9iamVjdC5VSUQsIERPTU9iamVjdFRhZy5ub25lKTtcbiAgICB9XG5cbiAgICBjaGVja2JveENsaWNrZWQoaW5kZXg6IG51bWJlcikge1xuXG4gICAgICAgIGlmKGluZGV4IDwgdGhpcy5vcmlnaW5hbENoZWNrYm94ZXMubGVuZ3RoKSB7XG5cbiAgICAgICAgICAgIGxldCBvcmlnaW5hbElucHV0ID0gdGhpcy5vcmlnaW5hbENoZWNrYm94ZXNbaW5kZXhdLmZpcnN0Q2hpbGQgYXMgSFRNTElucHV0RWxlbWVudDtcbiAgICAgICAgICAgIG9yaWdpbmFsSW5wdXQuY2xpY2soKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHN0YXRpYyBjaGVja0ZvclRhc2tMaXN0RWxlbWVudChkb21FbGVtZW50OiBET01PYmplY3QpIHtcblxuICAgICAgICBpZihkb21FbGVtZW50Lm9yaWdpbmFsRWxlbWVudC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKFwidGFzay1saXN0LWl0ZW1cIikubGVuZ3RoID4gMCApIHtcblxuICAgICAgICAgICAgcmV0dXJuIG5ldyBUYXNrTGlzdERPTU9iamVjdChkb21FbGVtZW50KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBkb21FbGVtZW50O1xuICAgIH1cbn0iLCIvKlxuICogRmlsZTogbXVsdGktY29sdW1uLW1hcmtkb3duL3NyYy91dGlsaXRpZXMvY3NzRGVmaW5pdGlvbnMudHNcbiAqIENyZWF0ZWQgRGF0ZTogV2VkbmVzZGF5LCBGZWJydWFyeSAxNnRoIDIwMjIsIDExOjA5OjA2IGFtXG4gKiBBdXRob3I6IENhbWVyb24gUm9iaW5zb25cbiAqIFxuICogQ29weXJpZ2h0IChjKSAyMDIyIENhbWVyb24gUm9iaW5zb25cbiAqL1xuXG5leHBvcnQgZW51bSBNdWx0aUNvbHVtbkxheW91dENTUyB7XG5cbiAgICBSZWdpb25Sb290Q29udGFpbmVyRGl2ID0gXCJtY20tY29sdW1uLXJvb3QtY29udGFpbmVyXCIsXG4gICAgUmVnaW9uRXJyb3JDb250YWluZXJEaXYgPSBcIm1jbS1jb2x1bW4tZXJyb3ItcmVnaW9uLXdyYXBwZXJcIixcbiAgICBSZWdpb25Db250ZW50Q29udGFpbmVyRGl2ID0gXCJtY20tY29sdW1uLXJlZ2lvbi13cmFwcGVyXCIsXG4gICAgUmVnaW9uQ29sdW1uQ29udGFpbmVyRGl2ID0gXCJtY20tY29sdW1uLXBhcmVudC1jb250YWluZXJcIixcbiAgICBDb2x1bW5EdWFsRWxlbWVudENvbnRhaW5lciA9IFwibWNtLWNvbHVtbi1lbGVtZW50LXdyYXBwZXJcIixcbiAgICBPcmlnaW5hbEVsZW1lbnRUeXBlID0gXCJtY20tb3JpZ2luYWwtY29sdW1uLWVsZW1lbnRcIixcbiAgICBDbG9uZWRFbGVtZW50VHlwZSA9IFwibWNtLWNsb25lZC1jb2x1bW4tZWxlbWVudFwiLFxuXG4gICAgQ29udGVudE92ZXJmbG93QXV0b1Njcm9sbCA9IFwibWNtLWNvbnRlbnQtb3ZlcmZsb3ctYXV0by1zY3JvbGxcIixcbiAgICBDb250ZW50T3ZlcmZsb3dIaWRkZW4gPSBcIm1jbS1jb250ZW50LW92ZXJmbG93LWhpZGRlblwiLFxuXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIC8vXG5cbiAgICBTaW5nbGVDb2x1bW5TbWFsbCA9IFwibWNtLXNpbmdsZS1jb2x1bW4tc21hbGxcIixcbiAgICBTaW5nbGVDb2x1bW5NZWQgPSBcIm1jbS1zaW5nbGUtY29sdW1uLW1lZGl1bVwiLFxuICAgIFNpbmdsZUNvbHVtbkxhcmdlID0gXCJtY20tc2luZ2xlLWNvbHVtbi1sYXJnZVwiLFxuICAgIFNpbmdsZUNvbHVtbkZ1bGwgPSBcIm1jbS1zaW5nbGUtY29sdW1uLWZ1bGxcIixcblxuICAgIFNpbmdsZUNvbHVtbkxlZnRMYXlvdXQgPSBcIm1jbS1zaW5nbGVjb2wtbGF5b3V0LWxlZnRcIixcbiAgICBTaW5nbGVDb2x1bW5DZW50ZXJMYXlvdXQgPSBcIm1jbS1zaW5nbGVjb2wtbGF5b3V0LWNlbnRlclwiLFxuICAgIFNpbmdsZUNvbHVtblJpZ2h0TGF5b3V0ID0gXCJtY20tc2luZ2xlY29sLWxheW91dC1yaWdodFwiLFxuXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIC8vXG5cbiAgICBUd29FcXVhbENvbHVtbnMgPSBcIm1jbS10d28tZXF1YWwtY29sdW1uc1wiLFxuXG4gICAgVHdvQ29sdW1uU21hbGwgPSBcIm1jbS10d28tY29sdW1uLXNtYWxsXCIsXG4gICAgVHdvQ29sdW1uTGFyZ2UgPSBcIm1jbS10d28tY29sdW1uLWxhcmdlXCIsXG5cbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gLy9cblxuICAgIFRocmVlRXF1YWxDb2x1bW5zID0gXCJtY20tdGhyZWUtZXF1YWwtY29sdW1uc1wiLFxuXG4gICAgVGhyZWVDb2x1bW5fTGFyZ2UgPSBcIm1jbS10aHJlZS1jb2x1bW4tbGFyZ2VcIixcbiAgICBUaHJlZUNvbHVtbl9TbWFsbCA9IFwibWNtLXRocmVlLWNvbHVtbi1zbWFsbFwiLFxufVxuXG5leHBvcnQgZW51bSBNdWx0aUNvbHVtblN0eWxlQ1NTIHtcblxuICAgIFJlZ2lvbkVycm9yTWVzc2FnZSA9IFwibWNtLWNvbHVtbi1lcnJvci1tZXNzYWdlXCIsXG4gICAgUmVnaW9uU2V0dGluZ3MgPSBcIm1jbS1jb2x1bW4tc2V0dGluZ3Mtd3JhcHBlclwiLFxuICAgIFJlZ2lvbkNvbnRlbnQgPSBcIm1jbS1jb2x1bW4tY29udGVudC13cmFwcGVyXCIsXG4gICAgUmVnaW9uRW5kVGFnID0gXCJtY20tY29sdW1uLWVuZC10YWctd3JhcHBlclwiLFxuICAgIENvbHVtbkVuZFRhZyA9IFwibWNtLWNvbHVtbi1icmVhay10YWctd3JhcHBlclwiLFxuICAgIFJlZ2lvblNoYWRvdyA9IFwibWNtLXJlZ2lvbi1zaGFkb3dcIixcbiAgICBDb2x1bW5TaGFkb3cgPSBcIm1jbS1jb2x1bW4tc2hhZG93XCIsXG4gICAgQ29sdW1uQm9yZGVyID0gXCJtY20tY29sdW1uLWJvcmRlclwiLFxuICAgIENvbHVtbkNvbnRlbnQgPSBcIm1jbS1jb2x1bW4tZGl2XCJcbn0iLCIvKipcbiAqIEZpbGU6IC9zcmMvZG9tX21hbmFnZXIvcmVnaW9uYWxfbWFuYWdlcnMvUmVnaW9uTWFuYWdlci50cyAgICAgICAgICAgICAgICAgICAqXG4gKiBDcmVhdGVkIERhdGU6IFN1bmRheSwgTWF5IDIybmQgMjAyMiwgNzo0OSBwbSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICogQXV0aG9yOiBDYW1lcm9uIFJvYmluc29uICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpcbiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMjIgQ2FtZXJvbiBSb2JpbnNvbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICovXG5cbmltcG9ydCB7IERPTU9iamVjdCwgRE9NT2JqZWN0VGFnLCBUYXNrTGlzdERPTU9iamVjdCB9IGZyb20gJy4uL2RvbU9iamVjdCc7XG5pbXBvcnQgeyBNdWx0aUNvbHVtblNldHRpbmdzLCBDb2x1bW5MYXlvdXQsIGdldERlZmF1bHRNdWx0aUNvbHVtblNldHRpbmdzIH0gZnJvbSBcIi4uLy4uL3JlZ2lvblNldHRpbmdzXCI7XG5pbXBvcnQgeyBNdWx0aUNvbHVtbkxheW91dENTUywgTXVsdGlDb2x1bW5TdHlsZUNTUyB9IGZyb20gJy4uLy4uL3V0aWxpdGllcy9jc3NEZWZpbml0aW9ucyc7XG5pbXBvcnQgeyBGaWxlRE9NTWFuYWdlciB9IGZyb20gJy4uL2RvbU1hbmFnZXInO1xuaW1wb3J0IHsgRWxlbWVudFJlbmRlclR5cGUsIGdldEVsZW1lbnRSZW5kZXJUeXBlIH0gZnJvbSAnc3JjL3V0aWxpdGllcy9lbGVtZW50UmVuZGVyVHlwZVBhcnNlcic7XG5pbXBvcnQgeyBSZWdpb25NYW5hZ2VyRGF0YSB9IGZyb20gJy4vcmVnaW9uTWFuYWdlckNvbnRhaW5lcic7XG5pbXBvcnQgeyBzZWFyY2hDaGlsZHJlbkZvck5vZGVUeXBlIH0gZnJvbSAnc3JjL3V0aWxpdGllcy91dGlscyc7XG5cbmV4cG9ydCB0eXBlIE11bHRpQ29sdW1uUmVuZGVyRGF0YSA9IHsgXG4gICAgcGFyZW50UmVuZGVyRWxlbWVudDogSFRNTEVsZW1lbnQsIFxuICAgIHBhcmVudFJlbmRlclNldHRpbmdzOiBNdWx0aUNvbHVtblNldHRpbmdzLFxuICAgIGRvbU9iamVjdHM6IERPTU9iamVjdFtdXG59XG5cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBSZWdpb25NYW5hZ2VyIHtcblxuICAgIHByb3RlY3RlZCBkb21MaXN0OiBET01PYmplY3RbXSA9IFtdO1xuICAgIHByb3RlY3RlZCBkb21PYmplY3RNYXA6IE1hcDxzdHJpbmcsIERPTU9iamVjdD4gPSBuZXcgTWFwKCk7XG4gICAgcHJpdmF0ZSBfcmVnaW9uUGFyZW50OiBIVE1MRWxlbWVudDtcbiAgICBwdWJsaWMgZ2V0IHJlZ2lvblBhcmVudCgpOiBIVE1MRWxlbWVudCB7XG4gICAgICAgIHJldHVybiB0aGlzLl9yZWdpb25QYXJlbnQ7XG4gICAgfVxuICAgIHB1YmxpYyBzZXQgcmVnaW9uUGFyZW50KHZhbHVlOiBIVE1MRWxlbWVudCkge1xuICAgICAgICB0aGlzLl9yZWdpb25QYXJlbnQgPSB2YWx1ZTtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgZmlsZU1hbmFnZXI6IEZpbGVET01NYW5hZ2VyO1xuICAgIHByb3RlY3RlZCByZWdpb25hbFNldHRpbmdzOiBNdWx0aUNvbHVtblNldHRpbmdzID0gZ2V0RGVmYXVsdE11bHRpQ29sdW1uU2V0dGluZ3MoKTtcblxuICAgIHByb3RlY3RlZCByZWdpb25LZXk6IHN0cmluZztcblxuICAgIGNvbnN0cnVjdG9yKGRhdGE6IFJlZ2lvbk1hbmFnZXJEYXRhKSB7XG5cbiAgICAgICAgdGhpcy5kb21MaXN0ID0gZGF0YS5kb21MaXN0O1xuICAgICAgICB0aGlzLmRvbU9iamVjdE1hcCA9IGRhdGEuZG9tT2JqZWN0TWFwO1xuICAgICAgICB0aGlzLnJlZ2lvblBhcmVudCA9IGRhdGEucmVnaW9uUGFyZW50O1xuXG4gICAgICAgIHRoaXMuZmlsZU1hbmFnZXIgPSBkYXRhLmZpbGVNYW5hZ2VyO1xuICAgICAgICB0aGlzLnJlZ2lvbmFsU2V0dGluZ3MgPSBkYXRhLnJlZ2lvbmFsU2V0dGluZ3M7XG5cbiAgICAgICAgdGhpcy5yZWdpb25LZXkgPSBkYXRhLnJlZ2lvbktleTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0UmVnaW9uRGF0YSgpOiBSZWdpb25NYW5hZ2VyRGF0YSB7XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGRvbUxpc3Q6IHRoaXMuZG9tTGlzdCxcbiAgICAgICAgICAgIGRvbU9iamVjdE1hcDogdGhpcy5kb21PYmplY3RNYXAsXG4gICAgICAgICAgICByZWdpb25QYXJlbnQ6IHRoaXMucmVnaW9uUGFyZW50LFxuXG4gICAgICAgICAgICBmaWxlTWFuYWdlcjogdGhpcy5maWxlTWFuYWdlcixcbiAgICAgICAgICAgIHJlZ2lvbmFsU2V0dGluZ3M6IHRoaXMucmVnaW9uYWxTZXR0aW5ncyxcblxuICAgICAgICAgICAgcmVnaW9uS2V5OiB0aGlzLnJlZ2lvbktleSxcbiAgICAgICAgICAgIHJvb3RFbGVtZW50OiBudWxsXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgcHVibGljIGFkZE9iamVjdChzaWJsaW5nc0Fib3ZlOiBIVE1MRGl2RWxlbWVudCwgc2libGluZ3NCZWxvdzogSFRNTERpdkVsZW1lbnQsIG9iajogRE9NT2JqZWN0KTogbnVtYmVyIHtcblxuICAgICAgICBsZXQgbmV4dE9iaiA9IHNpYmxpbmdzQmVsb3cuY2hpbGRyZW5bMF0gYXMgSFRNTEVsZW1lbnQ7XG5cbiAgICAgICAgbGV0IGFkZEF0SW5kZXggPSBzaWJsaW5nc0Fib3ZlLmNoaWxkcmVuLmxlbmd0aDtcblxuICAgICAgICBpZiAoc2libGluZ3NBYm92ZS5jaGlsZHJlbi5sZW5ndGggPiAwKSB7XG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogV2Ugd2FudCB0byBmaW5kIHRoZSBmaXJzdCBzaWJsaW5nIHdpdGhvdXRoIFwiXCIgZm9yIGFuIGlubmVyIHRleHQgc28gd2UgY2FuIHVzZSB0aGF0IHRvIGFuY2hvciBvdXJcbiAgICAgICAgICAgICAqIGVsZW1lbnQgaW50byB0aGUgZG9tTGlzdC4gRm9yIG1vc3QgaXRlbXMgdGhlIGZpcnN0IGVsZW1lbnQgYmVmb3JlIG91ciBuZXcgZWxlbWVudCB3aWxsIGhhdmUgdGhlIHByb3BlclxuICAgICAgICAgICAgICogaW5uZXJUZXh0LiBTb21ldGltZXMgb3RoZXIgZWxlbWVudHMgYXJlIGVtcHR5IGFuZCB3ZXJlIGNhdXNpbmcgaXNzdWVzLlxuICAgICAgICAgICAgICogXG4gICAgICAgICAgICAgKiBOb3cgd2UgbG9vcCBiYWNrIHRocm91Z2ggdGhlIHByZXZpb3VzIHNpYmxpbmdzIGxvb2tpbmcgZm9yIHRoZSBmaXJzdCBvbmUgd2l0aCBhIHZhbGlkIGlubmVyIHRleHQgYW5kIHVzaW5nIHRoYXQgXG4gICAgICAgICAgICAgKiBhcyB0aGUgYW5jaG9yIGFuZCBvZmZzZXR0aW5nIG91ciBhZGRBdEluZGV4IGJ5IHRoZSBudW1iZXIgb2YgZW1wdHkgc3RyaW5nIGVsZW1lbnRzIHdlIGZvdW5kLlxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBsZXQgcHJldlNpYmxpbmdJbm5lclRleHQgPSBcIlwiXG4gICAgICAgICAgICBsZXQgcHJldlNpYmxpbmdPZmZzZXQgPSAwO1xuICAgICAgICAgICAgZm9yKGxldCBpID0gc2libGluZ3NBYm92ZS5jaGlsZHJlbi5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuXG4gICAgICAgICAgICAgICAgbGV0IG9iaiA9IHNpYmxpbmdzQWJvdmUuY2hpbGRyZW5baV0gYXMgSFRNTEVsZW1lbnQ7XG4gICAgICAgICAgICAgICAgaWYob2JqLmlubmVyVGV4dCAhPT0gXCJcIikge1xuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgICAgICBwcmV2U2libGluZ0lubmVyVGV4dCA9IG9iai5pbm5lclRleHQ7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHByZXZTaWJsaW5nT2Zmc2V0Kys7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZvciAobGV0IGkgPSB0aGlzLmRvbUxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5kb21MaXN0W2ldLm5vZGVLZXkgPT09IHByZXZTaWJsaW5nSW5uZXJUZXh0KSB7XG4gICAgICAgICAgICAgICAgICAgIGFkZEF0SW5kZXggPSBpICsgMSArIHByZXZTaWJsaW5nT2Zmc2V0O1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgbmV4dEVsSW5kZXggPSBhZGRBdEluZGV4O1xuICAgICAgICBsZXQgbmV4dE9ialRleHQgPSBcIlwiO1xuICAgICAgICBpZiAobmV4dE9iaiAhPT0gdW5kZWZpbmVkKSB7XG5cbiAgICAgICAgICAgIGxldCBmb3VuZE5leHQgPSBmYWxzZTtcbiAgICAgICAgICAgIG5leHRPYmpUZXh0ID0gbmV4dE9iai5pbm5lclRleHQ7XG5cbiAgICAgICAgICAgIGZvciAobGV0IGkgPSBhZGRBdEluZGV4OyBpIDwgdGhpcy5kb21MaXN0Lmxlbmd0aDsgaSsrKSB7XG5cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5kb21MaXN0W2ldLm5vZGVLZXkgPT09IG5leHRPYmouaW5uZXJUZXh0LnRyaW0oKSkge1xuXG4gICAgICAgICAgICAgICAgICAgIG5leHRFbEluZGV4ID0gaTtcbiAgICAgICAgICAgICAgICAgICAgZm91bmROZXh0ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gY29uc29sZS5sb2coXCIgUHJldjogXCIsIEFycmF5LmZyb20oc2libGluZ3NBYm92ZS5jaGlsZHJlbikuc2xpY2UoLTMpLCBcIkFkZGluZzogXCIsIG9iai5vcmlnaW5hbEVsZW1lbnQsIFwiIE5leHQ6IFwiLCBzaWJsaW5nc0JlbG93LmNoaWxkcmVuWzBdLCBcIk92ZXJ3cml0aW5nOlwiLCB0aGlzLmRvbUxpc3Quc2xpY2UoYWRkQXRJbmRleCwgbmV4dEVsSW5kZXgpKTtcbiAgICAgICAgdGhpcy5kb21MaXN0LnNwbGljZShhZGRBdEluZGV4LCBuZXh0RWxJbmRleCAtIGFkZEF0SW5kZXgsIG9iaik7XG4gICAgICAgIHRoaXMuZG9tT2JqZWN0TWFwLnNldChvYmouVUlELCBvYmopO1xuXG4gICAgICAgIC8vIC8qKlxuICAgICAgICAvLyAgKiBNYWtlIGEgY29weSBvZiB0aGUgbGlzdCB0byBsb2csIG9ubHkgYmVjYXVzZVxuICAgICAgICAvLyAgKiBjb25zb2xlIGxvZyB1cGRhdGVzIGl0cyByZWZlcmVuY2VzIHdpdGggdXBkYXRlcyBpbiBtZW1vcnkuXG4gICAgICAgIC8vICAqL1xuICAgICAgICAvLyBsZXQgeCA9IHRoaXMuZG9tTGlzdC5zbGljZSgwKTtcbiAgICAgICAgLy8gY29uc29sZS5sb2coeCk7XG4gICAgICAgIHJldHVybiBhZGRBdEluZGV4O1xuICAgIH1cblxuICAgIHB1YmxpYyByZW1vdmVPYmplY3Qob2JqZWN0VUlEOiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgLy8gLyoqXG4gICAgICAgIC8vICAqIE1ha2UgYSBjb3B5IG9mIHRoZSBsaXN0IHRvIGxvZ1xuICAgICAgICAvLyAgKi9cbiAgICAgICAgLy8gbGV0IHggPSBkb21MaXN0LnNsaWNlKDApO1xuICAgICAgICAvLyBjb25zb2xlLmxvZyh4KTtcbiAgICAgICAgLy8gR2V0IHRoZSBvYmplY3QgYnkga2V5LCByZW1vdmUgaXQgZnJvbSB0aGUgbWFwIGFuZCB0aGVuXG4gICAgICAgIC8vIGZyb20gdGhlIGxpc3QuXG4gICAgICAgIGxldCBvYmogPSB0aGlzLmRvbU9iamVjdE1hcC5nZXQob2JqZWN0VUlEKTtcbiAgICAgICAgdGhpcy5kb21PYmplY3RNYXAuZGVsZXRlKG9iamVjdFVJRCk7XG5cbiAgICAgICAgaWYgKG9iaiA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5kb21MaXN0LmNvbnRhaW5zKG9iaikpIHtcbiAgICAgICAgICAgIHRoaXMuZG9tTGlzdC5yZW1vdmUob2JqKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLmRvbUxpc3QubGVuZ3RoID09PSAwICYmIHRoaXMuZmlsZU1hbmFnZXIgIT09IG51bGwpIHtcbiAgICAgICAgICAgIHRoaXMuZmlsZU1hbmFnZXIucmVtb3ZlUmVnaW9uKHRoaXMucmVnaW9uS2V5KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHggPSBkb21MaXN0LnNsaWNlKDApO1xuICAgICAgICAvLyBjb25zb2xlLmxvZyh4KTtcbiAgICB9XG5cbiAgICBwdWJsaWMgdXBkYXRlRWxlbWVudFRhZyhvYmplY3RVSUQ6IHN0cmluZywgbmV3VGFnOiBET01PYmplY3RUYWcpOiB2b2lkIHtcblxuICAgICAgICBsZXQgb2JqID0gdGhpcy5kb21PYmplY3RNYXAuZ2V0KG9iamVjdFVJRCk7XG4gICAgICAgIGxldCBpbmRleCA9IHRoaXMuZG9tTGlzdC5pbmRleE9mKG9iaik7XG4gICAgICAgIGlmIChpbmRleCAhPT0gLTEpIHtcbiAgICAgICAgICAgIHRoaXMuZG9tTGlzdFtpbmRleF0udGFnID0gbmV3VGFnO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHVibGljIHNldFJlZ2lvbmFsU2V0dGluZ3MocmVnaW9uU2V0dGluZ3M6IE11bHRpQ29sdW1uU2V0dGluZ3MpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5yZWdpb25hbFNldHRpbmdzID0gcmVnaW9uU2V0dGluZ3M7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBvYmplY3QgY29udGFpbmluZyBhbGwgbmVjZXNzYXJ5IGluZm9ybWF0aW9uIGZvciB0aGUgcmVnaW9uXG4gICAgICogdG8gYmUgcmVuZGVyZWQgdG8gdGhlIHByZXZpZXcgcGFuZS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIGEgTXVsdGlDb2x1bW5SZW5kZXJEYXRhIG9iamVjdCB3aXRoIHRoZSByb290IERPTSBlbGVtZW50LCBzZXR0aW5ncyBvYmplY3QsIGFuZFxuICAgICAqIGFsbCBjaGlsZCBvYmplY3RzIGluIHRoZSBvcmRlciB0aGV5IHNob3VsZCBiZSByZW5kZXJlZC5cbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0UmVnaW9uUmVuZGVyRGF0YSgpOiBNdWx0aUNvbHVtblJlbmRlckRhdGEge1xuXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBwYXJlbnRSZW5kZXJFbGVtZW50OiB0aGlzLnJlZ2lvblBhcmVudCxcbiAgICAgICAgICAgIHBhcmVudFJlbmRlclNldHRpbmdzOiB0aGlzLnJlZ2lvbmFsU2V0dGluZ3MsXG4gICAgICAgICAgICBkb21PYmplY3RzOiB0aGlzLmRvbUxpc3RcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIGZ1Y3Rpb24gaXMgY2FsbGVkIHdoZW4gYSBzdGFydCB0YWcgaXMgcmVtb3ZlZCBmcm9tIHZpZXcgbWVhbmluZ1xuICAgICAqIG91ciBwYXJlbnQgZWxlbWVudCBzdG9yaW5nIHRoZSBtdWx0aS1jb2x1bW4gcmVnaW9uIGlzIHJlbW92ZWQuIEl0XG4gICAgICogcmVtb3ZlcyB0aGUgQ1NTIGNsYXNzIGZyb20gYWxsIG9mIHRoZSBlbGVtZW50cyBzbyB0aGV5IHdpbGwgYmVcbiAgICAgKiByZS1yZW5kZXJlZCBpbiB0aGUgcHJldmlldyB3aW5kb3cuXG4gICAgICovXG4gICAgcHVibGljIGRpc3BsYXlPcmlnaW5hbEVsZW1lbnRzKCkge1xuXG5cbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLmRvbUxpc3QubGVuZ3RoOyBpKyspIHtcblxuICAgICAgICAgICAgaWYgKHRoaXMuZG9tTGlzdFtpXS5vcmlnaW5hbEVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmRvbUxpc3RbaV0ub3JpZ2luYWxFbGVtZW50LnJlbW92ZUNsYXNzZXMoW011bHRpQ29sdW1uU3R5bGVDU1MuUmVnaW9uRW5kVGFnLFxuICAgICAgICAgICAgICAgIE11bHRpQ29sdW1uU3R5bGVDU1MuQ29sdW1uRW5kVGFnLFxuICAgICAgICAgICAgICAgIE11bHRpQ29sdW1uU3R5bGVDU1MuUmVnaW9uU2V0dGluZ3MsXG4gICAgICAgICAgICAgICAgTXVsdGlDb2x1bW5TdHlsZUNTUy5SZWdpb25Db250ZW50XSk7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuZG9tTGlzdFtpXS5vcmlnaW5hbEVsZW1lbnQucGFyZW50RWxlbWVudCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRvbUxpc3RbaV0ub3JpZ2luYWxFbGVtZW50LnBhcmVudEVsZW1lbnQucmVtb3ZlQ2hpbGQodGhpcy5kb21MaXN0W2ldLm9yaWdpbmFsRWxlbWVudCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIFxuICAgIHB1YmxpYyBnZXRJRCgpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gdGhpcy5yZWdpb25LZXk7XG4gICAgfVxuXG4gICAgcHVibGljIHVwZGF0ZVJlbmRlcmVkTWFya2Rvd24oKSB7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBUaGlzIGZ1bmN0aW9uIGFjdHMgYXMgdGhlIHVwZGF0ZSBsb29wIGZvciB0aGUgbXVsdGktY29sdW1uIHJlZ2lvbnMuXG4gICAgICAgICAqIEhlcmUgd2UgbG9vcCB0aHJvdWdoIGFsbCBvZiB0aGUgZWxlbWVudHMgd2l0aGluIHRoZSByZW5kZXJlZCByZWdpb24gYW5kXG4gICAgICAgICAqIHBvdGVudGlhbGx5IHVwZGF0ZSBob3cgdGhpbmdzIGFyZSByZW5kZXJlZC4gV2UgbmVlZCB0byBkbyB0aGlzIGZvclxuICAgICAgICAgKiBjb21wYXRhYmlsaXR5IHdpdGggb3RoZXIgcGx1Z2lucy5cbiAgICAgICAgICpcbiAgICAgICAgICogSWYgdGhlIG11bHRpLWNvbHVtbiByZWdpb24gaXMgcmVuZGVyZWQgYmVmb3JlIG90aGVyIHBsdWdpbnMgdGhhdCBlZmZlY3RcbiAgICAgICAgICogY29udGVudCB3aXRoaW4gdGhlIHJlZ2lvbiBvdXIgcmVuZGVyZWQgZGF0YSBtYXkgbm90IHByb3Blcmx5IGRpc3BsYXlcbiAgICAgICAgICogdGhlIGNvbnRlbnQgZnJvbSB0aGUgb3RoZXIgcGx1Z2luLiBIZXJlIHdlIGxvb3AgdGhyb3VnaCB0aGUgZWxlbWVudHNcbiAgICAgICAgICogYWZ0ZXIgYWxsIHBsdWdpbnMgaGF2ZSBoYWQgYSBjaGFuY2UgdG8gcnVuIGFuZCBjYW4gbWFrZSBjaGFuZ2VzIHRvIHRoZVxuICAgICAgICAgKiBET00gYXQgdGhpcyBwb2ludC5cbiAgICAgICAgICovXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5kb21MaXN0Lmxlbmd0aDsgaSsrKSB7XG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogSGVyZSB3ZSBjaGVjayBmb3Igc3BlY2lhbCBjYXNlc1xuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBpZiAodGhpcy5kb21MaXN0W2ldIGluc3RhbmNlb2YgVGFza0xpc3RET01PYmplY3QpIHtcblxuICAgICAgICAgICAgICAgIHRoaXMuZml4Q2xvbmVkQ2hlY2tMaXN0QnV0dG9ucyh0aGlzLmRvbUxpc3RbaV0gYXMgVGFza0xpc3RET01PYmplY3QpO1xuICAgICAgICAgICAgfVxuXG5cbiAgICAgICAgICAgIGxldCBlbGVtZW50VHlwZSA9IHRoaXMuZG9tTGlzdFtpXS5lbGVtZW50VHlwZTtcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBJZiB0aGUgZWxlbWVudCBpcyBub3QgY3VycmVudGx5IGEgc3BlY2lhbCByZW5kZXIgZWxlbWVudCB3ZSBjaGVjayBhZ2FpblxuICAgICAgICAgICAgICogYXMgdGhlIG9yaWdpbmFsIGVsZW1lbnQgbWF5IGhhdmUgYmVlbiB1cGRhdGVkLlxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIFRPRE86IGZpbmQgYSB3YXkgdG8gXCJPZmZpY2lhbGx5XCIgbWFyayBub3JtYWwgZWxlbWVudHMgcmF0aGVyIHRoYW5cbiAgICAgICAgICAgICAqIGNvbnRpbnVvdXNseSBzZWFyY2ggZm9yIHNwZWNpYWwgcmVuZGVyIHR5cGVzLlxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBpZiAoZWxlbWVudFR5cGUgIT09IEVsZW1lbnRSZW5kZXJUeXBlLnNwZWNpYWxSZW5kZXIgJiZcbiAgICAgICAgICAgICAgICBlbGVtZW50VHlwZSAhPT0gRWxlbWVudFJlbmRlclR5cGUuc3BlY2lhbFNpbmdsZUVsZW1lbnRSZW5kZXIgJiYgXG4gICAgICAgICAgICAgICAgZWxlbWVudFR5cGUgIT09IEVsZW1lbnRSZW5kZXJUeXBlLnVuUmVuZGVyZWQpIHtcblxuICAgICAgICAgICAgICAgIC8vIElmIHRoZSBuZXcgcmVzdWx0IHJldHVybnMgYXMgYSBzcGVjaWFsIHJlbmRlcmVyIHdlIHVwZGF0ZSBzb1xuICAgICAgICAgICAgICAgIC8vIHRoaXMgd29udCBydW4gYWdhaW4gZm9yIHRoaXMgaXRlbS5cbiAgICAgICAgICAgICAgICBlbGVtZW50VHlwZSA9IGdldEVsZW1lbnRSZW5kZXJUeXBlKHRoaXMuZG9tTGlzdFtpXS5vcmlnaW5hbEVsZW1lbnQpO1xuICAgICAgICAgICAgICAgIHRoaXMuZG9tTGlzdFtpXS5vcmlnaW5hbEVsZW1lbnQuY2xpZW50SGVpZ2h0O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoZWxlbWVudFR5cGUgPT09IEVsZW1lbnRSZW5kZXJUeXBlLnNwZWNpYWxSZW5kZXIgfHxcbiAgICAgICAgICAgICAgICBlbGVtZW50VHlwZSA9PT0gRWxlbWVudFJlbmRlclR5cGUuc3BlY2lhbFNpbmdsZUVsZW1lbnRSZW5kZXIgfHwgXG4gICAgICAgICAgICAgICAgZWxlbWVudFR5cGUgPT09IEVsZW1lbnRSZW5kZXJUeXBlLmNhbnZhc1JlbmRlckVsZW1lbnQpIHtcblxuICAgICAgICAgICAgICAgIHRoaXMuZG9tTGlzdFtpXS5lbGVtZW50VHlwZSA9IGVsZW1lbnRUeXBlO1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0VXBEdWFsUmVuZGVyKHRoaXMuZG9tTGlzdFtpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIGZ1bmN0aW9uIHRha2VzIGluIHRoZSBvcmlnaW5hbCBlbGVtZW50IGFuZCBpdHMgY2xvbmUgYW5kIGNoZWNrcyBpZlxuICAgICAqIHRoZSBlbGVtZW50IGNvbnRhaW5zIGEgdGFzay1saXN0LWl0ZW0gY2xhc3MuIElmIHNvIGl0IGxvb3BzIHRocm91Z2ggYWxsXG4gICAgICogaXRlbXMgaW4gdGhlIGxpc3QgYW5kIGZpeGVzIHRoZWlyIGNoZWNrYm94ZXMgdG8gcHJvcGVybHkgZmlyZSBhbiBldmVudC5cbiAgICAgKiBUaGUgbmV3IGNoZWNrYm94IGNhbGxzIHRoZSBjbGljayBmdW5jdGlvbiBvbiB0aGUgb3JpZ2luYWwgY2hlY2tib3ggc29cbiAgICAgKiBjb21wYXRhYmlsaXR5IHdpdGggb3RoZXIgcGx1Z2lucyAqc2hvdWxkKiByZW1haW4uXG4gICAgICogQHBhcmFtIGRvbUVsZW1lbnRcbiAgICAgKiBAcGFyYW0gaW5pdGFsaXplQ2hlY2tib3hlc1xuICAgICAqL1xuICAgIHByb3RlY3RlZCBmaXhDbG9uZWRDaGVja0xpc3RCdXR0b25zKGRvbUVsZW1lbnQ6IFRhc2tMaXN0RE9NT2JqZWN0LCBpbml0YWxpemVDaGVja2JveGVzOiBib29sZWFuID0gZmFsc2UpIHtcblxuICAgICAgICBpZihkb21FbGVtZW50Lm9yaWdpbmFsRWxlbWVudCA9PT0gbnVsbCB8fCBkb21FbGVtZW50LmNsb25lZEVsZW1lbnQgPT09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBlbGVtZW50OiBIVE1MRWxlbWVudCA9IGRvbUVsZW1lbnQub3JpZ2luYWxFbGVtZW50O1xuICAgICAgICBsZXQgY2xvbmVkRWxlbWVudDogSFRNTEVsZW1lbnQgPSBkb21FbGVtZW50LmNsb25lZEVsZW1lbnQ7XG5cbiAgICAgICAgbGV0IGNsb25lZExpc3RDaGVja2JveGVzID0gQXJyYXkuZnJvbShjbG9uZWRFbGVtZW50LmdldEVsZW1lbnRzQnlDbGFzc05hbWUoXCJ0YXNrLWxpc3QtaXRlbVwiKSkgYXMgSFRNTEVsZW1lbnRbXTtcbiAgICAgICAgbGV0IG9yaWdpbmFsTGlzdENoZWNrYm94ZXMgPSBBcnJheS5mcm9tKGVsZW1lbnQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZShcInRhc2stbGlzdC1pdGVtXCIpKSBhcyBIVE1MRWxlbWVudFtdO1xuXG4gICAgICAgIGlmIChpbml0YWxpemVDaGVja2JveGVzID09PSB0cnVlKSB7XG5cbiAgICAgICAgICAgIC8vIFdoZW4gd2UgaW5pdGFsaXplIHdlIHJlbW92ZSB0aGUgb2xkIGlucHV0IGNoZWNrYm94IHRoYXQgY29udGFpbnNcbiAgICAgICAgICAgIC8vIHRoZSB3ZWlyZCBjYWxsYmFjayBzaXR1YXRpb24gY2F1c2luZyB0aGUgYnVnLiBUaGVuIHdlIGNyZWF0ZSBhIG5ld1xuICAgICAgICAgICAgLy8gY2hlY2tib3ggdG8gcmVwbGFjZSBpdCBhbmQgc2V0IGl0IHVwIHRvIGZpcmUgdGhlIGNsaWNrIGV2ZW50IG9uXG4gICAgICAgICAgICAvLyB0aGUgb3JpZ2luYWwgY2hlY2tib3ggc28gZnVuY3Rpb25hbGl0eSBpcyByZXN0b3JlZC5cbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgb3JpZ2luYWxMaXN0Q2hlY2tib3hlcy5sZW5ndGg7IGkrKykge1xuXG4gICAgICAgICAgICAgICAgY29uc3QgY2hlY2tib3ggPSBjcmVhdGVFbCgnaW5wdXQnKTtcblxuICAgICAgICAgICAgICAgIGxldCBvcmlnaW5hbElucHV0ID0gb3JpZ2luYWxMaXN0Q2hlY2tib3hlc1tpXS5maXJzdENoaWxkIGFzIEhUTUxJbnB1dEVsZW1lbnQ7XG5cbiAgICAgICAgICAgICAgICBjaGVja2JveC5jaGVja2VkID0gb3JpZ2luYWxJbnB1dC5jaGVja2VkO1xuICAgICAgICAgICAgICAgIGNsb25lZExpc3RDaGVja2JveGVzW2ldLnJlcGxhY2VDaGlsZChjaGVja2JveCwgY2xvbmVkTGlzdENoZWNrYm94ZXNbaV0uY2hpbGRyZW5bMF0pO1xuICAgICAgICAgICAgICAgIGNoZWNrYm94LmFkZENsYXNzKCd0YXNrLWxpc3QtaXRlbS1jaGVja2JveCcpO1xuICAgICAgICAgICAgICAgIGNoZWNrYm94LnR5cGUgPSAnY2hlY2tib3gnO1xuICAgICAgICAgICAgICAgIGNoZWNrYm94Lm9uQ2xpY2tFdmVudCgoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGRvbUVsZW1lbnQuY2hlY2tib3hDbGlja2VkKGkpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuXG4gICAgICAgICAgICAvLyBXaGVuZXZlciB3ZSByZWFjaCB0aGlzIHBvaW50IHdlIHVwZGF0ZSBvdXIgbGlzdCBvZiBvcmlnaW5hbCBjaGVja2JveGVzXG4gICAgICAgICAgICAvLyB0aGF0IG1heSBiZSBkaWZmZXJlbnQgZnJvbSBvdXIgY2FjaGUuIFRoaXMgaXMgZHVlIHRvIGhvdyBvYnNpZGlhblxuICAgICAgICAgICAgLy8gY2hhbmdlcyB0aGUgRE9NIHVuZGVybmVhdGggdXMgc28gd2UgbmVlZCB0byBjb25zdGFudGx5IHVwZGF0ZSBvdXIgY2FjaGUuXG4gICAgICAgICAgICBkb21FbGVtZW50Lm9yaWdpbmFsQ2hlY2tib3hlcyA9IG9yaWdpbmFsTGlzdENoZWNrYm94ZXM7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBXaGVuIHRoZSBUYXNrcyBwbHVnaW4gaXMgaW5zdGFsbGVkIHRoZSBjbG9uZWQgY29weSBvZiB0aGUgb3JpZ2luYWwgZWxlbWVudCBjb250YWluc1xuICAgICAgICAvLyBhbiBleHRyYSBlbGVtZW50IGZvciBzb21lIHJlYXNvbi4gSWYgdGhpcyBvY2N1cnMgZm9yIG90aGVyIHJlYXNvbnMgaGVyZSB3ZSBhZGp1c3RcbiAgICAgICAgLy8gdGhhdCB0byBrZWVwIHRoZSBjbG9uZSB0aGUgc2FtZSBhcyB0aGUgb3JpZ2luYWwuXG4gICAgICAgIGlmIChjbG9uZWRMaXN0Q2hlY2tib3hlcy5sZW5ndGggPiBvcmlnaW5hbExpc3RDaGVja2JveGVzLmxlbmd0aCkge1xuXG4gICAgICAgICAgICBmb3IgKGxldCBpID0gb3JpZ2luYWxMaXN0Q2hlY2tib3hlcy5sZW5ndGg7IGkgPCBjbG9uZWRMaXN0Q2hlY2tib3hlcy5sZW5ndGg7IGkrKykge1xuXG4gICAgICAgICAgICAgICAgZG9tRWxlbWVudC5jbG9uZWRFbGVtZW50LnJlbW92ZUNoaWxkKGNsb25lZExpc3RDaGVja2JveGVzW2ldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByb3RlY3RlZCBzZXRVcER1YWxSZW5kZXIoZG9tRWxlbWVudDogRE9NT2JqZWN0KSB7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIElmIG91ciBlbGVtZW50IGlzIG9mIFwic3BlY2lhbFJlbmRlclwiIHR5cGUgaXQgKm1heSogbmVlZCB0byBiZSByZW5kZXJlZFxuICAgICAgICAgKiB1c2luZyB0aGUgb3JpZ2luYWwgZWxlbWVudCByYXRoZXIgdGhhbiBhIGNvcHkuIEZvciBleGFtcGxlLCBhbiBlbGVtZW50XG4gICAgICAgICAqIG1heSBoYXZlIGFuIG9uQ2xpY2sgZXZlbnQgdGhhdCB3b3VsZCBub3QgZ2V0IGNvcHBpZWQgdG8gdGhlIGNsb25lLlxuICAgICAgICAgKlxuICAgICAgICAgKiBJZiB3ZSBqdXN0IG1vdmVkIHRoZXNlIGVsZW1lbnRzIGludG8gdGhlIHJlZ2lvbiBpdCB3b3VsZCBnZXRcbiAgICAgICAgICogbW92ZWQgYmFjayBvdXQgaW50byB0aGUgb3JpZ2luYWwgbG9jYXRpb24gaW4gdGhlIERPTSBieSBvYnNpZGlhblxuICAgICAgICAgKiB3aGVuIHNjcm9sbGluZyBvciB3aGVuIHRoZSBmaWxlIGlzIHVwZGF0ZWQuIE9uIHRoZSBuZXh0IHJlZnJlc2ggaXRcbiAgICAgICAgICogd291bGQgYmUgbW92ZWQgYmFjayBidXQgdGhhdCBjYW4gbGVhZCB0byBhIHJlZ2lvbiBqdW1waW5nXG4gICAgICAgICAqIGFyb3VuZCBhcyB0aGUgaXRlbSBpcyBtb3ZlZCBpbiBhbmQgb3V0LlxuICAgICAgICAgKlxuICAgICAgICAgKiBIZXJlIHdlIHNldCB1cCB0aGUgZGl2IHRvIGNvbnRhaW4gdGhlIGVsZW1lbnQgYW5kIGNyZWF0ZVxuICAgICAgICAgKiBhIHZpc3VhbCBvbmx5IGNsb25lIG9mIGl0LiBUaGUgY2xvbmUgd2lsbCBvbmx5IGJlIHZpc2libGVcbiAgICAgICAgICogd2hlbiB0aGUgb3JpZ2luYWwgaXMgbm90IGluIHRoZSBtdWx0aS1jb2x1bW4gcmVnaW9uIHNvIGl0XG4gICAgICAgICAqIHNhdmVzIHVzIGZyb20gdGhlIHZpc3VhbCBub2lzZSBvZiB0aGUgcmVnaW9uIGp1bXBpbmcgYXJvdW5kLlxuICAgICAgICAgKi9cblxuICAgICAgICAgbGV0IG9yaWdpbmFsRWxlbWVudCA9IGRvbUVsZW1lbnQub3JpZ2luYWxFbGVtZW50O1xuICAgICAgICAgbGV0IGNsb25lZEVsZW1lbnQgPSBkb21FbGVtZW50LmNsb25lZEVsZW1lbnQ7XG4gICAgICAgICBsZXQgY29udGFpbmVyRWxlbWVudDogSFRNTERpdkVsZW1lbnQgPSBkb21FbGVtZW50LmVsZW1lbnRDb250YWluZXI7XG5cbiAgICAgICAgLy8gR2V0IGhlaWdodCBvZiB0aGUgb3JpZ2luYWwgYW5kIGNsb25lZCBlbGVtZW50LiBJZiB0aGUgZWxlbWVudCBpcyBub3QgY3VycmVudGx5IHJlbmRlcmVkXG4gICAgICAgIC8vIGl0IHdpbGwgaGF2ZSAwIGhlaWdodCBzbyB3ZSBuZWVkIHRvIHRlbXBvcmFyaWx5IHJlbmRlciBpdCB0byBnZXQgdGhlIGhlaWdodC5cbiAgICAgICAgbGV0IG9yaWdpbmFsRWxlbWVudEhlaWdodCA9IGdldEVsZW1lbnRDbGllbnRIZWlnaHQob3JpZ2luYWxFbGVtZW50LCBjb250YWluZXJFbGVtZW50KTtcbiAgICAgICAgbGV0IGNsb25lZEVsZW1lbnRIZWlnaHQgPSBnZXRFbGVtZW50Q2xpZW50SGVpZ2h0KGNsb25lZEVsZW1lbnQsIGNvbnRhaW5lckVsZW1lbnQpO1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBXZSBvbmx5IHdhbnQgdG8gY2xvbmUgdGhlIGVsZW1lbnQgb25jZSB0byByZWR1Y2UgR0MuIEJ1dCBpZiB0aGUgY2xvbmVkIFxuICAgICAgICAgKiBlbGVtZW50J3MgaGVpZ2h0IGlzIG5vdCBlcXVhbCB0byB0aGUgb3JpZ2luYWwgZWxlbWVudCwgdGhpcyBtZWFucyB0aGVcbiAgICAgICAgICogaXRlbSBlbGVtZW50IGhhcyBiZWVuIHVwZGF0ZWQgc29tZXdoZXJlIGVsc2Ugd2l0aG91dCB0aGUgZG9tIGJlaW5nIFxuICAgICAgICAgKiByZWZyZXNoZWQuIFRoaXMgY2FuIG9jY3VyIHdoZW4gZWxlbWVudHMgYXJlIHVwZGF0ZWQgYnkgb3RoZXIgcGx1Z2lucywgXG4gICAgICAgICAqIHN1Y2ggYXMgRGF0YXZpZXcuXG4gICAgICAgICAqL1xuICAgICAgICBpZigoY2xvbmVkRWxlbWVudCA9PT0gbnVsbCAgfHwgXG4gICAgICAgICAgIE1hdGguYWJzKGNsb25lZEVsZW1lbnRIZWlnaHQgLSBvcmlnaW5hbEVsZW1lbnRIZWlnaHQpID4gMTAgfHxcbiAgICAgICAgICAgZG9tRWxlbWVudC5jbG9uZWRFbGVtZW50UmVhZHlGb3JVcGRhdGUoKSA9PT0gdHJ1ZSkgJiZcbiAgICAgICAgICAgZG9tRWxlbWVudC5lbGVtZW50VHlwZSAhPT0gRWxlbWVudFJlbmRlclR5cGUuY2FudmFzUmVuZGVyRWxlbWVudCkge1xuICAgICAgICAgICAgXG4gICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhcIlVwZGF0aW5nIENsb25lZCBFbGVtZW50LlwiLCBjbG9uZWRFbGVtZW50SGVpZ2h0LCBvcmlnaW5hbEVsZW1lbnRIZWlnaHQpXG4gICAgICAgICAgICAvLyBVcGRhdGUgY2xvbmUgYW5kIHJlZmVyZW5jZS5cbiAgICAgICAgICAgIGNsb25lRWxlbWVudCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoZG9tRWxlbWVudC5lbGVtZW50VHlwZSA9PT0gRWxlbWVudFJlbmRlclR5cGUuY2FudmFzUmVuZGVyRWxlbWVudCAmJiBcbiAgICAgICAgICAgZG9tRWxlbWVudC5jYW52YXNSZWFkeUZvclVwZGF0ZSgpKSB7XG5cbiAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKFwiVXBkYXRpbmcgY2FudmFzIHJlLXJlbmRlclwiKVxuICAgICAgICAgICAgY29udGFpbmVyRWxlbWVudC5hcHBlbmRDaGlsZChvcmlnaW5hbEVsZW1lbnQpO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBjbG9uZUNhbnZhcyhvcmlnaW5hbENhbnZhczogSFRNTENhbnZhc0VsZW1lbnQpOiBIVE1MQ2FudmFzRWxlbWVudCB7XG5cbiAgICAgICAgICAgICAgICAvL2NyZWF0ZSBhIG5ldyBjYW52YXNcbiAgICAgICAgICAgICAgICBsZXQgY2xvbmVkQ2FudmFzOiBIVE1MQ2FudmFzRWxlbWVudCA9IG9yaWdpbmFsQ2FudmFzLmNsb25lTm9kZSh0cnVlKSBhcyBIVE1MQ2FudmFzRWxlbWVudDtcbiAgICAgICAgICAgICAgICBsZXQgY29udGV4dDogQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJEID0gY2xvbmVkQ2FudmFzLmdldENvbnRleHQoJzJkJyk7XG4gICAgICAgICAgICBcbiAgICAgICAgICAgICAgICAvL3NldCBkaW1lbnNpb25zXG4gICAgICAgICAgICAgICAgY2xvbmVkQ2FudmFzLndpZHRoID0gb3JpZ2luYWxDYW52YXMud2lkdGg7XG4gICAgICAgICAgICAgICAgY2xvbmVkQ2FudmFzLmhlaWdodCA9IG9yaWdpbmFsQ2FudmFzLmhlaWdodDtcblxuICAgICAgICAgICAgICAgIGlmKGNsb25lZENhbnZhcy53aWR0aCA9PT0gMCB8fCBjbG9uZWRDYW52YXMuaGVpZ2h0ID09PSAwKXtcbiAgICAgICAgICAgICAgICAgICAgLy8gRG9udCB3YW50IHRvIHJlbmRlciBpZiB0aGUgd2lkdGggaXMgMCBhcyBpdCB0aHJvd3MgYW4gZXJyb3JcbiAgICAgICAgICAgICAgICAgICAgLy8gd291bGQgaGFwcGVuIGlmIHRoZSBvbGQgY2FudmFzIGhhc250IGJlZW4gcmVuZGVyZWQgeWV0LlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gY2xvbmVkQ2FudmFzO1xuICAgICAgICAgICAgICAgIH0gXG5cbiAgICAgICAgICAgICAgICAvL2FwcGx5IHRoZSBvbGQgY2FudmFzIHRvIHRoZSBuZXcgb25lXG4gICAgICAgICAgICAgICAgY29udGV4dC5kcmF3SW1hZ2Uob3JpZ2luYWxDYW52YXMsIDAsIDApO1xuICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgLy9yZXR1cm4gdGhlIG5ldyBjYW52YXNcbiAgICAgICAgICAgICAgICByZXR1cm4gY2xvbmVkQ2FudmFzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBsZXQgY2FudmFzID0gc2VhcmNoQ2hpbGRyZW5Gb3JOb2RlVHlwZShvcmlnaW5hbEVsZW1lbnQsIFwiY2FudmFzXCIpO1xuICAgICAgICAgICAgaWYoY2FudmFzICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgZG9tRWxlbWVudC51cGRhdGVDbG9uZWRFbGVtZW50KG9yaWdpbmFsRWxlbWVudC5jbG9uZU5vZGUodHJ1ZSkgYXMgSFRNTERpdkVsZW1lbnQpO1xuICAgICAgICAgICAgICAgIGNsb25lZEVsZW1lbnQgPSBkb21FbGVtZW50LmNsb25lZEVsZW1lbnQ7XG4gICAgICAgICAgICAgICAgY2xvbmVkRWxlbWVudC5hZGRDbGFzcyhNdWx0aUNvbHVtbkxheW91dENTUy5DbG9uZWRFbGVtZW50VHlwZSk7XG4gICAgICAgICAgICAgICAgY2xvbmVkRWxlbWVudC5yZW1vdmVDbGFzc2VzKFtNdWx0aUNvbHVtblN0eWxlQ1NTLlJlZ2lvbkNvbnRlbnQsIE11bHRpQ29sdW1uTGF5b3V0Q1NTLk9yaWdpbmFsRWxlbWVudFR5cGVdKTtcbiAgICAgICAgICAgICAgICBjb250YWluZXJFbGVtZW50LmFwcGVuZENoaWxkKGNsb25lZEVsZW1lbnQpO1xuXG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IGNsb25lZEVsZW1lbnQuY2hpbGRyZW4ubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICAgICAgICAgICAgY2xvbmVkRWxlbWVudC5jaGlsZHJlbltpXS5kZXRhY2goKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2xvbmVkRWxlbWVudC5hcHBlbmRDaGlsZChjbG9uZUNhbnZhcyhjYW52YXMgYXMgSFRNTENhbnZhc0VsZW1lbnQpKVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjb250YWluZXJFbGVtZW50LnJlbW92ZUNoaWxkKG9yaWdpbmFsRWxlbWVudCk7XG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgIC8qKiBcbiAgICAgICAgICogSWYgdGhlIGNvbnRhaW5lciBlbGVtZW50IGhhcyBsZXNzIHRoYW4gMiBjaGlsZHJlbiB3ZSBuZWVkIHRvIG1vdmUgdGhlXG4gICAgICAgICAqIG9yaWdpbmFsIGVsZW1lbnQgYmFjayBpbnRvIGl0LiBIb3dldmVyIHNvbWUgZWxlbWVudHMgY29uc3RhbnRseSBnZXQgbW92ZWRcbiAgICAgICAgICogaW4gYW5kIG91dCBjYXVzaW5nIHNvbWUgdW53YW50ZWQgYmVoYXZpb3IuIFRob3NlIGVsZW1lbnQgd2lsbCBiZSB0YWdnZWRcbiAgICAgICAgICogYXMgc3BlY2lhbFNpbmdsZUVsZW1lbnRSZW5kZXIgc28gd2UgaWdub3JlIHRob3NlIGVsZW1lbnRzIGhlcmUuXG4gICAgICAgICAqL1xuICAgICAgICBpZihkb21FbGVtZW50LmVsZW1lbnRDb250YWluZXIuY2hpbGRyZW4ubGVuZ3RoIDwgMiAmJiBcbiAgICAgICAgICAgZG9tRWxlbWVudC5lbGVtZW50VHlwZSAhPT0gRWxlbWVudFJlbmRlclR5cGUuc3BlY2lhbFNpbmdsZUVsZW1lbnRSZW5kZXIgJiZcbiAgICAgICAgICAgZG9tRWxlbWVudC5lbGVtZW50VHlwZSAhPT0gRWxlbWVudFJlbmRlclR5cGUuY2FudmFzUmVuZGVyRWxlbWVudCkge1xuXG4gICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhcIlVwZGF0aW5nIGR1YWwgcmVuZGVyaW5nLlwiLCBkb21FbGVtZW50LCBkb21FbGVtZW50Lm9yaWdpbmFsRWxlbWVudC5wYXJlbnRFbGVtZW50LCBkb21FbGVtZW50Lm9yaWdpbmFsRWxlbWVudC5wYXJlbnRFbGVtZW50Py5jaGlsZEVsZW1lbnRDb3VudCk7XG5cbiAgICAgICAgICAgIC8vIE1ha2Ugc3VyZSBvdXIgQ1NTIGlzIHVwIHRvIGRhdGUuXG4gICAgICAgICAgICBvcmlnaW5hbEVsZW1lbnQuYWRkQ2xhc3MoTXVsdGlDb2x1bW5MYXlvdXRDU1MuT3JpZ2luYWxFbGVtZW50VHlwZSk7XG4gICAgICAgICAgICBjbG9uZWRFbGVtZW50LmFkZENsYXNzKE11bHRpQ29sdW1uTGF5b3V0Q1NTLkNsb25lZEVsZW1lbnRUeXBlKTtcbiAgICAgICAgICAgIGNsb25lZEVsZW1lbnQucmVtb3ZlQ2xhc3NlcyhbTXVsdGlDb2x1bW5TdHlsZUNTUy5SZWdpb25Db250ZW50LCBNdWx0aUNvbHVtbkxheW91dENTUy5PcmlnaW5hbEVsZW1lbnRUeXBlXSk7XG4gICAgXG4gICAgICAgICAgICBmb3IgKGxldCBpID0gY29udGFpbmVyRWxlbWVudC5jaGlsZHJlbi5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICAgICAgICAgIGNvbnRhaW5lckVsZW1lbnQuY2hpbGRyZW5baV0uZGV0YWNoKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb250YWluZXJFbGVtZW50LmFwcGVuZENoaWxkKG9yaWdpbmFsRWxlbWVudCk7XG4gICAgICAgICAgICBjb250YWluZXJFbGVtZW50LmFwcGVuZENoaWxkKGNsb25lZEVsZW1lbnQpO1xuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gY2xvbmVFbGVtZW50KCkge1xuICAgICAgICAgICAgZG9tRWxlbWVudC51cGRhdGVDbG9uZWRFbGVtZW50KG9yaWdpbmFsRWxlbWVudC5jbG9uZU5vZGUodHJ1ZSkgYXMgSFRNTERpdkVsZW1lbnQpO1xuICAgICAgICAgICAgY2xvbmVkRWxlbWVudCA9IGRvbUVsZW1lbnQuY2xvbmVkRWxlbWVudDtcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBJZiB3ZSB1cGRhdGVkIHRoZSBjbG9uZWQgZWxlbWVudCwgd2Ugd2FudCB0byBhbHNvIHVwZGF0ZSB0aGVcbiAgICAgICAgICAgICAqIGVsZW1lbnQgcmVuZGVyZWQgaW4gdGhlIHBhcmVudCBjb250YWluZXIuXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGZvciAobGV0IGkgPSBjb250YWluZXJFbGVtZW50LmNoaWxkcmVuLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgICAgICAgICAgY29udGFpbmVyRWxlbWVudC5jaGlsZHJlbltpXS5kZXRhY2goKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gVXBkYXRlIENTUywgd2UgYWRkIGNsb25lZCBjbGFzcyBhbmQgcmVtb3ZlIGNsYXNzZXMgZnJvbSBvcmlnaW5hbEVsZW1lbnQgdGhhdCBkbyBub3QgYXBwbHkuXG4gICAgICAgICAgICBjbG9uZWRFbGVtZW50LmFkZENsYXNzKE11bHRpQ29sdW1uTGF5b3V0Q1NTLkNsb25lZEVsZW1lbnRUeXBlKTtcbiAgICAgICAgICAgIGNsb25lZEVsZW1lbnQucmVtb3ZlQ2xhc3NlcyhbTXVsdGlDb2x1bW5TdHlsZUNTUy5SZWdpb25Db250ZW50LCBNdWx0aUNvbHVtbkxheW91dENTUy5PcmlnaW5hbEVsZW1lbnRUeXBlXSk7XG4gICAgICAgICAgICBjb250YWluZXJFbGVtZW50LmFwcGVuZENoaWxkKGNsb25lZEVsZW1lbnQpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB1cCB0aGUgQ1NTIGNsYXNzZXMgYW5kIHRoZSBudW1iZXIgb2YgY29sdW1ucyBiYXNlZCBvbiB0aGUgcGFzc2VkIHNldHRpbmdzLlxuICAgICAqIEBwYXJhbSBzZXR0aW5ncyBUaGUgdXNlciBkZWZpbmVkIHNldHRpbmdzIHRoYXQgZGV0ZXJtaW5lIHdoYXQgQ1NTIGlzIHNldCBoZXJlLlxuICAgICAqIEBwYXJhbSBtdWx0aUNvbHVtblBhcmVudCBUaGUgcGFyZW50IG9iamVjdCB0aGF0IHRoZSBjb2x1bW4gZGl2cyB3aWxsIGJlIGNyZWF0ZWQgdW5kZXIuXG4gICAgICogQHJldHVybnMgVGhlIGxpc3Qgb2YgY29sdW1uIGRpdnMgY3JlYXRlZCB1bmRlciB0aGUgcGFzc2VkIHBhcmVudCBlbGVtZW50LlxuICAgICAqL1xuICAgIGdldENvbHVtbkNvbnRlbnREaXZzKHNldHRpbmdzOiBNdWx0aUNvbHVtblNldHRpbmdzLCBtdWx0aUNvbHVtblBhcmVudDogSFRNTERpdkVsZW1lbnQpOiBIVE1MRGl2RWxlbWVudFtdIHtcblxuICAgICAgICBsZXQgY29sdW1uQ29udGVudERpdnM6IEhUTUxEaXZFbGVtZW50W10gPSBbXVxuICAgICAgICBsZXQgc3R5bGVTdHI6IHN0cmluZyA9IFwiXCJcbiAgICAgICAgaWYoc2V0dGluZ3MuY29sdW1uU3BhY2luZyAhPT0gXCJcIikge1xuXG4gICAgICAgICAgICBzdHlsZVN0ciA9IGBtYXJnaW4taW5saW5lOiAke3NldHRpbmdzLmNvbHVtblNwYWNpbmd9O2BcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKHNldHRpbmdzLm51bWJlck9mQ29sdW1ucyA9PT0gMikge1xuXG4gICAgICAgICAgICBzd2l0Y2goc2V0dGluZ3MuY29sdW1uTGF5b3V0KSB7XG4gICAgICAgICAgICAgICAgY2FzZShDb2x1bW5MYXlvdXQuc3RhbmRhcmQpOlxuICAgICAgICAgICAgICAgIGNhc2UoQ29sdW1uTGF5b3V0Lm1pZGRsZSk6XG4gICAgICAgICAgICAgICAgY2FzZShDb2x1bW5MYXlvdXQuY2VudGVyKTpcbiAgICAgICAgICAgICAgICBjYXNlKENvbHVtbkxheW91dC50aGlyZCk6XG4gICAgICAgICAgICAgICAgICAgIGNvbHVtbkNvbnRlbnREaXZzLnB1c2gobXVsdGlDb2x1bW5QYXJlbnQuY3JlYXRlRGl2KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsczogYCR7TXVsdGlDb2x1bW5TdHlsZUNTUy5Db2x1bW5Db250ZW50fSAke011bHRpQ29sdW1uTGF5b3V0Q1NTLlR3b0VxdWFsQ29sdW1uc31gXG4gICAgICAgICAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgICAgICAgICAgbXVsdGlDb2x1bW5QYXJlbnQuY3JlYXRlRGl2KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsczogYG1jbS1jb2x1bW4tc3BhY2VyYCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGF0dHI6IHtcInN0eWxlXCI6IHN0eWxlU3RyfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgY29sdW1uQ29udGVudERpdnMucHVzaChtdWx0aUNvbHVtblBhcmVudC5jcmVhdGVEaXYoe1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xzOiBgJHtNdWx0aUNvbHVtblN0eWxlQ1NTLkNvbHVtbkNvbnRlbnR9ICR7TXVsdGlDb2x1bW5MYXlvdXRDU1MuVHdvRXF1YWxDb2x1bW5zfWBcbiAgICAgICAgICAgICAgICAgICAgfSkpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgIGNhc2UoQ29sdW1uTGF5b3V0LmxlZnQpOlxuICAgICAgICAgICAgICAgIGNhc2UoQ29sdW1uTGF5b3V0LmZpcnN0KTpcbiAgICAgICAgICAgICAgICAgICAgY29sdW1uQ29udGVudERpdnMucHVzaChtdWx0aUNvbHVtblBhcmVudC5jcmVhdGVEaXYoe1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xzOiBgJHtNdWx0aUNvbHVtblN0eWxlQ1NTLkNvbHVtbkNvbnRlbnR9ICR7TXVsdGlDb2x1bW5MYXlvdXRDU1MuVHdvQ29sdW1uTGFyZ2V9YFxuICAgICAgICAgICAgICAgICAgICB9KSk7XG4gICAgICAgICAgICAgICAgICAgIG11bHRpQ29sdW1uUGFyZW50LmNyZWF0ZURpdih7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbHM6IGBtY20tY29sdW1uLXNwYWNlcmAsXG4gICAgICAgICAgICAgICAgICAgICAgICBhdHRyOiB7XCJzdHlsZVwiOiBzdHlsZVN0cn1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIGNvbHVtbkNvbnRlbnREaXZzLnB1c2gobXVsdGlDb2x1bW5QYXJlbnQuY3JlYXRlRGl2KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsczogYCR7TXVsdGlDb2x1bW5TdHlsZUNTUy5Db2x1bW5Db250ZW50fSAke011bHRpQ29sdW1uTGF5b3V0Q1NTLlR3b0NvbHVtblNtYWxsfWBcbiAgICAgICAgICAgICAgICAgICAgfSkpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgIGNhc2UoQ29sdW1uTGF5b3V0LnJpZ2h0KTpcbiAgICAgICAgICAgICAgICBjYXNlKENvbHVtbkxheW91dC5zZWNvbmQpOlxuICAgICAgICAgICAgICAgIGNhc2UoQ29sdW1uTGF5b3V0Lmxhc3QpOlxuICAgICAgICAgICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2cy5wdXNoKG11bHRpQ29sdW1uUGFyZW50LmNyZWF0ZURpdih7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbHM6IGAke011bHRpQ29sdW1uU3R5bGVDU1MuQ29sdW1uQ29udGVudH0gJHtNdWx0aUNvbHVtbkxheW91dENTUy5Ud29Db2x1bW5TbWFsbH1gXG4gICAgICAgICAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgICAgICAgICAgbXVsdGlDb2x1bW5QYXJlbnQuY3JlYXRlRGl2KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsczogYG1jbS1jb2x1bW4tc3BhY2VyYCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGF0dHI6IHtcInN0eWxlXCI6IHN0eWxlU3RyfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgY29sdW1uQ29udGVudERpdnMucHVzaChtdWx0aUNvbHVtblBhcmVudC5jcmVhdGVEaXYoe1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xzOiBgJHtNdWx0aUNvbHVtblN0eWxlQ1NTLkNvbHVtbkNvbnRlbnR9ICR7TXVsdGlDb2x1bW5MYXlvdXRDU1MuVHdvQ29sdW1uTGFyZ2V9YFxuICAgICAgICAgICAgICAgICAgICB9KSk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYoc2V0dGluZ3MubnVtYmVyT2ZDb2x1bW5zID09PSAzKSB7XG5cbiAgICAgICAgICAgIHN3aXRjaChzZXR0aW5ncy5jb2x1bW5MYXlvdXQpIHtcbiAgICAgICAgICAgICAgICBjYXNlKENvbHVtbkxheW91dC5zdGFuZGFyZCk6XG4gICAgICAgICAgICAgICAgICAgIGNvbHVtbkNvbnRlbnREaXZzLnB1c2gobXVsdGlDb2x1bW5QYXJlbnQuY3JlYXRlRGl2KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsczogYCR7TXVsdGlDb2x1bW5TdHlsZUNTUy5Db2x1bW5Db250ZW50fSAke011bHRpQ29sdW1uTGF5b3V0Q1NTLlRocmVlRXF1YWxDb2x1bW5zfWBcbiAgICAgICAgICAgICAgICAgICAgfSkpO1xuICAgICAgICAgICAgICAgICAgICBtdWx0aUNvbHVtblBhcmVudC5jcmVhdGVEaXYoe1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xzOiBgbWNtLWNvbHVtbi1zcGFjZXJgLFxuICAgICAgICAgICAgICAgICAgICAgICAgYXR0cjoge1wic3R5bGVcIjogc3R5bGVTdHJ9XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2cy5wdXNoKG11bHRpQ29sdW1uUGFyZW50LmNyZWF0ZURpdih7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbHM6IGAke011bHRpQ29sdW1uU3R5bGVDU1MuQ29sdW1uQ29udGVudH0gJHtNdWx0aUNvbHVtbkxheW91dENTUy5UaHJlZUVxdWFsQ29sdW1uc31gXG4gICAgICAgICAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgICAgICAgICAgbXVsdGlDb2x1bW5QYXJlbnQuY3JlYXRlRGl2KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsczogYG1jbS1jb2x1bW4tc3BhY2VyYCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGF0dHI6IHtcInN0eWxlXCI6IHN0eWxlU3RyfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgY29sdW1uQ29udGVudERpdnMucHVzaChtdWx0aUNvbHVtblBhcmVudC5jcmVhdGVEaXYoe1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xzOiBgJHtNdWx0aUNvbHVtblN0eWxlQ1NTLkNvbHVtbkNvbnRlbnR9ICR7TXVsdGlDb2x1bW5MYXlvdXRDU1MuVGhyZWVFcXVhbENvbHVtbnN9YFxuICAgICAgICAgICAgICAgICAgICB9KSk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgY2FzZShDb2x1bW5MYXlvdXQubGVmdCk6XG4gICAgICAgICAgICAgICAgY2FzZShDb2x1bW5MYXlvdXQuZmlyc3QpOlxuICAgICAgICAgICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2cy5wdXNoKG11bHRpQ29sdW1uUGFyZW50LmNyZWF0ZURpdih7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbHM6IGAke011bHRpQ29sdW1uU3R5bGVDU1MuQ29sdW1uQ29udGVudH0gJHtNdWx0aUNvbHVtbkxheW91dENTUy5UaHJlZUNvbHVtbl9MYXJnZX1gXG4gICAgICAgICAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgICAgICAgICAgbXVsdGlDb2x1bW5QYXJlbnQuY3JlYXRlRGl2KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsczogYG1jbS1jb2x1bW4tc3BhY2VyYCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGF0dHI6IHtcInN0eWxlXCI6IHN0eWxlU3RyfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgY29sdW1uQ29udGVudERpdnMucHVzaChtdWx0aUNvbHVtblBhcmVudC5jcmVhdGVEaXYoe1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xzOiBgJHtNdWx0aUNvbHVtblN0eWxlQ1NTLkNvbHVtbkNvbnRlbnR9ICR7TXVsdGlDb2x1bW5MYXlvdXRDU1MuVGhyZWVDb2x1bW5fU21hbGx9YFxuICAgICAgICAgICAgICAgICAgICB9KSk7XG4gICAgICAgICAgICAgICAgICAgIG11bHRpQ29sdW1uUGFyZW50LmNyZWF0ZURpdih7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbHM6IGBtY20tY29sdW1uLXNwYWNlcmAsXG4gICAgICAgICAgICAgICAgICAgICAgICBhdHRyOiB7XCJzdHlsZVwiOiBzdHlsZVN0cn1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIGNvbHVtbkNvbnRlbnREaXZzLnB1c2gobXVsdGlDb2x1bW5QYXJlbnQuY3JlYXRlRGl2KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsczogYCR7TXVsdGlDb2x1bW5TdHlsZUNTUy5Db2x1bW5Db250ZW50fSAke011bHRpQ29sdW1uTGF5b3V0Q1NTLlRocmVlQ29sdW1uX1NtYWxsfWBcbiAgICAgICAgICAgICAgICAgICAgfSkpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgIGNhc2UoQ29sdW1uTGF5b3V0Lm1pZGRsZSk6XG4gICAgICAgICAgICAgICAgY2FzZShDb2x1bW5MYXlvdXQuY2VudGVyKTpcbiAgICAgICAgICAgICAgICBjYXNlKENvbHVtbkxheW91dC5zZWNvbmQpOlxuICAgICAgICAgICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2cy5wdXNoKG11bHRpQ29sdW1uUGFyZW50LmNyZWF0ZURpdih7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbHM6IGAke011bHRpQ29sdW1uU3R5bGVDU1MuQ29sdW1uQ29udGVudH0gJHtNdWx0aUNvbHVtbkxheW91dENTUy5UaHJlZUNvbHVtbl9TbWFsbH1gXG4gICAgICAgICAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgICAgICAgICAgbXVsdGlDb2x1bW5QYXJlbnQuY3JlYXRlRGl2KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsczogYG1jbS1jb2x1bW4tc3BhY2VyYCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGF0dHI6IHtcInN0eWxlXCI6IHN0eWxlU3RyfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgY29sdW1uQ29udGVudERpdnMucHVzaChtdWx0aUNvbHVtblBhcmVudC5jcmVhdGVEaXYoe1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xzOiBgJHtNdWx0aUNvbHVtblN0eWxlQ1NTLkNvbHVtbkNvbnRlbnR9ICR7TXVsdGlDb2x1bW5MYXlvdXRDU1MuVGhyZWVDb2x1bW5fTGFyZ2V9YFxuICAgICAgICAgICAgICAgICAgICB9KSk7XG4gICAgICAgICAgICAgICAgICAgIG11bHRpQ29sdW1uUGFyZW50LmNyZWF0ZURpdih7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbHM6IGBtY20tY29sdW1uLXNwYWNlcmAsXG4gICAgICAgICAgICAgICAgICAgICAgICBhdHRyOiB7XCJzdHlsZVwiOiBzdHlsZVN0cn1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIGNvbHVtbkNvbnRlbnREaXZzLnB1c2gobXVsdGlDb2x1bW5QYXJlbnQuY3JlYXRlRGl2KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsczogYCR7TXVsdGlDb2x1bW5TdHlsZUNTUy5Db2x1bW5Db250ZW50fSAke011bHRpQ29sdW1uTGF5b3V0Q1NTLlRocmVlQ29sdW1uX1NtYWxsfWBcbiAgICAgICAgICAgICAgICAgICAgfSkpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgIGNhc2UoQ29sdW1uTGF5b3V0LnJpZ2h0KTpcbiAgICAgICAgICAgICAgICBjYXNlKENvbHVtbkxheW91dC50aGlyZCk6XG4gICAgICAgICAgICAgICAgY2FzZShDb2x1bW5MYXlvdXQubGFzdCk6XG4gICAgICAgICAgICAgICAgICAgIGNvbHVtbkNvbnRlbnREaXZzLnB1c2gobXVsdGlDb2x1bW5QYXJlbnQuY3JlYXRlRGl2KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsczogYCR7TXVsdGlDb2x1bW5TdHlsZUNTUy5Db2x1bW5Db250ZW50fSAke011bHRpQ29sdW1uTGF5b3V0Q1NTLlRocmVlQ29sdW1uX1NtYWxsfWBcbiAgICAgICAgICAgICAgICAgICAgfSkpO1xuICAgICAgICAgICAgICAgICAgICBtdWx0aUNvbHVtblBhcmVudC5jcmVhdGVEaXYoe1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xzOiBgbWNtLWNvbHVtbi1zcGFjZXJgLFxuICAgICAgICAgICAgICAgICAgICAgICAgYXR0cjoge1wic3R5bGVcIjogc3R5bGVTdHJ9XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2cy5wdXNoKG11bHRpQ29sdW1uUGFyZW50LmNyZWF0ZURpdih7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbHM6IGAke011bHRpQ29sdW1uU3R5bGVDU1MuQ29sdW1uQ29udGVudH0gJHtNdWx0aUNvbHVtbkxheW91dENTUy5UaHJlZUNvbHVtbl9TbWFsbH1gXG4gICAgICAgICAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgICAgICAgICAgbXVsdGlDb2x1bW5QYXJlbnQuY3JlYXRlRGl2KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsczogYG1jbS1jb2x1bW4tc3BhY2VyYCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGF0dHI6IHtcInN0eWxlXCI6IHN0eWxlU3RyfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgY29sdW1uQ29udGVudERpdnMucHVzaChtdWx0aUNvbHVtblBhcmVudC5jcmVhdGVEaXYoe1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xzOiBgJHtNdWx0aUNvbHVtblN0eWxlQ1NTLkNvbHVtbkNvbnRlbnR9ICR7TXVsdGlDb2x1bW5MYXlvdXRDU1MuVGhyZWVDb2x1bW5fTGFyZ2V9YFxuICAgICAgICAgICAgICAgICAgICB9KSk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGNvbHVtbkNvbnRlbnREaXZzO1xuICAgIH1cblxuICAgIHB1YmxpYyBhYnN0cmFjdCByZW5kZXJSZWdpb25FbGVtZW50c1RvU2NyZWVuKCk6IHZvaWQ7XG4gICAgcHVibGljIGFic3RyYWN0IGV4cG9ydFJlZ2lvbkVsZW1lbnRzVG9QREYocGRmUGFyZW50RWxlbWVudDogSFRNTEVsZW1lbnQpOiB2b2lkO1xuICAgIHB1YmxpYyBhYnN0cmFjdCByZW5kZXJSZWdpb25FbGVtZW50c1RvTGl2ZVByZXZpZXcocGFyZW50RWxlbWVudDogSFRNTEVsZW1lbnQpOiB2b2lkXG59XG5cblxuZnVuY3Rpb24gZ2V0RWxlbWVudENsaWVudEhlaWdodChlbGVtZW50OiBIVE1MRWxlbWVudCwgcGFyZW50UmVuZGVyRWxlbWVudDogSFRNTERpdkVsZW1lbnQpOiBudW1iZXIge1xuXG4gICAgbGV0IGhlaWdodCA9IGVsZW1lbnQuY2xpZW50SGVpZ2h0O1xuICAgIGlmKGhlaWdodCA9PT0gMCkge1xuICAgICAgICBwYXJlbnRSZW5kZXJFbGVtZW50LmFwcGVuZENoaWxkKGVsZW1lbnQpO1xuICAgICAgICBoZWlnaHQgPSBlbGVtZW50LmNsaWVudEhlaWdodFxuICAgICAgICBwYXJlbnRSZW5kZXJFbGVtZW50LnJlbW92ZUNoaWxkKGVsZW1lbnQpO1xuICAgIH1cbiAgICByZXR1cm4gaGVpZ2h0XG59IiwiLyoqXG4gKiBGaWxlOiAvc3JjL2RvbV9tYW5hZ2VyL3JlZ2lvbmFsX21hbmFnZXJzL3JlZ2lvbkRPTU1hbmFnZXIudHMgICAgICAgICAgICAgICAgKlxuICogQ3JlYXRlZCBEYXRlOiBTdW5kYXksIE1heSAyMm5kIDIwMjIsIDc6NDYgcG0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpcbiAqIEF1dGhvcjogQ2FtZXJvbiBSb2JpbnNvbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICogQ29weXJpZ2h0IChjKSAyMDIyIENhbWVyb24gUm9iaW5zb24gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpcbiAqL1xuXG5pbXBvcnQgeyBET01PYmplY3QsIERPTU9iamVjdFRhZywgVGFza0xpc3RET01PYmplY3QgfSBmcm9tICcuLi9kb21PYmplY3QnO1xuaW1wb3J0IHsgTXVsdGlDb2x1bW5TZXR0aW5ncywgQ29udGVudE92ZXJmbG93VHlwZSB9IGZyb20gXCIuLi8uLi9yZWdpb25TZXR0aW5nc1wiO1xuaW1wb3J0IHsgTXVsdGlDb2x1bW5MYXlvdXRDU1MsIE11bHRpQ29sdW1uU3R5bGVDU1MgfSBmcm9tICcuLi8uLi91dGlsaXRpZXMvY3NzRGVmaW5pdGlvbnMnO1xuaW1wb3J0IHsgTWFya2Rvd25SZW5kZXJDaGlsZCB9IGZyb20gJ29ic2lkaWFuJztcbmltcG9ydCB7IFJlZ2lvbk1hbmFnZXIgfSBmcm9tICcuL3JlZ2lvbk1hbmFnZXInO1xuaW1wb3J0IHsgZ2V0SGVhZGluZ0NvbGxhcHNlRWxlbWVudCB9IGZyb20gJ3NyYy91dGlsaXRpZXMvZWxlbWVudFJlbmRlclR5cGVQYXJzZXInO1xuXG5leHBvcnQgY2xhc3MgU3RhbmRhcmRNdWx0aUNvbHVtblJlZ2lvbk1hbmFnZXIgZXh0ZW5kcyBSZWdpb25NYW5hZ2VyIHtcblxuXG4gICAgcHVibGljIHJlbmRlclJlZ2lvbkVsZW1lbnRzVG9TY3JlZW4oKTogdm9pZCB7XG5cbiAgICAgICAgdGhpcy5yZW5kZXJDb2x1bW5NYXJrZG93bih0aGlzLnJlZ2lvblBhcmVudCwgdGhpcy5kb21MaXN0LCB0aGlzLnJlZ2lvbmFsU2V0dGluZ3MpO1xuICAgIH1cbiAgICBwdWJsaWMgZXhwb3J0UmVnaW9uRWxlbWVudHNUb1BERihwZGZQYXJlbnRFbGVtZW50OiBIVE1MRWxlbWVudCk6IHZvaWQge1xuXG4gICAgICAgIC8vIERlZmF1bHQgc2V0IHNoYWRvdyB0byBvZmYgZm9yIGV4cG9ydGluZyBQREZzXG4gICAgICAgIGxldCByZW5kZXJTZXR0aW5ncyA9IHRoaXMucmVnaW9uYWxTZXR0aW5ncztcbiAgICAgICAgcmVuZGVyU2V0dGluZ3MuZHJhd1NoYWRvdyA9IGZhbHNlO1xuICAgICAgICB0aGlzLnJlbmRlckNvbHVtbk1hcmtkb3duKHBkZlBhcmVudEVsZW1lbnQsIHRoaXMuZG9tTGlzdC5zbGljZSgpLCByZW5kZXJTZXR0aW5ncyk7XG4gICAgfVxuICAgIHB1YmxpYyByZW5kZXJSZWdpb25FbGVtZW50c1RvTGl2ZVByZXZpZXcocGFyZW50RWxlbWVudDogSFRNTEVsZW1lbnQpOiB2b2lkIHtcblxuICAgICAgICB0aGlzLnJlbmRlckNvbHVtbk1hcmtkb3duKHBhcmVudEVsZW1lbnQsIHRoaXMuZG9tTGlzdCwgdGhpcy5yZWdpb25hbFNldHRpbmdzKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogVGhpcyBmdW5jdGlvbiB0YWtlcyBpbiB0aGUgZGF0YSBmb3IgdGhlIG11bHRpLWNvbHVtbiByZWdpb24gYW5kIHNldHMgdXAgdGhlIFxuICAgICAqIHVzZXIgZGVmaW5lZCBudW1iZXIgb2YgY2hpbGRyZW4gd2l0aCB0aGUgcHJvcGVyIGNzcyBjbGFzc2VzIHRvIGJlIHJlbmRlcmVkIHByb3Blcmx5LlxuICAgICAqIFxuICAgICAqIEBwYXJhbSBwYXJlbnRFbGVtZW50IFRoZSBlbGVtZW50IHRoYXQgdGhlIG11bHRpLWNvbHVtbiByZWdpb24gd2lsbCBiZSByZW5kZXJlZCB1bmRlci5cbiAgICAgKiBAcGFyYW0gcmVnaW9uRWxlbWVudHMgVGhlIGxpc3Qgb2YgRE9NIG9iamVjdHMgdGhhdCB3aWxsIGJlIGNvcHBpZWQgdW5kZXIgdGhlIHBhcmVudCBvYmplY3RcbiAgICAgKiBAcGFyYW0gc2V0dGluZ3MgVGhlIHNldHRpbmdzIHRoZSB1c2VyIGhhcyBkZWZpbmVkIGZvciB0aGUgcmVnaW9uLlxuICAgICAqL1xuICAgIHByaXZhdGUgcmVuZGVyQ29sdW1uTWFya2Rvd24ocGFyZW50RWxlbWVudDogSFRNTEVsZW1lbnQsIHJlZ2lvbkVsZW1lbnRzOiBET01PYmplY3RbXSwgc2V0dGluZ3M6IE11bHRpQ29sdW1uU2V0dGluZ3MpIHtcblxuICAgICAgICBsZXQgbXVsdGlDb2x1bW5QYXJlbnQgPSBjcmVhdGVEaXYoe1xuICAgICAgICAgICAgY2xzOiBNdWx0aUNvbHVtbkxheW91dENTUy5SZWdpb25Db2x1bW5Db250YWluZXJEaXYsXG4gICAgICAgIH0pO1xuXG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFBhc3Mgb3VyIHBhcmVudCBkaXYgYW5kIHNldHRpbmdzIHRvIHBhcnNlciB0byBjcmVhdGUgdGhlIHJlcXVpcmVkXG4gICAgICAgICAqIGNvbHVtbiBkaXZzIGFzIGNoaWxkcmVuIG9mIHRoZSBwYXJlbnQuXG4gICAgICAgICAqL1xuICAgICAgICBsZXQgY29sdW1uQ29udGVudERpdnMgPSB0aGlzLmdldENvbHVtbkNvbnRlbnREaXZzKHNldHRpbmdzLCBtdWx0aUNvbHVtblBhcmVudCk7XG4gICAgICAgIGlmKHNldHRpbmdzLmRyYXdTaGFkb3cgPT09IHRydWUpIHtcbiAgICAgICAgICAgIG11bHRpQ29sdW1uUGFyZW50LmFkZENsYXNzKE11bHRpQ29sdW1uU3R5bGVDU1MuUmVnaW9uU2hhZG93KTtcbiAgICAgICAgfVxuICAgICAgICBmb3IobGV0IGkgPSAwOyBpIDwgY29sdW1uQ29udGVudERpdnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmKHNldHRpbmdzLmRyYXdCb3JkZXIgPT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2c1tpXS5hZGRDbGFzcyhNdWx0aUNvbHVtblN0eWxlQ1NTLkNvbHVtbkJvcmRlcik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKHNldHRpbmdzLmRyYXdTaGFkb3cgPT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2c1tpXS5hZGRDbGFzcyhNdWx0aUNvbHVtblN0eWxlQ1NTLkNvbHVtblNoYWRvdyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDcmVhdGUgbWFya2Rvd24gcmVuZGVyZXIgdG8gcGFyc2UgdGhlIHBhc3NlZCBtYXJrZG93blxuICAgICAgICAvLyBiZXR3ZWVuIHRoZSB0YWdzLlxuICAgICAgICBsZXQgbWFya2Rvd25SZW5kZXJDaGlsZCA9IG5ldyBNYXJrZG93blJlbmRlckNoaWxkKFxuICAgICAgICAgICAgbXVsdGlDb2x1bW5QYXJlbnRcbiAgICAgICAgKTtcblxuICAgICAgICAvLyBSZW1vdmUgZXZlcnkgb3RoZXIgY2hpbGQgZnJvbSB0aGUgcGFyZW50IHNvIFxuICAgICAgICAvLyB3ZSBkb250IGVuZCB1cCB3aXRoIG11bHRpcGxlIHNldHMgb2YgZGF0YS4gVGhpcyBzaG91bGRcbiAgICAgICAgLy8gcmVhbGx5IG9ubHkgbmVlZCB0byBsb29wIG9uY2UgZm9yIGkgPSAwIGJ1dCBsb29wIGp1c3RcbiAgICAgICAgLy8gaW4gY2FzZS5cbiAgICAgICAgZm9yKGxldCBpID0gcGFyZW50RWxlbWVudC5jaGlsZHJlbi5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICAgICAgcGFyZW50RWxlbWVudC5jaGlsZHJlbltpXS5kZXRhY2goKTtcbiAgICAgICAgfVxuICAgICAgICBwYXJlbnRFbGVtZW50LmFwcGVuZENoaWxkKG1hcmtkb3duUmVuZGVyQ2hpbGQuY29udGFpbmVyRWwpO1xuXG4gICAgICAgIHRoaXMuYXBwZW5kRWxlbWVudHNUb0NvbHVtbnMocmVnaW9uRWxlbWVudHMsIGNvbHVtbkNvbnRlbnREaXZzLCBzZXR0aW5ncyk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhcHBlbmRFbGVtZW50c1RvQ29sdW1ucyhyZWdpb25FbGVtZW50czogRE9NT2JqZWN0W10sIGNvbHVtbkNvbnRlbnREaXZzOiBIVE1MRGl2RWxlbWVudFtdLCBzZXR0aW5nczogTXVsdGlDb2x1bW5TZXR0aW5ncykge1xuXG4gICAgICAgIGxldCBjb2x1bW5JbmRleCA9IDA7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcmVnaW9uRWxlbWVudHMubGVuZ3RoOyBpKyspIHtcblxuICAgICAgICAgICAgaWYgKHJlZ2lvbkVsZW1lbnRzW2ldLnRhZyA9PT0gRE9NT2JqZWN0VGFnLm5vbmUgfHxcbiAgICAgICAgICAgICAgICByZWdpb25FbGVtZW50c1tpXS50YWcgPT09IERPTU9iamVjdFRhZy5jb2x1bW5CcmVhaykge1xuXG4gICAgICAgICAgICAgICAgLy8gV2Ugc3RvcmUgdGhlIGVsZW1lbnRzIGluIGEgd3JhcHBlciBjb250YWluZXIgdW50aWwgd2UgZGV0ZXJtaW5lXG4gICAgICAgICAgICAgICAgbGV0IGVsZW1lbnQgPSBjcmVhdGVEaXYoe1xuICAgICAgICAgICAgICAgICAgICBjbHM6IE11bHRpQ29sdW1uTGF5b3V0Q1NTLkNvbHVtbkR1YWxFbGVtZW50Q29udGFpbmVyLFxuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgaWYoc2V0dGluZ3MuY29udGVudE92ZXJmbG93ID09PSBDb250ZW50T3ZlcmZsb3dUeXBlLmhpZGRlbikge1xuICAgICAgICAgICAgICAgICAgICBlbGVtZW50LmFkZENsYXNzKE11bHRpQ29sdW1uTGF5b3V0Q1NTLkNvbnRlbnRPdmVyZmxvd0hpZGRlbilcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGVsZW1lbnQuYWRkQ2xhc3MoTXVsdGlDb2x1bW5MYXlvdXRDU1MuQ29udGVudE92ZXJmbG93QXV0b1Njcm9sbClcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZWdpb25FbGVtZW50c1tpXS5lbGVtZW50Q29udGFpbmVyID0gZWxlbWVudDtcblxuICAgICAgICAgICAgICAgIC8vIE90aGVyd2lzZSB3ZSBqdXN0IG1ha2UgYSBjb3B5IG9mIHRoZSBvcmlnaW5hbCBlbGVtZW50IHRvIGRpc3BsYXkuXG4gICAgICAgICAgICAgICAgbGV0IGNsb25lZEVsZW1lbnQgPSByZWdpb25FbGVtZW50c1tpXS5vcmlnaW5hbEVsZW1lbnQuY2xvbmVOb2RlKHRydWUpIGFzIEhUTUxEaXZFbGVtZW50O1xuICAgICAgICAgICAgICAgIGxldCBoZWFkaW5nQ29sbGFwc2VFbGVtZW50ID0gZ2V0SGVhZGluZ0NvbGxhcHNlRWxlbWVudChjbG9uZWRFbGVtZW50KTtcbiAgICAgICAgICAgICAgICBpZihoZWFkaW5nQ29sbGFwc2VFbGVtZW50ICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgcmVtb3ZlcyB0aGUgY29sbGFwc2UgYXJyb3cgZnJvbSB0aGUgdmlldyBpZiBpdCBleGlzdHMuXG4gICAgICAgICAgICAgICAgICAgIGhlYWRpbmdDb2xsYXBzZUVsZW1lbnQuZGV0YWNoKCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmVnaW9uRWxlbWVudHNbaV0uY2xvbmVkRWxlbWVudCA9IGNsb25lZEVsZW1lbnQ7XG4gICAgICAgICAgICAgICAgZWxlbWVudC5hcHBlbmRDaGlsZChjbG9uZWRFbGVtZW50KTtcblxuICAgICAgICAgICAgICAgIGlmIChyZWdpb25FbGVtZW50c1tpXSBpbnN0YW5jZW9mIFRhc2tMaXN0RE9NT2JqZWN0KSB7XG5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5maXhDbG9uZWRDaGVja0xpc3RCdXR0b25zKHJlZ2lvbkVsZW1lbnRzW2ldIGFzIFRhc2tMaXN0RE9NT2JqZWN0LCB0cnVlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoZWxlbWVudCAhPT0gbnVsbCAmJiByZWdpb25FbGVtZW50c1tpXS50YWcgIT09IERPTU9iamVjdFRhZy5jb2x1bW5CcmVhaykge1xuXG4gICAgICAgICAgICAgICAgICAgIGNvbHVtbkNvbnRlbnREaXZzW2NvbHVtbkluZGV4XS5hcHBlbmRDaGlsZChlbGVtZW50KTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAgICAgKiBJZiB0aGUgdGFnIGlzIGEgY29sdW1uIGJyZWFrIHdlIHVwZGF0ZSB0aGUgY29sdW1uIGluZGV4IGFmdGVyXG4gICAgICAgICAgICAgICAgICogYXBwZW5kaW5nIHRoZSBpdGVtIHRvIHRoZSBjb2x1bW4gZGl2LiBUaGlzIGtlZXBzIHRoZSBtYWluIERPTVxuICAgICAgICAgICAgICAgICAqIGNsZWFuZXIgYnkgcmVtb3Zpbmcgb3RoZXIgaXRlbXMgYW5kIHBsYWNpbmcgdGhlbSBhbGwgd2l0aGluXG4gICAgICAgICAgICAgICAgICogYSByZWdpb24gY29udGFpbmVyLlxuICAgICAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgICAgIGlmIChyZWdpb25FbGVtZW50c1tpXS50YWcgPT09IERPTU9iamVjdFRhZy5jb2x1bW5CcmVhayAmJlxuICAgICAgICAgICAgICAgICAgICAoY29sdW1uSW5kZXggKyAxKSA8IHNldHRpbmdzLm51bWJlck9mQ29sdW1ucykge1xuXG4gICAgICAgICAgICAgICAgICAgIGNvbHVtbkluZGV4Kys7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufVxuXG4iLCJpbXBvcnQgeyBET01PYmplY3QsIERPTU9iamVjdFRhZywgVGFza0xpc3RET01PYmplY3QgfSBmcm9tICcuLi9kb21PYmplY3QnO1xuaW1wb3J0IHsgTXVsdGlDb2x1bW5TZXR0aW5ncywgQ29sdW1uTGF5b3V0LCBTaW5nbGVDb2x1bW5TaXplIH0gZnJvbSBcIi4uLy4uL3JlZ2lvblNldHRpbmdzXCI7XG5pbXBvcnQgeyBNdWx0aUNvbHVtbkxheW91dENTUywgTXVsdGlDb2x1bW5TdHlsZUNTUyB9IGZyb20gJy4uLy4uL3V0aWxpdGllcy9jc3NEZWZpbml0aW9ucyc7XG5pbXBvcnQgeyBNYXJrZG93blJlbmRlckNoaWxkIH0gZnJvbSAnb2JzaWRpYW4nO1xuaW1wb3J0IHsgUmVnaW9uTWFuYWdlciB9IGZyb20gJy4vcmVnaW9uTWFuYWdlcic7XG5pbXBvcnQgeyBnZXRIZWFkaW5nQ29sbGFwc2VFbGVtZW50IH0gZnJvbSAnc3JjL3V0aWxpdGllcy9lbGVtZW50UmVuZGVyVHlwZVBhcnNlcic7XG5cblxuZXhwb3J0IGNsYXNzIFNpbmdsZUNvbHVtblJlZ2lvbk1hbmFnZXIgZXh0ZW5kcyBSZWdpb25NYW5hZ2VyIHtcblxuXG4gICAgcHVibGljIHJlbmRlclJlZ2lvbkVsZW1lbnRzVG9TY3JlZW4oKTogdm9pZCB7XG5cbiAgICAgICAgdGhpcy5yZW5kZXJDb2x1bW5NYXJrZG93bih0aGlzLnJlZ2lvblBhcmVudCwgdGhpcy5kb21MaXN0LCB0aGlzLnJlZ2lvbmFsU2V0dGluZ3MpO1xuICAgIH1cbiAgICBwdWJsaWMgZXhwb3J0UmVnaW9uRWxlbWVudHNUb1BERihwZGZQYXJlbnRFbGVtZW50OiBIVE1MRWxlbWVudCk6IHZvaWQge1xuXG4gICAgICAgIC8vIERlZmF1bHQgc2V0IHNoYWRvdyB0byBvZmYgZm9yIGV4cG9ydGluZyBQREZzXG4gICAgICAgIGxldCByZW5kZXJTZXR0aW5ncyA9IHRoaXMucmVnaW9uYWxTZXR0aW5ncztcbiAgICAgICAgcmVuZGVyU2V0dGluZ3MuZHJhd1NoYWRvdyA9IGZhbHNlO1xuICAgICAgICB0aGlzLnJlbmRlckNvbHVtbk1hcmtkb3duKHBkZlBhcmVudEVsZW1lbnQsIHRoaXMuZG9tTGlzdC5zbGljZSgpLCByZW5kZXJTZXR0aW5ncyk7XG4gICAgfVxuICAgIHB1YmxpYyByZW5kZXJSZWdpb25FbGVtZW50c1RvTGl2ZVByZXZpZXcocGFyZW50RWxlbWVudDogSFRNTEVsZW1lbnQpOiB2b2lkIHtcblxuICAgICAgICB0aGlzLnJlbmRlckNvbHVtbk1hcmtkb3duKHBhcmVudEVsZW1lbnQsIHRoaXMuZG9tTGlzdCwgdGhpcy5yZWdpb25hbFNldHRpbmdzKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogVGhpcyBmdW5jdGlvbiB0YWtlcyBpbiB0aGUgZGF0YSBmb3IgdGhlIG11bHRpLWNvbHVtbiByZWdpb24gYW5kIHNldHMgdXAgdGhlXG4gICAgICogdXNlciBkZWZpbmVkIG51bWJlciBvZiBjaGlsZHJlbiB3aXRoIHRoZSBwcm9wZXIgY3NzIGNsYXNzZXMgdG8gYmUgcmVuZGVyZWQgcHJvcGVybHkuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gcGFyZW50RWxlbWVudCBUaGUgZWxlbWVudCB0aGF0IHRoZSBtdWx0aS1jb2x1bW4gcmVnaW9uIHdpbGwgYmUgcmVuZGVyZWQgdW5kZXIuXG4gICAgICogQHBhcmFtIHJlZ2lvbkVsZW1lbnRzIFRoZSBsaXN0IG9mIERPTSBvYmplY3RzIHRoYXQgd2lsbCBiZSBjb3BwaWVkIHVuZGVyIHRoZSBwYXJlbnQgb2JqZWN0XG4gICAgICogQHBhcmFtIHNldHRpbmdzIFRoZSBzZXR0aW5ncyB0aGUgdXNlciBoYXMgZGVmaW5lZCBmb3IgdGhlIHJlZ2lvbi5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgcmVuZGVyQ29sdW1uTWFya2Rvd24ocGFyZW50RWxlbWVudDogSFRNTEVsZW1lbnQsIHJlZ2lvbkVsZW1lbnRzOiBET01PYmplY3RbXSwgc2V0dGluZ3M6IE11bHRpQ29sdW1uU2V0dGluZ3MpIHtcblxuICAgICAgICBsZXQgbXVsdGlDb2x1bW5QYXJlbnQgPSBjcmVhdGVEaXYoe1xuICAgICAgICAgICAgY2xzOiBNdWx0aUNvbHVtbkxheW91dENTUy5SZWdpb25Db2x1bW5Db250YWluZXJEaXYsXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmKGlzTGVmdExheW91dCh0aGlzLnJlZ2lvbmFsU2V0dGluZ3MuY29sdW1uUG9zaXRpb24pKXtcbiAgICAgICAgICAgIG11bHRpQ29sdW1uUGFyZW50LmFkZENsYXNzKE11bHRpQ29sdW1uTGF5b3V0Q1NTLlNpbmdsZUNvbHVtbkxlZnRMYXlvdXQpXG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZihpc1JpZ2h0TGF5b3V0KHRoaXMucmVnaW9uYWxTZXR0aW5ncy5jb2x1bW5Qb3NpdGlvbikpIHtcbiAgICAgICAgICAgIG11bHRpQ29sdW1uUGFyZW50LmFkZENsYXNzKE11bHRpQ29sdW1uTGF5b3V0Q1NTLlNpbmdsZUNvbHVtblJpZ2h0TGF5b3V0KVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgbXVsdGlDb2x1bW5QYXJlbnQuYWRkQ2xhc3MoTXVsdGlDb2x1bW5MYXlvdXRDU1MuU2luZ2xlQ29sdW1uQ2VudGVyTGF5b3V0KVxuICAgICAgICB9XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFBhc3Mgb3VyIHBhcmVudCBkaXYgYW5kIHNldHRpbmdzIHRvIHBhcnNlciB0byBjcmVhdGUgdGhlIHJlcXVpcmVkXG4gICAgICAgICAqIGNvbHVtbiBkaXZzIGFzIGNoaWxkcmVuIG9mIHRoZSBwYXJlbnQuXG4gICAgICAgICAqL1xuICAgICAgICBsZXQgY29sdW1uQ29udGVudERpdiA9IHRoaXMuY3JlYXRlQ29sdW1uQ29udGVudERpdnMobXVsdGlDb2x1bW5QYXJlbnQpO1xuICAgICAgICBpZiAoc2V0dGluZ3MuZHJhd0JvcmRlciA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgY29sdW1uQ29udGVudERpdi5hZGRDbGFzcyhNdWx0aUNvbHVtblN0eWxlQ1NTLkNvbHVtbkJvcmRlcik7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHNldHRpbmdzLmRyYXdTaGFkb3cgPT09IHRydWUpIHtcbiAgICAgICAgICAgIGNvbHVtbkNvbnRlbnREaXYuYWRkQ2xhc3MoTXVsdGlDb2x1bW5TdHlsZUNTUy5Db2x1bW5TaGFkb3cpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ3JlYXRlIG1hcmtkb3duIHJlbmRlcmVyIHRvIHBhcnNlIHRoZSBwYXNzZWQgbWFya2Rvd25cbiAgICAgICAgLy8gYmV0d2VlbiB0aGUgdGFncy5cbiAgICAgICAgbGV0IG1hcmtkb3duUmVuZGVyQ2hpbGQgPSBuZXcgTWFya2Rvd25SZW5kZXJDaGlsZChcbiAgICAgICAgICAgIG11bHRpQ29sdW1uUGFyZW50XG4gICAgICAgICk7XG5cbiAgICAgICAgLy8gUmVtb3ZlIGV2ZXJ5IG90aGVyIGNoaWxkIGZyb20gdGhlIHBhcmVudCBzbyBcbiAgICAgICAgLy8gd2UgZG9udCBlbmQgdXAgd2l0aCBtdWx0aXBsZSBzZXRzIG9mIGRhdGEuIFRoaXMgc2hvdWxkXG4gICAgICAgIC8vIHJlYWxseSBvbmx5IG5lZWQgdG8gbG9vcCBvbmNlIGZvciBpID0gMCBidXQgbG9vcCBqdXN0XG4gICAgICAgIC8vIGluIGNhc2UuXG4gICAgICAgIGZvciAobGV0IGkgPSBwYXJlbnRFbGVtZW50LmNoaWxkcmVuLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgICAgICBwYXJlbnRFbGVtZW50LmNoaWxkcmVuW2ldLmRldGFjaCgpO1xuICAgICAgICB9XG4gICAgICAgIHBhcmVudEVsZW1lbnQuYXBwZW5kQ2hpbGQobWFya2Rvd25SZW5kZXJDaGlsZC5jb250YWluZXJFbCk7XG5cbiAgICAgICAgdGhpcy5hcHBlbmRFbGVtZW50c1RvQ29sdW1ucyhyZWdpb25FbGVtZW50cywgY29sdW1uQ29udGVudERpdiwgc2V0dGluZ3MpO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBhcHBlbmRFbGVtZW50c1RvQ29sdW1ucyhyZWdpb25FbGVtZW50czogRE9NT2JqZWN0W10sIGNvbHVtbkNvbnRlbnREaXY6IEhUTUxEaXZFbGVtZW50LCBzZXR0aW5nczogTXVsdGlDb2x1bW5TZXR0aW5ncykge1xuXG5cbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCByZWdpb25FbGVtZW50cy5sZW5ndGg7IGkrKykge1xuXG4gICAgICAgICAgICBpZiAocmVnaW9uRWxlbWVudHNbaV0udGFnID09PSBET01PYmplY3RUYWcubm9uZSB8fFxuICAgICAgICAgICAgICAgIHJlZ2lvbkVsZW1lbnRzW2ldLnRhZyA9PT0gRE9NT2JqZWN0VGFnLmNvbHVtbkJyZWFrKSB7XG5cbiAgICAgICAgICAgICAgICAvLyBXZSBzdG9yZSB0aGUgZWxlbWVudHMgaW4gYSB3cmFwcGVyIGNvbnRhaW5lciB1bnRpbCB3ZSBkZXRlcm1pbmVcbiAgICAgICAgICAgICAgICBsZXQgZWxlbWVudCA9IGNyZWF0ZURpdih7XG4gICAgICAgICAgICAgICAgICAgIGNsczogTXVsdGlDb2x1bW5MYXlvdXRDU1MuQ29sdW1uRHVhbEVsZW1lbnRDb250YWluZXIsXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgcmVnaW9uRWxlbWVudHNbaV0uZWxlbWVudENvbnRhaW5lciA9IGVsZW1lbnQ7XG5cbiAgICAgICAgICAgICAgICAvLyBPdGhlcndpc2Ugd2UganVzdCBtYWtlIGEgY29weSBvZiB0aGUgb3JpZ2luYWwgZWxlbWVudCB0byBkaXNwbGF5LlxuICAgICAgICAgICAgICAgIGxldCBjbG9uZWRFbGVtZW50ID0gcmVnaW9uRWxlbWVudHNbaV0ub3JpZ2luYWxFbGVtZW50LmNsb25lTm9kZSh0cnVlKSBhcyBIVE1MRGl2RWxlbWVudDtcbiAgICAgICAgICAgICAgICBsZXQgaGVhZGluZ0NvbGxhcHNlRWxlbWVudCA9IGdldEhlYWRpbmdDb2xsYXBzZUVsZW1lbnQoY2xvbmVkRWxlbWVudCk7XG4gICAgICAgICAgICAgICAgaWYoaGVhZGluZ0NvbGxhcHNlRWxlbWVudCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIHJlbW92ZXMgdGhlIGNvbGxhcHNlIGFycm93IGZyb20gdGhlIHZpZXcgaWYgaXQgZXhpc3RzLlxuICAgICAgICAgICAgICAgICAgICBoZWFkaW5nQ29sbGFwc2VFbGVtZW50LmRldGFjaCgpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJlZ2lvbkVsZW1lbnRzW2ldLmNsb25lZEVsZW1lbnQgPSBjbG9uZWRFbGVtZW50O1xuICAgICAgICAgICAgICAgIGVsZW1lbnQuYXBwZW5kQ2hpbGQoY2xvbmVkRWxlbWVudCk7XG5cbiAgICAgICAgICAgICAgICBpZiAocmVnaW9uRWxlbWVudHNbaV0gaW5zdGFuY2VvZiBUYXNrTGlzdERPTU9iamVjdCkge1xuXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZml4Q2xvbmVkQ2hlY2tMaXN0QnV0dG9ucyhyZWdpb25FbGVtZW50c1tpXSBhcyBUYXNrTGlzdERPTU9iamVjdCwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGVsZW1lbnQgIT09IG51bGwpIHtcblxuICAgICAgICAgICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2LmFwcGVuZENoaWxkKGVsZW1lbnQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIGNyZWF0ZUNvbHVtbkNvbnRlbnREaXZzKG11bHRpQ29sdW1uUGFyZW50OiBIVE1MRGl2RWxlbWVudCk6IEhUTUxEaXZFbGVtZW50IHtcblxuICAgICAgICBsZXQgY29udGVudERpdiA9IG11bHRpQ29sdW1uUGFyZW50LmNyZWF0ZURpdih7XG4gICAgICAgICAgICBjbHM6IGAke011bHRpQ29sdW1uU3R5bGVDU1MuQ29sdW1uQ29udGVudH1gXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmKHRoaXMucmVnaW9uYWxTZXR0aW5ncy5jb2x1bW5TaXplID09PSBTaW5nbGVDb2x1bW5TaXplLnNtYWxsKSB7XG4gICAgICAgICAgICBjb250ZW50RGl2LmFkZENsYXNzKGAke011bHRpQ29sdW1uTGF5b3V0Q1NTLlNpbmdsZUNvbHVtblNtYWxsfWApXG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZih0aGlzLnJlZ2lvbmFsU2V0dGluZ3MuY29sdW1uU2l6ZSA9PT0gU2luZ2xlQ29sdW1uU2l6ZS5sYXJnZSkge1xuICAgICAgICAgICAgY29udGVudERpdi5hZGRDbGFzcyhgJHtNdWx0aUNvbHVtbkxheW91dENTUy5TaW5nbGVDb2x1bW5MYXJnZX1gKVxuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYodGhpcy5yZWdpb25hbFNldHRpbmdzLmNvbHVtblNpemUgPT09IFNpbmdsZUNvbHVtblNpemUuZnVsbCkge1xuICAgICAgICAgICAgY29udGVudERpdi5hZGRDbGFzcyhgJHtNdWx0aUNvbHVtbkxheW91dENTUy5TaW5nbGVDb2x1bW5GdWxsfWApXG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBjb250ZW50RGl2LmFkZENsYXNzKGAke011bHRpQ29sdW1uTGF5b3V0Q1NTLlNpbmdsZUNvbHVtbk1lZH1gKVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGNvbnRlbnREaXY7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBpc0NlbnRlcmVkKGxheW91dDogQ29sdW1uTGF5b3V0KTogYm9vbGVhbiB7XG5cbiAgICBpZihsYXlvdXQgPT09IENvbHVtbkxheW91dC5zdGFuZGFyZCB8fFxuICAgICAgIGxheW91dCA9PT0gQ29sdW1uTGF5b3V0Lm1pZGRsZSAgIHx8XG4gICAgICAgbGF5b3V0ID09PSBDb2x1bW5MYXlvdXQuY2VudGVyICAgfHxcbiAgICAgICBsYXlvdXQgPT09IENvbHVtbkxheW91dC5zZWNvbmQgICAgKSB7XG5cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlXG59XG5cbmZ1bmN0aW9uIGlzTGVmdExheW91dChsYXlvdXQ6IENvbHVtbkxheW91dCk6IGJvb2xlYW4ge1xuXG4gICAgaWYobGF5b3V0ID09PSBDb2x1bW5MYXlvdXQubGVmdCB8fFxuICAgICAgIGxheW91dCA9PT0gQ29sdW1uTGF5b3V0LmZpcnN0ICkge1xuIFxuICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgIH1cbiBcbiAgICAgcmV0dXJuIGZhbHNlXG59XG5cbmZ1bmN0aW9uIGlzUmlnaHRMYXlvdXQobGF5b3V0OiBDb2x1bW5MYXlvdXQpOiBib29sZWFuIHtcblxuICAgIGlmKGxheW91dCA9PT0gQ29sdW1uTGF5b3V0LnJpZ2h0IHx8XG4gICAgICAgbGF5b3V0ID09PSBDb2x1bW5MYXlvdXQudGhpcmQgfHxcbiAgICAgICBsYXlvdXQgPT09IENvbHVtbkxheW91dC5sYXN0ICkge1xuIFxuICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgIH1cbiBcbiAgICAgcmV0dXJuIGZhbHNlXG59IiwiLyoqXG4gKiBGaWxlOiAvc3JjL2RvbV9tYW5hZ2VyL3JlZ2lvbmFsX21hbmFnZXJzL2F1dG9MYXlvdXRSZWdpb25NYW5hZ2VyLnRzICAgICAgICAgKlxuICogQ3JlYXRlZCBEYXRlOiBTdW5kYXksIE1heSAyMm5kIDIwMjIsIDEwOjIzIHBtICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpcbiAqIEF1dGhvcjogQ2FtZXJvbiBSb2JpbnNvbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICogQ29weXJpZ2h0IChjKSAyMDIyIENhbWVyb24gUm9iaW5zb24gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpcbiAqL1xuXG5pbXBvcnQgeyBET01PYmplY3QsIERPTU9iamVjdFRhZywgVGFza0xpc3RET01PYmplY3QgfSBmcm9tICcuLi9kb21PYmplY3QnO1xuaW1wb3J0IHsgTXVsdGlDb2x1bW5TZXR0aW5ncyB9IGZyb20gXCIuLi8uLi9yZWdpb25TZXR0aW5nc1wiO1xuaW1wb3J0IHsgTXVsdGlDb2x1bW5MYXlvdXRDU1MsIE11bHRpQ29sdW1uU3R5bGVDU1MgfSBmcm9tICcuLi8uLi91dGlsaXRpZXMvY3NzRGVmaW5pdGlvbnMnO1xuaW1wb3J0IHsgUmVnaW9uTWFuYWdlciB9IGZyb20gJy4vcmVnaW9uTWFuYWdlcic7XG5pbXBvcnQgeyBnZXRIZWFkaW5nQ29sbGFwc2VFbGVtZW50LCBoYXNIZWFkZXIgfSBmcm9tICdzcmMvdXRpbGl0aWVzL2VsZW1lbnRSZW5kZXJUeXBlUGFyc2VyJztcblxuZXhwb3J0IGNsYXNzIEF1dG9MYXlvdXRSZWdpb25NYW5hZ2VyIGV4dGVuZHMgUmVnaW9uTWFuYWdlciB7XG5cbiAgICBwcml2YXRlIHByZXZpb3VzQ29sdW1uSGVpZ2h0czogbnVtYmVyW10gPSBbXVxuXG4gICAgcHJpdmF0ZSBjb2x1bW5QYXJlbnQ6IEhUTUxEaXZFbGVtZW50O1xuICAgIHByaXZhdGUgY29sdW1uRGl2czogSFRNTERpdkVsZW1lbnRbXTtcblxuICAgIHB1YmxpYyByZW5kZXJSZWdpb25FbGVtZW50c1RvU2NyZWVuKCk6IHZvaWQge1xuXG4gICAgICAgICB0aGlzLnJlbmRlckNvbHVtbk1hcmtkb3duKHRoaXMucmVnaW9uUGFyZW50LCB0aGlzLmRvbUxpc3QsIHRoaXMucmVnaW9uYWxTZXR0aW5ncyk7XG4gICAgfVxuICAgIHB1YmxpYyBleHBvcnRSZWdpb25FbGVtZW50c1RvUERGKHBkZlBhcmVudEVsZW1lbnQ6IEhUTUxFbGVtZW50KTogdm9pZCB7XG5cbiAgICAgICAgLy8gRGVmYXVsdCBzZXQgc2hhZG93IHRvIG9mZiBmb3IgZXhwb3J0aW5nIFBERnNcbiAgICAgICAgbGV0IHJlbmRlclNldHRpbmdzID0gdGhpcy5yZWdpb25hbFNldHRpbmdzO1xuICAgICAgICByZW5kZXJTZXR0aW5ncy5kcmF3U2hhZG93ID0gZmFsc2U7XG4gICAgICAgIHRoaXMucmVuZGVyQ29sdW1uTWFya2Rvd24ocGRmUGFyZW50RWxlbWVudCwgdGhpcy5kb21MaXN0LnNsaWNlKCksIHJlbmRlclNldHRpbmdzKTtcbiAgICB9XG4gICAgcHVibGljIHJlbmRlclJlZ2lvbkVsZW1lbnRzVG9MaXZlUHJldmlldyhwYXJlbnRFbGVtZW50OiBIVE1MRWxlbWVudCk6IHZvaWQge1xuXG4gICAgICAgIHRoaXMucmVuZGVyQ29sdW1uTWFya2Rvd24ocGFyZW50RWxlbWVudCwgdGhpcy5kb21MaXN0LCB0aGlzLnJlZ2lvbmFsU2V0dGluZ3MpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBUaGlzIGZ1bmN0aW9uIHRha2VzIGluIHRoZSBkYXRhIGZvciB0aGUgbXVsdGktY29sdW1uIHJlZ2lvbiBhbmQgc2V0cyB1cCB0aGUgXG4gICAgICogdXNlciBkZWZpbmVkIG51bWJlciBvZiBjaGlsZHJlbiB3aXRoIHRoZSBwcm9wZXIgY3NzIGNsYXNzZXMgdG8gYmUgcmVuZGVyZWQgcHJvcGVybHkuXG4gICAgICogXG4gICAgICogQHBhcmFtIHBhcmVudEVsZW1lbnQgVGhlIGVsZW1lbnQgdGhhdCB0aGUgbXVsdGktY29sdW1uIHJlZ2lvbiB3aWxsIGJlIHJlbmRlcmVkIHVuZGVyLlxuICAgICAqIEBwYXJhbSByZWdpb25FbGVtZW50cyBUaGUgbGlzdCBvZiBET00gb2JqZWN0cyB0aGF0IHdpbGwgYmUgY29wcGllZCB1bmRlciB0aGUgcGFyZW50IG9iamVjdFxuICAgICAqIEBwYXJhbSBzZXR0aW5ncyBUaGUgc2V0dGluZ3MgdGhlIHVzZXIgaGFzIGRlZmluZWQgZm9yIHRoZSByZWdpb24uXG4gICAgICovXG4gICAgcHJpdmF0ZSByZW5kZXJDb2x1bW5NYXJrZG93bihwYXJlbnRFbGVtZW50OiBIVE1MRWxlbWVudCwgcmVnaW9uRWxlbWVudHM6IERPTU9iamVjdFtdLCBzZXR0aW5nczogTXVsdGlDb2x1bW5TZXR0aW5ncykge1xuXG4gICAgICAgIGxldCBtdWx0aUNvbHVtblBhcmVudCA9IGNyZWF0ZURpdih7XG4gICAgICAgICAgICBjbHM6IE11bHRpQ29sdW1uTGF5b3V0Q1NTLlJlZ2lvbkNvbHVtbkNvbnRhaW5lckRpdixcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuY29sdW1uUGFyZW50ID0gbXVsdGlDb2x1bW5QYXJlbnQ7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFBhc3Mgb3VyIHBhcmVudCBkaXYgYW5kIHNldHRpbmdzIHRvIHBhcnNlciB0byBjcmVhdGUgdGhlIHJlcXVpcmVkXG4gICAgICAgICAqIGNvbHVtbiBkaXZzIGFzIGNoaWxkcmVuIG9mIHRoZSBwYXJlbnQuXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLmNvbHVtbkRpdnMgPSB0aGlzLmdldENvbHVtbkNvbnRlbnREaXZzKHNldHRpbmdzLCBtdWx0aUNvbHVtblBhcmVudCk7XG5cbiAgICAgICAgaWYgKHNldHRpbmdzLmRyYXdTaGFkb3cgPT09IHRydWUpIHtcbiAgICAgICAgICAgIG11bHRpQ29sdW1uUGFyZW50LmFkZENsYXNzKE11bHRpQ29sdW1uU3R5bGVDU1MuUmVnaW9uU2hhZG93KTtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuY29sdW1uRGl2cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYgKHNldHRpbmdzLmRyYXdCb3JkZXIgPT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbHVtbkRpdnNbaV0uYWRkQ2xhc3MoTXVsdGlDb2x1bW5TdHlsZUNTUy5Db2x1bW5Cb3JkZXIpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoc2V0dGluZ3MuZHJhd1NoYWRvdyA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuY29sdW1uRGl2c1tpXS5hZGRDbGFzcyhNdWx0aUNvbHVtblN0eWxlQ1NTLkNvbHVtblNoYWRvdyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBSZW1vdmUgZXZlcnkgb3RoZXIgY2hpbGQgZnJvbSB0aGUgcGFyZW50IHNvIFxuICAgICAgICAvLyB3ZSBkb250IGVuZCB1cCB3aXRoIG11bHRpcGxlIHNldHMgb2YgZGF0YS4gVGhpcyBzaG91bGRcbiAgICAgICAgLy8gcmVhbGx5IG9ubHkgbmVlZCB0byBsb29wIG9uY2UgZm9yIGkgPSAwIGJ1dCBsb29wIGp1c3RcbiAgICAgICAgLy8gaW4gY2FzZS5cbiAgICAgICAgZm9yIChsZXQgaSA9IHBhcmVudEVsZW1lbnQuY2hpbGRyZW4ubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICAgIHBhcmVudEVsZW1lbnQuY2hpbGRyZW5baV0uZGV0YWNoKCk7XG4gICAgICAgIH1cbiAgICAgICAgcGFyZW50RWxlbWVudC5hcHBlbmRDaGlsZChtdWx0aUNvbHVtblBhcmVudCk7XG5cbiAgICAgICAgdGhpcy5hcHBlbmRFbGVtZW50c1RvQ29sdW1ucyhyZWdpb25FbGVtZW50cywgdGhpcy5jb2x1bW5EaXZzLCBzZXR0aW5ncyk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhcHBlbmRFbGVtZW50c1RvQ29sdW1ucyhyZWdpb25FbGVtZW50czogRE9NT2JqZWN0W10sIGNvbHVtbkNvbnRlbnREaXZzOiBIVE1MRGl2RWxlbWVudFtdLCBzZXR0aW5nczogTXVsdGlDb2x1bW5TZXR0aW5ncykge1xuXG4gICAgICAgIGZ1bmN0aW9uIGJhbGFuY2VFbGVtZW50cygpIHtcblxuICAgICAgICAgICAgbGV0IHRvdGFsSGVpZ2h0ID0gcmVnaW9uRWxlbWVudHMubWFwKChlbDogRE9NT2JqZWN0LCBpbmRleDogbnVtYmVyKSA9PiB7IFxuXG4gICAgICAgICAgICAgICAgLy8gV2Ugb25seSB3YW50IHRvIGF0dGVtcHQgdG8gdXBkYXRlIHRoZSBlbGVtZW50UmVuZGVyZWRIZWlnaHQgaWYgaXQgaXMgMCBhbmQgaWYgaXQgaXMgbm90IGFuIHVucmVuZGVyZWQgZWxlbWVudCBzdWNoIGFzIGEgZW5kcmVnaW9uIHRhZy5cbiAgICAgICAgICAgICAgICBpZihlbC5lbGVtZW50UmVuZGVyZWRIZWlnaHQgPT09IDAgJiZcbiAgICAgICAgICAgICAgICAgICAgZWwudGFnICE9PSBET01PYmplY3RUYWcuY29sdW1uQnJlYWsgJiZcbiAgICAgICAgICAgICAgICAgICAgZWwudGFnICE9PSBET01PYmplY3RUYWcuZW5kUmVnaW9uICYmXG4gICAgICAgICAgICAgICAgICAgIGVsLnRhZyAhPT0gRE9NT2JqZWN0VGFnLnJlZ2lvblNldHRpbmdzICYmXG4gICAgICAgICAgICAgICAgICAgIGVsLnRhZyAhPT0gRE9NT2JqZWN0VGFnLnN0YXJ0UmVnaW9uKSB7XG4gICAgXG4gICAgICAgICAgICAgICAgICAgIC8vIEFkZCBlbGVtZW50IHRvIHJlbmRlcmVkIGRpdiBzbyB3ZSBjYW4gZXh0cmFjdCB0aGUgcmVuZGVyZWQgaGVpZ2h0LlxuICAgICAgICAgICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2c1swXS5hcHBlbmRDaGlsZChlbC5vcmlnaW5hbEVsZW1lbnQpXG4gICAgICAgICAgICAgICAgICAgIGVsLmVsZW1lbnRSZW5kZXJlZEhlaWdodCA9IGVsLm9yaWdpbmFsRWxlbWVudC5jbGllbnRIZWlnaHRcbiAgICAgICAgICAgICAgICAgICAgY29sdW1uQ29udGVudERpdnNbMF0ucmVtb3ZlQ2hpbGQoZWwub3JpZ2luYWxFbGVtZW50KVxuICAgICAgICAgICAgICAgIH1cbiAgICBcbiAgICAgICAgICAgICAgICByZXR1cm4gZWwuZWxlbWVudFJlbmRlcmVkSGVpZ2h0IFxuICAgICAgICAgICAgfSkucmVkdWNlKChwcmV2OiBudW1iZXIsIGN1cnI6IG51bWJlcikgPT4geyByZXR1cm4gcHJldiArIGN1cnIgfSwgMCk7XG4gICAgICAgICAgICBsZXQgbWF4Q29sdW1uQ29udGVudEhlaWdodCA9IE1hdGgudHJ1bmModG90YWxIZWlnaHQgLyBzZXR0aW5ncy5udW1iZXJPZkNvbHVtbnMpO1xuXG4gICAgICAgICAgICBmb3IobGV0IGkgPSAwOyBpIDwgY29sdW1uQ29udGVudERpdnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBqID0gY29sdW1uQ29udGVudERpdnNbaV0uY2hpbGRyZW4ubGVuZ3RoIC0gMTsgaiA+PSAwOyBqLS0pIHtcbiAgICAgICAgICAgICAgICAgICAgY29sdW1uQ29udGVudERpdnNbaV0uY2hpbGRyZW5bal0uZGV0YWNoKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBsZXQgY29sdW1uSW5kZXggPSAwO1xuICAgICAgICAgICAgbGV0IGN1cnJlbnRDb2x1bW5IZWlnaHQgPSAwO1xuICAgICAgICAgICAgZnVuY3Rpb24gY2hlY2tTaG91bGRTd2l0Y2hDb2x1bW5zKG5leHRFbGVtZW50SGVpZ2h0OiBudW1iZXIpIHtcbiAgICBcbiAgICAgICAgICAgICAgICBpZiAoY3VycmVudENvbHVtbkhlaWdodCArIG5leHRFbGVtZW50SGVpZ2h0ID4gbWF4Q29sdW1uQ29udGVudEhlaWdodCAmJlxuICAgICAgICAgICAgICAgICAgICAoY29sdW1uSW5kZXggKyAxKSA8IHNldHRpbmdzLm51bWJlck9mQ29sdW1ucykge1xuICAgIFxuICAgICAgICAgICAgICAgICAgICBjb2x1bW5JbmRleCsrO1xuICAgICAgICAgICAgICAgICAgICBjdXJyZW50Q29sdW1uSGVpZ2h0ID0gMDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcmVnaW9uRWxlbWVudHMubGVuZ3RoOyBpKyspIHtcblxuICAgICAgICAgICAgICAgIGlmIChyZWdpb25FbGVtZW50c1tpXS50YWcgPT09IERPTU9iamVjdFRhZy5ub25lIHx8XG4gICAgICAgICAgICAgICAgICAgIHJlZ2lvbkVsZW1lbnRzW2ldLnRhZyA9PT0gRE9NT2JqZWN0VGFnLmNvbHVtbkJyZWFrKSB7XG4gICAgXG4gICAgICAgICAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICAgICAgICAgKiBIZXJlIHdlIGNoZWNrIGlmIHdlIG5lZWQgdG8gc3dhcCB0byB0aGUgbmV4dCBjb2x1bW4gZm9yIHRoZSBjdXJyZW50IGVsZW1lbnQuXG4gICAgICAgICAgICAgICAgICAgICAqIElmIHRoZSB1c2VyIHdhbnRzIHRvIGtlZXAgaGVhZGluZ3Mgd2l0aCB0aGUgY29udGVudCBiZWxvdyBpdCB3ZSBhbHNvIG1ha2Ugc3VyZVxuICAgICAgICAgICAgICAgICAgICAgKiB0aGF0IHRoZSBsYXN0IGl0ZW0gaW4gYSBjb2x1bW4gaXMgbm90IGEgaGVhZGVyIGVsZW1lbnQgYnkgdXNpbmcgdGhlIGhlYWRlciBhbmRcbiAgICAgICAgICAgICAgICAgICAgICogdGhlIG5leHQgZWxlbWVudCdzIGhlaWdodCBhcyB0aGUgaGVpZ2h0IHZhbHVlLiBcbiAgICAgICAgICAgICAgICAgICAgICovXG4gICAgICAgICAgICAgICAgICAgIGlmKGhhc0hlYWRlcihyZWdpb25FbGVtZW50c1tpXS5vcmlnaW5hbEVsZW1lbnQpID09PSB0cnVlKSB7IC8vIFRPRE86IEFkZCB0aGlzIGFzIHNlbGVjdGFibGUgb3B0aW9uLlxuICAgIFxuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGhlYWRlckFuZE5leHRFbGVtZW50SGVpZ2h0ID0gcmVnaW9uRWxlbWVudHNbaV0uZWxlbWVudFJlbmRlcmVkSGVpZ2h0O1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYoaSA8IHJlZ2lvbkVsZW1lbnRzLmxlbmd0aCAtIDEpIHtcbiAgICBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoZWFkZXJBbmROZXh0RWxlbWVudEhlaWdodCArPSByZWdpb25FbGVtZW50c1tpICsgMV0uZWxlbWVudFJlbmRlcmVkSGVpZ2h0O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgIFxuICAgICAgICAgICAgICAgICAgICAgICAgY2hlY2tTaG91bGRTd2l0Y2hDb2x1bW5zKGhlYWRlckFuZE5leHRFbGVtZW50SGVpZ2h0KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICBcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoZWNrU2hvdWxkU3dpdGNoQ29sdW1ucyhyZWdpb25FbGVtZW50c1tpXS5lbGVtZW50UmVuZGVyZWRIZWlnaHQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRDb2x1bW5IZWlnaHQgKz0gcmVnaW9uRWxlbWVudHNbaV0uZWxlbWVudFJlbmRlcmVkSGVpZ2h0XG4gICAgXG4gICAgXG4gICAgICAgICAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICAgICAgICAgKiBXZSBzdG9yZSB0aGUgZWxlbWVudHMgaW4gYSB3cmFwcGVyIGNvbnRhaW5lciB1bnRpbCB3ZSBkZXRlcm1pbmUgaWYgd2Ugd2FudCB0byBcbiAgICAgICAgICAgICAgICAgICAgICogdXNlIHRoZSBvcmlnaW5hbCBlbGVtZW50IG9yIGEgY2xvbmUgb2YgdGhlIGVsZW1lbnQuIFRoaXMgaGVscHMgdXMgYnkgYWxsb3dpbmcgXG4gICAgICAgICAgICAgICAgICAgICAqIHVzIHRvIGNyZWF0ZSBhIHZpc3VhbCBvbmx5IGNsb25lIHdoaWxlIHRoZSB1cGRhdGUgbG9vcCBtb3ZlcyB0aGUgb3JpZ2luYWwgZWxlbWVudCBcbiAgICAgICAgICAgICAgICAgICAgICogaW50byB0aGUgY29sdW1ucy5cbiAgICAgICAgICAgICAgICAgICAgICovXG4gICAgICAgICAgICAgICAgICAgIGxldCBlbGVtZW50ID0gY3JlYXRlRGl2KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsczogTXVsdGlDb2x1bW5MYXlvdXRDU1MuQ29sdW1uRHVhbEVsZW1lbnRDb250YWluZXIsXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICByZWdpb25FbGVtZW50c1tpXS5lbGVtZW50Q29udGFpbmVyID0gZWxlbWVudDtcbiAgICBcbiAgICAgICAgICAgICAgICAgICAgbGV0IGNsb25lZEVsZW1lbnQgPSByZWdpb25FbGVtZW50c1tpXS5jbG9uZWRFbGVtZW50O1xuICAgICAgICAgICAgICAgICAgICBpZihyZWdpb25FbGVtZW50c1tpXS5jbG9uZWRFbGVtZW50ID09PSBudWxsKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNsb25lZEVsZW1lbnQgPSByZWdpb25FbGVtZW50c1tpXS5vcmlnaW5hbEVsZW1lbnQuY2xvbmVOb2RlKHRydWUpIGFzIEhUTUxEaXZFbGVtZW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGhlYWRpbmdDb2xsYXBzZUVsZW1lbnQgPSBnZXRIZWFkaW5nQ29sbGFwc2VFbGVtZW50KGNsb25lZEVsZW1lbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYoaGVhZGluZ0NvbGxhcHNlRWxlbWVudCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgcmVtb3ZlcyB0aGUgY29sbGFwc2UgYXJyb3cgZnJvbSB0aGUgdmlldyBpZiBpdCBleGlzdHMuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVhZGluZ0NvbGxhcHNlRWxlbWVudC5kZXRhY2goKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgICAgICAgICAgICAgICAgICByZWdpb25FbGVtZW50c1tpXS5jbG9uZWRFbGVtZW50ID0gY2xvbmVkRWxlbWVudDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbGVtZW50LmFwcGVuZENoaWxkKGNsb25lZEVsZW1lbnQpO1xuICAgIFxuICAgICAgICAgICAgICAgICAgICBpZiAocmVnaW9uRWxlbWVudHNbaV0gaW5zdGFuY2VvZiBUYXNrTGlzdERPTU9iamVjdCkge1xuICAgIFxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5maXhDbG9uZWRDaGVja0xpc3RCdXR0b25zKHJlZ2lvbkVsZW1lbnRzW2ldIGFzIFRhc2tMaXN0RE9NT2JqZWN0LCB0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgIFxuICAgICAgICAgICAgICAgICAgICBpZiAoZWxlbWVudCAhPT0gbnVsbCAmJiBcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbHVtbkNvbnRlbnREaXZzW2NvbHVtbkluZGV4XSAmJiBcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlZ2lvbkVsZW1lbnRzW2ldLnRhZyAhPT0gRE9NT2JqZWN0VGFnLmNvbHVtbkJyZWFrKSB7XG4gICAgXG4gICAgICAgICAgICAgICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2c1tjb2x1bW5JbmRleF0uYXBwZW5kQ2hpbGQoZWxlbWVudCk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWdpb25FbGVtZW50c1tpXS5lbGVtZW50UmVuZGVyZWRIZWlnaHQgPSBlbGVtZW50LmNsaWVudEhlaWdodDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgIFxuICAgICAgICAgICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAgICAgICAgICogSWYgdGhlIHRhZyBpcyBhIGNvbHVtbiBicmVhayB3ZSB1cGRhdGUgdGhlIGNvbHVtbiBpbmRleCBhZnRlclxuICAgICAgICAgICAgICAgICAgICAgKiBhcHBlbmRpbmcgdGhlIGl0ZW0gdG8gdGhlIGNvbHVtbiBkaXYuIFRoaXMga2VlcHMgdGhlIG1haW4gRE9NXG4gICAgICAgICAgICAgICAgICAgICAqIGNsZWFuZXIgYnkgcmVtb3Zpbmcgb3RoZXIgaXRlbXMgYW5kIHBsYWNpbmcgdGhlbSBhbGwgd2l0aGluXG4gICAgICAgICAgICAgICAgICAgICAqIGEgcmVnaW9uIGNvbnRhaW5lci5cbiAgICAgICAgICAgICAgICAgICAgICogXG4gICAgICAgICAgICAgICAgICAgICAqIFJlbW92aW5nIHRoZSBlbmQgY29sdW1uIHRhZyBhcyBhbiBvcHRpb24gZm9yIG5vdy5cbiAgICAgICAgICAgICAgICAgICAgICovXG4gICAgICAgICAgICAgICAgICAgIC8vIGlmIChyZWdpb25FbGVtZW50c1tpXS50YWcgPT09IERPTU9iamVjdFRhZy5jb2x1bW5CcmVhayAmJlxuICAgICAgICAgICAgICAgICAgICAvLyAgICAoY29sdW1uSW5kZXggKyAxKSA8IHNldHRpbmdzLm51bWJlck9mQ29sdW1ucykge1xuICAgIFxuICAgICAgICAgICAgICAgICAgICAvLyAgICAgY29sdW1uSW5kZXgrKztcbiAgICAgICAgICAgICAgICAgICAgLy8gICAgIGN1cnJlbnRDb2x1bW5IZWlnaHQgPSAwO1xuICAgICAgICAgICAgICAgICAgICAvLyB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEF0dGVtcHQgdG8gYmFsYW5jZWQgdGhlIGVsZW1lbnRzLiBXZSBuZWVkIHRvIGl0ZXJhdGUgb3ZlciB0aGUgZWxlbWVudHMgbXVsdGlwbGUgdGltZXMgYmVjYXVzZVxuICAgICAgICAgKiBvdXIgaW5pdGlhbCBiYWxhbmNlIGVzdGltYXRlIG1heSBub3QgYmUgcGVyZmVjdGx5IGJhbGFuY2VkIGR1ZSB0byBkaWZmZXJlbnQgY29sdW1uIHdpZHRocyBjYXVzaW5nIFxuICAgICAgICAgKiBlbGVtZW50cyB3aXRoaW4gdGhlbSB0byBiZSBvZiBkaWZmZXJlbnQgaGVpZ2h0cy4gVGhpcyBjYW4gY2F1c2UgdGhlIGVsZW1lbnRzIHRvIGp1bXAgYXJvdW5kIG9uIFxuICAgICAgICAgKiBzdWJzaXF1ZW50IHVwZGF0ZSBsb29wcyB3aGljaCBpcyBub3QgaWRlYWwuIEhlcmUgd2UgcmVuZGVyIHRoZSBlbGVtZW50cyB0byB0aGUgc2NyZWVuIGFuZCB1cGRhdGUgXG4gICAgICAgICAqIHRoZWlyIGhlaWdodCBhZnRlciBiZWluZyByZW5kZXJlZCBpbnRvIHRoZSBlc3RpbWF0ZWQgcG9zaXRpb24uIFxuICAgICAgICAgKiBcbiAgICAgICAgICogT25jZSBldmVyeXRoaW5nIGlzIHJlbmRlcmVkIHdlIGNoZWNrIGFsbCBvZiB0aGUgY29sdW1uIGhlaWdodHMgYWdhaW5zdCBvdXIgbGFzdCBpdGVyYXRpb24gYW5kIFxuICAgICAgICAgKiBpZiBub3RoaW5nIGhhcyBjaGFuZ2VkIHdlIGtub3cgd2UgYXJlIGJhbGFuY2VkLlxuICAgICAgICAgKiBcbiAgICAgICAgICogVGhlcmUgaXMgcHJvYmFibHkgYSBiZXR0ZXIgd2F5IG9mIGFjY29tcGxpc2hpbmcgdGhpcyB0YXNrIGJ1dCB0aGlzIHdvcmtzIGZvciB0aGUgdGltZSBiZWluZy5cbiAgICAgICAgICovXG4gICAgICAgIGZvcihsZXQgaSA9IDA7IGkgPCA1OyBpKyspIHtcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgYmFsYW5jZUVsZW1lbnRzKClcblxuICAgICAgICAgICAgbGV0IGJhbGFuY2VkID0gdHJ1ZTtcbiAgICAgICAgICAgIGZvcihsZXQgaiA9IDA7IGogPCBjb2x1bW5Db250ZW50RGl2cy5sZW5ndGg7IGorKykge1xuXG4gICAgICAgICAgICAgICAgLy8gSWYgdGhlIGNvbHVtbiBoZWlnaHRzIGFyZSB1bmRlZmluZWQgd2Ugc2V0IGRlZmF1bHQgdG8gemVybyBzbyBub3QgdG8gZW5jb3VudGVyIGFuIGVycm9yLlxuICAgICAgICAgICAgICAgIGlmKCF0aGlzLnByZXZpb3VzQ29sdW1uSGVpZ2h0c1tqXSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnByZXZpb3VzQ29sdW1uSGVpZ2h0cy5wdXNoKDApXG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gaWYgdGhpcyByZW5kZXIgaGVpZ2h0IGlzIG5vdCB0aGUgc2FtZSBhcyB0aGUgcHJldmlvdXMgaGVpZ2h0IHdlIGFyZSBzdGlsbCBiYWxhbmNpbmcuXG4gICAgICAgICAgICAgICAgaWYodGhpcy5wcmV2aW91c0NvbHVtbkhlaWdodHNbal0gIT09IGNvbHVtbkNvbnRlbnREaXZzW2pdLmNsaWVudEhlaWdodCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnByZXZpb3VzQ29sdW1uSGVpZ2h0c1tqXSA9IGNvbHVtbkNvbnRlbnREaXZzW2pdLmNsaWVudEhlaWdodFxuICAgICAgICAgICAgICAgICAgICBiYWxhbmNlZCA9IGZhbHNlXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBpZiB3ZSBtYWRlIGl0IG91dCBvZiB0aGUgbG9vcCBhbmQgYWxsIG9mIHRoZSBjb2x1bW5zIGFyZSB0aGUgc2FtZSBoZWlnaHQgYXMgbGFzdCB1cGRhdGVcbiAgICAgICAgICAgIC8vIHdlJ3JlIGJhbGFuY2VkIHNvIHdlIGNhbiBicmVhayBvdXQgb2YgdGhlIGxvb3AuXG4gICAgICAgICAgICBpZihiYWxhbmNlZCA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHVibGljIHVwZGF0ZVJlbmRlcmVkTWFya2Rvd24oKSB7XG5cbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLmRvbUxpc3QubGVuZ3RoOyBpKyspIHtcblxuICAgICAgICAgICAgbGV0IGVsID0gdGhpcy5kb21MaXN0W2ldXG4gICAgICAgICAgICBsZXQgb3JpZ2luYWxDbGllbnRIZWlnaHQgPSAwO1xuICAgICAgICAgICAgaWYgKGVsLm9yaWdpbmFsRWxlbWVudCkge1xuICAgICAgICAgICAgICAgIG9yaWdpbmFsQ2xpZW50SGVpZ2h0ID0gZWwub3JpZ2luYWxFbGVtZW50LmNsaWVudEhlaWdodFxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IGNsb25lZENsaWVudEhlaWdodCA9IDA7XG4gICAgICAgICAgICBpZiAoZWwuY2xvbmVkRWxlbWVudCkge1xuICAgICAgICAgICAgICAgIGNsb25lZENsaWVudEhlaWdodCA9IGVsLmNsb25lZEVsZW1lbnQuY2xpZW50SGVpZ2h0XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChvcmlnaW5hbENsaWVudEhlaWdodCA8IGNsb25lZENsaWVudEhlaWdodCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZG9tTGlzdFtpXS5lbGVtZW50UmVuZGVyZWRIZWlnaHQgPSBjbG9uZWRDbGllbnRIZWlnaHQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLmRvbUxpc3RbaV0uZWxlbWVudFJlbmRlcmVkSGVpZ2h0ID0gb3JpZ2luYWxDbGllbnRIZWlnaHQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgdmFsaWRDb2x1bW5zID0gdHJ1ZTtcbiAgICAgICAgaWYodGhpcy5jb2x1bW5QYXJlbnQgIT09IG51bGwgJiYgdGhpcy5jb2x1bW5EaXZzICE9PSBudWxsICYmIHRoaXMuY29sdW1uRGl2cyAhPT0gdW5kZWZpbmVkICYmXG4gICAgICAgICAgICB0aGlzLmNvbHVtbkRpdnMubGVuZ3RoID09PSB0aGlzLnJlZ2lvbmFsU2V0dGluZ3MubnVtYmVyT2ZDb2x1bW5zKSB7XG5cbiAgICAgICAgICAgIGxldCB0b3RhbEhlaWdodCA9IHRoaXMuZG9tTGlzdC5tYXAoKGVsOiBET01PYmplY3QsIGluZGV4OiBudW1iZXIpID0+IHsgXG5cbiAgICAgICAgICAgICAgICAvLyBXZSBvbmx5IHdhbnQgdG8gYXR0ZW1wdCB0byB1cGRhdGUgdGhlIGVsZW1lbnRSZW5kZXJlZEhlaWdodCBpZiBpdCBpcyAwIGFuZCBpZiBpdCBpcyBub3QgYW4gdW5yZW5kZXJlZCBlbGVtZW50IHN1Y2ggYXMgYSBlbmRyZWdpb24gdGFnLlxuICAgICAgICAgICAgICAgIGlmKGVsLmVsZW1lbnRSZW5kZXJlZEhlaWdodCA9PT0gMCAmJlxuICAgICAgICAgICAgICAgICAgICBlbC50YWcgIT09IERPTU9iamVjdFRhZy5jb2x1bW5CcmVhayAmJlxuICAgICAgICAgICAgICAgICAgICBlbC50YWcgIT09IERPTU9iamVjdFRhZy5lbmRSZWdpb24gJiZcbiAgICAgICAgICAgICAgICAgICAgZWwudGFnICE9PSBET01PYmplY3RUYWcucmVnaW9uU2V0dGluZ3MgJiZcbiAgICAgICAgICAgICAgICAgICAgZWwudGFnICE9PSBET01PYmplY3RUYWcuc3RhcnRSZWdpb24pIHtcbiAgICBcbiAgICAgICAgICAgICAgICAgICAgLy8gQWRkIGVsZW1lbnQgdG8gcmVuZGVyZWQgZGl2IHNvIHdlIGNhbiBleHRyYWN0IHRoZSByZW5kZXJlZCBoZWlnaHQuXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY29sdW1uUGFyZW50LmFwcGVuZENoaWxkKGVsLm9yaWdpbmFsRWxlbWVudClcbiAgICAgICAgICAgICAgICAgICAgZWwuZWxlbWVudFJlbmRlcmVkSGVpZ2h0ID0gZWwub3JpZ2luYWxFbGVtZW50LmNsaWVudEhlaWdodFxuICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbHVtblBhcmVudC5yZW1vdmVDaGlsZChlbC5vcmlnaW5hbEVsZW1lbnQpXG4gICAgICAgICAgICAgICAgfVxuICAgIFxuICAgICAgICAgICAgICAgIHJldHVybiBlbC5lbGVtZW50UmVuZGVyZWRIZWlnaHQgXG4gICAgICAgICAgICB9KS5yZWR1Y2UoKHByZXY6IG51bWJlciwgY3VycjogbnVtYmVyKSA9PiB7IHJldHVybiBwcmV2ICsgY3VyciB9LCAwKTtcbiAgICAgICAgICAgIGxldCBtYXhDb2x1bW5Db250ZW50SGVpZ2h0ID0gTWF0aC50cnVuYyh0b3RhbEhlaWdodCAvIHRoaXMucmVnaW9uYWxTZXR0aW5ncy5udW1iZXJPZkNvbHVtbnMpO1xuXG4gICAgICAgICAgICBmb3IobGV0IGkgPSAwOyBpIDwgdGhpcy5jb2x1bW5EaXZzLmxlbmd0aCAtIDE7IGkrKykge1xuXG4gICAgICAgICAgICAgICAgbGV0IGNvbHVtbkhlaWdodCA9IDBcbiAgICAgICAgICAgICAgICBmb3IobGV0IGogPSAwOyBqIDwgdGhpcy5jb2x1bW5EaXZzW2ldLmNoaWxkcmVuLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbHVtbkhlaWdodCArPSB0aGlzLmNvbHVtbkRpdnNbaV0uY2hpbGRyZW5bal0uY2xpZW50SGVpZ2h0XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYoY29sdW1uSGVpZ2h0ID4gbWF4Q29sdW1uQ29udGVudEhlaWdodCkge1xuICAgICAgICAgICAgICAgICAgICB2YWxpZENvbHVtbnMgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYodmFsaWRDb2x1bW5zID09PSBmYWxzZSkge1xuXG4gICAgICAgICAgICB0aGlzLnJlbmRlckNvbHVtbk1hcmtkb3duKHRoaXMucmVnaW9uUGFyZW50LCB0aGlzLmRvbUxpc3QsIHRoaXMucmVnaW9uYWxTZXR0aW5ncyk7XG4gICAgICAgIH1cblxuICAgICAgICBzdXBlci51cGRhdGVSZW5kZXJlZE1hcmtkb3duKCk7XG4gICAgfVxufVxuXG4iLCIvKipcbiAqIEZpbGU6IC9zcmMvZG9tX21hbmFnZXIvcmVnaW9uYWxfbWFuYWdlcnMvcmVnaW9uTWFuYWdlckNvbnRhaW5lci50cyAgICAgICAgICAqXG4gKiBDcmVhdGVkIERhdGU6IFN1bmRheSwgTWF5IDIybmQgMjAyMiwgNzo1MCBwbSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICogQXV0aG9yOiBDYW1lcm9uIFJvYmluc29uICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpcbiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMjIgQ2FtZXJvbiBSb2JpbnNvbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICovXG5cbmltcG9ydCB7IHBhcnNlQ29sdW1uU2V0dGluZ3MsIHBhcnNlU2luZ2xlQ29sdW1uU2V0dGluZ3MgfSBmcm9tIFwiLi4vLi4vdXRpbGl0aWVzL3NldHRpbmdzUGFyc2VyXCI7XG5pbXBvcnQgeyBET01PYmplY3QgfSBmcm9tICcuLi9kb21PYmplY3QnO1xuaW1wb3J0IHsgTXVsdGlDb2x1bW5TZXR0aW5ncywgZ2V0RGVmYXVsdE11bHRpQ29sdW1uU2V0dGluZ3MgfSBmcm9tIFwiLi4vLi4vcmVnaW9uU2V0dGluZ3NcIjtcbmltcG9ydCB7IEZpbGVET01NYW5hZ2VyIH0gZnJvbSAnLi4vZG9tTWFuYWdlcic7XG5pbXBvcnQgeyBTdGFuZGFyZE11bHRpQ29sdW1uUmVnaW9uTWFuYWdlciBhcyBTdGFuZGFyZE11bHRpQ29sdW1uUmVnaW9uTWFuYWdlciB9IGZyb20gJy4vc3RhbmRhcmRNdWx0aUNvbHVtblJlZ2lvbk1hbmFnZXInO1xuaW1wb3J0IHsgU2luZ2xlQ29sdW1uUmVnaW9uTWFuYWdlciB9IGZyb20gXCIuL3NpbmdsZUNvbHVtblJlZ2lvbk1hbmFnZXJcIjtcbmltcG9ydCB7IFJlZ2lvbk1hbmFnZXIgfSBmcm9tIFwiLi9yZWdpb25NYW5hZ2VyXCI7XG5pbXBvcnQgeyBBdXRvTGF5b3V0UmVnaW9uTWFuYWdlciB9IGZyb20gJy4vYXV0b0xheW91dFJlZ2lvbk1hbmFnZXInO1xuXG4vKipcbiAqIFRoaXMgY2xhc3MgYWN0cyBhcyBhbiBhYnN0cmFjdGlvbiBmb3IgdGhlIGFjdHVhbCByZWdpb25hbCBtYW5hZ2VyLiBJdCBpcyB1c2VkIHRvIHVwZGF0ZSB0aGVcbiAqIHN1YmNsYXNzIG9mIFJlZ2lvbmFsTWFuYWdlciBkZXBlbmRpbmcgb24gdXNlciBwcmVmZXJlbmNlcyB0byBtYWtlIHJlbmRlcmluZyBtb3JlIHNpbXBsaWZpZWQuXG4gKi9cbmV4cG9ydCBjbGFzcyBSZWdpb25NYW5hZ2VyQ29udGFpbmVyIHtcblxuICAgIHByb3RlY3RlZCByZWdpb246IFJlZ2lvbk1hbmFnZXI7XG4gICAgY29uc3RydWN0b3IocGFyZW50RmlsZU1hbmFnZXI6IEZpbGVET01NYW5hZ2VyLCByZWdpb25LZXk6IHN0cmluZywgcm9vdEVsZW1lbnQ6IEhUTUxFbGVtZW50LCByZWdpb25QYXJlbnQ6IEhUTUxFbGVtZW50KSB7XG4gICAgICAgIHRoaXMucmVnaW9uID0gbmV3IFN0YW5kYXJkTXVsdGlDb2x1bW5SZWdpb25NYW5hZ2VyKGNyZWF0ZURlZmF1bHRSZWdpb25NYW5hZ2VyRGF0YShyZWdpb25QYXJlbnQsIHBhcmVudEZpbGVNYW5hZ2VyLCByZWdpb25LZXksIHJvb3RFbGVtZW50KSk7XG4gICAgfVxuXG4gICAgcHVibGljIGdldFJlZ2lvbigpOiBSZWdpb25NYW5hZ2VyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucmVnaW9uO1xuICAgIH1cblxuICAgIHB1YmxpYyBzZXRSZWdpb25TZXR0aW5ncyhzZXR0aW5nc1RleHQ6IHN0cmluZyk6IFJlZ2lvbk1hbmFnZXIge1xuXG4gICAgICAgIGxldCByZWdpb25hbFNldHRpbmdzID0gcGFyc2VDb2x1bW5TZXR0aW5ncyhzZXR0aW5nc1RleHQpO1xuICAgICAgICBpZiAocmVnaW9uYWxTZXR0aW5ncy5udW1iZXJPZkNvbHVtbnMgPT09IDEpIHtcblxuICAgICAgICAgICAgcmVnaW9uYWxTZXR0aW5ncyA9IHBhcnNlU2luZ2xlQ29sdW1uU2V0dGluZ3Moc2V0dGluZ3NUZXh0LCByZWdpb25hbFNldHRpbmdzKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnJlZ2lvbi5zZXRSZWdpb25hbFNldHRpbmdzKHJlZ2lvbmFsU2V0dGluZ3MpO1xuXG4gICAgICAgIGlmIChyZWdpb25hbFNldHRpbmdzLm51bWJlck9mQ29sdW1ucyA9PT0gMSkge1xuXG4gICAgICAgICAgICBpZih0aGlzLnJlZ2lvbiBpbnN0YW5jZW9mIFNpbmdsZUNvbHVtblJlZ2lvbk1hbmFnZXIgPT09IGZhbHNlKSB7XG5cbiAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmRlYnVnKFwiQ29udmVydGluZyByZWdpb24gdG8gc2luZ2xlIGNvbHVtbi5cIilcbiAgICAgICAgICAgICAgICB0aGlzLmNvbnZlcnRUb1NpbmdsZUNvbHVtbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYocmVnaW9uYWxTZXR0aW5ncy5hdXRvTGF5b3V0ID09PSB0cnVlKSB7XG5cbiAgICAgICAgICAgIGlmKHRoaXMucmVnaW9uIGluc3RhbmNlb2YgQXV0b0xheW91dFJlZ2lvbk1hbmFnZXIgPT09IGZhbHNlKSB7XG5cbiAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmRlYnVnKFwiQ29udmVydGluZyByZWdpb24gdG8gYXV0byBsYXlvdXQuXCIpXG4gICAgICAgICAgICAgICAgdGhpcy5jb252ZXJ0VG9BdXRvTGF5b3V0KClcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChyZWdpb25hbFNldHRpbmdzLm51bWJlck9mQ29sdW1ucyA+PSAyKSB7XG5cbiAgICAgICAgICAgIGlmKHRoaXMucmVnaW9uIGluc3RhbmNlb2YgU3RhbmRhcmRNdWx0aUNvbHVtblJlZ2lvbk1hbmFnZXIgPT09IGZhbHNlKSB7XG5cbiAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmRlYnVnKFwiQ29udmVydGluZyByZWdpb24gdG8gc3RhbmRhcmQgbXVsdGktY29sdW1uXCIpXG4gICAgICAgICAgICAgICAgdGhpcy5jb252ZXJ0VG9TdGFuZGFyZE11bHRpQ29sdW1uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcy5yZWdpb247XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBjb252ZXJ0VG9TaW5nbGVDb2x1bW4oKTogU2luZ2xlQ29sdW1uUmVnaW9uTWFuYWdlciB7XG5cbiAgICAgICAgbGV0IGRhdGEgPSB0aGlzLnJlZ2lvbi5nZXRSZWdpb25EYXRhKCk7XG4gICAgICAgIHRoaXMucmVnaW9uID0gbmV3IFNpbmdsZUNvbHVtblJlZ2lvbk1hbmFnZXIoZGF0YSk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXMucmVnaW9uIGFzIFNpbmdsZUNvbHVtblJlZ2lvbk1hbmFnZXI7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBjb252ZXJ0VG9TdGFuZGFyZE11bHRpQ29sdW1uKCk6IFN0YW5kYXJkTXVsdGlDb2x1bW5SZWdpb25NYW5hZ2VyIHtcblxuICAgICAgICBsZXQgZGF0YSA9IHRoaXMucmVnaW9uLmdldFJlZ2lvbkRhdGEoKTtcbiAgICAgICAgdGhpcy5yZWdpb24gPSBuZXcgU3RhbmRhcmRNdWx0aUNvbHVtblJlZ2lvbk1hbmFnZXIoZGF0YSk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXMucmVnaW9uIGFzIFN0YW5kYXJkTXVsdGlDb2x1bW5SZWdpb25NYW5hZ2VyO1xuICAgIH1cblxuICAgIHByaXZhdGUgY29udmVydFRvQXV0b0xheW91dCgpOiBBdXRvTGF5b3V0UmVnaW9uTWFuYWdlciB7XG5cbiAgICAgICAgbGV0IGRhdGEgPSB0aGlzLnJlZ2lvbi5nZXRSZWdpb25EYXRhKCk7XG4gICAgICAgIHRoaXMucmVnaW9uID0gbmV3IEF1dG9MYXlvdXRSZWdpb25NYW5hZ2VyKGRhdGEpO1xuXG4gICAgICAgIHJldHVybiB0aGlzLnJlZ2lvbiBhcyBBdXRvTGF5b3V0UmVnaW9uTWFuYWdlcjtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZURlZmF1bHRSZWdpb25NYW5hZ2VyRGF0YShyZWdpb25QYXJlbnQ6IEhUTUxFbGVtZW50LCBmaWxlTWFuYWdlcjogRmlsZURPTU1hbmFnZXIsIHJlZ2lvbktleTogc3RyaW5nLCByb290RWxlbWVudDogSFRNTEVsZW1lbnQpOiBSZWdpb25NYW5hZ2VyRGF0YSB7XG5cbiAgICByZXR1cm4ge1xuICAgICAgICBkb21MaXN0OiBbXSxcbiAgICAgICAgZG9tT2JqZWN0TWFwOiBuZXcgTWFwKCksXG4gICAgICAgIHJlZ2lvblBhcmVudDogcmVnaW9uUGFyZW50LFxuICAgICAgICBmaWxlTWFuYWdlcjogZmlsZU1hbmFnZXIsXG4gICAgICAgIHJlZ2lvbmFsU2V0dGluZ3M6IGdldERlZmF1bHRNdWx0aUNvbHVtblNldHRpbmdzKCksXG4gICAgICAgIHJlZ2lvbktleTogcmVnaW9uS2V5LFxuICAgICAgICByb290RWxlbWVudDogcm9vdEVsZW1lbnRcbiAgICB9O1xufVxuXG5leHBvcnQgdHlwZSBSZWdpb25NYW5hZ2VyRGF0YSA9IHtcbiAgICBkb21MaXN0OiBET01PYmplY3RbXTtcbiAgICBkb21PYmplY3RNYXA6IE1hcDxzdHJpbmcsIERPTU9iamVjdD47XG4gICAgcmVnaW9uUGFyZW50OiBIVE1MRWxlbWVudDtcblxuICAgIGZpbGVNYW5hZ2VyOiBGaWxlRE9NTWFuYWdlcjtcbiAgICByZWdpb25hbFNldHRpbmdzOiBNdWx0aUNvbHVtblNldHRpbmdzO1xuXG4gICAgcmVnaW9uS2V5OiBzdHJpbmc7XG4gICAgcm9vdEVsZW1lbnQ6IEhUTUxFbGVtZW50O1xufTtcbiIsIi8qXG4gKiBGaWxlOiBtdWx0aS1jb2x1bW4tbWFya2Rvd24vc3JjL2RvbU1hbmFnZXIudHNcbiAqIENyZWF0ZWQgRGF0ZTogU2F0dXJkYXksIEphbnVhcnkgMzB0aCAyMDIyLCAzOjE2OjMyIHBtXG4gKiBBdXRob3I6IENhbWVyb24gUm9iaW5zb25cbiAqIFxuICogQ29weXJpZ2h0IChjKSAyMDIyIENhbWVyb24gUm9iaW5zb25cbiAqL1xuXG5pbXBvcnQgeyBSZWdpb25NYW5hZ2VyIH0gZnJvbSBcIi4vcmVnaW9uYWxfbWFuYWdlcnMvcmVnaW9uTWFuYWdlclwiO1xuaW1wb3J0IHsgUmVnaW9uTWFuYWdlckNvbnRhaW5lciB9IGZyb20gXCIuL3JlZ2lvbmFsX21hbmFnZXJzL3JlZ2lvbk1hbmFnZXJDb250YWluZXJcIjtcblxuLyoqXG4gKiBUaGlzIGNsYXNzIGhhbmRsZXMgdGhlIGdsb2JhbCBtYW5hZ2VycyBrZWVwaW5nIHRyYWNrIG9mIGFsbCBvcGVuIGZpbGVzIHRoYXRcbiAqIGNvbnRhaW4gTUNNLVJlZ2lvbnMuXG4gKi9cbmV4cG9ydCBjbGFzcyBHbG9iYWxET01NYW5hZ2VyIHtcbiAgICBtYW5hZ2VyczogTWFwPHN0cmluZywgRmlsZURPTU1hbmFnZXI+O1xuXG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHRoaXMubWFuYWdlcnMgPSBuZXcgTWFwKCk7XG4gICAgfVxuXG4gICAgcHVibGljIHJlbW92ZUZpbGVNYW5hZ2VyQ2FsbGJhY2soa2V5OiBzdHJpbmcpIHtcbiAgICAgICAgaWYodGhpcy5tYW5hZ2Vycy5oYXMoa2V5KSA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgdGhpcy5tYW5hZ2Vycy5kZWxldGUoa2V5KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyBnZXRGaWxlTWFuYWdlcihrZXk6IHN0cmluZykge1xuXG4gICAgICAgIGxldCBmaWxlTWFuYWdlciA9IG51bGw7XG4gICAgICAgIGlmKHRoaXMubWFuYWdlcnMuaGFzKGtleSkgPT09IHRydWUpIHtcbiAgICAgICAgICAgIGZpbGVNYW5hZ2VyID0gdGhpcy5tYW5hZ2Vycy5nZXQoa2V5KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGZpbGVNYW5hZ2VyID0gY3JlYXRlRmlsZURPTU1hbmFnZXIodGhpcywga2V5KTtcbiAgICAgICAgICAgIHRoaXMubWFuYWdlcnMuc2V0KGtleSwgZmlsZU1hbmFnZXIpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGZpbGVNYW5hZ2VyO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXRBbGxGaWxlTWFuYWdlcnMoKSB7XG4gICAgICAgIHJldHVybiBBcnJheS5mcm9tKHRoaXMubWFuYWdlcnMudmFsdWVzKCkpO1xuICAgIH1cbn1cblxuZXhwb3J0IHR5cGUgRmlsZURPTU1hbmFnZXIgPSB7XG4gICAgcmVnaW9uTWFwOiBNYXA8c3RyaW5nLCBSZWdpb25NYW5hZ2VyQ29udGFpbmVyPixcbiAgICBoYXNTdGFydFRhZzogYm9vbGVhbixcbiAgICBjcmVhdGVSZWdpb25hbE1hbmFnZXI6IChyZWdpb25LZXk6IHN0cmluZywgcm9vdEVsZW1lbnQ6IEhUTUxFbGVtZW50LCBlcnJvckVsZW1lbnQ6IEhUTUxFbGVtZW50LCByZW5kZXJSZWdpb25FbGVtZW50OiBIVE1MRWxlbWVudCkgPT4gUmVnaW9uTWFuYWdlclxuICAgIGdldFJlZ2lvbmFsQ29udGFpbmVyOiAocmVnaW9uS2V5OiBzdHJpbmcpID0+IFJlZ2lvbk1hbmFnZXJDb250YWluZXIgfCBudWxsLFxuICAgIGdldEFsbFJlZ2lvbmFsTWFuYWdlcnM6ICgpID0+IFJlZ2lvbk1hbmFnZXJbXSxcbiAgICByZW1vdmVSZWdpb246IChyZWdpb25LZXk6IHN0cmluZykgPT4gdm9pZCxcbiAgICBzZXRIYXNTdGFydFRhZzogKCkgPT4gdm9pZCxcbiAgICBnZXRIYXNTdGFydFRhZzogKCkgPT4gYm9vbGVhbixcbiAgICBnZXROdW1iZXJPZlJlZ2lvbnM6ICgpID0+IG51bWJlcixcbiAgICBjaGVja0tleUV4aXN0czogKGNoZWNrS2V5OiBzdHJpbmcpID0+IGJvb2xlYW5cbn1cbmZ1bmN0aW9uIGNyZWF0ZUZpbGVET01NYW5hZ2VyKHBhcmVudE1hbmFnZXI6IEdsb2JhbERPTU1hbmFnZXIsIGZpbGVLZXk6IHN0cmluZyk6IEZpbGVET01NYW5hZ2VyIHtcbiAgICBcbiAgICBsZXQgcmVnaW9uTWFwOiBNYXA8c3RyaW5nLCBSZWdpb25NYW5hZ2VyQ29udGFpbmVyPiA9IG5ldyBNYXAoKTtcbiAgICBsZXQgaGFzU3RhcnRUYWc6IGJvb2xlYW4gPSBmYWxzZTtcblxuICAgIGZ1bmN0aW9uIHJlbW92ZVJlZ2lvbihyZWdpb25LZXk6IHN0cmluZyk6IHZvaWQge1xuXG4gICAgICAgIGxldCByZWdpb25Db250YWluZXIgPSByZWdpb25NYXAuZ2V0KHJlZ2lvbktleSk7XG4gICAgICAgIGlmKHJlZ2lvbkNvbnRhaW5lcikge1xuICAgICAgICAgICAgbGV0IHJlZ2lvbmFsTWFuYWdlciA9IHJlZ2lvbkNvbnRhaW5lci5nZXRSZWdpb24oKTtcbiAgICAgICAgICAgIHJlZ2lvbmFsTWFuYWdlci5kaXNwbGF5T3JpZ2luYWxFbGVtZW50cygpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmVnaW9uTWFwLmRlbGV0ZShyZWdpb25LZXkpO1xuICAgICAgICBcbiAgICAgICAgaWYocmVnaW9uTWFwLnNpemUgPT09IDApIHtcbiAgICAgICAgICAgIHBhcmVudE1hbmFnZXIucmVtb3ZlRmlsZU1hbmFnZXJDYWxsYmFjayhmaWxlS2V5KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNyZWF0ZVJlZ2lvbmFsTWFuYWdlcihyZWdpb25LZXk6IHN0cmluZywgcm9vdEVsZW1lbnQ6IEhUTUxFbGVtZW50LCBlcnJvckVsZW1lbnQ6IEhUTUxFbGVtZW50LCByZW5kZXJSZWdpb25FbGVtZW50OiBIVE1MRWxlbWVudCk6IFJlZ2lvbk1hbmFnZXIge1xuXG4gICAgICAgIC8vVE9ETzogVXNlIHRoZSBlcnJvciBlbGVtZW50IHdoZW5ldmVyIHRoZXJlIGlzIGFuIGVycm9yLlxuXG4gICAgICAgIGxldCByZWdvbmFsQ29udGFpbmVyID0gbmV3IFJlZ2lvbk1hbmFnZXJDb250YWluZXIodGhpcywgcmVnaW9uS2V5LCByb290RWxlbWVudCwgcmVuZGVyUmVnaW9uRWxlbWVudCk7XG4gICAgICAgIHJlZ2lvbk1hcC5zZXQocmVnaW9uS2V5LCByZWdvbmFsQ29udGFpbmVyKTtcbiAgICAgICAgcmV0dXJuIHJlZ29uYWxDb250YWluZXIuZ2V0UmVnaW9uKCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0UmVnaW9uYWxDb250YWluZXIocmVnaW9uS2V5OiBzdHJpbmcpOiBSZWdpb25NYW5hZ2VyQ29udGFpbmVyIHwgbnVsbCB7XG5cbiAgICAgICAgbGV0IHJlZ29uYWxNYW5hZ2VyID0gbnVsbDtcbiAgICAgICAgaWYocmVnaW9uTWFwLmhhcyhyZWdpb25LZXkpID09PSB0cnVlKSB7XG4gICAgICAgICAgICByZWdvbmFsTWFuYWdlciA9IHJlZ2lvbk1hcC5nZXQocmVnaW9uS2V5KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByZWdvbmFsTWFuYWdlcjtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBnZXRBbGxSZWdpb25hbE1hbmFnZXJzKCk6IFJlZ2lvbk1hbmFnZXJbXSB7XG5cbiAgICAgICAgbGV0IGNvbnRhaW5lcnMgPSBBcnJheS5mcm9tKHJlZ2lvbk1hcC52YWx1ZXMoKSlcbiAgICAgICAgbGV0IHJlZ2lvbnM6IFJlZ2lvbk1hbmFnZXJbXSA9IGNvbnRhaW5lcnMubWFwKChjdXJyKSA9PiB7IHJldHVybiBjdXJyLmdldFJlZ2lvbigpIH0pO1xuICAgICAgICByZXR1cm4gcmVnaW9ucztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBzZXRIYXNTdGFydFRhZygpIHtcbiAgICAgICAgaGFzU3RhcnRUYWcgPSB0cnVlO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldEhhc1N0YXJ0VGFnKCkge1xuICAgICAgICByZXR1cm4gaGFzU3RhcnRUYWc7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0TnVtYmVyT2ZSZWdpb25zKCkge1xuICAgICAgICByZXR1cm4gcmVnaW9uTWFwLnNpemVcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjaGVja0tleUV4aXN0cyhjaGVja0tleTogc3RyaW5nKSB7XG4gICAgICAgIHJldHVybiByZWdpb25NYXAuaGFzKGNoZWNrS2V5KTtcbiAgICB9XG5cbiAgICByZXR1cm4geyByZWdpb25NYXA6IHJlZ2lvbk1hcCwgXG4gICAgICAgIGhhc1N0YXJ0VGFnOiBoYXNTdGFydFRhZywgIFxuICAgICAgICBjcmVhdGVSZWdpb25hbE1hbmFnZXI6IGNyZWF0ZVJlZ2lvbmFsTWFuYWdlciwgXG4gICAgICAgIGdldFJlZ2lvbmFsQ29udGFpbmVyOiBnZXRSZWdpb25hbENvbnRhaW5lcixcbiAgICAgICAgZ2V0QWxsUmVnaW9uYWxNYW5hZ2VyczogZ2V0QWxsUmVnaW9uYWxNYW5hZ2VycyxcbiAgICAgICAgcmVtb3ZlUmVnaW9uOiByZW1vdmVSZWdpb24sIFxuICAgICAgICBzZXRIYXNTdGFydFRhZzogc2V0SGFzU3RhcnRUYWcsIFxuICAgICAgICBnZXRIYXNTdGFydFRhZzogZ2V0SGFzU3RhcnRUYWcsXG4gICAgICAgIGdldE51bWJlck9mUmVnaW9uczogZ2V0TnVtYmVyT2ZSZWdpb25zLFxuICAgICAgICBjaGVja0tleUV4aXN0czogY2hlY2tLZXlFeGlzdHNcbiAgICB9XG59IiwiLypcbiAqIEZpbGVuYW1lOiBtdWx0aS1jb2x1bW4tbWFya2Rvd24vc3JjL2xpdmVfcHJldmlldy9NdWx0aUNvbHVtbk1hcmtkb3duX1dpZGdldC50c1xuICogQ3JlYXRlZCBEYXRlOiBUdWVzZGF5LCBBdWd1c3QgMTZ0aCAyMDIyLCA0OjM4OjQzIHBtXG4gKiBBdXRob3I6IENhbWVyb24gUm9iaW5zb25cbiAqIFxuICogQ29weXJpZ2h0IChjKSAyMDIyIENhbWVyb24gUm9iaW5zb25cbiAqL1xuXG5pbXBvcnQgeyBNYXJrZG93blJlbmRlckNoaWxkLCBNYXJrZG93blJlbmRlcmVyLCBURmlsZSwgV29ya3NwYWNlTGVhZiB9IGZyb20gXCJvYnNpZGlhblwiO1xuaW1wb3J0IHsgV2lkZ2V0VHlwZSB9IGZyb20gXCJAY29kZW1pcnJvci92aWV3XCI7XG5pbXBvcnQgeyBnZXREZWZhdWx0TXVsdGlDb2x1bW5TZXR0aW5ncywgTXVsdGlDb2x1bW5TZXR0aW5ncyB9IGZyb20gXCIuLi9yZWdpb25TZXR0aW5nc1wiO1xuaW1wb3J0IHsgZmluZFNldHRpbmdzQ29kZWJsb2NrLCBmaW5kU3RhcnRDb2RlYmxvY2sgfSBmcm9tIFwiLi4vdXRpbGl0aWVzL3RleHRQYXJzZXJcIjtcbmltcG9ydCB7IHBhcnNlQ29sdW1uU2V0dGluZ3MsIHBhcnNlU2luZ2xlQ29sdW1uU2V0dGluZ3MgfSBmcm9tIFwiLi4vdXRpbGl0aWVzL3NldHRpbmdzUGFyc2VyXCI7XG5pbXBvcnQgeyBTdGFuZGFyZE11bHRpQ29sdW1uUmVnaW9uTWFuYWdlciB9IGZyb20gXCIuLi9kb21fbWFuYWdlci9yZWdpb25hbF9tYW5hZ2Vycy9zdGFuZGFyZE11bHRpQ29sdW1uUmVnaW9uTWFuYWdlclwiO1xuaW1wb3J0IHsgUmVnaW9uTWFuYWdlckRhdGEgfSBmcm9tIFwiLi4vZG9tX21hbmFnZXIvcmVnaW9uYWxfbWFuYWdlcnMvcmVnaW9uTWFuYWdlckNvbnRhaW5lclwiO1xuaW1wb3J0IHsgZ2V0VUlEIH0gZnJvbSBcIi4uL3V0aWxpdGllcy91dGlsc1wiO1xuaW1wb3J0IHsgRE9NT2JqZWN0IH0gZnJvbSBcIi4uL2RvbV9tYW5hZ2VyL2RvbU9iamVjdFwiO1xuaW1wb3J0IHsgUmVnaW9uTWFuYWdlciB9IGZyb20gXCIuLi9kb21fbWFuYWdlci9yZWdpb25hbF9tYW5hZ2Vycy9yZWdpb25NYW5hZ2VyXCI7XG5pbXBvcnQgeyBTaW5nbGVDb2x1bW5SZWdpb25NYW5hZ2VyIH0gZnJvbSBcIi4uL2RvbV9tYW5hZ2VyL3JlZ2lvbmFsX21hbmFnZXJzL3NpbmdsZUNvbHVtblJlZ2lvbk1hbmFnZXJcIjtcbmltcG9ydCB7IEF1dG9MYXlvdXRSZWdpb25NYW5hZ2VyIH0gZnJvbSBcIi4uL2RvbV9tYW5hZ2VyL3JlZ2lvbmFsX21hbmFnZXJzL2F1dG9MYXlvdXRSZWdpb25NYW5hZ2VyXCI7XG5cbmV4cG9ydCBjbGFzcyBNdWx0aUNvbHVtbk1hcmtkb3duX0xpdmVQcmV2aWV3X1dpZGdldCBleHRlbmRzIFdpZGdldFR5cGUge1xuXG4gICAgY29udGVudERhdGE6IHN0cmluZztcbiAgICB0ZW1wUGFyZW50OiBIVE1MRGl2RWxlbWVudDtcbiAgICBkb21MaXN0OiBET01PYmplY3RbXSA9IFtdO1xuICAgIHNldHRpbmdzVGV4dDogc3RyaW5nO1xuICAgIHJlZ2lvblNldHRpbmdzOiBNdWx0aUNvbHVtblNldHRpbmdzID0gZ2V0RGVmYXVsdE11bHRpQ29sdW1uU2V0dGluZ3MoKTtcbiAgICByZWdpb25NYW5hZ2VyOiBSZWdpb25NYW5hZ2VyO1xuXG4gICAgY29uc3RydWN0b3IoY29udGVudERhdGE6IHN0cmluZykge1xuICAgICAgICBzdXBlcigpO1xuICAgICAgICB0aGlzLmNvbnRlbnREYXRhID0gY29udGVudERhdGE7XG5cbiAgICAgICAgLy8gRmluZCB0aGUgc2V0dGluZ3MgZGVmaW5lZCBpbiB0aGUgY29udGVudCwgaWYgaXQgZXhpc3RzLlxuICAgICAgICAvLyBJZiB0aGUgc2V0dGluZ3MgY29kZWJsb2NrIGlzbnQgZGVmaW5lZCBhdHRlbXB0IHRvIGdldCB0aGUgcmVnaW9uIGNvZGVibG9jayB0eXBlLlxuICAgICAgICBsZXQgc2V0dGluZ3NTdGFydERhdGEgPSBmaW5kU2V0dGluZ3NDb2RlYmxvY2sodGhpcy5jb250ZW50RGF0YSk7XG4gICAgICAgIGlmKHNldHRpbmdzU3RhcnREYXRhLmZvdW5kID09PSBmYWxzZSkge1xuICAgICAgICAgICAgc2V0dGluZ3NTdGFydERhdGEgPSBmaW5kU3RhcnRDb2RlYmxvY2sodGhpcy5jb250ZW50RGF0YSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHNldHRpbmdzU3RhcnREYXRhLmZvdW5kID09PSB0cnVlKSB7XG5cbiAgICAgICAgICAgIHRoaXMuc2V0dGluZ3NUZXh0ID0gdGhpcy5jb250ZW50RGF0YS5zbGljZShzZXR0aW5nc1N0YXJ0RGF0YS5zdGFydFBvc2l0aW9uLCBzZXR0aW5nc1N0YXJ0RGF0YS5lbmRQb3NpdGlvbik7XG4gICAgICAgICAgICB0aGlzLmNvbnRlbnREYXRhID0gdGhpcy5jb250ZW50RGF0YS5yZXBsYWNlKHRoaXMuc2V0dGluZ3NUZXh0LCBcIlwiKTtcblxuICAgICAgICAgICAgLy8gUGFyc2UgdGhlIHNldHRpbmdzLCB1cGRhdGluZyB0aGUgZGVmYXVsdCBzZXR0aW5ncy5cbiAgICAgICAgICAgIHRoaXMucmVnaW9uU2V0dGluZ3MgPSBwYXJzZUNvbHVtblNldHRpbmdzKHRoaXMuc2V0dGluZ3NUZXh0KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFJlbmRlciB0aGUgbWFya2Rvd24gY29udGVudCB0byBvdXIgdGVtcCBwYXJlbnQgZWxlbWVudC5cbiAgICAgICAgdGhpcy50ZW1wUGFyZW50ID0gY3JlYXRlRGl2KCk7XG4gICAgICAgIGxldCBlbGVtZW50TWFya2Rvd25SZW5kZXJlciA9IG5ldyBNYXJrZG93blJlbmRlckNoaWxkKHRoaXMudGVtcFBhcmVudCk7XG4gICAgICAgIE1hcmtkb3duUmVuZGVyZXIucmVuZGVyTWFya2Rvd24odGhpcy5jb250ZW50RGF0YSwgdGhpcy50ZW1wUGFyZW50LCBcIlwiLCBlbGVtZW50TWFya2Rvd25SZW5kZXJlcik7XG5cbiAgICAgICAgLy8gdGFrZSBhbGwgZWxlbWVudHMsIGluIG9yZGVyLCBhbmQgY3JlYXRlIG91ciBET00gbGlzdC5cbiAgICAgICAgbGV0IGFyciA9IEFycmF5LmZyb20odGhpcy50ZW1wUGFyZW50LmNoaWxkcmVuKTtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBhcnIubGVuZ3RoOyBpKyspIHtcblxuICAgICAgICAgICAgbGV0IGVsID0gdGhpcy5maXhFbGVtZW50UmVuZGVyKGFycltpXSk7XG4gICAgICAgICAgICB0aGlzLmRvbUxpc3QucHVzaChuZXcgRE9NT2JqZWN0KGVsIGFzIEhUTUxFbGVtZW50LCBbXCJcIl0pKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFNldCB1cCB0aGUgcmVnaW9uIG1hbmFnZXIgZGF0YSBiZWZvcmUgdGhlbiBjcmVhdGluZyBvdXIgcmVnaW9uIG1hbmFnZXIuXG4gICAgICAgIGxldCByZWdpb25EYXRhOiBSZWdpb25NYW5hZ2VyRGF0YSA9IHtcbiAgICAgICAgICAgIGRvbUxpc3Q6IHRoaXMuZG9tTGlzdCxcbiAgICAgICAgICAgIGRvbU9iamVjdE1hcDogbmV3IE1hcDxzdHJpbmcsIERPTU9iamVjdD4oKSxcbiAgICAgICAgICAgIHJlZ2lvblBhcmVudDogY3JlYXRlRGl2KCksXG4gICAgICAgICAgICBmaWxlTWFuYWdlcjogbnVsbCxcbiAgICAgICAgICAgIHJlZ2lvbmFsU2V0dGluZ3M6IHRoaXMucmVnaW9uU2V0dGluZ3MsXG4gICAgICAgICAgICByZWdpb25LZXk6IGdldFVJRCgpLFxuICAgICAgICAgICAgcm9vdEVsZW1lbnQ6IGNyZWF0ZURpdigpXG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gRmluYWxseSBzZXR1cCB0aGUgdHlwZSBvZiByZWdpb24gbWFuYWdlciByZXF1aXJlZC5cbiAgICAgICAgaWYgKHRoaXMucmVnaW9uU2V0dGluZ3MubnVtYmVyT2ZDb2x1bW5zID09PSAxKSB7XG4gICAgICAgICAgICB0aGlzLnJlZ2lvblNldHRpbmdzID0gcGFyc2VTaW5nbGVDb2x1bW5TZXR0aW5ncyh0aGlzLnNldHRpbmdzVGV4dCwgdGhpcy5yZWdpb25TZXR0aW5ncyk7XG4gICAgICAgICAgICB0aGlzLnJlZ2lvbk1hbmFnZXIgPSBuZXcgU2luZ2xlQ29sdW1uUmVnaW9uTWFuYWdlcihyZWdpb25EYXRhKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh0aGlzLnJlZ2lvblNldHRpbmdzLmF1dG9MYXlvdXQgPT09IHRydWUpIHtcbiAgICAgICAgICAgIHRoaXMucmVnaW9uTWFuYWdlciA9IG5ldyBBdXRvTGF5b3V0UmVnaW9uTWFuYWdlcihyZWdpb25EYXRhKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMucmVnaW9uTWFuYWdlciA9IG5ldyBTdGFuZGFyZE11bHRpQ29sdW1uUmVnaW9uTWFuYWdlcihyZWdpb25EYXRhKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZpeEVsZW1lbnRSZW5kZXIoZWw6IEVsZW1lbnQpOiBFbGVtZW50IHtcblxuICAgICAgICBsZXQgZml4ZWRFbCA9IGZpeEltYWdlUmVuZGVyKGVsKTtcbiAgICAgICAgcmV0dXJuIGZpeGVkRWw7XG4gICAgfVxuXG4gICAgdG9ET00oKSB7XG4gICAgICAgIC8vIENyZWF0ZSBvdXIgZWxlbWVudCB0byBob2xkIGFsbCBvZiB0aGUgbGl2ZSBwcmV2aWV3IGVsZW1lbnRzLlxuICAgICAgICBsZXQgZWwgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiZGl2XCIpO1xuICAgICAgICBlbC5jbGFzc05hbWUgPSBcIm1jbS1jbS1wcmV2aWV3XCI7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEZvciBzaXR1YXRpb25zIHdoZXJlIHdlIG5lZWQgdG8ga25vdyB0aGUgcmVuZGVyZWQgaGVpZ2h0LCBBdXRvTGF5b3V0LCBcbiAgICAgICAgICogdGhlIGVsZW1lbnQgbXVzdCBiZSByZW5kZXJlZCBvbnRvIHRoZSBzY3JlZW4gdG8gZ2V0IHRoZSBpbmZvLCBldmVuIGlmIFxuICAgICAgICAgKiBvbmx5IGZvciBhIG1vbWVudC4gSGVyZSB3ZSBhdHRlbXB0IHRvIGdldCBhIGxlYWYgZnJvbSB0aGUgYXBwIHNvIHdlIFxuICAgICAgICAgKiBjYW4gYnJpZWZseSBhcHBlbmQgb3VyIGVsZW1lbnQsIGNoZWNrIGFueSBkYXRhIGlmIHJlcXVpcmVkLCBhbmQgdGhlblxuICAgICAgICAgKiByZW1vdmUgaXQuXG4gICAgICAgICAqL1xuICAgICAgICBsZXQgbGVhZjogV29ya3NwYWNlTGVhZiA9IG51bGw7XG4gICAgICAgIGlmIChhcHApIHtcbiAgICAgICAgICAgIGxldCBsZWF2ZXMgPSBhcHAud29ya3NwYWNlLmdldExlYXZlc09mVHlwZShcIm1hcmtkb3duXCIpO1xuICAgICAgICAgICAgaWYgKGxlYXZlcy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgbGVhZiA9IGxlYXZlc1swXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLnJlZ2lvbk1hbmFnZXIpIHtcblxuICAgICAgICAgICAgaWYgKGxlYWYpIHtcbiAgICAgICAgICAgICAgICBsZWFmLnZpZXcuY29udGFpbmVyRWwuYXBwZW5kQ2hpbGQoZWwpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLnJlZ2lvbk1hbmFnZXIucmVuZGVyUmVnaW9uRWxlbWVudHNUb0xpdmVQcmV2aWV3KGVsKTtcblxuICAgICAgICAgICAgaWYgKGxlYWYpIHtcbiAgICAgICAgICAgICAgICBsZWFmLnZpZXcuY29udGFpbmVyRWwucmVtb3ZlQ2hpbGQoZWwpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGVsO1xuICAgIH1cbn1cblxuZXhwb3J0IGNsYXNzIE11bHRpQ29sdW1uTWFya2Rvd25fRGVmaW5lZFNldHRpbmdzX0xpdmVQcmV2aWV3X1dpZGdldCBleHRlbmRzIFdpZGdldFR5cGUge1xuXG4gICAgY29udGVudERhdGE6IHN0cmluZztcblxuICAgIGNvbnN0cnVjdG9yKGNvbnRlbnREYXRhOiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIoKTtcblxuICAgICAgICB0aGlzLmNvbnRlbnREYXRhID0gY29udGVudERhdGE7XG4gICAgfVxuXG4gICAgdG9ET00oKSB7XG4gICAgICAgIC8vIENyZWF0ZSBvdXIgZWxlbWVudCB0byBob2xkIGFsbCBvZiB0aGUgbGl2ZSBwcmV2aWV3IGVsZW1lbnRzLlxuICAgICAgICBsZXQgZWwgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiZGl2XCIpO1xuICAgICAgICBlbC5jbGFzc05hbWUgPSBcIm1jbS1jbS1zZXR0aW5ncy1wcmV2aWV3XCI7XG5cbiAgICAgICAgbGV0IGxhYmVsRGl2ID0gZWwuY3JlYXRlRGl2KClcbiAgICAgICAgbGV0IGxhYmVsID0gbGFiZWxEaXYuY3JlYXRlU3Bhbih7XG4gICAgICAgICAgICBjbHM6IFwibWNtLWNvbC1zZXR0aW5ncy1wcmV2aWV3XCJcbiAgICAgICAgfSlcbiAgICAgICAgbGFiZWwudGV4dENvbnRlbnQgPSBcIkNvbHVtbiBTZXR0aW5nczpcIjtcblxuICAgICAgICBsZXQgbGlzdCA9IGVsLmNyZWF0ZUVsKFwidWxcIilcbiAgICAgICAgbGV0IGxpbmVzID0gdGhpcy5jb250ZW50RGF0YS5zcGxpdChcIlxcblwiKVxuICAgICAgICBmb3IobGV0IGkgPSAxOyBpIDwgbGluZXMubGVuZ3RoIC0gMTsgaSsrKSB7XG4gICAgICAgICAgICBsZXQgaXRlbSA9IGxpc3QuY3JlYXRlRWwoXCJsaVwiKVxuICAgICAgICAgICAgaXRlbS50ZXh0Q29udGVudCA9IGxpbmVzW2ldXG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZWw7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBmaXhJbWFnZVJlbmRlcihlbDogRWxlbWVudCk6IEVsZW1lbnQge1xuXG4gICAgbGV0IGZpeGVkRWwgPSBlbDtcbiAgICBsZXQgaXRlbXMgPSBlbC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKFwiaW50ZXJuYWwtZW1iZWRcIik7XG4gICAgaWYoaXRlbXMubGVuZ3RoID09PSAxKSB7XG5cbiAgICAgICAgbGV0IGVtYmVkID0gaXRlbXNbMF07XG4gICAgICAgIGxldCBhbHQgPSBlbWJlZC5nZXRBdHRyKFwiYWx0XCIpXG4gICAgICAgIGxldCBzcmMgPSBlbWJlZC5nZXRBdHRyKFwic3JjXCIpXG5cbiAgICAgICAgbGV0IGFURmlsZXMgPSBhcHAudmF1bHQuZ2V0QWxsTG9hZGVkRmlsZXMoKVxuICAgICAgICBsZXQgcmVzb3VyY2VQYXRoID0gXCJcIlxuICAgICAgICBmb3IobGV0IGkgPSAwOyBpIDwgYVRGaWxlcy5sZW5ndGg7IGkrKykge1xuXG4gICAgICAgICAgICBsZXQgYWJzdHJhY3RGaWxlID0gYVRGaWxlc1tpXTtcbiAgICAgICAgICAgIGlmKGFic3RyYWN0RmlsZSBpbnN0YW5jZW9mIFRGaWxlID09PSBmYWxzZSkge1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IGZpbGUgPSBhYnN0cmFjdEZpbGUgYXMgVEZpbGU7XG5cbiAgICAgICAgICAgIGlmKGZpbGUubmFtZSA9PT0gc3JjICYmIGhhc0ltYWdlRXh0ZW5zaW9uKGZpbGUuZXh0ZW5zaW9uKSA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgIHJlc291cmNlUGF0aCA9IGFwcC52YXVsdC5nZXRSZXNvdXJjZVBhdGgoZmlsZSlcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGFsdCA9PT0gc3JjICYmIHJlc291cmNlUGF0aCAhPT0gXCJcIikge1xuXG4gICAgICAgICAgICBmaXhlZEVsID0gY3JlYXRlRGl2KHtcbiAgICAgICAgICAgICAgICBjbHM6IFwiaW50ZXJuYWwtZW1iZWQgaW1hZ2UtZW1iZWQgaXMtbG9hZGVkXCIsXG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgZml4ZWRFbC5zZXRBdHRyKFwiYWx0XCIsIGFsdCk7XG5cbiAgICAgICAgICAgIGxldCBpbWFnZSA9IGZpeGVkRWwuY3JlYXRlRWwoXCJpbWdcIik7XG4gICAgICAgICAgICBpbWFnZS5zZXRBdHRyKFwic3JjXCIsIHJlc291cmNlUGF0aCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gZml4ZWRFbDtcbn1cblxuZnVuY3Rpb24gaGFzSW1hZ2VFeHRlbnNpb24oZXh0ZW5zaW9uOiBzdHJpbmcpOiBib29sZWFuIHtcblxuICAgIGV4dGVuc2lvbiA9IGV4dGVuc2lvbi50b0xvd2VyQ2FzZSgpO1xuICAgIHN3aXRjaChleHRlbnNpb24pIHtcbiAgICAgICAgY2FzZSBcInBuZ1wiOlxuICAgICAgICBjYXNlIFwianBnXCI6XG4gICAgICAgIGNhc2UgXCJqcGVnXCI6XG4gICAgICAgIGNhc2UgXCJnaWZcIjpcbiAgICAgICAgY2FzZSBcImJtcFwiOlxuICAgICAgICBjYXNlIFwic3ZnXCI6XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xufSIsIi8qXG4gKiBGaWxlbmFtZTogbXVsdGktY29sdW1uLW1hcmtkb3duL3NyYy9saXZlX3ByZXZpZXcvY202X2xpdmVQcmV2aWV3LnRzXG4gKiBDcmVhdGVkIERhdGU6IE1vbmRheSwgQXVndXN0IDFzdCAyMDIyLCAxOjUxOjE2IHBtXG4gKiBBdXRob3I6IENhbWVyb24gUm9iaW5zb25cbiAqIFxuICogQ29weXJpZ2h0IChjKSAyMDIyIENhbWVyb24gUm9iaW5zb25cbiAqL1xuXG5pbXBvcnQgeyBFZGl0b3JTdGF0ZSwgRXh0ZW5zaW9uLCBMaW5lLCBSYW5nZVNldEJ1aWxkZXIsIFN0YXRlRmllbGQsIFRyYW5zYWN0aW9uIH0gZnJvbSBcIkBjb2RlbWlycm9yL3N0YXRlXCI7XG5pbXBvcnQgeyBEZWNvcmF0aW9uLCBEZWNvcmF0aW9uU2V0LCBFZGl0b3JWaWV3IH0gZnJvbSBcIkBjb2RlbWlycm9yL3ZpZXdcIjtcbmltcG9ydCB7IHN5bnRheFRyZWUsIHRva2VuQ2xhc3NOb2RlUHJvcCB9IGZyb20gXCJAY29kZW1pcnJvci9sYW5ndWFnZVwiO1xuaW1wb3J0IHsgY29udGFpbnNSZWdpb25TdGFydCwgZmluZEVuZFRhZywgZmluZFNldHRpbmdzQ29kZWJsb2NrLCBmaW5kU3RhcnRDb2RlYmxvY2ssIGZpbmRTdGFydFRhZyB9IGZyb20gXCIuLi91dGlsaXRpZXMvdGV4dFBhcnNlclwiO1xuaW1wb3J0IHsgTXVsdGlDb2x1bW5NYXJrZG93bl9EZWZpbmVkU2V0dGluZ3NfTGl2ZVByZXZpZXdfV2lkZ2V0LCBNdWx0aUNvbHVtbk1hcmtkb3duX0xpdmVQcmV2aWV3X1dpZGdldCB9IGZyb20gXCIuL21jbV9saXZlUHJldmlld193aWRnZXRcIjtcbmltcG9ydCB7IGVkaXRvclZpZXdGaWVsZCB9IGZyb20gXCJvYnNpZGlhblwiO1xuXG5leHBvcnQgY29uc3QgbXVsdGlDb2x1bW5NYXJrZG93bl9TdGF0ZUZpZWxkID0gU3RhdGVGaWVsZC5kZWZpbmU8RGVjb3JhdGlvblNldD4oe1xuXHRjcmVhdGUoc3RhdGUpOiBEZWNvcmF0aW9uU2V0IHtcblx0XHRyZXR1cm4gRGVjb3JhdGlvbi5ub25lO1xuXHR9LFxuXHR1cGRhdGUob2xkU3RhdGU6IERlY29yYXRpb25TZXQsIHRyYW5zYWN0aW9uOiBUcmFuc2FjdGlvbik6IERlY29yYXRpb25TZXQge1xuXHRcdGNvbnN0IGJ1aWxkZXIgPSBuZXcgUmFuZ2VTZXRCdWlsZGVyPERlY29yYXRpb24+KCk7XG4gICAgICAgIGxldCBnZW5lcmF0ZWQgPSBmYWxzZTtcblxuXHRcdHN5bnRheFRyZWUodHJhbnNhY3Rpb24uc3RhdGUpLml0ZXJhdGUoe1xuXHRcdFx0ZW50ZXIobm9kZSkge1xuXG4gICAgICAgICAgICAgICAgLy8gV2Ugb25seSB3YW50IHRvIHJ1biB0aGUgZ2VuZXJhdGlvbiBvbmNlIHBlciBzdGF0ZSBjaGFuZ2UuIElmXG4gICAgICAgICAgICAgICAgLy8gYSBwcmV2aW91cyBub2RlIGhhcyBzdWNlc3NmdWxseSBnZW5lcmF0ZWQgcmVnaW9ucyB3ZSBpZ25vcmUgYWxsXG4gICAgICAgICAgICAgICAgLy8gb3RoZXIgbm9kZXMgaW4gdGhlIHN0YXRlLlxuICAgICAgICAgICAgICAgIGlmKGdlbmVyYXRlZCA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYoaXNFZGl0b3JJbkxpdmVQcmV2aWV3KHRyYW5zYWN0aW9uLnN0YXRlKSA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmRlYnVnKFwiVXNlciBkaXNhYmxlZCBsaXZlIHByZXZpZXcuXCIpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cblx0XHRcdFx0Ly8gV2Ugd2FudCB0byBydW4gb24gdGhlIHdob2xlIGZpbGUgc28gd2UgZG9udCBqdXN0IGxvb2sgZm9yIGEgc2luZ2xlIHRva2VuLlxuXHRcdFx0XHRjb25zdCB0b2tlblByb3BzID0gbm9kZS50eXBlLnByb3A8c3RyaW5nPih0b2tlbkNsYXNzTm9kZVByb3ApO1xuXHRcdFx0XHRpZiAodG9rZW5Qcm9wcyAhPT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0LyoqXG5cdFx0XHRcdCAqIFdoZW4gd2UgaGF2ZSB0aGUgd2hpbGUgZmlsZSB3ZSB0aGVuIGdldCB0aGUgZW50aXJlIGRvYyB0ZXh0IGFuZCBjaGVjayBpZiBpdCBcblx0XHRcdFx0ICogY29udGFpbnMgYSBNQ00gcmVnaW9uIHNvIHdlIGtub3cgdG8gYnJlYWsgb3Igbm90LlxuXHRcdFx0XHQgKi9cbiAgICAgICAgICAgICAgICBsZXQgZG9jTGVuZ3RoID0gdHJhbnNhY3Rpb24uc3RhdGUuZG9jLmxlbmd0aFxuICAgICAgICAgICAgICAgIGxldCBkb2NUZXh0ID0gdHJhbnNhY3Rpb24uc3RhdGUuZG9jLnNsaWNlU3RyaW5nKDAsIGRvY0xlbmd0aCk7XG5cdFx0XHRcdGlmIChjb250YWluc1JlZ2lvblN0YXJ0KGRvY1RleHQpID09PSBmYWxzZSkge1xuXHRcdFx0XHRcdC8vIGNvbnNvbGUuZGVidWcoXCJObyBzdGFydCB0YWcgaW4gZG9jdW1lbnQuXCIpXG5cdFx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gV2Ugd2FudCB0byBrbm93IHdoZXJlIHRoZSB1c2VyJ3MgY3Vyc29yIGlzLCBpdCBjYW4gYmVcblx0XHRcdFx0Ly8gc2VsZWN0aW5nIG11bHRpcGxlIHJlZ2lvbnMgb2YgdGV4dCBhcyB3ZWxsIHNvIHdlIG5lZWQgdG8ga25vd1xuXHRcdFx0XHQvLyBhbGwgbG9jYXRpb25zLiBVc2VkIHRvIGtub3cgaWYgd2Ugc2hvdWxkIHJlbmRlciByZWdpb24gYXMgdGV4dCBvciBhcyBwcmV2aWV3LlxuXHRcdFx0XHRsZXQgcmFuZ2VzID0gZ2V0Q3Vyc29yTGluZUxvY2F0aW9ucygpO1xuXG5cdFx0XHRcdC8vIFNldHVwIG91ciBsb29wIHRvIHJlbmRlciB0aGUgcmVnaW9ucyBhcyBNQ00uIFxuXHRcdFx0XHRsZXQgd29ya2luZ0ZpbGVUZXh0ID0gZG9jVGV4dDtcblxuXHRcdFx0XHRsZXQgbG9vcEluZGV4ID0gMDtcblx0XHRcdFx0bGV0IHN0YXJ0SW5kZXhPZmZzZXQgPSAwO1xuXHRcdFx0XHR3aGlsZSAodHJ1ZSkge1xuXG5cdFx0XHRcdFx0Ly8gSWYgdGhlcmUgYXJlIG11bHRpcGxlIGtpbmRzIG9mIHN0YXJ0IGJsb2NrcywgdGhlIG9sZCB3YXkgb2YgcGFyc2luZyB3b3VsZCBjYXVzZSBpc3N1ZXMuXG5cdFx0XHRcdFx0Ly8gTm93IHNlYXJjaCBmb3IgYm90aCBraW5kcyBhbmQgZGV0ZXJtaW5lIHdoYXQgdG8gZG8gYWZ0ZXIgc2VhcmNoLlxuXHRcdFx0XHRcdGxldCBzdGFydFRhZ0RhdGFfY29kZWJsb2NrU3RhcnQgPSBmaW5kU3RhcnRDb2RlYmxvY2sod29ya2luZ0ZpbGVUZXh0KTtcblx0XHRcdFx0XHRsZXQgc3RhcnRUYWdEYXRhX2RlcHJlY2lhdGVkU3RhcnQgPSBmaW5kU3RhcnRUYWcod29ya2luZ0ZpbGVUZXh0KTtcblxuXHRcdFx0XHRcdC8vIERlZmF1bHQgdG8gY29kZWJsb2NrIFN0eWxlLiBUaGVuIGNoZWNrLCBpZiBjb2RlYmxvY2sgd2FzIG5vdCBmb3VuZCBhbmQgZGVwcmVjaWF0ZWQgU3RhcnQgd2FzLCBzZXQgc3RhcnRUYWcgdG8gZGVwcmVjaWF0ZWQuXG5cdFx0XHRcdFx0bGV0IHN0YXJ0VGFnRGF0YSA9IHN0YXJ0VGFnRGF0YV9jb2RlYmxvY2tTdGFydDtcblx0XHRcdFx0XHRpZihzdGFydFRhZ0RhdGFfY29kZWJsb2NrU3RhcnQuZm91bmQgPT09IGZhbHNlICYmIHN0YXJ0VGFnRGF0YV9kZXByZWNpYXRlZFN0YXJ0LmZvdW5kID09PSB0cnVlKSB7XG5cdFx0XHRcdFx0XHRcblx0XHRcdFx0XHRcdHN0YXJ0VGFnRGF0YSA9IHN0YXJ0VGFnRGF0YV9kZXByZWNpYXRlZFN0YXJ0XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGVsc2UgaWYoc3RhcnRUYWdEYXRhX2NvZGVibG9ja1N0YXJ0LmZvdW5kID09PSB0cnVlICYmIHN0YXJ0VGFnRGF0YV9kZXByZWNpYXRlZFN0YXJ0LmZvdW5kID09PSB0cnVlKSB7XG5cblx0XHRcdFx0XHRcdC8vIElmIGJvdGgga2luZHMgd2VyZSBmb3VuZCB3ZSB3YW50IHRvIHN0YXJ0IHdpdGggdGhlIG9uZSBjbG9zZXIgdG8gdGhlIHRvcCBvZiB0aGUgZG9jdW1lbnQgYXMgQ002IHJlcXVpcmVzIHdlIHdvcmsgaW4gb3JkZXIuXG5cdFx0XHRcdFx0XHRpZiAoc3RhcnRUYWdEYXRhX2NvZGVibG9ja1N0YXJ0LnN0YXJ0UG9zaXRpb24gPiBzdGFydFRhZ0RhdGFfZGVwcmVjaWF0ZWRTdGFydC5zdGFydFBvc2l0aW9uKSB7XG5cblx0XHRcdFx0XHRcdFx0c3RhcnRUYWdEYXRhID0gc3RhcnRUYWdEYXRhX2RlcHJlY2lhdGVkU3RhcnRcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFxuXHRcdFx0XHRcdGlmKHN0YXJ0VGFnRGF0YS5mb3VuZCA9PT0gZmFsc2UpIHtcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdC8vIFNlYXJjaCBmb3IgdGhlIGZpcnN0IGVuZCB0YWcgYWZ0ZXIgYSBzdGFydCBibG9jay4gKE5vIHJlY3Vyc2l2ZSBjb2x1bW5zLilcblx0XHRcdFx0XHRsZXQgZW5kVGFnRGF0YSA9IGZpbmRFbmRUYWcod29ya2luZ0ZpbGVUZXh0LnNsaWNlKHN0YXJ0VGFnRGF0YS5zdGFydFBvc2l0aW9uKSk7XG5cdFx0XHRcdFx0aWYoZW5kVGFnRGF0YS5mb3VuZCA9PT0gZmFsc2UpIHtcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdC8qKlxuXHRcdFx0XHRcdCAqIEZvciB0aGUgcmVnaW9uIHdlIGZvdW5kIGdldCB0aGUgc3RhcnQgYW5kIGVuZCBwb3NpdGlvbiBvZiB0aGUgdGFncyBzbyB3ZSBcblx0XHRcdFx0XHQgKiBjYW4gc2xpY2UgaXQgb3V0IG9mIHRoZSBkb2N1bWVudC5cblx0XHRcdFx0XHQgKi9cblx0XHRcdFx0XHRsZXQgc3RhcnRJbmRleCA9IHN0YXJ0SW5kZXhPZmZzZXQgKyBzdGFydFRhZ0RhdGEuc3RhcnRQb3NpdGlvblxuXHRcdFx0XHRcdGxldCBlbmRJbmRleCA9IHN0YXJ0SW5kZXggKyBlbmRUYWdEYXRhLnN0YXJ0UG9zaXRpb24gKyBlbmRUYWdEYXRhLm1hdGNoTGVuZ3RoIC8vIFdpdGhvdXQgdGhlIG1hdGNoTGVuZ3RoIHdpbGwgbGVhdmUgdGhlIGVuZCB0YWcgb24gdGhlIHNjcmVlbi5cblxuXHRcdFx0XHRcdC8vIFRoaXMgdGV4dCBpcyB0aGUgZW50aXJlIHJlZ2lvbiBkYXRhIGluY2x1ZGluZyB0aGUgc3RhcnQgYW5kIGVuZCB0YWdzLlxuXHRcdFx0XHRcdGxldCBlbGVtZW50VGV4dCA9IGRvY1RleHQuc2xpY2Uoc3RhcnRJbmRleCwgZW5kSW5kZXgpXG5cblx0XHRcdFx0XHQvKipcblx0XHRcdFx0XHQgKiBVcGRhdGUgb3VyIHN0YXJ0IG9mZnNldCBhbmQgdGhlIHdvcmtpbmcgdGV4dCBvZiB0aGUgZmlsZSBzbyBvdXIgbmV4dCBcblx0XHRcdFx0XHQgKiBpdGVyYXRpb24ga25vd3Mgd2hlcmUgd2UgbGVmdCBvZmZcblx0XHRcdFx0XHQgKi9cblx0XHRcdFx0XHRzdGFydEluZGV4T2Zmc2V0ID0gZW5kSW5kZXhcblx0XHRcdFx0XHR3b3JraW5nRmlsZVRleHQgPSBkb2NUZXh0LnNsaWNlKGVuZEluZGV4KTtcblxuXG5cdFx0XHRcdFx0Ly8gSGVyZSB3ZSBjaGVjayBpZiB0aGUgY3Vyc29yIGlzIGluIHRoaXMgc3BlY2lmaWMgcmVnaW9uLlxuXHRcdFx0XHRcdGxldCBjdXJzb3JJblJlZ2lvbiA9IGNoZWNrQ3Vyc29ySW5SZWdpb24oc3RhcnRJbmRleCwgZW5kSW5kZXgsIHJhbmdlcyk7XG5cdFx0XHRcdFx0aWYoY3Vyc29ySW5SZWdpb24gPT09IHRydWUpIHtcblx0XHRcdFx0XHRcdFxuXHRcdFx0XHRcdFx0Ly8gSWYgdGhlIGN1cnNvciBpcyB3aXRoaW4gdGhlIHJlZ2lvbiB3ZSB0aGVuIG5lZWQgdG8ga25vdyBpZlxuXHRcdFx0XHRcdFx0Ly8gaXQgaXMgd2l0aGluIG91ciBzZXR0aW5ncyBibG9jayAoaWYgaXQgZXhpc3RzLilcblx0XHRcdFx0XHRcdGxldCBzZXR0aW5nc1N0YXJ0RGF0YSA9IGZpbmRTdGFydENvZGVibG9jayhlbGVtZW50VGV4dCk7XG5cdFx0XHRcdFx0XHRpZihzZXR0aW5nc1N0YXJ0RGF0YS5mb3VuZCA9PT0gZmFsc2UpIHtcblx0XHRcdFx0XHRcdFx0c2V0dGluZ3NTdGFydERhdGEgPSBmaW5kU2V0dGluZ3NDb2RlYmxvY2soZWxlbWVudFRleHQpO1xuXHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRpZihzZXR0aW5nc1N0YXJ0RGF0YS5mb3VuZCA9PT0gdHJ1ZSkge1xuXG5cdFx0XHRcdFx0XHRcdC8vIFNpbmNlIHRoZSBzZXR0aW5ncyBibG9jayBleGlzdHMgY2hlY2sgaWYgdGhlIGN1cnNvciBpcyB3aXRoaW4gdGhhdCByZWdpb24uXG5cdFx0XHRcdFx0XHRcdGxldCBjb2RlYmxvY2tTdGFydEluZGV4ID0gc3RhcnRJbmRleCArIHNldHRpbmdzU3RhcnREYXRhLnN0YXJ0UG9zaXRpb247XG5cdFx0XHRcdFx0XHRcdGxldCBjb2RlYmxvY2tFbmRJbmRleCA9IHN0YXJ0SW5kZXggKyBzZXR0aW5nc1N0YXJ0RGF0YS5lbmRQb3NpdGlvbjtcblx0XHRcdFx0XHRcdFx0bGV0IHNldHRpbmdzVGV4dCA9IGRvY1RleHQuc2xpY2UoY29kZWJsb2NrU3RhcnRJbmRleCwgY29kZWJsb2NrRW5kSW5kZXggKVxuXG5cdFx0XHRcdFx0XHRcdGxldCBjdXJzb3JJbkNvZGVibG9jayA9IGNoZWNrQ3Vyc29ySW5SZWdpb24oY29kZWJsb2NrU3RhcnRJbmRleCwgY29kZWJsb2NrRW5kSW5kZXgsIHJhbmdlcyk7XG5cdFx0XHRcdFx0XHRcdGlmKGN1cnNvckluQ29kZWJsb2NrID09PSBmYWxzZSkge1xuXHRcblx0XHRcdFx0XHRcdFx0XHQvLyBJZiB0aGUgY3Vyc29yIGlzIG5vdCB3aXRoaW4gdGhlIHJlZ2lvbiB3ZSBwYXNzIHRoZSBkYXRhIHRvIHRoZVxuXHRcdFx0XHRcdFx0XHRcdC8vIHNldHRpbmdzIHZpZXcgc28gaXQgY2FuIGJlIGRpc3BsYXllZCBpbiB0aGUgcmVnaW9uLlxuXHRcdFx0XHRcdFx0XHRcdGJ1aWxkZXIuYWRkKFxuXHRcdFx0XHRcdFx0XHRcdFx0Y29kZWJsb2NrU3RhcnRJbmRleCxcblx0XHRcdFx0XHRcdFx0XHRcdGNvZGVibG9ja0VuZEluZGV4ICsgMSxcblx0XHRcdFx0XHRcdFx0XHRcdERlY29yYXRpb24ucmVwbGFjZSh7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdHdpZGdldDogbmV3IE11bHRpQ29sdW1uTWFya2Rvd25fRGVmaW5lZFNldHRpbmdzX0xpdmVQcmV2aWV3X1dpZGdldChzZXR0aW5nc1RleHQpLFxuXHRcdFx0XHRcdFx0XHRcdFx0fSlcblx0XHRcdFx0XHRcdFx0XHQpO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9XHRcdFx0XHRcdFx0XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGVsc2Uge1xuXG5cdFx0XHRcdFx0XHQvLyBBdCB0aGlzIHBvaW50IGlmIHRoZSBjdXJzb3IgaXNudCBpbiB0aGUgcmVnaW9uIHdlIHBhc3MgdGhlIGRhdGEgdG8gdGhlXG5cdFx0XHRcdFx0XHQvLyBlbGVtZW50IHRvIGJlIHJlbmRlcmVkLlxuXHRcdFx0XHRcdFx0YnVpbGRlci5hZGQoXG5cdFx0XHRcdFx0XHRcdHN0YXJ0SW5kZXgsXG5cdFx0XHRcdFx0XHRcdGVuZEluZGV4LFxuXHRcdFx0XHRcdFx0XHREZWNvcmF0aW9uLnJlcGxhY2Uoe1xuXHRcdFx0XHRcdFx0XHRcdHdpZGdldDogbmV3IE11bHRpQ29sdW1uTWFya2Rvd25fTGl2ZVByZXZpZXdfV2lkZ2V0KGVsZW1lbnRUZXh0KSxcblx0XHRcdFx0XHRcdFx0fSlcblx0XHRcdFx0XHRcdCk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGdlbmVyYXRlZCA9IHRydWU7XG5cblx0XHRcdFx0XHQvLyBJbmZpbml0ZSBsb29wIHByb3RlY3Rpb24uXG5cdFx0XHRcdFx0bG9vcEluZGV4Kys7XG5cdFx0XHRcdFx0aWYobG9vcEluZGV4ID4gMTAwKSB7XG5cdFx0XHRcdFx0XHRjb25zb2xlLndhcm4oXCJQb3RlbnRpYWwgaXNzdWUgd2l0aCByZW5kZXJpbmcgTXVsdGktQ29sdW1uIE1hcmtkb3duIGxpdmUgcHJldmlldyByZWdpb25zLiBJZiBwcm9ibGVtIHBlcnNpc3RzIHBsZWFzZSBmaWxlIGEgYnVnIHJlcG9ydCB3aXRoIGRldmVsb3Blci5cIilcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fSxcblx0XHR9KTtcbiBcblx0XHRyZXR1cm4gYnVpbGRlci5maW5pc2goKTtcblxuXHRcdGZ1bmN0aW9uIGdldEN1cnNvckxpbmVMb2NhdGlvbnMoKTogeyBsaW5lOiBMaW5lLCBwb3NpdGlvbjogbnVtYmVyIH1bXSB7XG5cblx0XHRcdGxldCByYW5nZXM6IHsgbGluZTogTGluZSwgcG9zaXRpb246IG51bWJlciB9W10gPSBbXTtcblxuXHRcdFx0aWYgKHRyYW5zYWN0aW9uLnN0YXRlLnNlbGVjdGlvbi5yYW5nZXMpIHtcblxuXHRcdFx0XHRyYW5nZXMgPSB0cmFuc2FjdGlvbi5zdGF0ZS5zZWxlY3Rpb24ucmFuZ2VzLmZpbHRlcigocmFuZ2UpID0+IHtcblxuXHRcdFx0XHRcdHJldHVybiByYW5nZS5lbXB0eTtcblx0XHRcdFx0fSkubWFwKChyYW5nZSkgPT4ge1xuXG5cdFx0XHRcdFx0bGV0IGxpbmUgPSB0cmFuc2FjdGlvbi5zdGF0ZS5kb2MubGluZUF0KHJhbmdlLmhlYWQpO1xuXHRcdFx0XHRcdGxldCB0ZXh0ID0gYCR7bGluZS5udW1iZXJ9OiR7cmFuZ2UuaGVhZCAtIGxpbmUuZnJvbX1gO1xuXG5cdFx0XHRcdFx0cmV0dXJuIHtcblx0XHRcdFx0XHRcdGxpbmU6IGxpbmUsXG5cdFx0XHRcdFx0XHRwb3NpdGlvbjogcmFuZ2UuaGVhZFxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSk7XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiByYW5nZXM7XG5cdFx0fVxuXG4gICAgICAgIGZ1bmN0aW9uIHZhbHVlSXNJblJhbmdlKHZhbHVlOiBudW1iZXIsIG1pblZhbDogbnVtYmVyLCBtYXhWYWw6IG51bWJlciwgaW5jbHVzaXZlOiBib29sZWFuID0gdHJ1ZSkge1xuXG4gICAgICAgICAgICBpZihpbmNsdXNpdmUgPT09IHRydWUgJiYgKHZhbHVlID09PSBtaW5WYWwgfHwgdmFsdWUgPT09IG1heFZhbCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKG1pblZhbCA8IHZhbHVlICYmIHZhbHVlIDwgbWF4VmFsKSB7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cblx0XHRmdW5jdGlvbiBjaGVja0N1cnNvckluUmVnaW9uKHN0YXJ0SW5kZXg6IG51bWJlcixcblx0XHRcdFx0XHRcdFx0XHRlbmRJbmRleDogbnVtYmVyLCBcblx0XHRcdFx0XHRcdFx0XHRyYW5nZXM6IHsgbGluZTogTGluZSwgcG9zaXRpb246IG51bWJlciB9W10gKTogYm9vbGVhbiB7XG5cblx0XHRcdGZvciAobGV0IGkgPSAwOyBpIDwgcmFuZ2VzLmxlbmd0aDsgaSsrKSB7XG5cblx0XHRcdFx0Ly8gVE9ETzogTWF5YmUgbG9vayBpbnRvIGxpbWl0aW5nIHRoaXMgdG8gdGhlIHNlY29uZCBhbmQgc2Vjb25kIHRvIGxhc3QgbGluZVxuXHRcdFx0XHQvLyBvZiB0aGUgcmVnaW9uIGFzIGNsaWNraW5nIHJpZ2h0IGF0IHRoZSB0b3Agb3IgYm90dG9tIG9mIHRoZSByZWdpb25cblx0XHRcdFx0Ly8gc3dhcHMgaXQgdG8gdW5yZW5kZXJlZC5cblx0XHRcdFx0bGV0IHJhbmdlID0gcmFuZ2VzW2ldO1xuXHRcdFx0XHRpZih2YWx1ZUlzSW5SYW5nZShyYW5nZS5wb3NpdGlvbiwgc3RhcnRJbmRleCwgZW5kSW5kZXgpID09PSB0cnVlKSB7XG5cdFx0XHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0aWYodHJhbnNhY3Rpb24uc3RhdGUuc2VsZWN0aW9uKXtcblx0XHRcdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCB0cmFuc2FjdGlvbi5zdGF0ZS5zZWxlY3Rpb24ucmFuZ2VzLmxlbmd0aDsgaSsrKSB7XG5cblx0XHRcdFx0XHRsZXQgcmFuZ2UgPSB0cmFuc2FjdGlvbi5zdGF0ZS5zZWxlY3Rpb24ucmFuZ2VzW2ldO1xuXG5cdFx0XHRcdFx0Ly8gSWYgZWl0aGVyIHRoZSBzdGFydCBvciBlbmQgb2YgdGhlIHNlbGVjdGlvbiBpcyB3aXRoaW4gdGhlXG5cdFx0XHRcdFx0Ly8gcmVnaW9uIHJhbmdlIHdlIGRvIG5vdCByZW5kZXIgbGl2ZSBwcmV2aWV3LlxuXHRcdFx0XHRcdGlmKHZhbHVlSXNJblJhbmdlKHJhbmdlLmZyb20sIHN0YXJ0SW5kZXgsIGVuZEluZGV4KSB8fCBcblx0XHRcdFx0XHQgICB2YWx1ZUlzSW5SYW5nZShyYW5nZS50bywgc3RhcnRJbmRleCwgZW5kSW5kZXgpKSB7XG5cdFx0XHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHQvLyAvLyBPciBpZiB0aGUgZW50aXJlIHJlZ2lvbiBpcyB3aXRoaW4gdGhlIHNlbGVjdGlvbiByYW5nZVxuXHRcdFx0XHRcdC8vIHdlIGRvIG5vdCByZW5kZXIgdGhlIGxpdmUgcHJldmlldy5cblx0XHRcdFx0XHRpZih2YWx1ZUlzSW5SYW5nZShzdGFydEluZGV4LCByYW5nZS5mcm9tLCByYW5nZS50bykgJiYgXG5cdFx0XHRcdFx0ICAgdmFsdWVJc0luUmFuZ2UoZW5kSW5kZXgsIHJhbmdlLmZyb20sIHJhbmdlLnRvKSkge1xuXHRcdFx0XHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cdH0sXG5cdHByb3ZpZGUoZmllbGQ6IFN0YXRlRmllbGQ8RGVjb3JhdGlvblNldD4pOiBFeHRlbnNpb24ge1xuXHRcdHJldHVybiBFZGl0b3JWaWV3LmRlY29yYXRpb25zLmZyb20oZmllbGQpO1xuXHR9LFxufSk7XG5cbmZ1bmN0aW9uIGlzRWRpdG9ySW5MaXZlUHJldmlldyhzdGF0ZTogRWRpdG9yU3RhdGUpOiBib29sZWFuIHtcblx0XG5cdGxldCBtZFZpZXcgPSBzdGF0ZS5maWVsZChlZGl0b3JWaWV3RmllbGQpO1xuXHRsZXQgdmlld1N0YXRlID0gbWRWaWV3LmxlYWYuZ2V0Vmlld1N0YXRlKCk7XG5cblx0bGV0IHN0YXRlRGF0YSA9IG51bGw7XG5cdGlmKHZpZXdTdGF0ZS5zdGF0ZSkge1xuXHRcdHN0YXRlRGF0YSA9IHZpZXdTdGF0ZS5zdGF0ZTtcblx0fVxuXG5cdHJldHVybiAoXG5cdFx0c3RhdGVEYXRhICYmIHN0YXRlRGF0YS5tb2RlID09IFwic291cmNlXCIgJiYgc3RhdGVEYXRhLnNvdXJjZSA9PSB0cnVlXG5cdCk7XG59IiwiLypcclxuICogRmlsZTogbXVsdGktY29sdW1uLW1hcmtkb3duL3NyYy9tYWluLnRzXHJcbiAqIENyZWF0ZWQgRGF0ZTogVHVlc2RheSwgT2N0b2JlciA1dGggMjAyMSwgMTowOSBwbVxyXG4gKiBBdXRob3I6IENhbWVyb24gUm9iaW5zb25cclxuICogXHJcbiAqIENvcHlyaWdodCAoYykgMjAyMiBDYW1lcm9uIFJvYmluc29uXHJcbiAqL1xyXG5cclxuaW1wb3J0IHsgTm90aWNlLCBQbHVnaW4sICBNYXJrZG93blJlbmRlckNoaWxkLCBNYXJrZG93blJlbmRlcmVyLCBURmlsZSB9IGZyb20gJ29ic2lkaWFuJztcclxuaW1wb3J0ICogYXMgbXVsdGlDb2x1bW5QYXJzZXIgZnJvbSAnLi91dGlsaXRpZXMvdGV4dFBhcnNlcic7XHJcbmltcG9ydCB7IEZpbGVET01NYW5hZ2VyLCBHbG9iYWxET01NYW5hZ2VyIH0gZnJvbSAnLi9kb21fbWFuYWdlci9kb21NYW5hZ2VyJztcclxuaW1wb3J0IHsgTXVsdGlDb2x1bW5SZW5kZXJEYXRhIH0gZnJvbSBcIi4vZG9tX21hbmFnZXIvcmVnaW9uYWxfbWFuYWdlcnMvcmVnaW9uTWFuYWdlclwiO1xyXG5pbXBvcnQgeyBSZWdpb25NYW5hZ2VyIH0gZnJvbSBcIi4vZG9tX21hbmFnZXIvcmVnaW9uYWxfbWFuYWdlcnMvcmVnaW9uTWFuYWdlclwiO1xyXG5pbXBvcnQgeyBSZWdpb25NYW5hZ2VyQ29udGFpbmVyIH0gZnJvbSBcIi4vZG9tX21hbmFnZXIvcmVnaW9uYWxfbWFuYWdlcnMvcmVnaW9uTWFuYWdlckNvbnRhaW5lclwiO1xyXG5pbXBvcnQgeyBET01PYmplY3QsIERPTU9iamVjdFRhZywgVGFza0xpc3RET01PYmplY3QgfSBmcm9tICcuL2RvbV9tYW5hZ2VyL2RvbU9iamVjdCc7XHJcbmltcG9ydCB7IGZpbGVTdGlsbEluVmlldywgZ2V0RmlsZUxlYWYsIGdldExlYWZTb3VyY2VNb2RlLCBnZXRVSUQgfSBmcm9tICcuL3V0aWxpdGllcy91dGlscyc7XHJcbmltcG9ydCB7IE11bHRpQ29sdW1uTGF5b3V0Q1NTLCBNdWx0aUNvbHVtblN0eWxlQ1NTIH0gZnJvbSAnLi91dGlsaXRpZXMvY3NzRGVmaW5pdGlvbnMnO1xyXG5pbXBvcnQgeyBFbGVtZW50UmVuZGVyVHlwZSB9IGZyb20gJy4vdXRpbGl0aWVzL2VsZW1lbnRSZW5kZXJUeXBlUGFyc2VyJztcclxuaW1wb3J0IHsgbXVsdGlDb2x1bW5NYXJrZG93bl9TdGF0ZUZpZWxkIH0gZnJvbSAnLi9saXZlX3ByZXZpZXcvY202X2xpdmVQcmV2aWV3JztcclxuaW1wb3J0IHsgcGFyc2VTdGFydFJlZ2lvbkNvZGVCbG9ja0lEIH0gZnJvbSAnLi91dGlsaXRpZXMvc2V0dGluZ3NQYXJzZXInO1xyXG5cclxuY29uc3QgQ09ERUJMT0NLX1NUQVJUX1NUUlMgPSBbXHJcbiAgICBcInN0YXJ0LW11bHRpLWNvbHVtblwiLFxyXG4gICAgXCJtdWx0aS1jb2x1bW4tc3RhcnRcIlxyXG5dXHJcbmV4cG9ydCBkZWZhdWx0IGNsYXNzIE11bHRpQ29sdW1uTWFya2Rvd24gZXh0ZW5kcyBQbHVnaW4ge1xyXG5cclxuICAgIGdsb2JhbE1hbmFnZXI6IEdsb2JhbERPTU1hbmFnZXIgPSBuZXcgR2xvYmFsRE9NTWFuYWdlcigpO1xyXG5cclxuXHRhc3luYyBvbmxvYWQoKSB7XHJcblxyXG4gICAgICAgIGNvbnNvbGUubG9nKFwiTG9hZGluZyBtdWx0aS1jb2x1bW4gbWFya2Rvd25cIik7XHJcbiAgICAgICAgdGhpcy5nbG9iYWxNYW5hZ2VyID0gbmV3IEdsb2JhbERPTU1hbmFnZXIoKTtcclxuXHJcbiAgICAgICAgdGhpcy5yZWdpc3RlckVkaXRvckV4dGVuc2lvbihtdWx0aUNvbHVtbk1hcmtkb3duX1N0YXRlRmllbGQpXHJcblxyXG4gICAgICAgIGZvcihsZXQgaSA9IDA7IGkgPCBDT0RFQkxPQ0tfU1RBUlRfU1RSUy5sZW5ndGg7IGkrKykge1xyXG5cclxuICAgICAgICAgICAgbGV0IHN0YXJ0U3RyID0gQ09ERUJMT0NLX1NUQVJUX1NUUlNbaV1cclxuICAgICAgICAgICAgdGhpcy5zZXR1cE1hcmtkb3duQ29kZWJsb2NrUG9zdFByb2Nlc3NvcihzdGFydFN0cik7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHRoaXMuc2V0dXBNYXJrZG93blBvc3RQcm9jZXNzb3IoKTtcclxuXHJcbiAgICAgICAgLy9UT0RPOiBTZXQgdXAgdGhpcyBhcyBhIG1vZGFsIHRvIHNldCBzZXR0aW5ncyBhdXRvbWF0aWNhbGx5XHJcbiAgICAgICAgdGhpcy5hZGRDb21tYW5kKHsgICAgICAgICAgICBcclxuICAgICAgICAgICAgaWQ6IGBpbnNlcnQtbXVsdGktY29sdW1uLXJlZ2lvbmAsXHJcbiAgICAgICAgICAgIG5hbWU6IGBJbnNlcnQgTXVsdGktQ29sdW1uIFJlZ2lvbmAsXHJcbiAgICAgICAgICAgIGVkaXRvckNhbGxiYWNrOiAoZWRpdG9yLCB2aWV3KSA9PiB7XHJcblxyXG4gICAgICAgICAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgICAgICAgICBsZXQgY3Vyc29yU3RhcnRQb3NpdGlvbiA9IGVkaXRvci5nZXRDdXJzb3IoXCJmcm9tXCIpO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICBlZGl0b3IuZ2V0RG9jKCkucmVwbGFjZVNlbGVjdGlvbihcclxuYFxyXG5cXGBcXGBcXGBzdGFydC1tdWx0aS1jb2x1bW5cclxuSUQ6IElEXyR7Z2V0VUlEKDQpfVxyXG5OdW1iZXIgb2YgQ29sdW1uczogMlxyXG5MYXJnZXN0IENvbHVtbjogc3RhbmRhcmRcclxuXFxgXFxgXFxgXHJcblxyXG5cclxuXHJcbi0tLSBjb2x1bW4tZW5kIC0tLVxyXG5cclxuXHJcblxyXG49PT0gZW5kLW11bHRpLWNvbHVtblxyXG5cclxuJHtlZGl0b3IuZ2V0RG9jKCkuZ2V0U2VsZWN0aW9uKCl9YFxyXG4gICAgICAgICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgICAgICAgICAgXHJcbiAgICAgICAgICAgICAgICAgICAgY3Vyc29yU3RhcnRQb3NpdGlvbi5saW5lID0gY3Vyc29yU3RhcnRQb3NpdGlvbi5saW5lICsgN1xyXG4gICAgICAgICAgICAgICAgICAgIGN1cnNvclN0YXJ0UG9zaXRpb24uY2ggPSAwO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICBlZGl0b3Iuc2V0Q3Vyc29yKGN1cnNvclN0YXJ0UG9zaXRpb24pO1xyXG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xyXG4gICAgICAgICAgICAgICAgICAgIG5ldyBOb3RpY2UoXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIFwiRW5jb3VudGVyZWQgYW4gZXJyb3IgaW5zZXJ0aW5nIGEgbXVsdGktY29sdW1uIHJlZ2lvbi4gUGxlYXNlIHRyeSBhZ2FpbiBsYXRlci5cIlxyXG4gICAgICAgICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgdGhpcy5hZGRDb21tYW5kKHsgICAgICAgICAgICBcclxuICAgICAgICAgICAgaWQ6IGBhZGQtSURzLVRvLW11bHRpLWNvbHVtbi1yZWdpb25gLFxyXG4gICAgICAgICAgICBuYW1lOiBgRml4IE1pc3NpbmcgSURzIGZvciBNdWx0aS1Db2x1bW4gUmVnaW9uc2AsXHJcbiAgICAgICAgICAgIGVkaXRvckNhbGxiYWNrOiAoZWRpdG9yLCB2aWV3KSA9PiB7XHJcblxyXG4gICAgICAgICAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgICAgICAgICAvKipcclxuICAgICAgICAgICAgICAgICAgICAgKiBOb3Qgc3VyZSBpZiB0aGVyZSBpcyBhbiBlYXNpZXIgd2F5IHRvIGRvIHRoaXMuXHJcbiAgICAgICAgICAgICAgICAgICAgICogXHJcbiAgICAgICAgICAgICAgICAgICAgICogR2V0IGFsbCBvZiB0aGUgbGluZXMgb2YgdGhlIGRvY3VtZW50IHNwbGl0IGJ5IG5ld2xpbmVzLlxyXG4gICAgICAgICAgICAgICAgICAgICAqL1xyXG4gICAgICAgICAgICAgICAgICAgIGxldCBkb2NUZXh0ID0gZWRpdG9yLmdldFJhbmdlKHsgbGluZTogMCwgY2g6IDAgfSwgeyBsaW5lOiBlZGl0b3IuZ2V0RG9jKCkubGluZUNvdW50KCksIGNoOiAwfSk7XHJcbiAgICAgICAgICAgICAgICAgICAgbGV0IGxpbmVzID0gZG9jVGV4dC5zcGxpdChcIlxcblwiKTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgbGV0IHN0YXJ0Q29kZWJsb2NrID0gbXVsdGlDb2x1bW5QYXJzZXIuZmluZFN0YXJ0Q29kZWJsb2NrKGRvY1RleHQpO1xyXG4gICAgICAgICAgICAgICAgICAgIGxldCBsaW5lT2Zmc2V0ID0gMDtcclxuICAgICAgICAgICAgICAgICAgICBsZXQgbnVtQ29kZWJsb2Nrc1VwZGF0ZWQgPSAwO1xyXG4gICAgICAgICAgICAgICAgICAgIHdoaWxlKHN0YXJ0Q29kZWJsb2NrLmZvdW5kID09PSB0cnVlKSB7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgc3RhcnRSZXBsYWNlTGluZXMgPSAoZG9jVGV4dC5zbGljZSgwLCBzdGFydENvZGVibG9jay5zdGFydFBvc2l0aW9uKS5zcGxpdChcIlxcblwiKS5sZW5ndGggLSAxKSArIGxpbmVPZmZzZXQ7IC8vIC0xIHRvIFplcm8gaW5kZXggdGhlIHJlcGxhY2UgbGluZVxyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHNldHRpbmdzVGV4dCA9IGRvY1RleHQuc2xpY2Uoc3RhcnRDb2RlYmxvY2suc3RhcnRQb3NpdGlvbiwgc3RhcnRDb2RlYmxvY2suZW5kUG9zaXRpb24pO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgc2V0dGluZ3NJRCA9IHBhcnNlU3RhcnRSZWdpb25Db2RlQmxvY2tJRChzZXR0aW5nc1RleHQpO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYoc2V0dGluZ3NJRCA9PT0gXCJcIikge1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCByZXBsYWNlbWVudFRleHQgPSBlZGl0b3IuZ2V0UmFuZ2UoeyBsaW5lOiBzdGFydFJlcGxhY2VMaW5lcywgY2g6IDAgfSwgeyBsaW5lOiBzdGFydFJlcGxhY2VMaW5lcywgY2g6IHN0YXJ0Q29kZWJsb2NrLm1hdGNoTGVuZ3RofSkgKyBgXFxuSUQ6IElEXyR7Z2V0VUlEKDQpfWBcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVkaXRvci5yZXBsYWNlUmFuZ2UocmVwbGFjZW1lbnRUZXh0LCB7IGxpbmU6IHN0YXJ0UmVwbGFjZUxpbmVzLCBjaDogMCB9LCBcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7IGxpbmU6IHN0YXJ0UmVwbGFjZUxpbmVzLCBjaDogc3RhcnRDb2RlYmxvY2subWF0Y2hMZW5ndGh9KTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGFydFJlcGxhY2VMaW5lcyArPSAxOyAvLyB3ZSBhZGRlZCBhIGxpbmUgdG8gdGhlIGRvYyBzbyB1cGRhdGUgb3VyIG9mZnNldC5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG51bUNvZGVibG9ja3NVcGRhdGVkICs9IDE7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgbGluZU9mZnNldCA9IHN0YXJ0UmVwbGFjZUxpbmVzXHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBkb2NUZXh0ID0gZG9jVGV4dC5zbGljZShzdGFydENvZGVibG9jay5zdGFydFBvc2l0aW9uICsgc3RhcnRDb2RlYmxvY2subWF0Y2hMZW5ndGgpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBzdGFydENvZGVibG9jayA9IG11bHRpQ29sdW1uUGFyc2VyLmZpbmRTdGFydENvZGVibG9jayhkb2NUZXh0KTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIC8qKlxyXG4gICAgICAgICAgICAgICAgICAgICAqIExvb3AgdGhyb3VnaCBhbGwgb2YgdGhlIGxpbmVzIGNoZWNraW5nIGlmIHRoZSBsaW5lIGlzIGEgXHJcbiAgICAgICAgICAgICAgICAgICAgICogc3RhcnQgdGFnIGFuZCBpZiBzbyBpcyBpdCBtaXNzaW5nIGFuIElELlxyXG4gICAgICAgICAgICAgICAgICAgICAqL1xyXG4gICAgICAgICAgICAgICAgICAgIGxldCBsaW5lc1dpdGhvdXRJRHMgPSBbXVxyXG4gICAgICAgICAgICAgICAgICAgIGxldCB0ZXh0V2l0aG91dElEcyA9IFtdXHJcbiAgICAgICAgICAgICAgICAgICAgZm9yKGxldCBpID0gMDsgaSA8IGxpbmVzLmxlbmd0aDsgaSsrKSB7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgZGF0YSA9IG11bHRpQ29sdW1uUGFyc2VyLmlzU3RhcnRUYWdXaXRoSUQobGluZXNbaV0pO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZihkYXRhLmlzU3RhcnRUYWcgPT09IHRydWUgJiYgZGF0YS5oYXNLZXkgPT09IGZhbHNlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5lc1dpdGhvdXRJRHMucHVzaChpKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRleHRXaXRob3V0SURzLnB1c2gobGluZXNbaV0pXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICB9ICAgICAgICAgICAgICAgICAgICBcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgaWYobGluZXNXaXRob3V0SURzLmxlbmd0aCA9PT0gMCAmJiBudW1Db2RlYmxvY2tzVXBkYXRlZCA9PT0gMCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBuZXcgTm90aWNlIChcIkZvdW5kIDAgbWlzc2luZyBJRHMgaW4gdGhlIGN1cnJlbnQgZG9jdW1lbnQuXCIpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICAvKipcclxuICAgICAgICAgICAgICAgICAgICAgKiBOb3cgbG9vcCB0aHJvdWdoIGVhY2ggbGluZSB0aGF0IGlzIG1pc3NpbmcgYW4gSUQgYW5kXHJcbiAgICAgICAgICAgICAgICAgICAgICogZ2VuZXJhdGUgYSByYW5kb20gSUQgYW5kIHJlcGxhY2UgdGhlIG9yaWdpbmFsIHRleHQuXHJcbiAgICAgICAgICAgICAgICAgICAgICovXHJcbiAgICAgICAgICAgICAgICAgICAgZm9yKGxldCBpID0gMDsgaSA8IGxpbmVzV2l0aG91dElEcy5sZW5ndGg7IGkrKykge1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IG9yaWdpbmFsVGV4dCA9IHRleHRXaXRob3V0SURzW2ldXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCB0ZXh0ID0gb3JpZ2luYWxUZXh0O1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB0ZXh0ID0gdGV4dC50cmltRW5kKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKHRleHQuY2hhckF0KHRleHQubGVuZ3RoIC0gMSkgPT09IFwiOlwiKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXh0ID0gdGV4dC5zbGljZSgwLCB0ZXh0Lmxlbmd0aC0xKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICB0ZXh0ID0gYCR7dGV4dH06IElEXyR7Z2V0VUlEKDQpfWA7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBlZGl0b3IucmVwbGFjZVJhbmdlKHRleHQsIHsgbGluZTogbGluZXNXaXRob3V0SURzW2ldLCBjaDogMCB9LCBcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7IGxpbmU6IGxpbmVzV2l0aG91dElEc1tpXSwgY2g6IG9yaWdpbmFsVGV4dC5sZW5ndGh9KTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIG5ldyBOb3RpY2UgKGBSZXBsYWNlZCAke2xpbmVzV2l0aG91dElEcy5sZW5ndGggKyBudW1Db2RlYmxvY2tzVXBkYXRlZH0gbWlzc2luZyBJRChzKSBpbiB0aGUgY3VycmVudCBkb2N1bWVudC5gKTtcclxuICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcclxuICAgICAgICAgICAgICAgICAgICBuZXcgTm90aWNlKFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBcIkVuY291bnRlcmVkIGFuIGVycm9yIGFkZGlnbiBJRHMgdG8gbXVsdGktY29sdW1uIHJlZ2lvbnMuIFBsZWFzZSB0cnkgYWdhaW4gbGF0ZXIuXCJcclxuICAgICAgICAgICAgICAgICAgICApO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfSk7XHJcblxyXG4gICAgICAgIHRoaXMucmVnaXN0ZXJJbnRlcnZhbCh3aW5kb3cuc2V0SW50ZXJ2YWwoKCkgPT4ge1xyXG4gICAgICAgICAgICBcclxuICAgICAgICAgICAgdGhpcy5VcGRhdGVPcGVuRmlsZVByZXZpZXdzKCk7XHJcbiAgICAgICAgfSwgNTAwKSk7XHJcbiAgICB9XHJcblxyXG4gICAgVXBkYXRlT3BlbkZpbGVQcmV2aWV3cygpIHtcclxuXHJcbiAgICAgICAgbGV0IGZpbGVNYW5hZ2VycyA9IHRoaXMuZ2xvYmFsTWFuYWdlci5nZXRBbGxGaWxlTWFuYWdlcnMoKTtcclxuICAgICAgICBmaWxlTWFuYWdlcnMuZm9yRWFjaChlbGVtZW50ID0+IHtcclxuICAgICAgICAgICAgXHJcbiAgICAgICAgICAgIGxldCByZWdpb25hbE1hbmFnZXJzID0gZWxlbWVudC5nZXRBbGxSZWdpb25hbE1hbmFnZXJzKCk7XHJcbiAgICAgICAgICAgIHJlZ2lvbmFsTWFuYWdlcnMuZm9yRWFjaChyZWdpb25NYW5hZ2VyID0+IHtcclxuICAgICAgICAgICAgICAgIFxyXG4gICAgICAgICAgICAgICAgcmVnaW9uTWFuYWdlci51cGRhdGVSZW5kZXJlZE1hcmtkb3duKClcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgc2V0dXBNYXJrZG93blBvc3RQcm9jZXNzb3IoKSB7XHJcbiAgICAgICAgdGhpcy5yZWdpc3Rlck1hcmtkb3duUG9zdFByb2Nlc3Nvcihhc3luYyAoZWwsIGN0eCkgPT4ge1xyXG5cclxuICAgICAgICAgICAgY29uc3Qgc291cmNlUGF0aCA9IGN0eC5zb3VyY2VQYXRoO1xyXG5cclxuICAgICAgICAgICAgbGV0IGZpbGVET01NYW5hZ2VyID0gdGhpcy5nbG9iYWxNYW5hZ2VyLmdldEZpbGVNYW5hZ2VyKHNvdXJjZVBhdGgpO1xyXG4gICAgICAgICAgICBpZihmaWxlRE9NTWFuYWdlciA9PT0gbnVsbCkge1xyXG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coXCJGb3VuZCBudWxsIERPTSBtYW5hZ2VyLiBDb3VsZCBub3QgcHJvY2VzcyBtdWx0aS1jb2x1bW4gbWFya2Rvd24uXCIpXHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIC8qKlxyXG4gICAgICAgICAgICAgKiBIZXJlIHdlIGNoZWNrIGlmIHRoZSBleHBvcnQgXCJwcmludFwiIGZsYWcgaXMgaW4gdGhlIERPTSBzbyB3ZSBjYW4gZGV0ZXJtaW5lIGlmIHdlXHJcbiAgICAgICAgICAgICAqIGFyZSBleHBvcnRpbmcgYW5kIGhhbmRsZSB0aGF0IGNhc2UuXHJcbiAgICAgICAgICAgICAqL1xyXG4gICAgICAgICAgICBpZih0aGlzLmNoZWNrRXhwb3J0aW5nKGVsKSkge1xyXG5cclxuICAgICAgICAgICAgICAgIHRoaXMuZXhwb3J0RG9jdW1lbnRUb1BERihlbCwgZmlsZURPTU1hbmFnZXIsIHNvdXJjZVBhdGgpO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAvLyBHZXQgdGhlIGluZm8gZm9yIG91ciBjdXJyZW50IGNvbnRleHQgYW5kIHRoZW4gY2hlY2tcclxuICAgICAgICAgICAgLy8gaWYgdGhlIGVudGlyZSB0ZXh0IGNvbnRhaW5zIGEgc3RhcnQgdGFnLiBJZiB0aGVyZSBpc1xyXG4gICAgICAgICAgICAvLyBubyBzdGFydCB0YWcgaW4gdGhlIGRvY3VtZW50IHdlIGNhbiBqdXN0IHJldHVybiBhbmRcclxuICAgICAgICAgICAgLy8gaWdub3JlIHRoZSByZXN0IG9mIHRoZSBwYXJzaW5nLlxyXG4gICAgICAgICAgICBsZXQgaW5mbyA9IGN0eC5nZXRTZWN0aW9uSW5mbyhlbCk7XHJcblxyXG4gICAgICAgICAgICAvKipcclxuICAgICAgICAgICAgICogV2UgbmVlZCB0aGUgY29udGV4dCBpbmZvIHRvIHByb3Blcmx5IHBhcnNlIHNvIHJldHVybmluZyBoZXJlIFxyXG4gICAgICAgICAgICAgKiBpbmZvIGlzIG51bGwuIFRPRE86IFNldCBlcnJvciBpbiB2aWV3IGlmIHRoaXMgb2NjdXJzLlxyXG4gICAgICAgICAgICAgKi9cclxuICAgICAgICAgICAgaWYoIWluZm8pIHtcclxuXHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGxldCBkb2NTdHJpbmcgPSBpbmZvLnRleHQ7XHJcbiAgICAgICAgICAgIGxldCBkb2NMaW5lcyA9IGRvY1N0cmluZy5zcGxpdChcIlxcblwiKTtcclxuXHJcbiAgICAgICAgICAgIC8qKlxyXG4gICAgICAgICAgICAgKiBJZiB3ZSBlbmNvdW50ZXIgYSBzdGFydCB0YWcgb24gdGhlIGRvY3VtZW50IHdlIHNldCB0aGUgZmxhZyB0byBzdGFydFxyXG4gICAgICAgICAgICAgKiBwYXJzaW5nIHRoZSByZXN0IG9mIHRoZSBkb2N1bWVudC5cclxuICAgICAgICAgICAgICovXHJcbiAgICAgICAgICAgIGlmKG11bHRpQ29sdW1uUGFyc2VyLmNvbnRhaW5zU3RhcnRUYWcoZWwudGV4dENvbnRlbnQpIHx8IFxyXG4gICAgICAgICAgICAgICBtdWx0aUNvbHVtblBhcnNlci5jb250YWluc1N0YXJ0Q29kZUJsb2NrKGRvY1N0cmluZykpIHtcclxuXHJcbiAgICAgICAgICAgICAgICBmaWxlRE9NTWFuYWdlci5zZXRIYXNTdGFydFRhZygpO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAvKiogXHJcbiAgICAgICAgICAgICAqIElmIHRoZSBkb2N1bWVudCBkb2VzIG5vdCBjb250YWluIGFueSBzdGFydCB0YWdzIHdlIGlnbm9yZSB0aGVcclxuICAgICAgICAgICAgICogcmVzdCBvZiB0aGUgcGFyc2luZy4gVGhpcyBpcyBvbmx5IHNldCB0byB0cnVlIG9uY2UgdGhlIGZpcnN0XHJcbiAgICAgICAgICAgICAqIHN0YXJ0IHRhZyBlbGVtZW50IGlzIHBhcnNlZCBhYm92ZS5cclxuICAgICAgICAgICAgICovXHJcbiAgICAgICAgICAgIGlmKGZpbGVET01NYW5hZ2VyLmdldEhhc1N0YXJ0VGFnKCkgPT09IGZhbHNlKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIC8qKlxyXG4gICAgICAgICAgICAgKiBUYWtlIHRoZSBpbmZvIHByb3ZpZGVkIGFuZCBnZW5lcmF0ZSB0aGUgcmVxdWlyZWQgdmFyaWFibGVzIGZyb20gXHJcbiAgICAgICAgICAgICAqIHRoZSBsaW5lIHN0YXJ0IGFuZCBlbmQgdmFsdWVzLlxyXG4gICAgICAgICAgICAgKi9cclxuICAgICAgICAgICAgbGV0IGxpbmVzQWJvdmVBcnJheSA9IGRvY0xpbmVzLnNsaWNlKDAsIGluZm8ubGluZVN0YXJ0KVxyXG4gICAgICAgICAgICBsZXQgbGluZXNPZkVsZW1lbnQgPSBkb2NMaW5lcy5zbGljZShpbmZvLmxpbmVTdGFydCwgaW5mby5saW5lRW5kICsgMSk7XHJcbiAgICAgICAgICAgIGxldCB0ZXh0T2ZFbGVtZW50ID0gbGluZXNPZkVsZW1lbnQuam9pbihcIlxcblwiKVxyXG4gICAgICAgICAgICBsZXQgbGluZXNCZWxvd0FycmF5ID0gZG9jTGluZXMuc2xpY2UoaW5mby5saW5lRW5kICsgMSlcclxuXHJcbiAgICAgICAgICAgIC8vI3JlZ2lvbiBEZXByZWNpYXRlZCBTdGFydCBUYWdcclxuICAgICAgICAgICAgLyoqXHJcbiAgICAgICAgICAgICAqIElmIHRoZSBjdXJyZW50IGxpbmUgaXMgYSBzdGFydCB0YWcgd2Ugd2FudCB0byBzZXQgdXAgdGhlXHJcbiAgICAgICAgICAgICAqIHJlZ2lvbiBtYW5hZ2VyLiBUaGUgcmVnaW9uYWwgbWFuYWdlciB0YWtlcyBjYXJlXHJcbiAgICAgICAgICAgICAqIG9mIGFsbCBpdGVtcyBiZXR3ZWVuIGl0J3Mgc3RhcnQgYW5kIGVuZCB0YWdzIHdoaWxlIHRoZVxyXG4gICAgICAgICAgICAgKiBmaWxlIG1hbmFnZXIgd2UgZ290IGFib3ZlIGFib3ZlIHRha2VzIGNhcmUgb2YgYWxsIHJlZ2lvbmFsIFxyXG4gICAgICAgICAgICAgKiBtYW5hZ2VycyBpbiBlYWNoIGZpbGUuXHJcbiAgICAgICAgICAgICAqL1xyXG4gICAgICAgICAgICBpZihtdWx0aUNvbHVtblBhcnNlci5jb250YWluc1N0YXJ0VGFnKHRleHRPZkVsZW1lbnQpKSB7XHJcblxyXG4gICAgICAgICAgICAgICAgLyoqIFxyXG4gICAgICAgICAgICAgICAgICogU2V0IHVwIHRoZSBjdXJyZW50IGVsZW1lbnQgdG8gYWN0IGFzIHRoZSBwYXJlbnQgZm9yIHRoZSBcclxuICAgICAgICAgICAgICAgICAqIG11bHRpLWNvbHVtbiByZWdpb24uXHJcbiAgICAgICAgICAgICAgICAgKi9cclxuICAgICAgICAgICAgICAgIGVsLmNoaWxkcmVuWzBdLmRldGFjaCgpO1xyXG4gICAgICAgICAgICAgICAgZWwuY2xhc3NMaXN0LmFkZChNdWx0aUNvbHVtbkxheW91dENTUy5SZWdpb25Sb290Q29udGFpbmVyRGl2KVxyXG4gICAgICAgICAgICAgICAgbGV0IHJlbmRlckVycm9yUmVnaW9uID0gZWwuY3JlYXRlRGl2KHtcclxuICAgICAgICAgICAgICAgICAgICBjbHM6IGAke011bHRpQ29sdW1uTGF5b3V0Q1NTLlJlZ2lvbkVycm9yQ29udGFpbmVyRGl2fSAke011bHRpQ29sdW1uU3R5bGVDU1MuUmVnaW9uRXJyb3JNZXNzYWdlfWAsXHJcbiAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICAgIGxldCByZW5kZXJDb2x1bW5SZWdpb24gPSBlbC5jcmVhdGVEaXYoe1xyXG4gICAgICAgICAgICAgICAgICAgIGNsczogTXVsdGlDb2x1bW5MYXlvdXRDU1MuUmVnaW9uQ29udGVudENvbnRhaW5lckRpdlxyXG4gICAgICAgICAgICAgICAgfSlcclxuXHJcbiAgICAgICAgICAgICAgICBsZXQgc3RhcnRCbG9ja0RhdGEgPSBtdWx0aUNvbHVtblBhcnNlci5nZXRTdGFydEJsb2NrQWJvdmVMaW5lKGxpbmVzT2ZFbGVtZW50KVxyXG4gICAgICAgICAgICAgICAgaWYoc3RhcnRCbG9ja0RhdGEgPT09IG51bGwpIHtcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBcclxuICAgICAgICAgICAgICAgIGxldCByZWdpb25LZXkgPSBzdGFydEJsb2NrRGF0YS5zdGFydEJsb2NrS2V5O1xyXG4gICAgICAgICAgICAgICAgaWYoZmlsZURPTU1hbmFnZXIuY2hlY2tLZXlFeGlzdHMocmVnaW9uS2V5KSA9PT0gdHJ1ZSkge1xyXG5cclxuICAgICAgICAgICAgICAgICAgICBsZXQgeyBudW1iZXJPZlRhZ3MsIGtleXMgfSA9IG11bHRpQ29sdW1uUGFyc2VyLmNvdW50U3RhcnRUYWdzKGluZm8udGV4dCk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIGxldCBudW1NYXRjaGVzID0gMDtcclxuICAgICAgICAgICAgICAgICAgICBmb3IobGV0IGkgPSAwOyBpIDwgbnVtYmVyT2ZUYWdzOyBpKyspIHtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEJlY2F1c2Ugd2UgY2hlY2tlZCBpZiBrZXkgZXhpc3RzIG9uZSBvZiB0aGVzZSBoYXMgdG8gbWF0Y2guXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKGtleXNbaV0gPT09IHJlZ2lvbktleSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbnVtTWF0Y2hlcysrO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICAvLyBXZSBvbmx5IHdhbnQgdG8gZGlzcGxheSBhbiBlcnJvciBpZiB0aGVyZSBhcmUgbW9yZSB0aGFuIDIgb2YgdGhlIHNhbWUgaWQgYWNyb3NzXHJcbiAgICAgICAgICAgICAgICAgICAgLy8gdGhlIHdob2xlIGRvY3VtZW50LiBUaGlzIHByZXZlbnRzIGVycm9zIHdoZW4gb2JzaWRpYW4gcmVsb2FkcyB0aGUgd2hvbGUgZG9jdW1lbnRcclxuICAgICAgICAgICAgICAgICAgICAvLyBhbmQgdGhlcmUgYXJlIHR3byBvZiB0aGUgc2FtZSBrZXkgaW4gdGhlIG1hcC5cclxuICAgICAgICAgICAgICAgICAgICBpZihudW1NYXRjaGVzID49IDIpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYocmVnaW9uS2V5ID09PSBcIlwiKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW5kZXJFcnJvclJlZ2lvbi5pbm5lclRleHQgPSBcIkZvdW5kIG11bHRpcGxlIHJlZ2lvbnMgd2l0aCBlbXB0eSBJRHMuIFBsZWFzZSBzZXQgYSB1bmlxdWUgSUQgYWZ0ZXIgZWFjaCBzdGFydCB0YWcuXFxuRUc6ICc9PT0gbXVsdGktY29sdW1uLXN0YXJ0OiByYW5kb21JRCdcXG5PciB1c2UgJ0ZpeCBNaXNzaW5nIElEcycgaW4gdGhlIGNvbW1hbmQgcGFsZXR0ZSBhbmQgcmVsb2FkIHRoZSBkb2N1bWVudC5cIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVuZGVyRXJyb3JSZWdpb24uaW5uZXJUZXh0ID0gXCJSZWdpb24gSUQgYWxyZWFkeSBleGlzdHMgaW4gZG9jdW1lbnQsIHBsZWFzZSBzZXQgYSB1bmlxdWUgSUQuXFxuRUc6ICc9PT0gbXVsdGktY29sdW1uLXN0YXJ0OiByYW5kb21JRCdcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBlbC5pZCA9IGBNdWx0aUNvbHVtbklEOiR7cmVnaW9uS2V5fWBcclxuXHJcbiAgICAgICAgICAgICAgICBsZXQgZWxlbWVudE1hcmtkb3duUmVuZGVyZXIgPSBuZXcgTWFya2Rvd25SZW5kZXJDaGlsZChlbCk7XHJcbiAgICAgICAgICAgICAgICBmaWxlRE9NTWFuYWdlci5jcmVhdGVSZWdpb25hbE1hbmFnZXIocmVnaW9uS2V5LCBlbCwgcmVuZGVyRXJyb3JSZWdpb24sIHJlbmRlckNvbHVtblJlZ2lvbik7XHJcbiAgICAgICAgICAgICAgICBlbGVtZW50TWFya2Rvd25SZW5kZXJlci5vbnVubG9hZCA9ICgpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICBpZihmaWxlRE9NTWFuYWdlcikge1xyXG4gICAgXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGZpbGVET01NYW5hZ2VyLnJlbW92ZVJlZ2lvbihzdGFydEJsb2NrRGF0YS5zdGFydEJsb2NrS2V5KTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9O1xyXG4gICAgICAgICAgICAgICAgY3R4LmFkZENoaWxkKGVsZW1lbnRNYXJrZG93blJlbmRlcmVyKTtcclxuXHJcbiAgICAgICAgICAgICAgICAvKipcclxuICAgICAgICAgICAgICAgICAqIE5vdyB3ZSBoYXZlIGNyZWF0ZWQgb3VyIHJlZ2lvbmFsIG1hbmFnZXIgYW5kIGRlZmluZWQgd2hhdCBlbGVtZW50cyBcclxuICAgICAgICAgICAgICAgICAqIG5lZWQgdG8gYmUgcmVuZGVyZWQgaW50by4gU28gd2UgY2FuIHJldHVybiB3aXRob3V0IGFueSBtb3JlIHByb2Nlc3NpbmcuXHJcbiAgICAgICAgICAgICAgICAgKi9cclxuICAgICAgICAgICAgICAgIHJldHVyblxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIC8vI2VuZHJlZ2lvbiBEZXByZWNpYXRlZCBTdGFydCBUYWdcclxuXHJcbiAgICAgICAgICAgIC8qKlxyXG4gICAgICAgICAgICAgKiBDaGVjayBpZiBhbnkgb2YgdGhlIGxpbmVzIGFib3ZlIHVzIGNvbnRhaW4gYSBzdGFydCBibG9jaywgYW5kIGlmXHJcbiAgICAgICAgICAgICAqIHNvIGdldCB0aGUgbGluZXMgZnJvbSBvdXIgY3VycmVudCBlbGVtZW50IHRvIHRoZSBzdGFydCBibG9jay5cclxuICAgICAgICAgICAgICovXHJcbiAgICAgICAgICAgIGxldCBzdGFydEJvY2tBYm92ZSA9IG11bHRpQ29sdW1uUGFyc2VyLmdldFN0YXJ0QmxvY2tPckNvZGVibG9ja0Fib3ZlTGluZShsaW5lc0Fib3ZlQXJyYXkpO1xyXG4gICAgICAgICAgICBpZihzdGFydEJvY2tBYm92ZSA9PT0gbnVsbCkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIC8qKlxyXG4gICAgICAgICAgICAgKiBXZSBub3cga25vdyB3ZSdyZSB3aXRoaW4gYSBtdWx0aS1jb2x1bW4gcmVnaW9uLCBzbyB3ZSB1cGRhdGUgb3VyXHJcbiAgICAgICAgICAgICAqIGxpc3Qgb2YgbGluZXMgYWJvdmUgdG8ganVzdCBiZSB0aGUgaXRlbXMgd2l0aGluIHRoaXMgcmVnaW9uLlxyXG4gICAgICAgICAgICAgKi9cclxuICAgICAgICAgICAgbGluZXNBYm92ZUFycmF5ID0gc3RhcnRCb2NrQWJvdmUubGluZXNBYm92ZUFycmF5O1xyXG5cclxuICAgICAgICAgICAgLyoqXHJcbiAgICAgICAgICAgICAqIFdlIHVzZSB0aGUgc3RhcnQgYmxvY2sncyBrZXkgdG8gZ2V0IG91ciByZWdpb25hbCBtYW5hZ2VyLiBJZiB0aGlzXHJcbiAgICAgICAgICAgICAqIGxvb2t1cCBmYWlscyB3ZSBjYW4gbm90IGNvbnRpbnVlIHByb2Nlc3NpbmcgdGhpcyBlbGVtZW50LlxyXG4gICAgICAgICAgICAgKi9cclxuICAgICAgICAgICAgbGV0IHJlZ2lvbmFsQ29udGFpbmVyOiBSZWdpb25NYW5hZ2VyQ29udGFpbmVyID0gZmlsZURPTU1hbmFnZXIuZ2V0UmVnaW9uYWxDb250YWluZXIoc3RhcnRCb2NrQWJvdmUuc3RhcnRCbG9ja0tleSk7XHJcbiAgICAgICAgICAgIGlmKHJlZ2lvbmFsQ29udGFpbmVyID09PSBudWxsKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm5cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBsZXQgcmVnaW9uYWxNYW5hZ2VyOiBSZWdpb25NYW5hZ2VyID0gcmVnaW9uYWxDb250YWluZXIuZ2V0UmVnaW9uKCk7XHJcblxyXG4gICAgICAgICAgICAvKipcclxuICAgICAgICAgICAgICogVG8gbWFrZSBzdXJlIHdlJ3JlIHBsYWNpbmcgdGhlIGl0ZW0gaW4gdGhlIHJpZ2h0IGxvY2F0aW9uIChhbmQgXHJcbiAgICAgICAgICAgICAqIG92ZXJ3cml0ZSBlbGVtZW50cyB0aGF0IGFyZSBub3cgZ29uZSkgd2Ugbm93IHdhbnQgYWxsIG9mIHRoZVxyXG4gICAgICAgICAgICAgKiBsaW5lcyBhZnRlciB0aGlzIGVsZW1lbnQgdXAgdG8gdGhlIGVuZCB0YWcuXHJcbiAgICAgICAgICAgICAqL1xyXG4gICAgICAgICAgICBsaW5lc0JlbG93QXJyYXkgPSAgbXVsdGlDb2x1bW5QYXJzZXIuZ2V0RW5kQmxvY2tCZWxvdyhsaW5lc0JlbG93QXJyYXkpO1xyXG5cclxuICAgICAgICAgICAgLyoqXHJcbiAgICAgICAgICAgICAqIE5vdyB3ZSB0YWtlIHRoZSBsaW5lcyBhYm92ZSBvdXIgY3VycmVudCBlbGVtZW50IHVwIHVudGlsIHRoZVxyXG4gICAgICAgICAgICAgKiBzdGFydCByZWdpb24gdGFnIGFuZCByZW5kZXIgdGhhdCBpbnRvIGFuIEhUTUwgZWxlbWVudC4gV2Ugd2lsbCBcclxuICAgICAgICAgICAgICogdXNlIHRoZXNlIGVsZW1lbnRzIHRvIGRldGVybWluZSB3aGVyZSB0byBwbGFjZSBvdXIgY3VycmVudCBlbGVtZW50LlxyXG4gICAgICAgICAgICAgKi9cclxuICAgICAgICAgICAgbGV0IHNpYmxpbmdzQWJvdmU6IEhUTUxEaXZFbGVtZW50ID0gcmVuZGVyTWFya2Rvd25Gcm9tTGluZXMobGluZXNBYm92ZUFycmF5LCBzb3VyY2VQYXRoKTtcclxuXHJcbiAgICAgICAgICAgIGxldCBzaWJsaW5nc0JlbG93OiBIVE1MRGl2RWxlbWVudCA9IHJlbmRlck1hcmtkb3duRnJvbUxpbmVzKGxpbmVzQmVsb3dBcnJheSwgc291cmNlUGF0aCk7XHJcblxyXG4gICAgICAgICAgICAvKipcclxuICAgICAgICAgICAgICogU2V0IHVwIG91ciBkb20gb2JqZWN0IHRvIGJlIGFkZGVkIHRvIHRoZSBtYW5hZ2VyLlxyXG4gICAgICAgICAgICAgKi9cclxuICAgICAgICAgICAgbGV0IGN1cnJlbnRPYmplY3Q6IERPTU9iamVjdCA9IG5ldyBET01PYmplY3QoZWwsIGxpbmVzT2ZFbGVtZW50KVxyXG4gICAgICAgICAgICBlbC5pZCA9IGN1cnJlbnRPYmplY3QuVUlEO1xyXG5cclxuICAgICAgICAgICAgY3VycmVudE9iamVjdCA9IFRhc2tMaXN0RE9NT2JqZWN0LmNoZWNrRm9yVGFza0xpc3RFbGVtZW50KGN1cnJlbnRPYmplY3QpXHJcblxyXG4gICAgICAgICAgICAvKipcclxuICAgICAgICAgICAgICogTm93IHdlIGFkZCB0aGUgb2JqZWN0IHRvIHRoZSBtYW5hZ2VyIGFuZCB0aGVuIHNldHVwIHRoZVxyXG4gICAgICAgICAgICAgKiBjYWxsYmFjayBmb3Igd2hlbiB0aGUgb2JqZWN0IGlzIHJlbW92ZWQgZnJvbSB2aWV3IHRoYXQgd2lsbCByZW1vdmUgXHJcbiAgICAgICAgICAgICAqIHRoZSBpdGVtIGZyb20gdGhlIG1hbmFnZXIuXHJcbiAgICAgICAgICAgICAqL1xyXG4gICAgICAgICAgICByZWdpb25hbE1hbmFnZXIuYWRkT2JqZWN0KHNpYmxpbmdzQWJvdmUsIHNpYmxpbmdzQmVsb3csIGN1cnJlbnRPYmplY3QpO1xyXG5cclxuICAgICAgICAgICAgbGV0IGVsZW1lbnRNYXJrZG93blJlbmRlcmVyID0gbmV3IE1hcmtkb3duUmVuZGVyQ2hpbGQoZWwpO1xyXG4gICAgICAgICAgICBlbGVtZW50TWFya2Rvd25SZW5kZXJlci5vbnVubG9hZCA9ICgpID0+IHtcclxuXHJcbiAgICAgICAgICAgICAgICBpZihyZWdpb25hbENvbnRhaW5lciA9PT0gbnVsbCkge1xyXG4gICAgICAgICAgICAgICAgICAgIHJldHVyblxyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgXHJcbiAgICAgICAgICAgICAgICBsZXQgcmVnaW9uYWxNYW5hZ2VyOiBSZWdpb25NYW5hZ2VyID0gcmVnaW9uYWxDb250YWluZXIuZ2V0UmVnaW9uKCk7XHJcbiAgICAgICAgICAgICAgICBpZihyZWdpb25hbE1hbmFnZXIpIHtcclxuICAgICAgICAgICAgICAgICAgICBcclxuICAgICAgICAgICAgICAgICAgICAvLyBXZSBjYW4gYXR0ZW1wdCB0byB1cGRhdGUgdGhlIHZpZXcgaGVyZSBhZnRlciB0aGUgaXRlbSBpcyByZW1vdmVkXHJcbiAgICAgICAgICAgICAgICAgICAgLy8gYnV0IG5lZWQgdG8gZ2V0IHRoZSBpdGVtJ3MgcGFyZW50IGVsZW1lbnQgYmVmb3JlIHJlbW92aW5nIG9iamVjdCBmcm9tIG1hbmFnZXIuXHJcbiAgICAgICAgICAgICAgICAgICAgbGV0IHJlZ2lvblJlbmRlckRhdGE6IE11bHRpQ29sdW1uUmVuZGVyRGF0YSA9IHJlZ2lvbmFsTWFuYWdlci5nZXRSZWdpb25SZW5kZXJEYXRhKCk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIHJlZ2lvbmFsTWFuYWdlci5yZW1vdmVPYmplY3QoY3VycmVudE9iamVjdC5VSUQpO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAvKipcclxuICAgICAgICAgICAgICAgICAgICAgKiBOZWVkIHRvIGNoZWNrIGhlcmUgaWYgZWxlbWVudCBpcyBudWxsIGFzIHRoaXMgY2xvc3VyZSB3aWxsIGJlIGNhbGxlZFxyXG4gICAgICAgICAgICAgICAgICAgICAqIHJlcGVhdGVkbHkgb24gZmlsZSBjaGFuZ2UuXHJcbiAgICAgICAgICAgICAgICAgICAgICovXHJcbiAgICAgICAgICAgICAgICAgICAgaWYocmVnaW9uUmVuZGVyRGF0YS5wYXJlbnRSZW5kZXJFbGVtZW50ID09PSBudWxsKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgcmVnaW9uYWxNYW5hZ2VyLnJlbmRlclJlZ2lvbkVsZW1lbnRzVG9TY3JlZW4oKVxyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9O1xyXG4gICAgICAgICAgICBjdHguYWRkQ2hpbGQoZWxlbWVudE1hcmtkb3duUmVuZGVyZXIpO1xyXG5cclxuICAgICAgICAgICAgbGV0IGVsZW1lbnRUZXh0U3BhY2VkID0gbGluZXNPZkVsZW1lbnQucmVkdWNlKChwcmV2LCBjdXJyKSA9PiB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gcHJldiArIFwiXFxuXCIgKyBjdXJyO1xyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgLyoqXHJcbiAgICAgICAgICAgICAqIE5vdyB3ZSBjaGVjayBpZiBvdXIgY3VycmVudCBlbGVtZW50IGlzIGEgc3BlY2lhbCBmbGFnIHNvIHdlIGNhblxyXG4gICAgICAgICAgICAgKiBwcm9wZXJseSBzZXQgdGhlIGVsZW1lbnQgdGFnIHdpdGhpbiB0aGUgcmVnaW9uYWwgbWFuYWdlci5cclxuICAgICAgICAgICAgICovXHJcbiAgICAgICAgICAgIGlmKG11bHRpQ29sdW1uUGFyc2VyLmNvbnRhaW5zRW5kVGFnKGVsLnRleHRDb250ZW50KSA9PT0gdHJ1ZSkge1xyXG5cclxuICAgICAgICAgICAgICAgIGN1cnJlbnRPYmplY3QuZWxlbWVudFR5cGUgPSBFbGVtZW50UmVuZGVyVHlwZS51blJlbmRlcmVkXHJcbiAgICAgICAgICAgICAgICBlbC5hZGRDbGFzcyhNdWx0aUNvbHVtblN0eWxlQ1NTLlJlZ2lvbkVuZFRhZylcclxuICAgICAgICAgICAgICAgIHJlZ2lvbmFsTWFuYWdlci51cGRhdGVFbGVtZW50VGFnKGN1cnJlbnRPYmplY3QuVUlELCBET01PYmplY3RUYWcuZW5kUmVnaW9uKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBlbHNlIGlmKG11bHRpQ29sdW1uUGFyc2VyLmNvbnRhaW5zQ29sRW5kVGFnKGVsZW1lbnRUZXh0U3BhY2VkKSA9PT0gdHJ1ZSkge1xyXG5cclxuICAgICAgICAgICAgICAgIGN1cnJlbnRPYmplY3QuZWxlbWVudFR5cGUgPSBFbGVtZW50UmVuZGVyVHlwZS51blJlbmRlcmVkXHJcbiAgICAgICAgICAgICAgICBlbC5hZGRDbGFzcyhNdWx0aUNvbHVtblN0eWxlQ1NTLkNvbHVtbkVuZFRhZylcclxuICAgICAgICAgICAgICAgIHJlZ2lvbmFsTWFuYWdlci51cGRhdGVFbGVtZW50VGFnKGN1cnJlbnRPYmplY3QuVUlELCBET01PYmplY3RUYWcuY29sdW1uQnJlYWspO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGVsc2UgaWYobXVsdGlDb2x1bW5QYXJzZXIuY29udGFpbnNDb2xTZXR0aW5nc1RhZyhlbGVtZW50VGV4dFNwYWNlZCkgPT09IHRydWUpIHtcclxuXHJcbiAgICAgICAgICAgICAgICBjdXJyZW50T2JqZWN0LmVsZW1lbnRUeXBlID0gRWxlbWVudFJlbmRlclR5cGUudW5SZW5kZXJlZFxyXG4gICAgICAgICAgICAgICAgZWwuYWRkQ2xhc3MoTXVsdGlDb2x1bW5TdHlsZUNTUy5SZWdpb25TZXR0aW5ncylcclxuICAgICAgICAgICAgICAgIHJlZ2lvbmFsTWFuYWdlciA9IHJlZ2lvbmFsQ29udGFpbmVyLnNldFJlZ2lvblNldHRpbmdzKGVsZW1lbnRUZXh0U3BhY2VkKVxyXG4gICAgICAgICAgICAgICAgcmVnaW9uYWxNYW5hZ2VyLnVwZGF0ZUVsZW1lbnRUYWcoY3VycmVudE9iamVjdC5VSUQsIERPTU9iamVjdFRhZy5yZWdpb25TZXR0aW5ncyk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgICAgICBlbC5hZGRDbGFzcyhNdWx0aUNvbHVtblN0eWxlQ1NTLlJlZ2lvbkNvbnRlbnQpXHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgXHJcbiAgICAgICAgICAgIHJlZ2lvbmFsTWFuYWdlci5yZW5kZXJSZWdpb25FbGVtZW50c1RvU2NyZWVuKClcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgaXNTdGFydENvZGVibG9ja0luRXhwb3J0KG5vZGU6IEhUTUxFbGVtZW50KTogYm9vbGVhbiB7XHJcblxyXG4gICAgICAgIGZvcihsZXQgaSA9IDA7IGkgPCBDT0RFQkxPQ0tfU1RBUlRfU1RSUy5sZW5ndGg7IGkrKykge1xyXG5cclxuICAgICAgICAgICAgaWYobm9kZS5oYXNDbGFzcyhgYmxvY2stbGFuZ3VhZ2UtJHtDT0RFQkxPQ0tfU1RBUlRfU1RSU1tpXX1gKSkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgYXN5bmMgZXhwb3J0RG9jdW1lbnRUb1BERihlbDogSFRNTEVsZW1lbnQsIGZpbGVET01NYW5hZ2VyOiBGaWxlRE9NTWFuYWdlciwgc291cmNlUGF0aDogc3RyaW5nKSB7XHJcblxyXG4gICAgICAgIC8vIEEgdHJ1ZSBleHBvcnQgd2lsbCBiZSBwYXNzZWQgYW4gZWxlbWVudCB3aXRoIGFsbCBvdGhlciBpdGVtcyBpbiB0aGUgZG9jIGFzIGNoaWxkcmVuLiBcclxuICAgICAgICAvLyBTbyBpZiB0aGVyZSBhcmUgbm8gY2hpbGRyZW4gd2UgY2FuIGp1c3QgcmV0dXJuXHJcbiAgICAgICAgbGV0IGRvY0NoaWxkcmVuID0gQXJyYXkuZnJvbShlbC5jaGlsZE5vZGVzKTtcclxuICAgICAgICBpZihkb2NDaGlsZHJlbi5sZW5ndGggPT09IDApIHtcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgbGV0IGNoaWxkcmVuVG9SZW1vdmUgPSBbXTtcclxuICAgICAgICBcclxuICAgICAgICAvLyBUbyBleHBvcnQgY29kZWJsb2NrcyB3ZSBuZWVkIHRvIGdldCB0aGUgSURzIHNvIHdlIGNhbiBnZXQgdGhlIGRhdGEgZnJvbSBvdXIgbWFuYWdlcnMuXHJcbiAgICAgICAgLy8gaG93ZXZlciBzaW5jZSB0aGUgSUQgaXNudCBiZWluZyBzdG9yZWQgaW4gdGhlIGVsZW1lbnQgeWV0IHRoaXMgbWVhbnMgd2UgbmVlZCB0byByZWFkXHJcbiAgICAgICAgLy8gYWxsIG9mIHRoZSBJRHMgb3V0IG9mIHRoZSBmdWxsIGRvY3VtZW50LlxyXG4gICAgICAgIGxldCBjb2RlYmxvY2tTdGFydEJsb2NrcyA9IFtdXHJcbiAgICAgICAgbGV0IGFGaWxlID0gdGhpcy5hcHAudmF1bHQuZ2V0QWJzdHJhY3RGaWxlQnlQYXRoKHNvdXJjZVBhdGgpO1xyXG4gICAgICAgIGlmKGFGaWxlIGluc3RhbmNlb2YgVEZpbGUpIHtcclxuXHJcbiAgICAgICAgICAgIGxldCBmaWxlID0gYUZpbGUgYXMgVEZpbGVcclxuICAgICAgICAgICAgbGV0IGZpbGVUZXh0ID0gYXdhaXQgdGhpcy5hcHAudmF1bHQuY2FjaGVkUmVhZChmaWxlKSAvLyBJcyBjYWNoZWQgcmVhZCBPayBoZXJlPyBJdCBzaG91bGQgYmUuXHJcblxyXG4gICAgICAgICAgICAvLyBPbmNlIHdlIGhhdmUgb3VyIGRhdGEgd2Ugc2VhcmNoIHRoZSB0ZXh0IGZvciBhbGwgY29kZWJsb2NrIHN0YXJ0IHZhbHVlcy5cclxuICAgICAgICAgICAgLy8gc3RvcmluZyB0aGVtIGludG8gb3VyIHF1ZXVlLlxyXG4gICAgICAgICAgICBsZXQgY29kZUJsb2NrRGF0YSA9IG11bHRpQ29sdW1uUGFyc2VyLmZpbmRTdGFydENvZGVibG9jayhmaWxlVGV4dCk7XHJcbiAgICAgICAgICAgIHdoaWxlKGNvZGVCbG9ja0RhdGEuZm91bmQgPT09IHRydWUpIHtcclxuXHJcbiAgICAgICAgICAgICAgICBsZXQgY29kZWJsb2NrVGV4dCA9IGZpbGVUZXh0LnNsaWNlKGNvZGVCbG9ja0RhdGEuc3RhcnRQb3NpdGlvbiwgY29kZUJsb2NrRGF0YS5lbmRQb3NpdGlvbik7XHJcbiAgICAgICAgICAgICAgICBmaWxlVGV4dCA9IGZpbGVUZXh0LnNsaWNlKGNvZGVCbG9ja0RhdGEuZW5kUG9zaXRpb24pO1xyXG4gICAgICAgICAgICAgICAgY29kZWJsb2NrU3RhcnRCbG9ja3MucHVzaChjb2RlYmxvY2tUZXh0KTtcclxuXHJcbiAgICAgICAgICAgICAgICBjb2RlQmxvY2tEYXRhID0gbXVsdGlDb2x1bW5QYXJzZXIuZmluZFN0YXJ0Q29kZWJsb2NrKGZpbGVUZXh0KTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0gIFxyXG5cclxuICAgICAgICBsZXQgaW5CbG9jayA9IGZhbHNlO1xyXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZG9jQ2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcclxuXHJcbiAgICAgICAgICAgIGxldCBjaGlsZCA9IGRvY0NoaWxkcmVuW2ldO1xyXG4gICAgICAgICAgICBpZiAoY2hpbGQgaW5zdGFuY2VvZiBIVE1MRWxlbWVudCkge1xyXG4gICAgICAgICAgICAgICAgbGV0IGNoaWxkRWwgPSBjaGlsZCBhcyBIVE1MRWxlbWVudDtcclxuICAgICAgICAgICAgICAgIGlmIChpbkJsb2NrID09PSBmYWxzZSkge1xyXG4gICAgICAgICAgICAgICAgICAgIFxyXG4gICAgICAgICAgICAgICAgICAgIGxldCBmb3VuZEJsb2NrRGF0YSA9IGZhbHNlO1xyXG4gICAgICAgICAgICAgICAgICAgIGxldCByZWdpb25LZXkgPSBcIlwiO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICBsZXQgYmxvY2tEYXRhID0gbXVsdGlDb2x1bW5QYXJzZXIuaXNTdGFydFRhZ1dpdGhJRChjaGlsZC50ZXh0Q29udGVudCk7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKGJsb2NrRGF0YS5pc1N0YXJ0VGFnID09PSB0cnVlKSB7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBmb3VuZEJsb2NrRGF0YSA9IHRydWU7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChibG9ja0RhdGEuaGFzS2V5ID09PSB0cnVlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgZm91bmRLZXkgPSBtdWx0aUNvbHVtblBhcnNlci5nZXRTdGFydFRhZ0tleShjaGlsZC50ZXh0Q29udGVudCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZm91bmRLZXkgIT09IG51bGwpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWdpb25LZXkgPSBmb3VuZEtleTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICBlbHNlIGlmKGJsb2NrRGF0YS5pc1N0YXJ0VGFnID09PSBmYWxzZSAmJiB0aGlzLmlzU3RhcnRDb2RlYmxvY2tJbkV4cG9ydChjaGlsZCkpIHtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIElmIHRoZSBzdGFydCB0YWcgZnJvbSB0aGUgb2xkIHZlcnNpb24gaXMgbnVsbCB3ZSB0aGVuIGNoZWNrIHRvIHNlZSBpZiB0aGUgZWxlbWVudCBpc1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBhIGNvZGVibG9jayBzdGFydC4gSWYgaXQgaXMgd2UgdXNlIHRoZSBuZXh0IGF2YWlsYWJsZSBjb2RlYmxvY2sgZGF0YSB0byByZXRyaWV2ZSBvdXIgSUQuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBjb2RlYmxvY2tUZXh0ID0gY29kZWJsb2NrU3RhcnRCbG9ja3Muc2hpZnQoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYoY29kZWJsb2NrVGV4dCA9PT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKFwiRm91bmQgdW5kZWZpbmVkIGNvZGVibG9jayBkYXRhIHdoZW4gZXhwb3J0aW5nLlwiKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgaWQgPSBwYXJzZVN0YXJ0UmVnaW9uQ29kZUJsb2NrSUQoY29kZWJsb2NrVGV4dCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKGlkICE9PSBcIlwiKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3VuZEJsb2NrRGF0YSA9IHRydWU7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWdpb25LZXkgPSBpZDtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgaWYoZm91bmRCbG9ja0RhdGEgPT09IHRydWUgJiYgcmVnaW9uS2V5ICE9PSBcIlwiKSB7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBpbkJsb2NrID0gdHJ1ZTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSBjaGlsZC5jaGlsZHJlbi5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGQuY2hpbGRyZW5baV0uZGV0YWNoKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGQuaW5uZXJUZXh0ID0gXCJcIjtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkLmNsYXNzTGlzdC5hZGQoTXVsdGlDb2x1bW5MYXlvdXRDU1MuUmVnaW9uUm9vdENvbnRhaW5lckRpdik7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCByZW5kZXJFcnJvclJlZ2lvbiA9IGNoaWxkLmNyZWF0ZURpdih7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbHM6IGAke011bHRpQ29sdW1uTGF5b3V0Q1NTLlJlZ2lvbkVycm9yQ29udGFpbmVyRGl2fSwgJHtNdWx0aUNvbHVtblN0eWxlQ1NTLlJlZ2lvbkVycm9yTWVzc2FnZX1gLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHJlbmRlckNvbHVtblJlZ2lvbiA9IGNoaWxkLmNyZWF0ZURpdih7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbHM6IE11bHRpQ29sdW1uTGF5b3V0Q1NTLlJlZ2lvbkNvbnRlbnRDb250YWluZXJEaXZcclxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XHJcblxyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHJlZ2lvbmFsQ29udGFpbmVyOiBSZWdpb25NYW5hZ2VyQ29udGFpbmVyID0gZmlsZURPTU1hbmFnZXIuZ2V0UmVnaW9uYWxDb250YWluZXIocmVnaW9uS2V5KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJlZ2lvbmFsQ29udGFpbmVyID09PSBudWxsKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW5kZXJFcnJvclJlZ2lvbi5pbm5lclRleHQgPSBcIkVycm9yIHJlbmRlcmluZyBtdWx0aS1jb2x1bW4gcmVnaW9uLlxcblBsZWFzZSBjbG9zZSBhbmQgcmVvcGVuIHRoZSBmaWxlLCB0aGVuIG1ha2Ugc3VyZSB5b3UgYXJlIGluIHJlYWRpbmcgbW9kZSBiZWZvcmUgZXhwb3J0aW5nLlwiO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHJlZ2lvbmFsTWFuYWdlcjogUmVnaW9uTWFuYWdlciA9IHJlZ2lvbmFsQ29udGFpbmVyLmdldFJlZ2lvbigpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVnaW9uYWxNYW5hZ2VyLmV4cG9ydFJlZ2lvbkVsZW1lbnRzVG9QREYocmVuZGVyQ29sdW1uUmVnaW9uKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGVsc2Uge1xyXG5cclxuICAgICAgICAgICAgICAgICAgICBpZiAobXVsdGlDb2x1bW5QYXJzZXIuY29udGFpbnNFbmRUYWcoY2hpbGQudGV4dENvbnRlbnQpID09PSB0cnVlKSB7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBpbkJsb2NrID0gZmFsc2U7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICBjaGlsZHJlblRvUmVtb3ZlLnB1c2goY2hpbGQpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjaGlsZHJlblRvUmVtb3ZlLmZvckVhY2goY2hpbGQgPT4ge1xyXG4gICAgICAgICAgICBpZihjaGlsZC5wYXJlbnRFbGVtZW50ID09PSBlbCkge1xyXG4gICAgICAgICAgICAgICAgZWwucmVtb3ZlQ2hpbGQoY2hpbGQpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgY2hlY2tFeHBvcnRpbmcoZWxlbWVudDogSFRNTEVsZW1lbnQpOiBib29sZWFuIHtcclxuXHJcbiAgICAgICAgaWYoZWxlbWVudCA9PT0gbnVsbCkge1xyXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZihlbGVtZW50LmNsYXNzTGlzdC5jb250YWlucyhcInByaW50XCIpKSB7XHJcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYoZWxlbWVudC5wYXJlbnROb2RlICE9PSBudWxsKSB7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNoZWNrRXhwb3J0aW5nKGVsZW1lbnQucGFyZW50RWxlbWVudCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICB9XHJcblxyXG4gICAgc2V0dXBNYXJrZG93bkNvZGVibG9ja1Bvc3RQcm9jZXNzb3Ioc3RhcnRTdHI6IHN0cmluZykge1xyXG5cclxuICAgICAgICB0aGlzLnJlZ2lzdGVyTWFya2Rvd25Db2RlQmxvY2tQcm9jZXNzb3Ioc3RhcnRTdHIsIChzb3VyY2UsIGVsLCBjdHgpID0+IHtcclxuXHJcbiAgICAgICAgICAgIGNvbnN0IHNvdXJjZVBhdGggPSBjdHguc291cmNlUGF0aDtcclxuICAgICAgICBcclxuICAgICAgICAgICAgLy8gU2V0IHVwIG91ciBDU1Mgc28gdGhhdCB0aGUgY29kZWJsb2NrIG9ubHkgcmVuZGVycyB0aGlzIGRhdGEgaW4gcmVhZGluZyBtb2RlXHJcbiAgICAgICAgICAgIC8vIHNvdXJjZS9saXZlIHByZXZpZXcgbW9kZSBpcyBoYW5kbGVkIGJ5IHRoZSBDTTYgaW1wbGVtZW50YXRpb24uXHJcbiAgICAgICAgICAgIGVsLnBhcmVudEVsZW1lbnQ/LmFkZENsYXNzKFwicHJlaXZldy1tY20tc3RhcnQtYmxvY2tcIik7XHJcbiAgICAgICAgXHJcbiAgICAgICAgICAgIC8vIFRvIGRldGVybWluZSB3aGF0IGtpbmQgb2YgdmlldyB3ZSBhcmUgcmVuZGVyaW5nIGluIHdlIG5lZWQgYSBtYXJrZG93biBsZWFmLlxyXG4gICAgICAgICAgICAvLyBSZWFsbHkgdGhpcyBzaG91bGQgbmV2ZXIgcmV0dXJuIGhlcmUgc2luY2UgcmVuZGVyaW5nIGlzIG9ubHkgZG9uZSBpbiBtYXJrZG93biBsZWF2ZXMuXHJcbiAgICAgICAgICAgIGxldCBtYXJrZG93bkxlYXZlcyA9IGFwcC53b3Jrc3BhY2UuZ2V0TGVhdmVzT2ZUeXBlKFwibWFya2Rvd25cIik7XHJcbiAgICAgICAgICAgIGlmKG1hcmtkb3duTGVhdmVzLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgXHJcbiAgICAgICAgICAgIC8vIENoZWNrIHRoZSB0eXBlIG9mIHRoZSBsZWFmXHJcbiAgICAgICAgICAgIGxldCBmb3VuZEZpbGVMZWFmID0gZmFsc2U7XHJcbiAgICAgICAgICAgIGZvcihsZXQgaSA9IDA7IGkgPCBtYXJrZG93bkxlYXZlcy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgIFxyXG4gICAgICAgICAgICAgICAgbGV0IGZpbGVMZWFmID0gZ2V0RmlsZUxlYWYoc291cmNlUGF0aCk7XHJcbiAgICAgICAgICAgICAgICBpZihmaWxlTGVhZiA9PT0gbnVsbCkge1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgZm91bmRGaWxlTGVhZiA9IHRydWU7XHJcbiAgICAgICAgXHJcbiAgICAgICAgICAgICAgICBpZihnZXRMZWFmU291cmNlTW9kZShmaWxlTGVhZikgPT09IFwic291cmNlXCIpIHtcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICBcclxuICAgICAgICAgICAgaWYodGhpcy5nbG9iYWxNYW5hZ2VyID09PSBudWxsIHx8IHRoaXMuZ2xvYmFsTWFuYWdlciA9PT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhcIkdsb2JhbCBtYW5hZ2VyIGlzIHVuZGVmaW5lZD9cIik7XHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGxldCBmaWxlRE9NTWFuYWdlciA9IHRoaXMuZ2xvYmFsTWFuYWdlci5nZXRGaWxlTWFuYWdlcihzb3VyY2VQYXRoKTtcclxuICAgICAgICAgICAgaWYoZmlsZURPTU1hbmFnZXIgPT09IG51bGwpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBcclxuICAgICAgICAgICAgLy8gU2V0IGZpbGUgdG8gaGF2ZSBzdGFydCB0YWcuXHJcbiAgICAgICAgICAgIGZpbGVET01NYW5hZ2VyLnNldEhhc1N0YXJ0VGFnKCk7XHJcbiAgICAgICAgXHJcbiAgICAgICAgICAgIC8vIEdldCB0aGUgaW5mbyBmb3Igb3VyIGN1cnJlbnQgY29udGV4dCBhbmQgdGhlbiBjaGVja1xyXG4gICAgICAgICAgICAvLyBpZiB0aGUgZW50aXJlIHRleHQgY29udGFpbnMgYSBzdGFydCB0YWcuIElmIHRoZXJlIGlzXHJcbiAgICAgICAgICAgIC8vIG5vIHN0YXJ0IHRhZyBpbiB0aGUgZG9jdW1lbnQgd2UgY2FuIGp1c3QgcmV0dXJuIGFuZFxyXG4gICAgICAgICAgICAvLyBpZ25vcmUgdGhlIHJlc3Qgb2YgdGhlIHBhcnNpbmcuXHJcbiAgICAgICAgICAgIGxldCBpbmZvID0gY3R4LmdldFNlY3Rpb25JbmZvKGVsKTtcclxuICAgICAgICBcclxuICAgICAgICAgICAgLyoqXHJcbiAgICAgICAgICAgICAqIFdlIG5lZWQgdGhlIGNvbnRleHQgaW5mbyB0byBwcm9wZXJseSBwYXJzZSBzbyByZXR1cm5pbmcgaGVyZSBcclxuICAgICAgICAgICAgICogaW5mbyBpcyBudWxsLiBUT0RPOiBTZXQgZXJyb3IgaW4gdmlldyBpZiB0aGlzIG9jY3Vycy5cclxuICAgICAgICAgICAgICovXHJcbiAgICAgICAgICAgIGlmKCFpbmZvKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICBcclxuICAgICAgICAgICAgLyoqIFxyXG4gICAgICAgICAgICAgKiBTZXQgdXAgdGhlIGN1cnJlbnQgZWxlbWVudCB0byBhY3QgYXMgdGhlIHBhcmVudCBmb3IgdGhlIFxyXG4gICAgICAgICAgICAgKiBtdWx0aS1jb2x1bW4gcmVnaW9uLlxyXG4gICAgICAgICAgICAgKi9cclxuICAgICAgICAgICAgZWwuY2xhc3NMaXN0LmFkZChNdWx0aUNvbHVtbkxheW91dENTUy5SZWdpb25Sb290Q29udGFpbmVyRGl2KVxyXG4gICAgICAgICAgICBsZXQgcmVuZGVyRXJyb3JSZWdpb24gPSBlbC5jcmVhdGVEaXYoe1xyXG4gICAgICAgICAgICAgICAgY2xzOiBgJHtNdWx0aUNvbHVtbkxheW91dENTUy5SZWdpb25FcnJvckNvbnRhaW5lckRpdn0gJHtNdWx0aUNvbHVtblN0eWxlQ1NTLlJlZ2lvbkVycm9yTWVzc2FnZX1gLFxyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgbGV0IHJlbmRlckNvbHVtblJlZ2lvbiA9IGVsLmNyZWF0ZURpdih7XHJcbiAgICAgICAgICAgICAgICBjbHM6IE11bHRpQ29sdW1uTGF5b3V0Q1NTLlJlZ2lvbkNvbnRlbnRDb250YWluZXJEaXZcclxuICAgICAgICAgICAgfSlcclxuICAgICAgICBcclxuICAgICAgICAgICAgbGV0IHJlZ2lvbktleSA9IHBhcnNlU3RhcnRSZWdpb25Db2RlQmxvY2tJRChzb3VyY2UpO1xyXG4gICAgICAgIFxyXG4gICAgICAgICAgICBsZXQgY3JlYXRlTmV3UmVnaW9uTWFuYWdlciA9IHRydWU7XHJcbiAgICAgICAgICAgIGlmKGZpbGVET01NYW5hZ2VyLmNoZWNrS2V5RXhpc3RzKHJlZ2lvbktleSkgPT09IHRydWUpIHtcclxuICAgICAgICAgICAgICAgIFxyXG4gICAgICAgICAgICAgICAgY3JlYXRlTmV3UmVnaW9uTWFuYWdlciA9IGZhbHNlO1xyXG4gICAgICAgICAgICAgICAgbGV0IHsgbnVtYmVyT2ZUYWdzLCBrZXlzIH0gPSBtdWx0aUNvbHVtblBhcnNlci5jb3VudFN0YXJ0VGFncyhpbmZvLnRleHQpO1xyXG4gICAgICAgIFxyXG4gICAgICAgICAgICAgICAgbGV0IG51bU1hdGNoZXMgPSAwO1xyXG4gICAgICAgICAgICAgICAgZm9yKGxldCBpID0gMDsgaSA8IG51bWJlck9mVGFnczsgaSsrKSB7XHJcbiAgICAgICAgXHJcbiAgICAgICAgICAgICAgICAgICAgLy8gQmVjYXVzZSB3ZSBjaGVja2VkIGlmIGtleSBleGlzdHMgb25lIG9mIHRoZXNlIGhhcyB0byBtYXRjaC5cclxuICAgICAgICAgICAgICAgICAgICBpZihrZXlzW2ldID09PSByZWdpb25LZXkpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgbnVtTWF0Y2hlcysrO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICBcclxuICAgICAgICAgICAgICAgIC8vIFdlIG9ubHkgd2FudCB0byBkaXNwbGF5IGFuIGVycm9yIGlmIHRoZXJlIGFyZSBtb3JlIHRoYW4gMiBvZiB0aGUgc2FtZSBpZCBhY3Jvc3NcclxuICAgICAgICAgICAgICAgIC8vIHRoZSB3aG9sZSBkb2N1bWVudC4gVGhpcyBwcmV2ZW50cyBlcnJvcyB3aGVuIG9ic2lkaWFuIHJlbG9hZHMgdGhlIHdob2xlIGRvY3VtZW50XHJcbiAgICAgICAgICAgICAgICAvLyBhbmQgdGhlcmUgYXJlIHR3byBvZiB0aGUgc2FtZSBrZXkgaW4gdGhlIG1hcC5cclxuICAgICAgICAgICAgICAgIGlmKG51bU1hdGNoZXMgPj0gMikge1xyXG4gICAgICAgICAgICAgICAgICAgIGlmKHJlZ2lvbktleSA9PT0gXCJcIikge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICByZW5kZXJFcnJvclJlZ2lvbi5pbm5lclRleHQgPSBcIkZvdW5kIG11bHRpcGxlIHJlZ2lvbnMgd2l0aCBlbXB0eSBJRHMuIFBsZWFzZSBzZXQgYSB1bmlxdWUgSUQgYWZ0ZXIgZWFjaCBzdGFydCB0YWcuXFxuRUc6ICc9PT0gbXVsdGktY29sdW1uLXN0YXJ0OiByYW5kb21JRCdcXG5PciB1c2UgJ0ZpeCBNaXNzaW5nIElEcycgaW4gdGhlIGNvbW1hbmQgcGFsZXR0ZSBhbmQgcmVsb2FkIHRoZSBkb2N1bWVudC5cIlxyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgcmVuZGVyRXJyb3JSZWdpb24uaW5uZXJUZXh0ID0gXCJSZWdpb24gSUQgYWxyZWFkeSBleGlzdHMgaW4gZG9jdW1lbnQsIHBsZWFzZSBzZXQgYSB1bmlxdWUgSUQuXFxuRUc6ICc9PT0gbXVsdGktY29sdW1uLXN0YXJ0OiByYW5kb21JRCdcIlxyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgZWwuaWQgPSBgTXVsdGlDb2x1bW5JRDoke3JlZ2lvbktleX1gXHJcbiAgICAgICAgXHJcbiAgICAgICAgICAgIC8vIElmIHNvbWV0aGluZyBjaGFuZ2VzIGluIHRoZSBjb2RlYmxvY2sgd2UgZG9udCBuZWNlc3NhcmlseSB3YW50IHRvIHVwZGF0ZSBvdXJcclxuICAgICAgICAgICAgLy8gb2xkIHJlZmVyZW5jZSB0byB0aGUgcmVnaW9uIG1hbmFnZXIuIFRoaXMgY291bGQgYmUgYSBwb3RlbnRpYWwgYnVnIGFyZWEuXHJcbiAgICAgICAgICAgIGlmKGNyZWF0ZU5ld1JlZ2lvbk1hbmFnZXIgPT09IHRydWUpIHtcclxuICAgICAgICBcclxuICAgICAgICAgICAgICAgIC8vIENyZWF0ZSBhIG5ldyByZWdpb25hbCBtYW5hZ2VyLlxyXG4gICAgICAgICAgICAgICAgbGV0IGVsZW1lbnRNYXJrZG93blJlbmRlcmVyID0gbmV3IE1hcmtkb3duUmVuZGVyQ2hpbGQoZWwpO1xyXG4gICAgICAgICAgICAgICAgZmlsZURPTU1hbmFnZXIuY3JlYXRlUmVnaW9uYWxNYW5hZ2VyKHJlZ2lvbktleSwgZWwsIHJlbmRlckVycm9yUmVnaW9uLCByZW5kZXJDb2x1bW5SZWdpb24pO1xyXG4gICAgICAgIFxyXG4gICAgICAgICAgICAgICAgLy8gU2V0IHVwIHRoZSBvbiB1bmxvYWQgY2FsbGJhY2suIFRoaXMgY2FuIGJlIGNhbGxlZCBpZiB0aGUgdXNlciBjaGFuZ2VzXHJcbiAgICAgICAgICAgICAgICAvLyB0aGUgc3RhcnQvc2V0dGluZ3MgY29kZWJsb2NrIGluIGFueSB3YXkuIFdlIG9ubHkgd2FudCB0byB1bmxvYWRcclxuICAgICAgICAgICAgICAgIC8vIGlmIHRoZSBmaWxlIGlzIGJlaW5nIHJlbW92ZWQgZnJvbSB2aWV3LlxyXG4gICAgICAgICAgICAgICAgZWxlbWVudE1hcmtkb3duUmVuZGVyZXIub251bmxvYWQgPSAoKSA9PiB7XHJcbiAgICAgICAgXHJcbiAgICAgICAgICAgICAgICAgICAgaWYoZmlsZURPTU1hbmFnZXIgJiYgZmlsZVN0aWxsSW5WaWV3KHNvdXJjZVBhdGgpID09PSBmYWxzZSkge1xyXG4gICAgICAgIFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmRlYnVnKFwiRmlsZSBub3QgaW4gYW55IG1hcmtkb3duIGxlYWYuIFJlbW92aW5nIHJlZ2lvbiBmcm9tIGRvbSBtYW5hZ2VyLlwiKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICBmaWxlRE9NTWFuYWdlci5yZW1vdmVSZWdpb24ocmVnaW9uS2V5KTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9O1xyXG4gICAgICAgICAgICAgICAgY3R4LmFkZENoaWxkKGVsZW1lbnRNYXJrZG93blJlbmRlcmVyKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIFxyXG4gICAgICAgICAgICBsZXQgcmVnaW9uYWxNYW5hZ2VyQ29udGFpbmVyID0gZmlsZURPTU1hbmFnZXIuZ2V0UmVnaW9uYWxDb250YWluZXIocmVnaW9uS2V5KTtcclxuICAgICAgICAgICAgaWYocmVnaW9uYWxNYW5hZ2VyQ29udGFpbmVyICE9PSBudWxsKSB7XHJcbiAgICAgICAgXHJcbiAgICAgICAgICAgICAgICBsZXQgcmVnaW9uYWxNYW5hZ2VyID0gcmVnaW9uYWxNYW5hZ2VyQ29udGFpbmVyLnNldFJlZ2lvblNldHRpbmdzKHNvdXJjZSk7XHJcbiAgICAgICAgICAgICAgICByZWdpb25hbE1hbmFnZXIucmVnaW9uUGFyZW50ID0gZWw7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9KVxyXG4gICAgfVxyXG59XHJcblxyXG5cclxuZXhwb3J0IHR5cGUgbmVhcmJ5U2libGluZ3MgPSB7IFxyXG4gICAgc2libGluZ3NBYm92ZTogSFRNTERpdkVsZW1lbnQsXHJcbiAgICBjdXJyZW50T2JqZWN0OiBET01PYmplY3QsIFxyXG59XHJcbmZ1bmN0aW9uIHJlbmRlck1hcmtkb3duRnJvbUxpbmVzKG1kTGluZXM6IHN0cmluZ1tdLCBzb3VyY2VQYXRoOiBzdHJpbmcpOiBIVE1MRGl2RWxlbWVudCB7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBXZSByZS1yZW5kZXIgYWxsIG9mIHRoZSBpdGVtcyBhYm92ZSBvdXIgZWxlbWVudCwgdW50aWwgdGhlIHN0YXJ0IHRhZywgXHJcbiAgICAgKiBzbyB3ZSBjYW4gZGV0ZXJtaW5lIHdoZXJlIHRvIHBsYWNlIHRoZSBuZXcgaXRlbSBpbiB0aGUgbWFuYWdlci5cclxuICAgICAqIFxyXG4gICAgICogVE9ETzogQ2FuIHJlZHVjZSB0aGUgYW1vdW50IG5lZWRpbmcgdG8gYmUgcmVuZGVyZWQgYnkgb25seSByZW5kZXJpbmcgdG9cclxuICAgICAqIHRoZSBzdGFydCB0YWcgb3IgYSBjb2x1bW4tYnJlYWsgd2hpY2hldmVyIGlzIGNsb3Nlci5cclxuICAgICAqL1xyXG4gICAgbGV0IHNpYmxpbmdzID0gY3JlYXRlRGl2KCk7XHJcbiAgICBsZXQgbWFya2Rvd25SZW5kZXJDaGlsZCA9IG5ldyBNYXJrZG93blJlbmRlckNoaWxkKFxyXG4gICAgICAgIHNpYmxpbmdzXHJcbiAgICApO1xyXG4gICAgTWFya2Rvd25SZW5kZXJlci5yZW5kZXJNYXJrZG93bihcclxuICAgICAgICBtZExpbmVzLnJlZHVjZSgocHJldiwgY3VycmVudCkgPT4ge1xyXG4gICAgICAgICAgICByZXR1cm4gcHJldiArIFwiXFxuXCIgICsgY3VycmVudDtcclxuICAgICAgICB9LCBcIlwiKSxcclxuICAgICAgICBzaWJsaW5ncyxcclxuICAgICAgICBzb3VyY2VQYXRoLFxyXG4gICAgICAgIG1hcmtkb3duUmVuZGVyQ2hpbGRcclxuICAgICk7XHJcblxyXG4gICAgcmV0dXJuIHNpYmxpbmdzO1xyXG59XHJcbiJdLCJuYW1lcyI6WyJNYXJrZG93blJlbmRlckNoaWxkIiwiV2lkZ2V0VHlwZSIsIk1hcmtkb3duUmVuZGVyZXIiLCJURmlsZSIsIlN0YXRlRmllbGQiLCJEZWNvcmF0aW9uIiwiUmFuZ2VTZXRCdWlsZGVyIiwic3ludGF4VHJlZSIsInRva2VuQ2xhc3NOb2RlUHJvcCIsIkVkaXRvclZpZXciLCJlZGl0b3JWaWV3RmllbGQiLCJQbHVnaW4iLCJOb3RpY2UiLCJtdWx0aUNvbHVtblBhcnNlci5maW5kU3RhcnRDb2RlYmxvY2siLCJtdWx0aUNvbHVtblBhcnNlci5pc1N0YXJ0VGFnV2l0aElEIiwibXVsdGlDb2x1bW5QYXJzZXIuY29udGFpbnNTdGFydFRhZyIsIm11bHRpQ29sdW1uUGFyc2VyLmNvbnRhaW5zU3RhcnRDb2RlQmxvY2siLCJtdWx0aUNvbHVtblBhcnNlci5nZXRTdGFydEJsb2NrQWJvdmVMaW5lIiwibXVsdGlDb2x1bW5QYXJzZXIuY291bnRTdGFydFRhZ3MiLCJtdWx0aUNvbHVtblBhcnNlci5nZXRTdGFydEJsb2NrT3JDb2RlYmxvY2tBYm92ZUxpbmUiLCJtdWx0aUNvbHVtblBhcnNlci5nZXRFbmRCbG9ja0JlbG93IiwibXVsdGlDb2x1bW5QYXJzZXIuY29udGFpbnNFbmRUYWciLCJtdWx0aUNvbHVtblBhcnNlci5jb250YWluc0NvbEVuZFRhZyIsIm11bHRpQ29sdW1uUGFyc2VyLmNvbnRhaW5zQ29sU2V0dGluZ3NUYWciLCJtdWx0aUNvbHVtblBhcnNlci5nZXRTdGFydFRhZ0tleSJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7O0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQXVEQTtBQUNPLFNBQVMsU0FBUyxDQUFDLE9BQU8sRUFBRSxVQUFVLEVBQUUsQ0FBQyxFQUFFLFNBQVMsRUFBRTtBQUM3RCxJQUFJLFNBQVMsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLE9BQU8sS0FBSyxZQUFZLENBQUMsR0FBRyxLQUFLLEdBQUcsSUFBSSxDQUFDLENBQUMsVUFBVSxPQUFPLEVBQUUsRUFBRSxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRTtBQUNoSCxJQUFJLE9BQU8sS0FBSyxDQUFDLEtBQUssQ0FBQyxHQUFHLE9BQU8sQ0FBQyxFQUFFLFVBQVUsT0FBTyxFQUFFLE1BQU0sRUFBRTtBQUMvRCxRQUFRLFNBQVMsU0FBUyxDQUFDLEtBQUssRUFBRSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxPQUFPLENBQUMsRUFBRSxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUU7QUFDbkcsUUFBUSxTQUFTLFFBQVEsQ0FBQyxLQUFLLEVBQUUsRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxPQUFPLENBQUMsRUFBRSxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUU7QUFDdEcsUUFBUSxTQUFTLElBQUksQ0FBQyxNQUFNLEVBQUUsRUFBRSxNQUFNLENBQUMsSUFBSSxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEdBQUcsS0FBSyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLFFBQVEsQ0FBQyxDQUFDLEVBQUU7QUFDdEgsUUFBUSxJQUFJLENBQUMsQ0FBQyxTQUFTLEdBQUcsU0FBUyxDQUFDLEtBQUssQ0FBQyxPQUFPLEVBQUUsVUFBVSxJQUFJLEVBQUUsQ0FBQyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7QUFDOUUsS0FBSyxDQUFDLENBQUM7QUFDUDs7QUM3RUE7Ozs7OztBQU1HO0FBRUgsSUFBWSxZQU9YLENBQUE7QUFQRCxDQUFBLFVBQVksWUFBWSxFQUFBO0FBQ3BCLElBQUEsWUFBQSxDQUFBLFlBQUEsQ0FBQSxTQUFBLENBQUEsR0FBQSxDQUFBLENBQUEsR0FBQSxTQUFPLENBQUE7QUFDUCxJQUFBLFlBQUEsQ0FBQSxZQUFBLENBQUEsSUFBQSxDQUFBLEdBQUEsQ0FBQSxDQUFBLEdBQUEsSUFBRSxDQUFBO0FBQ0YsSUFBQSxZQUFBLENBQUEsWUFBQSxDQUFBLE1BQUEsQ0FBQSxHQUFBLENBQUEsQ0FBQSxHQUFBLE1BQUksQ0FBQTtBQUNKLElBQUEsWUFBQSxDQUFBLFlBQUEsQ0FBQSxVQUFBLENBQUEsR0FBQSxDQUFBLENBQUEsR0FBQSxVQUFRLENBQUE7QUFDUixJQUFBLFlBQUEsQ0FBQSxZQUFBLENBQUEsS0FBQSxDQUFBLEdBQUEsQ0FBQSxDQUFBLEdBQUEsS0FBRyxDQUFBO0FBQ0gsSUFBQSxZQUFBLENBQUEsWUFBQSxDQUFBLE9BQUEsQ0FBQSxHQUFBLENBQUEsQ0FBQSxHQUFBLE9BQUssQ0FBQTtBQUNULENBQUMsRUFQVyxZQUFZLEtBQVosWUFBWSxHQU92QixFQUFBLENBQUEsQ0FBQSxDQUFBO0FBRUQsSUFBWSxZQU9YLENBQUE7QUFQRCxDQUFBLFVBQVksWUFBWSxFQUFBO0FBQ3BCLElBQUEsWUFBQSxDQUFBLFlBQUEsQ0FBQSxTQUFBLENBQUEsR0FBQSxDQUFBLENBQUEsR0FBQSxTQUFPLENBQUE7QUFDUCxJQUFBLFlBQUEsQ0FBQSxZQUFBLENBQUEsSUFBQSxDQUFBLEdBQUEsQ0FBQSxDQUFBLEdBQUEsSUFBRSxDQUFBO0FBQ0YsSUFBQSxZQUFBLENBQUEsWUFBQSxDQUFBLE1BQUEsQ0FBQSxHQUFBLENBQUEsQ0FBQSxHQUFBLE1BQUksQ0FBQTtBQUNKLElBQUEsWUFBQSxDQUFBLFlBQUEsQ0FBQSxVQUFBLENBQUEsR0FBQSxDQUFBLENBQUEsR0FBQSxVQUFRLENBQUE7QUFDUixJQUFBLFlBQUEsQ0FBQSxZQUFBLENBQUEsS0FBQSxDQUFBLEdBQUEsQ0FBQSxDQUFBLEdBQUEsS0FBRyxDQUFBO0FBQ0gsSUFBQSxZQUFBLENBQUEsWUFBQSxDQUFBLE9BQUEsQ0FBQSxHQUFBLENBQUEsQ0FBQSxHQUFBLE9BQUssQ0FBQTtBQUNULENBQUMsRUFQVyxZQUFZLEtBQVosWUFBWSxHQU92QixFQUFBLENBQUEsQ0FBQSxDQUFBO0FBRUQsSUFBWSxZQVVYLENBQUE7QUFWRCxDQUFBLFVBQVksWUFBWSxFQUFBO0FBQ3BCLElBQUEsWUFBQSxDQUFBLFlBQUEsQ0FBQSxVQUFBLENBQUEsR0FBQSxDQUFBLENBQUEsR0FBQSxVQUFRLENBQUE7QUFDUixJQUFBLFlBQUEsQ0FBQSxZQUFBLENBQUEsTUFBQSxDQUFBLEdBQUEsQ0FBQSxDQUFBLEdBQUEsTUFBSSxDQUFBO0FBQ0osSUFBQSxZQUFBLENBQUEsWUFBQSxDQUFBLE9BQUEsQ0FBQSxHQUFBLENBQUEsQ0FBQSxHQUFBLE9BQUssQ0FBQTtBQUNMLElBQUEsWUFBQSxDQUFBLFlBQUEsQ0FBQSxRQUFBLENBQUEsR0FBQSxDQUFBLENBQUEsR0FBQSxRQUFNLENBQUE7QUFDTixJQUFBLFlBQUEsQ0FBQSxZQUFBLENBQUEsUUFBQSxDQUFBLEdBQUEsQ0FBQSxDQUFBLEdBQUEsUUFBTSxDQUFBO0FBQ04sSUFBQSxZQUFBLENBQUEsWUFBQSxDQUFBLFFBQUEsQ0FBQSxHQUFBLENBQUEsQ0FBQSxHQUFBLFFBQU0sQ0FBQTtBQUNOLElBQUEsWUFBQSxDQUFBLFlBQUEsQ0FBQSxPQUFBLENBQUEsR0FBQSxDQUFBLENBQUEsR0FBQSxPQUFLLENBQUE7QUFDTCxJQUFBLFlBQUEsQ0FBQSxZQUFBLENBQUEsT0FBQSxDQUFBLEdBQUEsQ0FBQSxDQUFBLEdBQUEsT0FBSyxDQUFBO0FBQ0wsSUFBQSxZQUFBLENBQUEsWUFBQSxDQUFBLE1BQUEsQ0FBQSxHQUFBLENBQUEsQ0FBQSxHQUFBLE1BQUksQ0FBQTtBQUNSLENBQUMs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