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.
3624 lines
563 KiB
3624 lines
563 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 = {}));
|
|
var AlignmentType;
|
|
(function (AlignmentType) {
|
|
AlignmentType[AlignmentType["left"] = 0] = "left";
|
|
AlignmentType[AlignmentType["center"] = 1] = "center";
|
|
AlignmentType[AlignmentType["right"] = 2] = "right";
|
|
})(AlignmentType || (AlignmentType = {}));
|
|
function getDefaultMultiColumnSettings() {
|
|
return {
|
|
numberOfColumns: 2,
|
|
columnLayout: ColumnLayout.standard,
|
|
drawBorder: true,
|
|
drawShadow: true,
|
|
autoLayout: false,
|
|
columnSize: SingleColumnSize.medium,
|
|
columnPosition: ColumnLayout.standard,
|
|
columnSpacing: "",
|
|
contentOverflow: ContentOverflowType.scroll,
|
|
alignment: AlignmentType.left
|
|
};
|
|
}
|
|
|
|
/**
|
|
* 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");
|
|
});
|
|
const ALIGNMENT_REGEX_ARR = [
|
|
"alignment",
|
|
"align",
|
|
"content align",
|
|
"align content",
|
|
"text align",
|
|
"align text"
|
|
].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;
|
|
}
|
|
settingsData = getSettingsDataFromKeys(settingsLine, ALIGNMENT_REGEX_ARR);
|
|
if (settingsData !== null) {
|
|
let alignmentType = AlignmentType.left;
|
|
settingsData = settingsData.toLowerCase().trim();
|
|
if (settingsData === "center") {
|
|
alignmentType = AlignmentType.center;
|
|
}
|
|
if (settingsData === "right") {
|
|
alignmentType = AlignmentType.right;
|
|
}
|
|
parsedSettings.alignment = alignmentType;
|
|
}
|
|
}
|
|
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 = ["^===\\s*?column-end\\s*?===\\s*?$",
|
|
"^===\\s*?end-column\\s*?===\\s*?$",
|
|
"^===\\s*?column-break\\s*?===\\s*?$",
|
|
"^===\\s*?break-column\\s*?===\\s*?$",
|
|
"^---\\s*?column-end\\s*?---\\s*?$",
|
|
"^---\\s*?end-column\\s*?---\\s*?$",
|
|
"^---\\s*?column-break\\s*?---\\s*?$",
|
|
"^---\\s*?break-column\\s*?---\\s*?$"];
|
|
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 INNER_COL_END_REGEX_ARR = [
|
|
/^-{3}\s*?column-end\s*?-{3}\s*?$\n?/m,
|
|
/^-{3}\s*?end-column\s*?-{3}\s*?$\n?/m,
|
|
/^-{3}\s*?column-break\s*?-{3}\s*?$\n?/m,
|
|
/^-{3}\s*?break-column\s*?-{3}\s*?$\n?/m,
|
|
/^={3}\s*?column-end\s*?={3}\s*?$\n?/m,
|
|
/^={3}\s*?end-column\s*?={3}\s*?$\n?/m,
|
|
/^={3}\s*?column-break\s*?={3}\s*?$\n?/m,
|
|
/^={3}\s*?break-column\s*?={3}\s*?$\n?/m
|
|
];
|
|
function checkForParagraphInnerColEndTag(text) {
|
|
for (let i = 0; i < INNER_COL_END_REGEX_ARR.length; i++) {
|
|
let regexResult = INNER_COL_END_REGEX_ARR[i].exec(text);
|
|
if (regexResult) {
|
|
return regexResult;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
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 CODEBLOCK_START_REGEX_STR = [
|
|
"multi-column-start",
|
|
"start-multi-column"
|
|
].reduce((prev, cur) => {
|
|
if (prev === "") {
|
|
return cur;
|
|
}
|
|
return `${prev}|${cur}`;
|
|
}, "");
|
|
const START_CODEBLOCK_REGEX = new RegExp(`\`\`\`(:?${CODEBLOCK_START_REGEX_STR})(.*?)\`\`\``, "ms");
|
|
function findStartCodeblock(text) {
|
|
let found = false;
|
|
let startPosition = -1;
|
|
let endPosition = -1;
|
|
let matchLength = 0;
|
|
let regexData = START_CODEBLOCK_REGEX.exec(text);
|
|
if (regexData !== null && regexData.length > 0) {
|
|
found = true;
|
|
startPosition = regexData.index;
|
|
matchLength = regexData[0].length;
|
|
endPosition = startPosition + matchLength;
|
|
}
|
|
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 ||
|
|
isInternalEmbed(element)) {
|
|
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("block-language-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 isInternalEmbed(element) {
|
|
let isEmbed = element.getElementsByClassName("internal-embed").length !== 0;
|
|
return isEmbed;
|
|
}
|
|
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 = [125, 125, 250, 20000];
|
|
const MID_BREAK_ERROR_MESSAGE = "Detected invalid column break syntax.\nPlease make sure column break tags are not in the middle of a paragraph block";
|
|
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 = {}));
|
|
var ElementColumnBreakType;
|
|
(function (ElementColumnBreakType) {
|
|
ElementColumnBreakType[ElementColumnBreakType["none"] = 0] = "none";
|
|
ElementColumnBreakType[ElementColumnBreakType["preBreak"] = 1] = "preBreak";
|
|
ElementColumnBreakType[ElementColumnBreakType["postBreak"] = 2] = "postBreak";
|
|
ElementColumnBreakType[ElementColumnBreakType["midBreak"] = 3] = "midBreak";
|
|
})(ElementColumnBreakType || (ElementColumnBreakType = {}));
|
|
class DOMObject {
|
|
constructor(element, linesOfElement, randomID = getUID(), tag = DOMObjectTag.none) {
|
|
this.clonedElement = null;
|
|
this.elementIsColumnBreak = ElementColumnBreakType.none;
|
|
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();
|
|
}
|
|
// If our tag is still none here, we now want to check for
|
|
// an in paragraph column break flag.
|
|
if (this.tag === DOMObjectTag.none) {
|
|
this.checkForPrePostColumnBreak();
|
|
}
|
|
}
|
|
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);
|
|
}
|
|
}
|
|
checkForPrePostColumnBreak() {
|
|
let textOfElement = this.originalElement.innerText;
|
|
let containsColumnBreak = checkForParagraphInnerColEndTag(textOfElement);
|
|
if (containsColumnBreak !== null) {
|
|
let text = this.originalElement.innerText;
|
|
let startIndex = containsColumnBreak.index;
|
|
let endIndex = startIndex + containsColumnBreak[0].length;
|
|
let pre = text.slice(0, startIndex);
|
|
let post = text.slice(endIndex);
|
|
let paragraph = this.originalElement.children[0];
|
|
if (this.originalElement.nodeName === "P") {
|
|
paragraph = this.originalElement;
|
|
}
|
|
// console.debug("Checking where column break is", startIndex, endIndex, text.length);
|
|
if (startIndex === 0) {
|
|
// console.debug("column break at start of element.")
|
|
this.elementIsColumnBreak = ElementColumnBreakType.preBreak;
|
|
}
|
|
else if (endIndex === text.length) {
|
|
// console.debug("Column break at end of element.")
|
|
this.elementIsColumnBreak = ElementColumnBreakType.postBreak;
|
|
}
|
|
else {
|
|
// console.debug("Column break in the middle of element?")
|
|
this.elementIsColumnBreak = ElementColumnBreakType.midBreak;
|
|
const ERROR_COLOR_CSS = "mcm-error-message-color";
|
|
const CENTER_ALIGN_SPAN_CSS = "mcm-span-content-alignment-center";
|
|
if (paragraph) {
|
|
paragraph.innerHTML = `${pre}\n<span class="${ERROR_COLOR_CSS} ${CENTER_ALIGN_SPAN_CSS}">${MID_BREAK_ERROR_MESSAGE}</span>\n\n${post}`.split("\n").join("<br>");
|
|
}
|
|
return;
|
|
}
|
|
if (paragraph) {
|
|
paragraph.innerText = `${pre}${post}`;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
class TaskListDOMObject extends DOMObject {
|
|
constructor(baseDOMObject) {
|
|
super(baseDOMObject.originalElement, baseDOMObject.linesOfElement, baseDOMObject.UID, DOMObjectTag.none);
|
|
this.originalCheckboxes = [];
|
|
this.checkboxElements = new Map();
|
|
}
|
|
checkboxClicked(index) {
|
|
if (this.checkboxElements.has(index)) {
|
|
this.checkboxElements.get(index).click();
|
|
}
|
|
if (index < this.originalCheckboxes.length) {
|
|
let originalInput = this.originalCheckboxes[index].getElementsByClassName('task-list-item-checkbox');
|
|
if (originalInput.length === 1) {
|
|
originalInput[0].click();
|
|
}
|
|
else {
|
|
console.error("Could not find checkbox to click.");
|
|
}
|
|
}
|
|
}
|
|
getCheckboxElement(index) {
|
|
var _a;
|
|
if (this.checkboxElements.has(index) === false) {
|
|
if (index < this.originalCheckboxes.length) {
|
|
let originalInput = (_a = this.originalCheckboxes[index]) === null || _a === void 0 ? void 0 : _a.getElementsByClassName('task-list-item-checkbox');
|
|
if ((originalInput === null || originalInput === void 0 ? void 0 : originalInput.length) === 1) {
|
|
this.checkboxElements.set(index, originalInput[0]);
|
|
}
|
|
else {
|
|
console.error("Could not find checkbox element to return.", this.originalCheckboxes, index);
|
|
}
|
|
}
|
|
}
|
|
return this.checkboxElements.get(index);
|
|
}
|
|
static checkForTaskListElement(domElement) {
|
|
if (domElement.originalElement.getElementsByClassName("task-list-item").length > 0) {
|
|
return new TaskListDOMObject(domElement);
|
|
}
|
|
return domElement;
|
|
}
|
|
static getChildCheckbox(el) {
|
|
let checkboxElements = el.getElementsByClassName('task-list-item-checkbox');
|
|
if (checkboxElements.length === 1) {
|
|
return checkboxElements[0];
|
|
}
|
|
return el.children[0];
|
|
}
|
|
}
|
|
|
|
/*
|
|
* 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["AlignmentLeft"] = "mcm-content-alignment-left";
|
|
MultiColumnLayoutCSS["AlignmentCenter"] = "mcm-content-alignment-center";
|
|
MultiColumnLayoutCSS["AlignmentRight"] = "mcm-content-alignment-right";
|
|
// ------------------------------------------------------ //
|
|
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 numberOfChildren() {
|
|
return this.domList.length;
|
|
}
|
|
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
|
|
};
|
|
}
|
|
/**
|
|
* Adds a new object to the region by finding where it should be relative to its siblings.
|
|
* @param siblingsAbove The Markdown text rendered elements for sibilings above this element in the dom
|
|
* @param siblingsBelow The Markdown text rendered elements for sibilings below this element in the dom
|
|
* @param obj The object to add.
|
|
* @returns Returns the index at which the object has been added.
|
|
*/
|
|
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;
|
|
}
|
|
addObjectAtIndex(obj, index) {
|
|
this.domList.splice(index, 0, obj);
|
|
this.domObjectMap.set(obj.UID, obj);
|
|
}
|
|
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);
|
|
obj.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) {
|
|
domElement.originalCheckboxes = originalListCheckboxes;
|
|
// 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 = domElement.getCheckboxElement(i);
|
|
checkbox.checked = originalInput === null || originalInput === void 0 ? void 0 : originalInput.checked;
|
|
clonedListCheckboxes[i].replaceChild(checkbox, TaskListDOMObject.getChildCheckbox(clonedListCheckboxes[i]));
|
|
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.", ElementRenderType[domElement.elementType], clonedElementHeight, originalElementHeight)
|
|
// Update clone and reference.
|
|
cloneElement();
|
|
}
|
|
if (domElement.elementType === ElementRenderType.canvasRenderElement &&
|
|
domElement.canvasReadyForUpdate()) {
|
|
// console.log("Updating canvas re-render")
|
|
containerElement.appendChild(originalElement);
|
|
if (clonedElement !== null && clonedElement.parentElement === containerElement) {
|
|
containerElement.removeChild(clonedElement);
|
|
}
|
|
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);
|
|
containerElement.appendChild(clonedElement);
|
|
}
|
|
/**
|
|
* 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) {
|
|
// If a standard element contains a column break tag and it is set as a pre content break tag we flip our index here.
|
|
if (regionElements[i].tag === DOMObjectTag.none &&
|
|
regionElements[i].elementIsColumnBreak === ElementColumnBreakType.preBreak &&
|
|
(columnIndex + 1) < settings.numberOfColumns) {
|
|
columnIndex++;
|
|
}
|
|
// 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);
|
|
}
|
|
if (settings.alignment === AlignmentType.center) {
|
|
element.addClass(MultiColumnLayoutCSS.AlignmentCenter);
|
|
}
|
|
else if (settings.alignment === AlignmentType.right) {
|
|
element.addClass(MultiColumnLayoutCSS.AlignmentRight);
|
|
}
|
|
else {
|
|
element.addClass(MultiColumnLayoutCSS.AlignmentLeft);
|
|
}
|
|
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++;
|
|
}
|
|
else if (regionElements[i].tag === DOMObjectTag.none &&
|
|
regionElements[i].elementIsColumnBreak === ElementColumnBreakType.postBreak &&
|
|
(columnIndex + 1) < settings.numberOfColumns) {
|
|
// If a standard element contains a column break tag and it is set as a post content break tag we flip our index here.
|
|
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;
|
|
if (settings.contentOverflow === ContentOverflowType.hidden) {
|
|
element.addClass(MultiColumnLayoutCSS.ContentOverflowHidden);
|
|
}
|
|
else {
|
|
element.addClass(MultiColumnLayoutCSS.ContentOverflowAutoScroll);
|
|
}
|
|
if (settings.alignment === AlignmentType.center) {
|
|
element.addClass(MultiColumnLayoutCSS.AlignmentCenter);
|
|
}
|
|
else if (settings.alignment === AlignmentType.right) {
|
|
element.addClass(MultiColumnLayoutCSS.AlignmentRight);
|
|
}
|
|
else {
|
|
element.addClass(MultiColumnLayoutCSS.AlignmentLeft);
|
|
}
|
|
// 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;
|
|
if (settings.contentOverflow === ContentOverflowType.hidden) {
|
|
element.addClass(MultiColumnLayoutCSS.ContentOverflowHidden);
|
|
}
|
|
else {
|
|
element.addClass(MultiColumnLayoutCSS.ContentOverflowAutoScroll);
|
|
}
|
|
if (settings.alignment === AlignmentType.center) {
|
|
element.addClass(MultiColumnLayoutCSS.AlignmentCenter);
|
|
}
|
|
else if (settings.alignment === AlignmentType.right) {
|
|
element.addClass(MultiColumnLayoutCSS.AlignmentRight);
|
|
}
|
|
else {
|
|
element.addClass(MultiColumnLayoutCSS.AlignmentLeft);
|
|
}
|
|
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);
|
|
}
|
|
}
|
|
fixExternalLinks(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 embed = null;
|
|
let fixedEl = el;
|
|
// image embeds can either be a <div class="internal-embed" or <p><div class="internal-embed"
|
|
// depending on the syntax this additional check is to fix false negatives when embed is
|
|
// the first case.
|
|
if (el.hasClass("internal-embed")) {
|
|
embed = el;
|
|
}
|
|
else {
|
|
let items = el.getElementsByClassName("internal-embed");
|
|
if (items.length !== 1) {
|
|
return el;
|
|
}
|
|
embed = items[0];
|
|
}
|
|
let customWidth = embed.attributes.getNamedItem("width");
|
|
let alt = embed.getAttr("alt");
|
|
let src = embed.getAttr("src");
|
|
// If the link source is not an image we dont want to make any adjustments.
|
|
if (filenameIsImage(src) === false) {
|
|
return el;
|
|
}
|
|
// Try to find the image file in the vault. This is very inefficient but works for now.
|
|
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 && isImageExtension(file.extension) === true) {
|
|
resourcePath = app.vault.getResourcePath(file);
|
|
break;
|
|
}
|
|
}
|
|
// If we found the resource path then we update the element to be a proper image render.
|
|
if (resourcePath !== "") {
|
|
fixedEl = createDiv({
|
|
cls: "internal-embed image-embed is-loaded",
|
|
});
|
|
fixedEl.setAttr("alt", alt);
|
|
let image = fixedEl.createEl("img");
|
|
image.setAttr("src", resourcePath);
|
|
if (customWidth !== null) {
|
|
image.setAttr("width", customWidth.value);
|
|
}
|
|
}
|
|
return fixedEl;
|
|
}
|
|
function fixExternalLinks(el) {
|
|
let items = el.getElementsByClassName("external-link");
|
|
for (let linkEl of Array.from(items)) {
|
|
let link = linkEl;
|
|
if (link === undefined ||
|
|
link === null) {
|
|
continue;
|
|
}
|
|
// Remove the href from the link and setup an event listener to open the link in the default browser.
|
|
let href = link.getAttr("href");
|
|
link.removeAttribute("href");
|
|
link.addEventListener("click", (ev) => {
|
|
window.open(href);
|
|
});
|
|
}
|
|
items = el.getElementsByClassName("internal-link");
|
|
for (let linkEl of Array.from(items)) {
|
|
let link = linkEl;
|
|
if (link === undefined ||
|
|
link === null) {
|
|
continue;
|
|
}
|
|
// Removing the href from internal links is all that seems to be required to fix the onclick.
|
|
link.removeAttribute("href");
|
|
}
|
|
return el;
|
|
}
|
|
function filenameIsImage(filename) {
|
|
let parts = filename.split(".");
|
|
if (parts.length <= 1) {
|
|
return false;
|
|
}
|
|
let extension = parts.last();
|
|
return isImageExtension(extension);
|
|
}
|
|
function isImageExtension(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 ignoreFurtherIterations = false;
|
|
language.syntaxTree(transaction.state).iterate({
|
|
enter(node) {
|
|
// If we find that the file does not contain any MCM regions we can flip this
|
|
// flag and skip all other node iterations, potentially saving a lot of compute time.
|
|
//
|
|
// 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 (ignoreFurtherIterations === true) {
|
|
return;
|
|
}
|
|
// Check if view is in live preview state.
|
|
if (transaction.state.field(obsidian.editorLivePreviewField) === false) {
|
|
// console.debug("User disabled live preview.")
|
|
ignoreFurtherIterations = true;
|
|
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.")
|
|
ignoreFurtherIterations = true;
|
|
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),
|
|
}));
|
|
}
|
|
ignoreFurtherIterations = 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);
|
|
},
|
|
});
|
|
|
|
/*
|
|
* 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 DEFAULT_SETTINGS = {
|
|
renderOnMobile: true
|
|
};
|
|
const CODEBLOCK_START_STRS = [
|
|
"start-multi-column",
|
|
"multi-column-start"
|
|
];
|
|
class MultiColumnMarkdown extends obsidian.Plugin {
|
|
constructor() {
|
|
super(...arguments);
|
|
this.settings = DEFAULT_SETTINGS;
|
|
this.globalManager = new GlobalDOMManager();
|
|
}
|
|
onload() {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
console.log("Loading multi-column markdown");
|
|
yield this.loadSettings();
|
|
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();
|
|
this.addCommand({
|
|
id: `toggle-mobile-rendering-mcm`,
|
|
name: `Toggle Mobile Rendering - Multi-Column Markdown`,
|
|
callback: () => __awaiter(this, void 0, void 0, function* () {
|
|
this.settings.renderOnMobile = !this.settings.renderOnMobile;
|
|
yield this.saveSettings();
|
|
console.log("render on mobile:", this.settings.renderOnMobile);
|
|
let noticeString = `Toggled mobile rendering ${this.settings.renderOnMobile ? "on" : "off"}.`;
|
|
if (obsidian.Platform.isMobile === true) {
|
|
noticeString += ` Please reload any open files for change to take effect.`;
|
|
}
|
|
new obsidian.Notice(noticeString);
|
|
})
|
|
});
|
|
//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) {
|
|
// Get the text of the settings block so we can check if it contains an ID,
|
|
// also so we can get the length of the first line, used to calculate where to append a new ID if needed
|
|
let settingsText = docText.slice(startCodeblock.startPosition, startCodeblock.endPosition);
|
|
let firstLineOfCodeblockLength = settingsText.split("\n")[0].length;
|
|
// We need the lines before the block to know where to start replacing text
|
|
// and the lines including the block to know where to set our offset to after this iteration.
|
|
let linesBefore = docText.slice(0, startCodeblock.startPosition);
|
|
let startReplacementLineIndex = (linesBefore.split("\n").length - 1) + lineOffset;
|
|
let linesOf = docText.slice(0, startCodeblock.endPosition);
|
|
let endReplacementLineIndex = (linesOf.split("\n").length - 1) + lineOffset;
|
|
let settingsID = parseStartRegionCodeBlockID(settingsText);
|
|
if (settingsID === "") {
|
|
// copy the first line of the codeblock and append a new ID, then replace the first line of the block
|
|
let replacementText = editor.getRange({ line: startReplacementLineIndex, ch: 0 }, { line: startReplacementLineIndex, ch: firstLineOfCodeblockLength }) + `\nID: ID_${getUID(4)}`;
|
|
editor.replaceRange(replacementText, { line: startReplacementLineIndex, ch: 0 }, { line: startReplacementLineIndex, ch: firstLineOfCodeblockLength });
|
|
endReplacementLineIndex += 1;
|
|
numCodeblocksUpdated += 1;
|
|
}
|
|
lineOffset = endReplacementLineIndex;
|
|
docText = docText.slice(startCodeblock.endPosition);
|
|
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* () {
|
|
if (this.settings.renderOnMobile === false &&
|
|
obsidian.Platform.isMobile === true) {
|
|
return;
|
|
}
|
|
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);
|
|
/**
|
|
* 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(textOfElement) === true) {
|
|
currentObject.elementType = ElementRenderType.unRendered;
|
|
el.addClass(MultiColumnStyleCSS.ColumnEndTag);
|
|
regionalManager.updateElementTag(currentObject.UID, DOMObjectTag.columnBreak);
|
|
}
|
|
else if (containsColSettingsTag(textOfElement) === true) {
|
|
currentObject.elementType = ElementRenderType.unRendered;
|
|
el.addClass(MultiColumnStyleCSS.RegionSettings);
|
|
regionalManager = regionalContainer.setRegionSettings(textOfElement);
|
|
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);
|
|
}
|
|
}
|
|
else {
|
|
console.error(`Error getting file from source path: ${sourcePath}`);
|
|
}
|
|
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) {
|
|
// If an old-style start tag.
|
|
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 || regionalContainer.getRegion().numberOfChildren === 0) {
|
|
// If the number of children is 0, we are probably in LivePreview, where the codeblock start regions have been processed by native obsidian live preview but do not have any children linked to them.
|
|
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;
|
|
if (this.settings.renderOnMobile === false &&
|
|
obsidian.Platform.isMobile === true) {
|
|
return;
|
|
}
|
|
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") {
|
|
// This was added when implementing live preview, but the reason it was originally added appears to no longer be an issue.
|
|
// Removing the return from here to fix bug where opening multiple copies of the document causes regions to not render.
|
|
console.debug("Leaf of file is in source mode. Should we be ignoring post processing here?");
|
|
// 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;
|
|
}
|
|
});
|
|
}
|
|
loadSettings() {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
this.settings = Object.assign({}, DEFAULT_SETTINGS, yield this.loadData());
|
|
});
|
|
}
|
|
saveSettings() {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
yield this.saveData(this.settings);
|
|
});
|
|
}
|
|
}
|
|
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/IHJlY2VpdmVyICE9PSBzdGF0ZSB8fCAhZiA6ICFzdGF0ZS5oYXMocmVjZWl2ZXIpKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IHdyaXRlIHByaXZhdGUgbWVtYmVyIHRvIGFuIG9iamVjdCB3aG9zZSBjbGFzcyBkaWQgbm90IGRlY2xhcmUgaXRcIik7XHJcbiAgICByZXR1cm4gKGtpbmQgPT09IFwiYVwiID8gZi5jYWxsKHJlY2VpdmVyLCB2YWx1ZSkgOiBmID8gZi52YWx1ZSA9IHZhbHVlIDogc3RhdGUuc2V0KHJlY2VpdmVyLCB2YWx1ZSkpLCB2YWx1ZTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fY2xhc3NQcml2YXRlRmllbGRJbihzdGF0ZSwgcmVjZWl2ZXIpIHtcclxuICAgIGlmIChyZWNlaXZlciA9PT0gbnVsbCB8fCAodHlwZW9mIHJlY2VpdmVyICE9PSBcIm9iamVjdFwiICYmIHR5cGVvZiByZWNlaXZlciAhPT0gXCJmdW5jdGlvblwiKSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCB1c2UgJ2luJyBvcGVyYXRvciBvbiBub24tb2JqZWN0XCIpO1xyXG4gICAgcmV0dXJuIHR5cGVvZiBzdGF0ZSA9PT0gXCJmdW5jdGlvblwiID8gcmVjZWl2ZXIgPT09IHN0YXRlIDogc3RhdGUuaGFzKHJlY2VpdmVyKTtcclxufVxyXG4iLCIvKlxuICogRmlsZW5hbWU6IG11bHRpLWNvbHVtbi1tYXJrZG93bi9zcmMvcmVnaW9uU2V0dGluZ3MudHNcbiAqIENyZWF0ZWQgRGF0ZTogVHVlc2RheSwgRmVicnVhcnkgMXN0IDIwMjIsIDEyOjIzOjUzIHBtXG4gKiBBdXRob3I6IENhbWVyb24gUm9iaW5zb25cbiAqIFxuICogQ29weXJpZ2h0IChjKSAyMDIyIENhbWVyb24gUm9iaW5zb25cbiAqL1xuXG5leHBvcnQgZW51bSBCb3JkZXJPcHRpb24ge1xuICAgIGVuYWJsZWQsXG4gICAgb24sXG4gICAgdHJ1ZSxcbiAgICBkaXNhYmxlZCxcbiAgICBvZmYsXG4gICAgZmFsc2Vcbn1cblxuZXhwb3J0IGVudW0gU2hhZG93T3B0aW9uIHtcbiAgICBlbmFibGVkLFxuICAgIG9uLFxuICAgIHRydWUsXG4gICAgZGlzYWJsZWQsXG4gICAgb2ZmLFxuICAgIGZhbHNlXG59XG5cbmV4cG9ydCBlbnVtIENvbHVtbkxheW91dCB7IFxuICAgIHN0YW5kYXJkLFxuICAgIGxlZnQsXG4gICAgZmlyc3QsXG4gICAgY2VudGVyLFxuICAgIG1pZGRsZSxcbiAgICBzZWNvbmQsXG4gICAgcmlnaHQsXG4gICAgdGhpcmQsXG4gICAgbGFzdFxufTtcblxuZXhwb3J0IGVudW0gU2luZ2xlQ29sdW1uU2l6ZSB7XG4gICAgc21hbGwsXG4gICAgbWVkaXVtLFxuICAgIGxhcmdlLFxuICAgIGZ1bGxcbn1cblxuZXhwb3J0IGVudW0gQ29udGVudE92ZXJmbG93VHlwZSB7XG4gICAgc2Nyb2xsLFxuICAgIGhpZGRlblxufVxuXG5leHBvcnQgZW51bSBBbGlnbm1lbnRUeXBlIHtcbiAgICBsZWZ0LFxuICAgIGNlbnRlcixcbiAgICByaWdodFxufVxuXG5leHBvcnQgdHlwZSBNdWx0aUNvbHVtblNldHRpbmdzID0ge1xuICAgIG51bWJlck9mQ29sdW1uczogbnVtYmVyLFxuICAgIGNvbHVtbkxheW91dDogQ29sdW1uTGF5b3V0LFxuICAgIGRyYXdCb3JkZXI6IGJvb2xlYW4sXG4gICAgZHJhd1NoYWRvdzogYm9vbGVhbixcbiAgICBhdXRvTGF5b3V0OiBib29sZWFuXG4gICAgY29sdW1uU2l6ZTogU2luZ2xlQ29sdW1uU2l6ZSxcbiAgICBjb2x1bW5Qb3NpdGlvbjogQ29sdW1uTGF5b3V0LFxuICAgIGNvbHVtblNwYWNpbmc6IHN0cmluZyxcbiAgICBjb250ZW50T3ZlcmZsb3c6IENvbnRlbnRPdmVyZmxvd1R5cGUsXG4gICAgYWxpZ25tZW50OiBBbGlnbm1lbnRUeXBlXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXREZWZhdWx0TXVsdGlDb2x1bW5TZXR0aW5ncygpOiBNdWx0aUNvbHVtblNldHRpbmdzIHtcblxuICAgIHJldHVybiB7XG4gICAgICAgIG51bWJlck9mQ29sdW1uczogMixcbiAgICAgICAgY29sdW1uTGF5b3V0OiBDb2x1bW5MYXlvdXQuc3RhbmRhcmQsXG4gICAgICAgIGRyYXdCb3JkZXI6IHRydWUsXG4gICAgICAgIGRyYXdTaGFkb3c6IHRydWUsXG4gICAgICAgIGF1dG9MYXlvdXQ6IGZhbHNlLFxuICAgICAgICBjb2x1bW5TaXplOiBTaW5nbGVDb2x1bW5TaXplLm1lZGl1bSxcbiAgICAgICAgY29sdW1uUG9zaXRpb246IENvbHVtbkxheW91dC5zdGFuZGFyZCxcbiAgICAgICAgY29sdW1uU3BhY2luZzogXCJcIixcbiAgICAgICAgY29udGVudE92ZXJmbG93OiBDb250ZW50T3ZlcmZsb3dUeXBlLnNjcm9sbCxcbiAgICAgICAgYWxpZ25tZW50OiBBbGlnbm1lbnRUeXBlLmxlZnRcbiAgICB9XG59IiwiLyoqXG4gKiBGaWxlOiAvc3JjL3V0aWxpdGllcy9zZXR0aW5nc1BhcnNlci50cyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gKiBDcmVhdGVkIERhdGU6IEZyaWRheSwgSnVuZSAzcmQgMjAyMiwgODoxNiBwbSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gKiBBdXRob3I6IENhbWVyb24gUm9iaW5zb24gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gKiBDb3B5cmlnaHQgKGMpIDIwMjIgQ2FtZXJvbiBSb2JpbnNvbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gKi9cblxuaW1wb3J0IHsgTXVsdGlDb2x1bW5TZXR0aW5ncywgQ29sdW1uTGF5b3V0LCBCb3JkZXJPcHRpb24sIFNoYWRvd09wdGlvbiwgZ2V0RGVmYXVsdE11bHRpQ29sdW1uU2V0dGluZ3MsIFNpbmdsZUNvbHVtblNpemUsIENvbnRlbnRPdmVyZmxvd1R5cGUsIEFsaWdubWVudFR5cGUgfSBmcm9tIFwiLi4vcmVnaW9uU2V0dGluZ3NcIjtcblxuLyoqXG4gKiBIZXJlIHdlIGRlZmluZSBhbGwgb2YgdGhlIHZhbGlkIHNldHRpbmdzIHN0cmluZ3MgdGhhdCB0aGUgdXNlciBjYW4gZW50ZXIgZm9yIGVhY2ggc2V0dGluZyB0eXBlLlxuICogVGhlIHN0cmluZ3MgYXJlIHRoZW4gbWFwcGVkIHR3aWNlLCBmaXJzdCB0byBhIHZhbGlkIHJlZ2V4IHN0cmluZyB0aGF0IHNlYXJjaGVzIGZvciB0aGUgc2V0dGluZ1xuICogbmFtZSwgaWdub3JpbmcgYWxsIGV4dHJhIHNwYWNlcyBhbmQgbGV0dGVyIGNhc2UsIGFuZCB0aGVuIG1hcGVkIHRvIGEgUmVnRXggb2JqZWN0IHRvIGJlIHVzZWQgXG4gKiB3aGVuIHBhcnNpbmcuXG4gKi9cbmNvbnN0IENPTF9QT1NJVElPTl9PUFRJT05fU1RSUzogc3RyaW5nW10gPSBbXG4gICAgXCJjb2x1bW4gcG9zaXRpb25cIixcbiAgICBcImNvbCBwb3NpdGlvblwiLFxuICAgIFwiY29sdW1uIGxvY2F0aW9uXCIsXG4gICAgXCJjb2wgbG9jYXRpb25cIixcbiAgICBcInNpbmdsZSBjb2x1bW4gbG9jYXRpb25cIixcbiAgICBcInNpbmdsZSBjb2x1bW4gcG9zaXRpb25cIixcbl07XG5jb25zdCBDT0xfUE9TSVRJT05fUkVHRVhfQVJSOiBSZWdFeHBbXSA9IENPTF9QT1NJVElPTl9PUFRJT05fU1RSUy5tYXAoY29udmVydFN0cmluZ1RvU2V0dGluZ3NSZWdleCkubWFwKCh2YWx1ZSkgPT4ge1xuICAgIHJldHVybiBuZXcgUmVnRXhwKHZhbHVlLCBcImlcIik7XG59KTtcblxuY29uc3QgQ09MX1NJWkVfT1BUSU9OX1NUUlM6IHN0cmluZ1tdID0gW1xuICAgIFwiY29sdW1uIHNpemVcIixcbiAgICBcImNvbHVtbiB3aWR0aFwiLFxuICAgIFwiY29sIHNpemVcIixcbiAgICBcImNvbCB3aWR0aFwiLFxuICAgIFwic2luZ2xlIGNvbHVtbiBzaXplXCIsXG4gICAgXCJzaW5nbGUgY29sIHNpemVcIixcbiAgICBcInNpbmdsZSBjb2x1bW4gd2lkdGhcIixcbiAgICBcInNpbmdsZSBjb2wgd2lkdGhcIlxuXTtcbmNvbnN0IENPTF9TSVpFX09QVElPTl9SRUdFWF9BUlI6IFJlZ0V4cFtdID0gQ09MX1NJWkVfT1BUSU9OX1NUUlMubWFwKGNvbnZlcnRTdHJpbmdUb1NldHRpbmdzUmVnZXgpLm1hcCgodmFsdWUpID0+IHtcbiAgICByZXR1cm4gbmV3IFJlZ0V4cCh2YWx1ZSwgXCJpXCIpO1xufSk7XG5cbmNvbnN0IE5VTUJFUl9PRl9DT0xVTU5TX1NUUlMgPSBbXG4gICAgXCJudW1iZXIgb2YgY29sdW1uc1wiXG5dXG5jb25zdCBOVU1CRVJfT0ZfQ09MVU1OU19SRUdFWF9BUlI6IFJlZ0V4cFtdID0gTlVNQkVSX09GX0NPTFVNTlNfU1RSUy5tYXAoY29udmVydFN0cmluZ1RvU2V0dGluZ3NSZWdleCkubWFwKCh2YWx1ZSkgPT4ge1xuICAgIHJldHVybiBuZXcgUmVnRXhwKHZhbHVlLCBcImlcIik7XG59KTtcblxuY29uc3QgTEFSR0VTVF9DT0xVTU5fU1RSUyA9IFtcbiAgICBcImxhcmdlc3QgY29sdW1uXCJcbl1cbmNvbnN0IExBUkdFU1RfQ09MVU1OX1JFR0VYX0FSUjogUmVnRXhwW10gPSBMQVJHRVNUX0NPTFVNTl9TVFJTLm1hcChjb252ZXJ0U3RyaW5nVG9TZXR0aW5nc1JlZ2V4KS5tYXAoKHZhbHVlKSA9PiB7XG4gICAgcmV0dXJuIG5ldyBSZWdFeHAodmFsdWUsIFwiaVwiKTtcbn0pO1xuXG5jb25zdCBEUkFXX0JPUkRFUl9TVFJTID0gW1xuICAgIFwiYm9yZGVyXCJcbl1cbmNvbnN0IERSQVdfQk9SREVSX1JFR0VYX0FSUjogUmVnRXhwW10gPSBEUkFXX0JPUkRFUl9TVFJTLm1hcChjb252ZXJ0U3RyaW5nVG9TZXR0aW5nc1JlZ2V4KS5tYXAoKHZhbHVlKSA9PiB7XG4gICAgcmV0dXJuIG5ldyBSZWdFeHAodmFsdWUsIFwiaVwiKTtcbn0pO1xuXG5jb25zdCBEUkFXX1NIQURPV19TVFJTID0gW1xuICAgIFwic2hhZG93XCJcbl1cbmNvbnN0IERSQVdfU0hBRE9XX1JFR0VYX0FSUjogUmVnRXhwW10gPSBEUkFXX1NIQURPV19TVFJTLm1hcChjb252ZXJ0U3RyaW5nVG9TZXR0aW5nc1JlZ2V4KS5tYXAoKHZhbHVlKSA9PiB7XG4gICAgcmV0dXJuIG5ldyBSZWdFeHAodmFsdWUsIFwiaVwiKTtcbn0pO1xuXG5jb25zdCBBVVRPX0xBWU9VVF9TRVRUSU5HX1NUUlMgPSBbXG4gICAgXCJhdXRvIGxheW91dFwiXG5dXG5jb25zdCBBVVRPX0xBWU9VVF9SRUdFWF9BUlI6IFJlZ0V4cFtdID0gQVVUT19MQVlPVVRfU0VUVElOR19TVFJTLm1hcChjb252ZXJ0U3RyaW5nVG9TZXR0aW5nc1JlZ2V4KS5tYXAoKHZhbHVlKSA9PiB7XG4gICAgcmV0dXJuIG5ldyBSZWdFeHAodmFsdWUsIFwiaVwiKTtcbn0pO1xuXG5jb25zdCBDT0xVTU5fU1BBQ0lOR19SRUdFWF9BUlI6IFJlZ0V4cFtdID0gW1xuICAgIFwiY29sdW1uIHNwYWNpbmdcIixcbl0ubWFwKCh2YWx1ZSkgPT4ge1xuICAgIHJldHVybiBuZXcgUmVnRXhwKGNvbnZlcnRTdHJpbmdUb1NldHRpbmdzUmVnZXgodmFsdWUpLCBcImlcIik7XG59KTtcblxuY29uc3QgQ09OVEVOVF9PVkVSRkxPV19SRUdFWF9BUlI6IFJlZ0V4cFtdID0gW1xuICAgIFwib3ZlcmZsb3dcIixcbiAgICBcImNvbnRlbnQgb3ZlcmZsb3dcIlxuXS5tYXAoKHZhbHVlKSA9PiB7XG4gICAgcmV0dXJuIG5ldyBSZWdFeHAoY29udmVydFN0cmluZ1RvU2V0dGluZ3NSZWdleCh2YWx1ZSksIFwiaVwiKVxufSk7XG5cbmNvbnN0IEFMSUdOTUVOVF9SRUdFWF9BUlI6IFJlZ0V4cFtdID0gW1xuICAgIFwiYWxpZ25tZW50XCIsXG4gICAgXCJhbGlnblwiLFxuICAgIFwiY29udGVudCBhbGlnblwiLFxuICAgIFwiYWxpZ24gY29udGVudFwiLFxuICAgIFwidGV4dCBhbGlnblwiLFxuICAgIFwiYWxpZ24gdGV4dFwiXG5dLm1hcCgodmFsdWUpID0+IHtcbiAgICByZXR1cm4gbmV3IFJlZ0V4cChjb252ZXJ0U3RyaW5nVG9TZXR0aW5nc1JlZ2V4KHZhbHVlKSwgXCJpXCIpO1xufSk7XG5cbi8qKlxuICogVGhpcyBmdW5jdGlvbiBzZWFyY2hlcyB0aGUgc2V0dGluZ3Mgc3RyaW5nIHRocm91Z2ggZWFjaCByZWdleCBvcHRpb24uIElmIG9uZSBvZiB0aGUgcmVnZXhcbiAqIHZhbHVlcyBtYXRjaCwgaXQgcmV0dXJucyB0aGUgZmlyc3QgZ3JvdXAgZm91bmQgYnkgdGhlIHJlZ2V4LiBUaGlzIGlzIGRlcGVuZGVkIG9uIHByb3BlclxuICogcmVnZXggZm9ybWF0dGluZyB3aGljaCBpcyBkb25lIGJ5IHRoZSBjb252ZXJ0U3RyaW5nVG9TZXR0aW5nc1JlZ2V4IGZ1bmN0aW9uIGRlZmluZWQgYmVsb3cuXG4gKiBcbiAqIEBwYXJhbSBzZXR0aW5nc1N0cmluZyBUaGUgdmFsdWUgdGhhdCBtYXkgbWF0Y2ggb25lIG9mIHRoZSBzZXR0aW5nIG9wdGlvbnMuXG4gKiBAcGFyYW0gdmFsaWRTZXR0aW5nRm9ybWF0UmVnRXggVGhlIHNldHRpbmdzIG9wdGlvbnMgdGhyb3VnaCB3aGljaCB0byBjaGVjayBhbGwgb3B0aW9ucy4gSWYgb25lIG9mIHRoZXNlIHJlZ2V4IFxuICogdmFsdWVzIG1hdGNoIG9uIHRoZSBzdHJpbmcgd2UgYnJlYWsgZnJvbSB0aGUgbG9vcCByZXR1cm5pbmcgdGhlIGZvdW5kIHZhbHVlLlxuICogXG4gKiBAcmV0dXJucyB0aGUgdXNlciBlbnRlcmVkIGRhdGEgaWYgdGhlIHNldHRpbmcgaXMgYSBtYXRjaCwgb3IgbnVsbCBpZiBub24gb2YgdGhlIG9wdGlvbnMgbWF0Y2hlZC5cbiAqL1xuZnVuY3Rpb24gZ2V0U2V0dGluZ3NEYXRhRnJvbUtleXMoc2V0dGluZ3NTdHJpbmc6IHN0cmluZywgdmFsaWRTZXR0aW5nRm9ybWF0UmVnRXg6IFJlZ0V4cFtdKTogc3RyaW5nIHwgbnVsbCB7XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHZhbGlkU2V0dGluZ0Zvcm1hdFJlZ0V4Lmxlbmd0aDsgaSsrKSB7XG5cbiAgICAgICAgbGV0IHJlZ2V4U2VhcmNoRGF0YSA9IHZhbGlkU2V0dGluZ0Zvcm1hdFJlZ0V4W2ldLmV4ZWMoc2V0dGluZ3NTdHJpbmcpXG4gICAgICAgIGlmKHJlZ2V4U2VhcmNoRGF0YSAhPT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuIHJlZ2V4U2VhcmNoRGF0YVsxXS50cmltKClcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBudWxsO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VTaW5nbGVDb2x1bW5TZXR0aW5ncyhzZXR0aW5nc1N0cjogc3RyaW5nLCBvcmlnaW5hbFNldHRpbmdzOiBNdWx0aUNvbHVtblNldHRpbmdzKTogTXVsdGlDb2x1bW5TZXR0aW5ncyB7XG5cbiAgICBsZXQgc2V0dGluZ3NMaW5lcyA9IHNldHRpbmdzU3RyLnNwbGl0KFwiXFxuXCIpO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2V0dGluZ3NMaW5lcy5sZW5ndGg7IGkrKykge1xuXG4gICAgICAgIGxldCBzZXR0aW5nc0xpbmUgPSBzZXR0aW5nc0xpbmVzW2ldO1xuICAgICAgICBsZXQgc2V0dGluZ3NEYXRhID0gZ2V0U2V0dGluZ3NEYXRhRnJvbUtleXMoc2V0dGluZ3NMaW5lLCBDT0xfUE9TSVRJT05fUkVHRVhfQVJSKTtcbiAgICAgICAgaWYgKHNldHRpbmdzRGF0YSAhPT0gbnVsbCkge1xuXG4gICAgICAgICAgICBvcmlnaW5hbFNldHRpbmdzLmNvbHVtblBvc2l0aW9uID0gcGFyc2VGb3JTaW5nbGVDb2x1bW5Mb2NhdGlvbihzZXR0aW5nc0RhdGEpO1xuICAgICAgICB9XG5cbiAgICAgICAgc2V0dGluZ3NEYXRhID0gZ2V0U2V0dGluZ3NEYXRhRnJvbUtleXMoc2V0dGluZ3NMaW5lLCBDT0xfU0laRV9PUFRJT05fUkVHRVhfQVJSKTtcbiAgICAgICAgaWYgKHNldHRpbmdzRGF0YSAhPT0gbnVsbCkge1xuXG4gICAgICAgICAgICBvcmlnaW5hbFNldHRpbmdzLmNvbHVtblNpemUgPSBwYXJzZUZvclNpbmdsZUNvbHVtblNpemUoc2V0dGluZ3NEYXRhKVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG9yaWdpbmFsU2V0dGluZ3M7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZUNvbHVtblNldHRpbmdzKHNldHRpbmdzU3RyOiBzdHJpbmcpOiBNdWx0aUNvbHVtblNldHRpbmdzIHtcblxuICAgIGxldCBwYXJzZWRTZXR0aW5ncyA9IGdldERlZmF1bHRNdWx0aUNvbHVtblNldHRpbmdzKCk7XG5cbiAgICBsZXQgc2V0dGluZ3NMaW5lcyA9IHNldHRpbmdzU3RyLnNwbGl0KFwiXFxuXCIpO1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzZXR0aW5nc0xpbmVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGxldCBzZXR0aW5nc0xpbmUgPSBzZXR0aW5nc0xpbmVzW2ldO1xuXG4gICAgICAgIGxldCBzZXR0aW5nc0RhdGEgPSBnZXRTZXR0aW5nc0RhdGFGcm9tS2V5cyhzZXR0aW5nc0xpbmUsIE5VTUJFUl9PRl9DT0xVTU5TX1JFR0VYX0FSUik7XG4gICAgICAgIGlmIChzZXR0aW5nc0RhdGEgIT09IG51bGwpIHtcblxuICAgICAgICAgICAgbGV0IG51bU9mQ29scyA9IHBhcnNlSW50KHNldHRpbmdzRGF0YSlcbiAgICAgICAgICAgIGlmIChOdW1iZXIuaXNOYU4obnVtT2ZDb2xzKSA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgICAgICBpZiAobnVtT2ZDb2xzID49IDEgJiYgbnVtT2ZDb2xzIDw9IDMpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyc2VkU2V0dGluZ3MubnVtYmVyT2ZDb2x1bW5zID0gbnVtT2ZDb2xzO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHNldHRpbmdzRGF0YSA9IGdldFNldHRpbmdzRGF0YUZyb21LZXlzKHNldHRpbmdzTGluZSwgTEFSR0VTVF9DT0xVTU5fUkVHRVhfQVJSKVxuICAgICAgICBpZiAoc2V0dGluZ3NEYXRhICE9PSBudWxsKSB7XG5cbiAgICAgICAgICAgIGxldCB1c2VyRGVmTGF5b3V0OiBDb2x1bW5MYXlvdXQgPSAoPGFueT5Db2x1bW5MYXlvdXQpW3NldHRpbmdzRGF0YV07XG4gICAgICAgICAgICBpZiAodXNlckRlZkxheW91dCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgcGFyc2VkU2V0dGluZ3MuY29sdW1uTGF5b3V0ID0gdXNlckRlZkxheW91dDtcbiAgICAgICAgICAgICAgICBwYXJzZWRTZXR0aW5ncy5jb2x1bW5Qb3NpdGlvbiA9IHVzZXJEZWZMYXlvdXQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBzZXR0aW5nc0RhdGEgPSBnZXRTZXR0aW5nc0RhdGFGcm9tS2V5cyhzZXR0aW5nc0xpbmUsIERSQVdfQk9SREVSX1JFR0VYX0FSUilcbiAgICAgICAgaWYgKHNldHRpbmdzRGF0YSAhPT0gbnVsbCkge1xuXG4gICAgICAgICAgICBsZXQgaXNCb3JkZXJEcmF3bjogQm9yZGVyT3B0aW9uID0gKDxhbnk+Qm9yZGVyT3B0aW9uKVtzZXR0aW5nc0RhdGFdO1xuICAgICAgICAgICAgaWYgKGlzQm9yZGVyRHJhd24gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIHN3aXRjaCAoaXNCb3JkZXJEcmF3bikge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIChCb3JkZXJPcHRpb24uZGlzYWJsZWQpOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIChCb3JkZXJPcHRpb24ub2ZmKTpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAoQm9yZGVyT3B0aW9uLmZhbHNlKTpcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhcnNlZFNldHRpbmdzLmRyYXdCb3JkZXIgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHNldHRpbmdzRGF0YSA9IGdldFNldHRpbmdzRGF0YUZyb21LZXlzKHNldHRpbmdzTGluZSwgRFJBV19TSEFET1dfUkVHRVhfQVJSKVxuICAgICAgICBpZiAoc2V0dGluZ3NEYXRhICE9PSBudWxsKSB7XG5cbiAgICAgICAgICAgIGxldCBpc1NoYWRvd0RyYXduOiBTaGFkb3dPcHRpb24gPSAoPGFueT5TaGFkb3dPcHRpb24pW3NldHRpbmdzRGF0YV07XG4gICAgICAgICAgICBpZiAoaXNTaGFkb3dEcmF3biAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgc3dpdGNoIChpc1NoYWRvd0RyYXduKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgKFNoYWRvd09wdGlvbi5kaXNhYmxlZCk6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgKFNoYWRvd09wdGlvbi5vZmYpOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIChTaGFkb3dPcHRpb24uZmFsc2UpOlxuICAgICAgICAgICAgICAgICAgICAgICAgcGFyc2VkU2V0dGluZ3MuZHJhd1NoYWRvdyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgc2V0dGluZ3NEYXRhID0gZ2V0U2V0dGluZ3NEYXRhRnJvbUtleXMoc2V0dGluZ3NMaW5lLCBBVVRPX0xBWU9VVF9SRUdFWF9BUlIpXG4gICAgICAgIGlmIChzZXR0aW5nc0RhdGEgIT09IG51bGwpIHtcblxuICAgICAgICAgICAgaWYoc2V0dGluZ3NEYXRhID09PSBcInRydWVcIikge1xuICAgICAgICAgICAgICAgIHBhcnNlZFNldHRpbmdzLmF1dG9MYXlvdXQgPSB0cnVlXG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBzZXR0aW5nc0RhdGEgPSBnZXRTZXR0aW5nc0RhdGFGcm9tS2V5cyhzZXR0aW5nc0xpbmUsIENPTFVNTl9TUEFDSU5HX1JFR0VYX0FSUik7XG4gICAgICAgIGlmKHNldHRpbmdzRGF0YSAhPT0gbnVsbCkge1xuXG4gICAgICAgICAgICBsZXQgcGFyc2VkID0gZ2V0TGVuZ3RoVW5pdChzZXR0aW5nc0RhdGEudHJpbSgpKTtcbiAgICAgICAgICAgIGxldCBzcGFjaW5nU3RyID0gXCJcIjtcblxuICAgICAgICAgICAgaWYocGFyc2VkLmlzVmFsaWQpIHtcblxuICAgICAgICAgICAgICAgIGxldCBub1VuaXRzU3RyID0gc2V0dGluZ3NEYXRhLnJlcGxhY2UocGFyc2VkLnVuaXRTdHIsIFwiXCIpLnRyaW0oKTtcbiAgICAgICAgICAgICAgICBsZXQgbm9Vbml0c051bSA9IHBhcnNlSW50KG5vVW5pdHNTdHIpO1xuICAgICAgICAgICAgICAgIGlmKGlzTmFOKG5vVW5pdHNOdW0pID09PSBmYWxzZSkge1xuXG4gICAgICAgICAgICAgICAgICAgIHNwYWNpbmdTdHIgPSBgJHtub1VuaXRzU3RyfSR7cGFyc2VkLnVuaXRTdHJ9YFxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgIGxldCBub1VuaXRzTnVtID0gcGFyc2VJbnQoc2V0dGluZ3NEYXRhLnRyaW0oKSk7XG4gICAgICAgICAgICAgICAgaWYoaXNOYU4obm9Vbml0c051bSkgPT09IGZhbHNlKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgc3BhY2luZ1N0ciA9IGAke25vVW5pdHNOdW19cHRgXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBwYXJzZWRTZXR0aW5ncy5jb2x1bW5TcGFjaW5nID0gc3BhY2luZ1N0cjtcbiAgICAgICAgfVxuXG4gICAgICAgIHNldHRpbmdzRGF0YSA9IGdldFNldHRpbmdzRGF0YUZyb21LZXlzKHNldHRpbmdzTGluZSwgQ09OVEVOVF9PVkVSRkxPV19SRUdFWF9BUlIpO1xuICAgICAgICBpZihzZXR0aW5nc0RhdGEgIT09IG51bGwpIHtcblxuICAgICAgICAgICAgbGV0IG92ZXJmbG93VHlwZSA9IENvbnRlbnRPdmVyZmxvd1R5cGUuc2Nyb2xsO1xuXG4gICAgICAgICAgICBzZXR0aW5nc0RhdGEgPSBzZXR0aW5nc0RhdGEudG9Mb3dlckNhc2UoKS50cmltKCk7XG4gICAgICAgICAgICBpZihzZXR0aW5nc0RhdGEgPT09IFwiaGlkZGVuXCIpIHtcbiAgICAgICAgICAgICAgICBvdmVyZmxvd1R5cGUgPSBDb250ZW50T3ZlcmZsb3dUeXBlLmhpZGRlbjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcGFyc2VkU2V0dGluZ3MuY29udGVudE92ZXJmbG93ID0gb3ZlcmZsb3dUeXBlO1xuICAgICAgICB9XG4gICAgICAgIHNldHRpbmdzRGF0YSA9IGdldFNldHRpbmdzRGF0YUZyb21LZXlzKHNldHRpbmdzTGluZSwgQUxJR05NRU5UX1JFR0VYX0FSUik7XG4gICAgICAgIGlmIChzZXR0aW5nc0RhdGEgIT09IG51bGwpIHtcbiAgICAgICAgICAgIGxldCBhbGlnbm1lbnRUeXBlID0gQWxpZ25tZW50VHlwZS5sZWZ0O1xuICAgICAgICAgICAgc2V0dGluZ3NEYXRhID0gc2V0dGluZ3NEYXRhLnRvTG93ZXJDYXNlKCkudHJpbSgpO1xuICAgICAgICAgICAgaWYgKHNldHRpbmdzRGF0YSA9PT0gXCJjZW50ZXJcIikge1xuICAgICAgICAgICAgICAgIGFsaWdubWVudFR5cGUgPSBBbGlnbm1lbnRUeXBlLmNlbnRlcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChzZXR0aW5nc0RhdGEgPT09IFwicmlnaHRcIikge1xuICAgICAgICAgICAgICAgIGFsaWdubWVudFR5cGUgPSBBbGlnbm1lbnRUeXBlLnJpZ2h0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcGFyc2VkU2V0dGluZ3MuYWxpZ25tZW50ID0gYWxpZ25tZW50VHlwZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBwYXJzZWRTZXR0aW5ncztcbn1cblxuZnVuY3Rpb24gZ2V0TGVuZ3RoVW5pdChsZW5ndGhTdHI6IHN0cmluZyk6IHsgaXNWYWxpZDogYm9vbGVhbiwgdW5pdFN0cjogc3RyaW5nIH0ge1xuXG4gICAgbGV0IGxhc3RDaGFyID0gbGVuZ3RoU3RyLnNsaWNlKGxlbmd0aFN0ci5sZW5ndGggLSAxKTtcbiAgICBsZXQgbGFzdFR3b0NoYXJzID0gbGVuZ3RoU3RyLnNsaWNlKGxlbmd0aFN0ci5sZW5ndGggLSAyKTtcblxuICAgIGxldCB1bml0U3RyID0gXCJcIlxuICAgIGxldCBpc1ZhbGlkID0gZmFsc2U7XG4gICAgaWYobGFzdENoYXIgPT09IFwiJVwiKSB7XG4gICAgICAgIHVuaXRTdHIgPSBsYXN0Q2hhcjtcbiAgICAgICAgaXNWYWxpZCA9IHRydWU7XG4gICAgfVxuICAgIGVsc2UgaWYobGFzdFR3b0NoYXJzID09PSBcImNtXCIgfHxcbiAgICAgICAgICAgIGxhc3RUd29DaGFycyA9PT0gXCJtbVwiIHx8XG4gICAgICAgICAgICBsYXN0VHdvQ2hhcnMgPT09IFwiaW5cIiB8fFxuICAgICAgICAgICAgbGFzdFR3b0NoYXJzID09PSBcInB4XCIgfHxcbiAgICAgICAgICAgIGxhc3RUd29DaGFycyA9PT0gXCJwdFwiIHx8XG4gICAgICAgICAgICBsYXN0VHdvQ2hhcnMgPT09IFwicGNcIiB8fFxuICAgICAgICAgICAgbGFzdFR3b0NoYXJzID09PSBcImVtXCIgfHxcbiAgICAgICAgICAgIGxhc3RUd29DaGFycyA9PT0gXCJleFwiIHx8XG4gICAgICAgICAgICBsYXN0VHdvQ2hhcnMgPT09IFwiY2hcIiB8fFxuICAgICAgICAgICAgbGFzdFR3b0NoYXJzID09PSBcInZ3XCIgfHxcbiAgICAgICAgICAgIGxhc3RUd29DaGFycyA9PT0gXCJ2aFwiICkge1xuICAgICAgICB1bml0U3RyID0gbGFzdFR3b0NoYXJzO1xuICAgICAgICBpc1ZhbGlkID0gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4geyBpc1ZhbGlkOiBpc1ZhbGlkLCB1bml0U3RyOiB1bml0U3RyIH1cbn1cblxuY29uc3QgQ09ERUJMT0NLX1JFR0lPTl9JRF9SRUdFWF9TVFJTID0gW1xuICAgIFwiaWRcIixcbiAgICBcInJlZ2lvbiBpZFwiXG5dXG5jb25zdCBDT0RFQkxPQ0tfUkVHSU9OX0lEX1JFR0VYX0FSUjogUmVnRXhwW10gPSBDT0RFQkxPQ0tfUkVHSU9OX0lEX1JFR0VYX1NUUlMubWFwKGNvbnZlcnRTdHJpbmdUb1NldHRpbmdzUmVnZXgpLm1hcCgodmFsdWUpID0+IHtcbiAgICByZXR1cm4gbmV3IFJlZ0V4cCh2YWx1ZSwgXCJpXCIpO1xufSk7XG5leHBvcnQgZnVuY3Rpb24gcGFyc2VTdGFydFJlZ2lvbkNvZGVCbG9ja0lEKHNldHRpbmdzU3RyOiBzdHJpbmcpOiBzdHJpbmcge1xuXG4gICAgbGV0IGNvZGVCbG9ja1JlZ2lvbklEID0gXCJcIlxuICAgIGxldCBzZXR0aW5nc0xpbmVzID0gc2V0dGluZ3NTdHIuc3BsaXQoXCJcXG5cIik7XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNldHRpbmdzTGluZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgbGV0IHNldHRpbmdzTGluZSA9IHNldHRpbmdzTGluZXNbaV07XG5cbiAgICAgICAgbGV0IHNldHRpbmdzRGF0YSA9IGdldFNldHRpbmdzRGF0YUZyb21LZXlzKHNldHRpbmdzTGluZSwgQ09ERUJMT0NLX1JFR0lPTl9JRF9SRUdFWF9BUlIpO1xuICAgICAgICBpZiAoc2V0dGluZ3NEYXRhICE9PSBudWxsKSB7XG5cbiAgICAgICAgICAgIGNvZGVCbG9ja1JlZ2lvbklEID0gc2V0dGluZ3NEYXRhXG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gY29kZUJsb2NrUmVnaW9uSUQ7XG59XG5cbmZ1bmN0aW9uIHBhcnNlRm9yU2luZ2xlQ29sdW1uTG9jYXRpb24obG9jYXRpb25TdHJpbmc6IHN0cmluZyk6IENvbHVtbkxheW91dHtcblxuICAgIHN3aXRjaCAobG9jYXRpb25TdHJpbmcudG9Mb3dlckNhc2UoKS50cmltKCkucmVwbGFjZShcIiBcIiwgXCJcIikpIHtcbiAgICAgICAgY2FzZSBcImxlZnRcIjpcbiAgICAgICAgY2FzZSBcImxlZnRzaWRlXCI6XG4gICAgICAgIGNhc2UgXCJsZWZ0bWFyZ2luXCI6XG4gICAgICAgIGNhc2UgXCJsZWZ0YWxpZ25cIjpcbiAgICAgICAgY2FzZSBcImxlZnRhbGlnbmVkXCI6XG4gICAgICAgIGNhc2UgXCJsZWZ0YWxpZ25lbWVudFwiOlxuICAgICAgICBjYXNlIFwiZmlyc3RcIjpcbiAgICAgICAgY2FzZSBcInN0YXJ0XCI6XG4gICAgICAgIGNhc2UgXCJiZWdpbm5pbmdcIjpcbiAgICAgICAgICAgIHJldHVybiBDb2x1bW5MYXlvdXQubGVmdFxuICAgICAgICBjYXNlIFwibWlkZGxlXCI6XG4gICAgICAgIGNhc2UgXCJtaWRkbGVhbGlnbmVkXCI6XG4gICAgICAgIGNhc2UgXCJtaWRkbGVhbGlnbm1lbnRcIjpcbiAgICAgICAgY2FzZSBcImNlbnRlclwiOlxuICAgICAgICBjYXNlIFwiY2VudGVyYWxpZ25lZFwiOlxuICAgICAgICBjYXNlIFwiY2VudGVyYWxpZ25tZW50XCI6XG4gICAgICAgIGNhc2UgXCJjZW50ZXJlZFwiOlxuICAgICAgICBjYXNlIFwic3RhbmRhcmRcIjpcbiAgICAgICAgICAgIHJldHVybiBDb2x1bW5MYXlvdXQuY2VudGVyXG4gICAgICAgIGNhc2UgXCJyaWdodFwiOlxuICAgICAgICBjYXNlIFwicmlnaHRzaWRlXCI6XG4gICAgICAgIGNhc2UgXCJyaWdodG1hcmdpblwiOlxuICAgICAgICBjYXNlIFwicmlnaHRhbGlnblwiOlxuICAgICAgICBjYXNlIFwicmlnaHRhbGlnbmVkXCI6XG4gICAgICAgIGNhc2UgXCJyaWdodGFsaWdubWVudFwiOlxuICAgICAgICBjYXNlIFwibGFzdFwiOlxuICAgICAgICBjYXNlIFwiZW5kXCI6XG4gICAgICAgICAgICByZXR1cm4gQ29sdW1uTGF5b3V0LnJpZ2h0XG4gICAgfVxuXG4gICAgcmV0dXJuIENvbHVtbkxheW91dC5jZW50ZXJcbn1cblxuZnVuY3Rpb24gcGFyc2VGb3JTaW5nbGVDb2x1bW5TaXplKHNpemVTdHJpbmc6IHN0cmluZyk6IFNpbmdsZUNvbHVtblNpemUge1xuXG4gICAgc3dpdGNoIChzaXplU3RyaW5nID0gc2l6ZVN0cmluZy50b0xvd2VyQ2FzZSgpLnRyaW0oKS5yZXBsYWNlKFwiIFwiLCBcIlwiKSkge1xuICAgICAgICBjYXNlIFwic21hbGxcIjpcbiAgICAgICAgY2FzZSBcInNtXCI6XG4gICAgICAgICAgICByZXR1cm4gU2luZ2xlQ29sdW1uU2l6ZS5zbWFsbDtcbiAgICAgICAgY2FzZSBcIm1lZGl1bVwiOlxuICAgICAgICBjYXNlIFwibWVkXCI6XG4gICAgICAgICAgICByZXR1cm4gU2luZ2xlQ29sdW1uU2l6ZS5tZWRpdW07XG4gICAgICAgIGNhc2UgXCJsYXJnZVwiOlxuICAgICAgICBjYXNlIFwibGdcIjpcbiAgICAgICAgICAgIHJldHVybiBTaW5nbGVDb2x1bW5TaXplLmxhcmdlO1xuICAgICAgICBjYXNlIFwiZnVsbFwiOlxuICAgICAgICBjYXNlIFwiZnVsbCBzaXplXCI6XG4gICAgICAgICAgICByZXR1cm4gU2luZ2xlQ29sdW1uU2l6ZS5mdWxsO1xuICAgIH1cblxuICAgIHJldHVybiBTaW5nbGVDb2x1bW5TaXplLm1lZGl1bVxufVxuXG5mdW5jdGlvbiBjb252ZXJ0U3RyaW5nVG9TZXR0aW5nc1JlZ2V4KG9yaWdpbmFsU3RyaW5nOiBTdHJpbmcpOiBzdHJpbmcge1xuXG4gICAgb3JpZ2luYWxTdHJpbmcgPSBvcmlnaW5hbFN0cmluZy5yZXBsYWNlKFwiIFwiLCBcIiAqXCIpO1xuICAgIFxuICAgIGxldCByZWdleFN0cmluZyA9IGAoPzoke29yaWdpbmFsU3RyaW5nfSAqOiAqKSguKilgO1xuICAgIHJldHVybiByZWdleFN0cmluZztcbn0iLCIvKlxuICogRmlsZTogbXVsdGktY29sdW1uLW1hcmtkb3duL3NyYy9NdWx0aUNvbHVtblBhcnNlci50c1xuICogQ3JlYXRlZCBEYXRlOiBTYXR1cmRheSwgSmFudWFyeSAyMm5kIDIwMjIsIDY6MDI6NDYgcG1cbiAqIEF1dGhvcjogQ2FtZXJvbiBSb2JpbnNvblxuICogXG4gKiBDb3B5cmlnaHQgKGMpIDIwMjIgQ2FtZXJvbiBSb2JpbnNvblxuICovXG5cbmltcG9ydCB7IHBhcnNlU3RhcnRSZWdpb25Db2RlQmxvY2tJRCB9IGZyb20gXCIuL3NldHRpbmdzUGFyc2VyXCI7XG5cbmNvbnN0IFNUQVJUX1JFR0VYX1NUUlMgPSBbXCI9PT0gKnN0YXJ0LW11bHRpLWNvbHVtbig6P1thLXpBLVowLTktX1xcXFxzXSopP1wiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICBcIj09PSAqbXVsdGktY29sdW1uLXN0YXJ0KDo/W2EtekEtWjAtOS1fXFxcXHNdKik/XCJdXG5jb25zdCBTVEFSVF9SRUdFWF9BUlI6IFJlZ0V4cFtdID0gW107XG5mb3IobGV0IGkgPSAwOyBpIDwgU1RBUlRfUkVHRVhfU1RSUy5sZW5ndGg7IGkrKykge1xuICAgIFNUQVJUX1JFR0VYX0FSUi5wdXNoKG5ldyBSZWdFeHAoU1RBUlRfUkVHRVhfU1RSU1tpXSkpO1xufVxuXG5jb25zdCBTVEFSVF9SRUdFWF9TVFJTX1dIT0xFX0xJTkUgPSBbXCJePT09ICpzdGFydC1tdWx0aS1jb2x1bW4oOj9bYS16QS1aMC05LV9cXFxcc10qKT8kXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJePT09ICptdWx0aS1jb2x1bW4tc3RhcnQoOj9bYS16QS1aMC05LV9cXFxcc10qKT8kXCJdXG5jb25zdCBTVEFSVF9SRUdFWF9BUlJfV0hPTEVfTElORTogUmVnRXhwW10gPSBbXTtcbmZvcihsZXQgaSA9IDA7IGkgPCBTVEFSVF9SRUdFWF9TVFJTX1dIT0xFX0xJTkUubGVuZ3RoOyBpKyspIHtcbiAgICBTVEFSVF9SRUdFWF9BUlJfV0hPTEVfTElORS5wdXNoKG5ldyBSZWdFeHAoU1RBUlRfUkVHRVhfU1RSU19XSE9MRV9MSU5FW2ldKSk7XG59XG5cblxuZXhwb3J0IGZ1bmN0aW9uIGZpbmRTdGFydFRhZyh0ZXh0OiBzdHJpbmcpOiB7IGZvdW5kOiBib29sZWFuLCBzdGFydFBvc2l0aW9uOiBudW1iZXIsIGVuZFBvc2l0aW9uOiBudW1iZXIsIG1hdGNoTGVuZ3RoOiBudW1iZXIgfSB7XG5cbiAgICBsZXQgZm91bmQgPSBmYWxzZTtcbiAgICBsZXQgc3RhcnRQb3NpdGlvbiA9IC0xO1xuICAgIGxldCBtYXRjaExlbmd0aCA9IDA7XG4gICAgZm9yKGxldCBpID0gMDsgaTwgU1RBUlRfUkVHRVhfQVJSLmxlbmd0aDsgaSsrKSB7XG5cbiAgICAgICAgbGV0IHJlZ2V4RGF0YSA9IFNUQVJUX1JFR0VYX0FSUltpXS5leGVjKHRleHQpXG4gICAgICAgIGlmKHJlZ2V4RGF0YSAhPT0gbnVsbCAmJiByZWdleERhdGEubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgc3RhcnRQb3NpdGlvbiA9IHJlZ2V4RGF0YS5pbmRleFxuICAgICAgICAgICAgbWF0Y2hMZW5ndGggPSByZWdleERhdGFbMF0ubGVuZ3RoO1xuXG4gICAgICAgICAgICBsZXQgbGluZSA9IHRleHQuc2xpY2Uoc3RhcnRQb3NpdGlvbiwgc3RhcnRQb3NpdGlvbiArIG1hdGNoTGVuZ3RoKTtcbiAgICAgICAgICAgIGlmKFNUQVJUX1JFR0VYX0FSUl9XSE9MRV9MSU5FW2ldLnRlc3QobGluZSkpIHtcbiAgICAgICAgICAgICAgICBmb3VuZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgbGV0IGVuZFBvc2l0aW9uID0gc3RhcnRQb3NpdGlvbiArIG1hdGNoTGVuZ3RoO1xuXG4gICAgcmV0dXJuIHsgZm91bmQsIHN0YXJ0UG9zaXRpb24sIGVuZFBvc2l0aW9uLCBtYXRjaExlbmd0aCB9O1xufVxuZXhwb3J0IGZ1bmN0aW9uIGNvbnRhaW5zU3RhcnRUYWcodGV4dDogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIGZpbmRTdGFydFRhZyh0ZXh0KS5mb3VuZFxufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNTdGFydFRhZ1dpdGhJRCh0ZXh0OiBzdHJpbmcpOiB7aXNTdGFydFRhZzogYm9vbGVhbiwgaGFzS2V5OiBib29sZWFufSB7XG5cbiAgICBsZXQgc3RhcnRUYWdEYXRhID0gZmluZFN0YXJ0VGFnKHRleHQpO1xuICAgIGlmKHN0YXJ0VGFnRGF0YS5mb3VuZCA9PT0gdHJ1ZSkge1xuXG4gICAgICAgIGxldCBrZXkgPSBnZXRTdGFydFRhZ0tleSh0ZXh0KVxuICAgICAgICBpZihrZXkgPT09IG51bGwgfHwga2V5ID09PSBcIlwiKSB7XG4gICAgICAgICAgICByZXR1cm4ge2lzU3RhcnRUYWc6IHRydWUsIGhhc0tleTogZmFsc2V9O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7aXNTdGFydFRhZzogdHJ1ZSwgaGFzS2V5OiB0cnVlfTtcbiAgICB9XG5cbiAgICByZXR1cm4ge2lzU3RhcnRUYWc6IGZhbHNlLCBoYXNLZXk6IGZhbHNlfTtcbn1cblxuY29uc3QgRU5EX1JFR0VYX1NUUlMgPSBbXCI9PT0gKmVuZC1tdWx0aS1jb2x1bW5cIixcbiAgICAgICAgICAgICAgICAgICAgICAgIFwiPT09ICptdWx0aS1jb2x1bW4tZW5kXCJdXG5jb25zdCBFTkRfUkVHRVhfQVJSOiBSZWdFeHBbXSA9IFtdO1xuZm9yKGxldCBpID0gMDsgaSA8IEVORF9SRUdFWF9TVFJTLmxlbmd0aDsgaSsrKSB7XG4gICAgRU5EX1JFR0VYX0FSUi5wdXNoKG5ldyBSZWdFeHAoRU5EX1JFR0VYX1NUUlNbaV0pKTtcbn1cblxudHlwZSBUYWdQb3NpdGlvbmluZ0RhdGEgPSB7XG4gICAgZm91bmQ6IGJvb2xlYW47XG4gICAgc3RhcnRQb3NpdGlvbjogbnVtYmVyO1xuICAgIGVuZFBvc2l0aW9uOiBudW1iZXI7XG4gICAgbWF0Y2hMZW5ndGg6IG51bWJlcjtcbn07XG5cbmV4cG9ydCBmdW5jdGlvbiBmaW5kRW5kVGFnKHRleHQ6IHN0cmluZyk6IFRhZ1Bvc2l0aW9uaW5nRGF0YSB7XG5cbiAgICAvLyBXZSB3YW50IHRvIGZpbmQgdGhlIGZpcnN0IGVuZCB0YWcgaW4gdGhlIHRleHQuXG4gICAgLy8gU28gaGVyZSB3ZSBsb29wIGJhY2t3YXJkcywgc2xpY2luZyBvZmYgdGhlIHRhaWwgdW50aWxcbiAgICAvLyB0aGVyZSBhcmUgbm8gbW9yZSBlbmQgdGFncyBhdmFpbGFibGVcbiAgICBsZXQgbGFzdFZhbGlkRGF0YSA9IGdldEVuZFRhZ0RhdGEodGV4dCk7XG4gICAgbGV0IHdvcmtpbmdSZWdleERhdGEgPSBsYXN0VmFsaWREYXRhO1xuICAgIHdoaWxlKHdvcmtpbmdSZWdleERhdGEuZm91bmQgPT09IHRydWUpIHtcblxuICAgICAgICBsYXN0VmFsaWREYXRhID0gd29ya2luZ1JlZ2V4RGF0YTtcbiAgICAgICAgdGV4dCA9IHRleHQuc2xpY2UoMCwgd29ya2luZ1JlZ2V4RGF0YS5zdGFydFBvc2l0aW9uKTtcbiAgICAgICAgd29ya2luZ1JlZ2V4RGF0YSA9IGdldEVuZFRhZ0RhdGEodGV4dCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGxhc3RWYWxpZERhdGE7XG59XG5leHBvcnQgZnVuY3Rpb24gY29udGFpbnNFbmRUYWcodGV4dDogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIGZpbmRFbmRUYWcodGV4dCkuZm91bmRcbn1cblxuZnVuY3Rpb24gZ2V0RW5kVGFnRGF0YSh0ZXh0OiBzdHJpbmcpIHtcblxuICAgIGxldCBmb3VuZCA9IGZhbHNlO1xuICAgIGxldCBzdGFydFBvc2l0aW9uID0gLTE7XG4gICAgbGV0IGVuZFBvc2l0aW9uID0gLTFcbiAgICBsZXQgbWF0Y2hMZW5ndGggPSAwO1xuICAgIGZvcihsZXQgaSA9IDA7IGk8IEVORF9SRUdFWF9BUlIubGVuZ3RoOyBpKyspIHtcblxuICAgICAgICBsZXQgcmVnZXhEYXRhID0gRU5EX1JFR0VYX0FSUltpXS5leGVjKHRleHQpXG4gICAgICAgIGlmKHJlZ2V4RGF0YSAhPT0gbnVsbCAmJiByZWdleERhdGEubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgZm91bmQgPSB0cnVlO1xuICAgICAgICAgICAgc3RhcnRQb3NpdGlvbiA9IHJlZ2V4RGF0YS5pbmRleFxuICAgICAgICAgICAgbWF0Y2hMZW5ndGggPSByZWdleERhdGFbMF0ubGVuZ3RoO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZW5kUG9zaXRpb24gPSBzdGFydFBvc2l0aW9uICsgbWF0Y2hMZW5ndGg7XG5cbiAgICByZXR1cm4geyBmb3VuZCwgc3RhcnRQb3NpdGlvbiwgZW5kUG9zaXRpb24sIG1hdGNoTGVuZ3RoIH07XG59XG5cbmNvbnN0IENPTF9SRUdFWF9TVFJTOiBzdHJpbmdbXSA9IFtcIl49PT1cXFxccyo/Y29sdW1uLWVuZFxcXFxzKj89PT1cXFxccyo/JFwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiXj09PVxcXFxzKj9lbmQtY29sdW1uXFxcXHMqPz09PVxcXFxzKj8kXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJePT09XFxcXHMqP2NvbHVtbi1icmVha1xcXFxzKj89PT1cXFxccyo/JFwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiXj09PVxcXFxzKj9icmVhay1jb2x1bW5cXFxccyo/PT09XFxcXHMqPyRcIixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIl4tLS1cXFxccyo/Y29sdW1uLWVuZFxcXFxzKj8tLS1cXFxccyo/JFwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiXi0tLVxcXFxzKj9lbmQtY29sdW1uXFxcXHMqPy0tLVxcXFxzKj8kXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJeLS0tXFxcXHMqP2NvbHVtbi1icmVha1xcXFxzKj8tLS1cXFxccyo/JFwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiXi0tLVxcXFxzKj9icmVhay1jb2x1bW5cXFxccyo/LS0tXFxcXHMqPyRcIl07XG5jb25zdCBDT0xfUkVHRVhfQVJSOiBSZWdFeHBbXSA9IFtdO1xuZm9yKGxldCBpID0gMDsgaSA8IENPTF9SRUdFWF9TVFJTLmxlbmd0aDsgaSsrKSB7XG4gICAgQ09MX1JFR0VYX0FSUi5wdXNoKG5ldyBSZWdFeHAoQ09MX1JFR0VYX1NUUlNbaV0pKTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBjb250YWluc0NvbEVuZFRhZyh0ZXh0OiBzdHJpbmcpOiBib29sZWFuIHtcblxuICAgIGxldCBmb3VuZCA9IGZhbHNlO1xuICAgIGZvcihsZXQgaSA9IDA7IGk8IENPTF9SRUdFWF9BUlIubGVuZ3RoOyBpKyspIHtcblxuICAgICAgICBpZihDT0xfUkVHRVhfQVJSW2ldLnRlc3QodGV4dCkpIHtcbiAgICAgICAgICAgIGZvdW5kID0gdHJ1ZTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGZvdW5kO1xufVxuXG5jb25zdCBJTk5FUl9DT0xfRU5EX1JFR0VYX0FSUjogUmVnRXhwW10gPSBbXG4gICAgL14tezN9XFxzKj9jb2x1bW4tZW5kXFxzKj8tezN9XFxzKj8kXFxuPy9tLFxuICAgIC9eLXszfVxccyo/ZW5kLWNvbHVtblxccyo/LXszfVxccyo/JFxcbj8vbSxcbiAgICAvXi17M31cXHMqP2NvbHVtbi1icmVha1xccyo/LXszfVxccyo/JFxcbj8vbSxcbiAgICAvXi17M31cXHMqP2JyZWFrLWNvbHVtblxccyo/LXszfVxccyo/JFxcbj8vbSxcbiAgICAvXj17M31cXHMqP2NvbHVtbi1lbmRcXHMqPz17M31cXHMqPyRcXG4/L20sXG4gICAgL149ezN9XFxzKj9lbmQtY29sdW1uXFxzKj89ezN9XFxzKj8kXFxuPy9tLFxuICAgIC9ePXszfVxccyo/Y29sdW1uLWJyZWFrXFxzKj89ezN9XFxzKj8kXFxuPy9tLFxuICAgIC9ePXszfVxccyo/YnJlYWstY29sdW1uXFxzKj89ezN9XFxzKj8kXFxuPy9tXG5dXG5leHBvcnQgZnVuY3Rpb24gY2hlY2tGb3JQYXJhZ3JhcGhJbm5lckNvbEVuZFRhZyh0ZXh0OiBzdHJpbmcpOiBSZWdFeHBFeGVjQXJyYXkgfCBudWxsIHtcblxuICAgIGZvcihsZXQgaSA9IDA7IGk8IElOTkVSX0NPTF9FTkRfUkVHRVhfQVJSLmxlbmd0aDsgaSsrKSB7XG5cbiAgICAgICAgbGV0IHJlZ2V4UmVzdWx0ID0gSU5ORVJfQ09MX0VORF9SRUdFWF9BUlJbaV0uZXhlYyh0ZXh0KTtcbiAgICAgICAgaWYocmVnZXhSZXN1bHQpIHtcbiAgICAgICAgICAgIHJldHVybiByZWdleFJlc3VsdDtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbn1cblxuY29uc3QgQ09MX0VMRU1FTlRfSU5ORVJfVEVYVF9SRUdFWF9TVFJTOiBzdHJpbmdbXSA9IFtcIj0gKmNvbHVtbi1lbmQgKj1cIixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIj0gKmVuZC1jb2x1bW4gKj1cIixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIj0gKmNvbHVtbi1icmVhayAqPVwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiPSAqYnJlYWstY29sdW1uICo9XCJdXG5jb25zdCBDT0xfRUxFTUVOVF9JTk5FUl9URVhUX1JFR0VYX0FSUjogUmVnRXhwW10gPSBbXTtcbmZvcihsZXQgaSA9IDA7IGkgPCBDT0xfRUxFTUVOVF9JTk5FUl9URVhUX1JFR0VYX1NUUlMubGVuZ3RoOyBpKyspIHtcbiAgICBDT0xfRUxFTUVOVF9JTk5FUl9URVhUX1JFR0VYX0FSUi5wdXNoKG5ldyBSZWdFeHAoQ09MX0VMRU1FTlRfSU5ORVJfVEVYVF9SRUdFWF9TVFJTW2ldKSk7XG59XG5leHBvcnQgZnVuY3Rpb24gZWxJbm5lclRleHRDb250YWluc0NvbEVuZFRhZyh0ZXh0OiBzdHJpbmcpOiBib29sZWFuIHtcblxuICAgIGxldCBmb3VuZCA9IGZhbHNlO1xuICAgIGZvcihsZXQgaSA9IDA7IGk8IENPTF9FTEVNRU5UX0lOTkVSX1RFWFRfUkVHRVhfQVJSLmxlbmd0aDsgaSsrKSB7XG5cbiAgICAgICAgaWYoQ09MX0VMRU1FTlRfSU5ORVJfVEVYVF9SRUdFWF9BUlJbaV0udGVzdCh0ZXh0KSkge1xuICAgICAgICAgICAgZm91bmQgPSB0cnVlO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gZm91bmQ7XG59XG5cbmNvbnN0IENPTF9TRVRUSU5HU19SRUdFWF9TVFJTID0gW1wiYGBgc2V0dGluZ3NcIixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiYGBgY29sdW1uLXNldHRpbmdzXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImBgYG11bHRpLWNvbHVtbi1zZXR0aW5nc1wiXTtcbmNvbnN0IENPTF9TRVRUSU5HU19SRUdFWF9BUlI6IFJlZ0V4cFtdID0gW107XG5mb3IobGV0IGkgPSAwOyBpIDwgQ09MX1NFVFRJTkdTX1JFR0VYX1NUUlMubGVuZ3RoOyBpKyspIHtcbiAgICBDT0xfU0VUVElOR1NfUkVHRVhfQVJSLnB1c2gobmV3IFJlZ0V4cChDT0xfU0VUVElOR1NfUkVHRVhfU1RSU1tpXSkpO1xufVxuZXhwb3J0IGZ1bmN0aW9uIGNvbnRhaW5zQ29sU2V0dGluZ3NUYWcodGV4dDogc3RyaW5nKTogYm9vbGVhbiB7XG5cbiAgICBsZXQgZm91bmQgPSBmYWxzZTtcbiAgICBmb3IobGV0IGkgPSAwOyBpPCBDT0xfU0VUVElOR1NfUkVHRVhfQVJSLmxlbmd0aDsgaSsrKSB7XG5cbiAgICAgICAgaWYoQ09MX1NFVFRJTkdTX1JFR0VYX0FSUltpXS50ZXN0KHRleHQpKSB7XG4gICAgICAgICAgICBmb3VuZCA9IHRydWU7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBmb3VuZDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGZpbmRTZXR0aW5nc0NvZGVibG9jayh0ZXh0OiBzdHJpbmcpOiB7IGZvdW5kOiBib29sZWFuLCBzdGFydFBvc2l0aW9uOiBudW1iZXIsIGVuZFBvc2l0aW9uOiBudW1iZXIsIG1hdGNoTGVuZ3RoOiBudW1iZXIgfSB7XG5cbiAgICBsZXQgZm91bmQgPSBmYWxzZTtcbiAgICBsZXQgc3RhcnRQb3NpdGlvbiA9IC0xO1xuICAgIGxldCBlbmRQb3NpdGlvbiA9IC0xXG4gICAgbGV0IG1hdGNoTGVuZ3RoID0gMDtcbiAgICBmb3IobGV0IGkgPSAwOyBpPCBDT0xfU0VUVElOR1NfUkVHRVhfQVJSLmxlbmd0aDsgaSsrKSB7XG5cbiAgICAgICAgbGV0IHJlZ2V4RGF0YSA9IENPTF9TRVRUSU5HU19SRUdFWF9BUlJbaV0uZXhlYyh0ZXh0KVxuICAgICAgICBpZihyZWdleERhdGEgIT09IG51bGwgJiYgcmVnZXhEYXRhLmxlbmd0aCA+IDApIHtcblxuICAgICAgICAgICAgZm91bmQgPSB0cnVlO1xuICAgICAgICAgICAgc3RhcnRQb3NpdGlvbiA9IHJlZ2V4RGF0YS5pbmRleFxuICAgICAgICAgICAgbWF0Y2hMZW5ndGggPSByZWdleERhdGFbMF0ubGVuZ3RoO1xuICAgICAgICAgICAgZW5kUG9zaXRpb24gPSBzdGFydFBvc2l0aW9uICsgbWF0Y2hMZW5ndGg7XG5cbiAgICAgICAgICAgIGxldCByZW1haW5pbmdUZXh0ID0gdGV4dC5zbGljZShlbmRQb3NpdGlvbilcbiAgICAgICAgICAgIHJlZ2V4RGF0YSA9IENPREVCTE9DS19FTkRfUkVHRVguZXhlYyhyZW1haW5pbmdUZXh0KVxuICAgICAgICAgICAgaWYocmVnZXhEYXRhICE9PSBudWxsICYmIHJlZ2V4RGF0YS5sZW5ndGggPiAwKSB7XG5cbiAgICAgICAgICAgICAgICBmb3VuZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgZW5kUG9zaXRpb24gKz0gcmVnZXhEYXRhLmluZGV4ICsgcmVnZXhEYXRhWzBdLmxlbmd0aCBcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHsgZm91bmQsIHN0YXJ0UG9zaXRpb24sIGVuZFBvc2l0aW9uLCBtYXRjaExlbmd0aCB9O1xufVxuXG5jb25zdCBDT0RFQkxPQ0tfU1RBUlRfUkVHRVhfU1RSOiBzdHJpbmcgPSBbXG5cIm11bHRpLWNvbHVtbi1zdGFydFwiLFxuXCJzdGFydC1tdWx0aS1jb2x1bW5cIlxuXS5yZWR1Y2UoKHByZXYsIGN1cikgPT4ge1xuICAgIGlmKHByZXYgPT09IFwiXCIpIHtcbiAgICAgICAgcmV0dXJuIGN1cjtcbiAgICB9XG4gICAgcmV0dXJuIGAke3ByZXZ9fCR7Y3VyfWA7XG59LCBcIlwiKVxuY29uc3QgU1RBUlRfQ09ERUJMT0NLX1JFR0VYOiBSZWdFeHAgPSBuZXcgUmVnRXhwKGBcXGBcXGBcXGAoOj8ke0NPREVCTE9DS19TVEFSVF9SRUdFWF9TVFJ9KSguKj8pXFxgXFxgXFxgYCwgXCJtc1wiKTtcblxuZXhwb3J0IGZ1bmN0aW9uIGZpbmRTdGFydENvZGVibG9jayh0ZXh0OiBzdHJpbmcpOiB7IGZvdW5kOiBib29sZWFuLCBzdGFydFBvc2l0aW9uOiBudW1iZXIsIGVuZFBvc2l0aW9uOiBudW1iZXIsIG1hdGNoTGVuZ3RoOiBudW1iZXIgfSB7XG5cbiAgICBsZXQgZm91bmQgPSBmYWxzZTtcbiAgICBsZXQgc3RhcnRQb3NpdGlvbiA9IC0xO1xuICAgIGxldCBlbmRQb3NpdGlvbiA9IC0xXG4gICAgbGV0IG1hdGNoTGVuZ3RoID0gMDtcblxuICAgIGxldCByZWdleERhdGEgPSBTVEFSVF9DT0RFQkxPQ0tfUkVHRVguZXhlYyh0ZXh0KVxuICAgIGlmKHJlZ2V4RGF0YSAhPT0gbnVsbCAmJiByZWdleERhdGEubGVuZ3RoID4gMCkge1xuXG4gICAgICAgIGZvdW5kID0gdHJ1ZTtcbiAgICAgICAgc3RhcnRQb3NpdGlvbiA9IHJlZ2V4RGF0YS5pbmRleFxuICAgICAgICBtYXRjaExlbmd0aCA9IHJlZ2V4RGF0YVswXS5sZW5ndGg7XG4gICAgICAgIGVuZFBvc2l0aW9uID0gc3RhcnRQb3NpdGlvbiArIG1hdGNoTGVuZ3RoO1xuICAgIH1cblxuICAgIHJldHVybiB7IGZvdW5kLCBzdGFydFBvc2l0aW9uLCBlbmRQb3NpdGlvbiwgbWF0Y2hMZW5ndGggfTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBjb250YWluc1N0YXJ0Q29kZUJsb2NrKHRleHQ6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBmaW5kU3RhcnRDb2RlYmxvY2sodGV4dCkuZm91bmRcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNvbnRhaW5zUmVnaW9uU3RhcnQodGV4dDogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIGNvbnRhaW5zU3RhcnRDb2RlQmxvY2sodGV4dCkgfHwgY29udGFpbnNTdGFydFRhZyh0ZXh0KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNvdW50U3RhcnRUYWdzKGluaXRpYWxUZXh0OiBzdHJpbmcpOiB7IG51bWJlck9mVGFnczogbnVtYmVyLCBrZXlzOiBzdHJpbmdbXSB9IHtcblxuICAgIGxldCBrZXlzOiBzdHJpbmdbXSA9IFtdO1xuICAgIGxldCB0ZXh0ID0gaW5pdGlhbFRleHRcbiAgICBsZXQgc3RhcnRUYWdEYXRhID0gZmluZFN0YXJ0VGFnKHRleHQpO1xuICAgIHdoaWxlKHN0YXJ0VGFnRGF0YS5mb3VuZCkge1xuICAgICAgICBcbiAgICAgICAgLy8gU2xpY2Ugb2ZmIGV2ZXJ5dGhpbmcgYmVmb3JlIHRoZSB0YWdcbiAgICAgICAgdGV4dCA9IHRleHQuc2xpY2Uoc3RhcnRUYWdEYXRhLnN0YXJ0UG9zaXRpb24pO1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBHZXQganVzdCB0aGUgc3RhcnQgdGFnIGxpbmUgYW5kIHRoZW4gc2V0IHRleHQgdG8gZXZlcnl0aGluZyBqdXN0XG4gICAgICAgICAqIGFmdGVyIHRoZSBzdGFydCB0YWcuXG4gICAgICAgICAqL1xuICAgICAgICBsZXQgdGFnID0gdGV4dC5zcGxpdChcIlxcblwiKVswXTtcbiAgICAgICAgdGV4dCA9IHRleHQuc2xpY2UoMSk7IC8vIFRoaXMgbW92ZXMgdGhlIHRleHQgMSBjaGFyYWN0ZXIgc28gd2UgZG9udCBtYXRjaCB0aGUgc2FtZSB0YWcuXG5cbiAgICAgICAgLy8gUGFyc2Ugb3V0IHRoZSBrZXkgYW5kIGFwcGVuZCB0byB0aGUgbGlzdC5cbiAgICAgICAgbGV0IGtleSA9IGdldFN0YXJ0VGFnS2V5KHRhZyk7XG4gICAgICAgIGlmKGtleSA9PT0gbnVsbCkge1xuICAgICAgICAgICAga2V5ID0gXCJcIlxuICAgICAgICB9XG4gICAgICAgIGtleXMucHVzaChrZXkpO1xuXG4gICAgICAgIC8vIFNlYXJjaCBhZ2FpbiBmb3IgYW5vdGhlciB0YWcgYmVmb3JlIGxvb3BpbmcuXG4gICAgICAgIHN0YXJ0VGFnRGF0YSA9IGZpbmRTdGFydFRhZyh0ZXh0KTtcbiAgICB9XG5cbiAgICB0ZXh0ID0gaW5pdGlhbFRleHQ7XG4gICAgc3RhcnRUYWdEYXRhID0gZmluZFN0YXJ0Q29kZWJsb2NrKHRleHQpO1xuICAgIHdoaWxlKHN0YXJ0VGFnRGF0YS5mb3VuZCkge1xuICAgICAgICBcbiAgICAgICAgbGV0IHNldHRpbmdzVGV4dCA9IHRleHQuc2xpY2Uoc3RhcnRUYWdEYXRhLnN0YXJ0UG9zaXRpb24sIHN0YXJ0VGFnRGF0YS5lbmRQb3NpdGlvbik7XG4gICAgICAgIHRleHQgPSB0ZXh0LnNsaWNlKHN0YXJ0VGFnRGF0YS5lbmRQb3NpdGlvbik7XG5cbiAgICAgICAgbGV0IGtleSA9IHBhcnNlU3RhcnRSZWdpb25Db2RlQmxvY2tJRChzZXR0aW5nc1RleHQpO1xuICAgICAgICBpZihrZXkgPT09IG51bGwpIHtcbiAgICAgICAgICAgIGtleSA9IFwiXCJcbiAgICAgICAgfVxuICAgICAgICBrZXlzLnB1c2goa2V5KTtcblxuICAgICAgICAvLyBTZWFyY2ggYWdhaW4gZm9yIGFub3RoZXIgdGFnIGJlZm9yZSBsb29waW5nLlxuICAgICAgICBzdGFydFRhZ0RhdGEgPSBmaW5kU3RhcnRDb2RlYmxvY2sodGV4dCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHsgbnVtYmVyT2ZUYWdzOiBrZXlzLmxlbmd0aCwga2V5cyB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0U3RhcnRCbG9ja09yQ29kZWJsb2NrQWJvdmVMaW5lKGxpbmVzQWJvdmVBcnJheTogc3RyaW5nW10pOiB7IFxuc3RhcnRCbG9ja0tleTogc3RyaW5nLCBcbmxpbmVzQWJvdmVBcnJheTogc3RyaW5nW10gfSB8IG51bGwge1xuXG4gICAgbGV0IHN0YXJ0QmxvY2sgPSBnZXRTdGFydEJsb2NrQWJvdmVMaW5lKGxpbmVzQWJvdmVBcnJheSk7XG4gICAgaWYoc3RhcnRCbG9jayAhPT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gc3RhcnRCbG9jaztcbiAgICB9XG5cbiAgICBsZXQgY29kZUJsb2NrID0gZ2V0U3RhcnRDb2RlQmxvY2tBYm92ZUxpbmUobGluZXNBYm92ZUFycmF5KVxuICAgIGlmKGNvZGVCbG9jayAhPT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gY29kZUJsb2NrO1xuICAgIH1cbiAgICByZXR1cm4gbnVsbFxufVxuXG4vKipcbiAqIFRoaXMgZnVuY3Rpb24gd2lsbCBmaWx0ZXIgYSBzZXQgb2Ygc3RyaW5ncywgcmV0dXJuaW5nIGFsbCBpdGVtcyBzdGFydGluZ1xuICogZnJvbSB0aGUgY2xvc2VzdCBvcGVuIHN0YXJ0IHRhZyB0aHJvdWdoIHRoZSBsYXN0IGl0ZW0gaW4gdGhlIHNldC4gXG4gKiBcbiAqIFRoZSBmdW5jdGlvbiBmaWx0ZXJzIG91dCBhbGwgZW5kIHRhZ3MgdG8gbWFrZSBzdXJlIHRoYXQgdGhlIHN0YXJ0IHRhZyB3ZSBcbiAqIGZpbmQgaXMgdGhlIHByb3BlciBzdGFydCB0YWcgZm9yIHRoZSBsaXN0IHNlbnQuIFxuICogQHBhcmFtIGxpbmVzQWJvdmVBcnJheSBcbiAqIEByZXR1cm5zIFxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0U3RhcnRCbG9ja0Fib3ZlTGluZShsaW5lc0Fib3ZlQXJyYXk6IHN0cmluZ1tdKTogeyBzdGFydEJsb2NrS2V5OiBzdHJpbmcsIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5lc0Fib3ZlQXJyYXk6IHN0cmluZ1tdIH0gfCBudWxsIHtcblxuICAgIC8vIFJlZHVjZSB0aGUgYXJyYXkgZG93biBpbnRvIGEgc2luZ2xlIHN0cmluZyBzbyB0aGF0IHdlIGNhblxuICAgIC8vIGVhc2lseSBSZWdFeCBvdmVyIHRoZSBzdHJpbmcgYW5kIGZpbmQgdGhlIGluZGljaWVzIHdlJ3JlIGxvb2tpbmcgZm9yLlxuICAgIGxldCBsaW5lc0Fib3ZlU3RyID0gbGluZXNBYm92ZUFycmF5LnJlZHVjZSgocHJldiwgY3VycmVudCkgPT4ge1xuICAgICAgICByZXR1cm4gcHJldiArIFwiXFxuXCIgICsgY3VycmVudDtcbiAgICB9LCBcIlwiKTtcblxuICAgIC8qXG4gICAgICAgICogRmlyc3QgdGhpbmcgd2UgbmVlZCB0byBkbyBpcyBjaGVjayBpZiB0aGVyZSBhcmUgYW55IGVuZCB0YWdzIGluIHRoZVxuICAgICAgICAqIHNldCBvZiBzdHJpbmdzICh3aGljaCBsb2dpY2FsbHkgd291bGQgY2xvc2Ugc3RhcnQgdGFncyBhbmQgdGhlcmVmb3JlXG4gICAgICAgICogdGhlIHN0YXJ0IHRhZyBpdCBjbG9zZXMgaXMgbm90IHdoYXQgd2Ugd2FudCkuIElmIHRoZXJlIGFyZSB3ZSB3YW50IHRvIFxuICAgICAgICAqIHNsb3dseSBuYXJyb3cgZG93biBvdXIgc2V0IG9mIHN0cmluZ3MgdW50aWwgdGhlIGxhc3QgZW5kIHRhZyBpcyBcbiAgICAgICAgKiByZW1vdmVkLiBUaGlzIG1ha2VzIGl0IGVhc2llciB0byBmaW5kIHRoZSBjbG9zZXN0IG9wZW4gc3RhcnQgdGFnIFxuICAgICAgICAqIGluIHRoZSBkYXRhLlxuICAgICAgICAqL1xuICAgIGxldCBlbmRUYWdTZXJhY2hEYXRhID0gZmluZEVuZFRhZyhsaW5lc0Fib3ZlU3RyKTtcbiAgICB3aGlsZShlbmRUYWdTZXJhY2hEYXRhLmZvdW5kID09PSB0cnVlKSB7XG5cbiAgICAgICAgLy8gR2V0IHRoZSBpbmRleCBvZiB3aGVyZSB0aGUgZmlyc3QgcmVnZXggbWF0Y2ggaW4gdGhlXG4gICAgICAgIC8vIHN0cmluZyBpcy4gdGhlbiB3ZSBzbGljZSBmcm9tIDAgdG8gaW5kZXggb2ZmIG9mIHRoZSBzdHJpbmdcbiAgICAgICAgLy8gc3BsaXQgaXQgYnkgbmV3bGluZSwgY3V0IG9mZiB0aGUgZmlyc3QgbGluZSAod2hpY2ggYWN0dWFsbHlcbiAgICAgICAgLy8gY29udGFpbnMgdGhlIHJlZ2V4KSB0aGVuIHJlZHVjZSBiYWNrIGRvd24gdG8gYSBzaW5nbGUgc3RyaW5nLlxuICAgICAgICAvL1xuICAgICAgICAvLyBUT0RPOiBUaGlzIGNvdWxkIGJlIHNpbXBsaWZpZWQgaWYgd2UganVzdCBzbGljZSB0aGUgdGV4dCBhZnRlclxuICAgICAgICAvLyB0aGUgZW5kIHRhZyBpbnN0ZWFkIG9mIHRoZSBiZWdpbmluZy5cbiAgICAgICAgbGV0IGluZGV4T2ZSZWdleCA9IGVuZFRhZ1NlcmFjaERhdGEuc3RhcnRQb3NpdGlvbjtcbiAgICAgICAgbGluZXNBYm92ZUFycmF5ID0gbGluZXNBYm92ZVN0ci5zbGljZShpbmRleE9mUmVnZXgpLnNwbGl0KFwiXFxuXCIpLnNwbGljZSgxKVxuICAgICAgICBsaW5lc0Fib3ZlU3RyID0gbGluZXNBYm92ZUFycmF5LnJlZHVjZSgocHJldiwgY3VycmVudCkgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIHByZXYgKyBcIlxcblwiICArIGN1cnJlbnQ7XG4gICAgICAgIH0sIFwiXCIpO1xuICAgICAgICBlbmRUYWdTZXJhY2hEYXRhID0gZmluZEVuZFRhZyhsaW5lc0Fib3ZlU3RyKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBOb3cgd2UgaGF2ZSB0aGUgc2V0IG9mIGxpbmVzIGFmdGVyIGFsbCBvdGhlciBlbmQgdGFncy4gV2Ugbm93XG4gICAgICogbmVlZCB0byBjaGVjayBpZiB0aGVyZSBpcyBzdGlsbCBhIHN0YXJ0IHRhZyBsZWZ0IGluIHRoZSBkYXRhLiBJZiBcbiAgICAgKiB0aGVyZSBpcyBubyBzdGFydCB0YWcgdGhlbiB3ZSB3YW50IHRvIHJldHVybiBhbiBlbXB0eSBhcnJheSBhbmQgZW1wdHkgXG4gICAgICoga2V5LlxuICAgICAqLyBcbiAgICBsZXQgc3RhcnRCbG9ja0tleSA9IFwiXCI7XG4gICAgbGV0IHN0YXJ0VGFnU2VhcmNoRGF0YSA9IGZpbmRTdGFydFRhZyhsaW5lc0Fib3ZlU3RyKTtcbiAgICBpZihzdGFydFRhZ1NlYXJjaERhdGEuZm91bmQgPT09IGZhbHNlKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICBlbHNlIHtcblxuICAgICAgICAvKipcbiAgICAgICAgICogTm93IHdlIGtub3cgdGhlcmUgaXMgYXQgbGVhc3QgMSBzdGFydCBrZXkgbGVmdCwgaG93ZXZlciB0aGVyZVxuICAgICAgICAgKiBtYXkgYmUgbXVsdGlwbGUgc3RhcnQga2V5cyBpZiB0aGUgdXNlciBpcyBub3QgY2xvc2luZyB0aGVpclxuICAgICAgICAgKiBibG9ja3MuIFdlIGN1cnJlbnRseSBkb250IGFsbG93IHJlY3VzaXZlIHNwbGl0dGluZyBzbyB3ZSBcbiAgICAgICAgICogd2FudCB0byBnZXQgdGhlIGxhc3Qga2V5IGluIG91ciByZW1haW5pbmcgc2V0LiBTYW1lIGlkZWEgYXNcbiAgICAgICAgICogYWJvdmUuXG4gICAgICAgICAqL1xuICAgICAgICB3aGlsZShzdGFydFRhZ1NlYXJjaERhdGEuZm91bmQgPT09IHRydWUpIHtcblxuICAgICAgICAgICAgLy8gR2V0IHRoZSBpbmRleCBvZiB3aGVyZSB0aGUgZmlyc3QgcmVnZXggbWF0Y2ggaW4gdGhlXG4gICAgICAgICAgICAvLyBzdHJpbmcgaXMuIHRoZW4gd2Ugc2xpY2UgZnJvbSAwIHRvIGluZGV4IG9mZiBvZiB0aGUgc3RyaW5nXG4gICAgICAgICAgICAvLyBzcGxpdCBpdCBieSBuZXdsaW5lLCBjdXQgb2ZmIHRoZSBmaXJzdCBsaW5lICh3aGljaCBhY3R1YWxseVxuICAgICAgICAgICAgLy8gY29udGFpbnMgdGhlIHJlZ2V4KSB0aGVuIHJlZHVjZSBiYWNrIGRvd24gdG8gYSBzaW5nbGUgc3RyaW5nLlxuICAgICAgICAgICAgLy9cbiAgICAgICAgICAgIC8vIFRPRE86IFRoaXMgY291bGQgYmUgc2ltcGxpZmllZCBpZiB3ZSBqdXN0IHNsaWNlIHRoZSB0ZXh0IGFmdGVyXG4gICAgICAgICAgICAvLyB0aGUgZW5kIHRhZyBpbnN0ZWFkIG9mIHRoZSBiZWdpbmluZy5cbiAgICAgICAgICAgIGxldCBzdGFydEluZGV4ID0gc3RhcnRUYWdTZWFyY2hEYXRhLnN0YXJ0UG9zaXRpb247XG5cbiAgICAgICAgICAgIGxpbmVzQWJvdmVBcnJheSA9IGxpbmVzQWJvdmVTdHIuc2xpY2Uoc3RhcnRJbmRleCkuc3BsaXQoXCJcXG5cIilcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgbGV0IHN0YXJ0VGFnID0gbGluZXNBYm92ZUFycmF5WzBdO1xuICAgICAgICAgICAgbGV0IGtleSA9IGdldFN0YXJ0VGFnS2V5KHN0YXJ0VGFnKTtcbiAgICAgICAgICAgIGlmKGtleSAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHN0YXJ0QmxvY2tLZXkgPSBrZXk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGxpbmVzQWJvdmVBcnJheSA9IGxpbmVzQWJvdmVBcnJheS5zcGxpY2UoMSlcbiAgICAgICAgICAgIGxpbmVzQWJvdmVTdHIgPSBsaW5lc0Fib3ZlQXJyYXkucmVkdWNlKChwcmV2LCBjdXJyZW50KSA9PiB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHByZXYgKyBcIlxcblwiICArIGN1cnJlbnQ7XG4gICAgICAgICAgICB9LCBcIlwiKTtcblxuICAgICAgICAgICAgc3RhcnRUYWdTZWFyY2hEYXRhID0gZmluZFN0YXJ0VGFnKGxpbmVzQWJvdmVTdHIpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYoc3RhcnRCbG9ja0tleSA9PT0gXCJcIikge1xuXG4gICAgICAgIGxldCBjb2RlQmxvY2tEYXRhID0gcGFyc2VDb2RlQmxvY2tTdGFydChsaW5lc0Fib3ZlQXJyYXkpXG4gICAgICAgIGlmKGNvZGVCbG9ja0RhdGEgIT09IG51bGwpIHtcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgc3RhcnRCbG9ja0tleSA9IGNvZGVCbG9ja0RhdGEuaWQ7XG5cbiAgICAgICAgICAgIGlmKGNvZGVCbG9ja0RhdGEuaW5kZXggPiAwKSB7XG4gICAgICAgICAgICAgICAgbGluZXNBYm92ZUFycmF5ID0gbGluZXNBYm92ZUFycmF5LnNsaWNlKGNvZGVCbG9ja0RhdGEuaW5kZXggKyAxKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB7IHN0YXJ0QmxvY2tLZXksIGxpbmVzQWJvdmVBcnJheSB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0U3RhcnRDb2RlQmxvY2tBYm92ZUxpbmUobGluZXNBYm92ZUFycmF5OiBzdHJpbmdbXSk6IHsgXG4gICAgc3RhcnRCbG9ja0tleTogc3RyaW5nLCBcbiAgICBsaW5lc0Fib3ZlQXJyYXk6IHN0cmluZ1tdIH0gfCBudWxsIHtcbiAgICBcbiAgICBsZXQgbGluZXNBYm92ZVN0ciA9IGxpbmVzQWJvdmVBcnJheS5yZWR1Y2UoKHByZXYsIGN1cnJlbnQpID0+IHtcbiAgICAgICAgcmV0dXJuIHByZXYgKyBcIlxcblwiICArIGN1cnJlbnQ7XG4gICAgfSwgXCJcIik7XG5cbiAgICAvKlxuICAgICAqIEZpcnN0IHRoaW5nIHdlIG5lZWQgdG8gZG8gaXMgY2hlY2sgaWYgdGhlcmUgYXJlIGFueSBlbmQgdGFncyBpbiB0aGVcbiAgICAgKiBzZXQgb2Ygc3RyaW5ncyAod2hpY2ggbG9naWNhbGx5IHdvdWxkIGNsb3NlIHN0YXJ0IHRhZ3MgYW5kIHRoZXJlZm9yZVxuICAgICAqIHRoZSBzdGFydCB0YWcgaXQgY2xvc2VzIGlzIG5vdCB3aGF0IHdlIHdhbnQpLiBJZiB0aGVyZSBhcmUgd2Ugd2FudCB0byBcbiAgICAgKiBzbG93bHkgbmFycm93IGRvd24gb3VyIHNldCBvZiBzdHJpbmdzIHVudGlsIHRoZSBsYXN0IGVuZCB0YWcgaXMgXG4gICAgICogcmVtb3ZlZC4gVGhpcyBtYWtlcyBpdCBlYXNpZXIgdG8gZmluZCB0aGUgY2xvc2VzdCBvcGVuIHN0YXJ0IHRhZyBcbiAgICAgKiBpbiB0aGUgZGF0YS5cbiAgICAgKi9cbiAgICBsZXQgZW5kVGFnU2VyYWNoRGF0YSA9IGZpbmRFbmRUYWcobGluZXNBYm92ZVN0cik7XG4gICAgd2hpbGUoZW5kVGFnU2VyYWNoRGF0YS5mb3VuZCA9PT0gdHJ1ZSkge1xuXG4gICAgICAgIC8vIEdldCB0aGUgaW5kZXggb2Ygd2hlcmUgdGhlIGZpcnN0IHJlZ2V4IG1hdGNoIGluIHRoZVxuICAgICAgICAvLyBzdHJpbmcgaXMuIHRoZW4gd2Ugc2xpY2UgZnJvbSAwIHRvIGluZGV4IG9mZiBvZiB0aGUgc3RyaW5nXG4gICAgICAgIC8vIHNwbGl0IGl0IGJ5IG5ld2xpbmUsIGN1dCBvZmYgdGhlIGZpcnN0IGxpbmUgKHdoaWNoIGFjdHVhbGx5XG4gICAgICAgIC8vIGNvbnRhaW5zIHRoZSByZWdleCkgdGhlbiByZWR1Y2UgYmFjayBkb3duIHRvIGEgc2luZ2xlIHN0cmluZy5cbiAgICAgICAgbGluZXNBYm92ZVN0ciA9IGxpbmVzQWJvdmVTdHIuc2xpY2UoZW5kVGFnU2VyYWNoRGF0YS5lbmRQb3NpdGlvbik7XG4gICAgICAgIGVuZFRhZ1NlcmFjaERhdGEgPSBmaW5kRW5kVGFnKGxpbmVzQWJvdmVTdHIpO1xuICAgIH1cblxuICAgIGxldCBzdGFydENvZGVCbG9ja0RhdGEgPSBmaW5kU3RhcnRDb2RlYmxvY2sobGluZXNBYm92ZVN0cik7XG4gICAgbGV0IGNvZGVCbG9ja1RleHQgPSBsaW5lc0Fib3ZlU3RyLnNsaWNlKHN0YXJ0Q29kZUJsb2NrRGF0YS5zdGFydFBvc2l0aW9uLCBzdGFydENvZGVCbG9ja0RhdGEuZW5kUG9zaXRpb24pXG5cbiAgICBsZXQgc3RhcnRCbG9ja0tleSA9IFwiXCIgICAgXG4gICAgaWYoc3RhcnRDb2RlQmxvY2tEYXRhLmZvdW5kID09PSBmYWxzZSkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgZWxzZSB7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIE5vdyB3ZSBrbm93IHRoZXJlIGlzIGF0IGxlYXN0IDEgc3RhcnQga2V5IGxlZnQsIGhvd2V2ZXIgdGhlcmVcbiAgICAgICAgICogbWF5IGJlIG11bHRpcGxlIHN0YXJ0IGtleXMgaWYgdGhlIHVzZXIgaXMgbm90IGNsb3NpbmcgdGhlaXJcbiAgICAgICAgICogYmxvY2tzLiBXZSBjdXJyZW50bHkgZG9udCBhbGxvdyByZWN1c2l2ZSBzcGxpdHRpbmcgc28gd2UgXG4gICAgICAgICAqIHdhbnQgdG8gZ2V0IHRoZSBsYXN0IGtleSBpbiBvdXIgcmVtYWluaW5nIHNldC4gU2FtZSBpZGVhIGFzXG4gICAgICAgICAqIGFib3ZlLlxuICAgICAgICAgKi9cbiAgICAgICAgd2hpbGUoc3RhcnRDb2RlQmxvY2tEYXRhLmZvdW5kID09PSB0cnVlKSB7XG5cbiAgICAgICAgICAgIC8vIEdldCB0aGUgaW5kZXggb2Ygd2hlcmUgdGhlIGZpcnN0IHJlZ2V4IG1hdGNoIGluIHRoZVxuICAgICAgICAgICAgLy8gc3RyaW5nIGlzLiB0aGVuIHdlIHNsaWNlIGZyb20gMCB0byBpbmRleCBvZmYgb2YgdGhlIHN0cmluZ1xuICAgICAgICAgICAgLy8gc3BsaXQgaXQgYnkgbmV3bGluZSwgY3V0IG9mZiB0aGUgZmlyc3QgbGluZSAod2hpY2ggYWN0dWFsbHlcbiAgICAgICAgICAgIC8vIGNvbnRhaW5zIHRoZSByZWdleCkgdGhlbiByZWR1Y2UgYmFjayBkb3duIHRvIGEgc2luZ2xlIHN0cmluZy5cblxuICAgICAgICAgICAgY29kZUJsb2NrVGV4dCA9IGxpbmVzQWJvdmVTdHIuc2xpY2Uoc3RhcnRDb2RlQmxvY2tEYXRhLnN0YXJ0UG9zaXRpb24sIHN0YXJ0Q29kZUJsb2NrRGF0YS5lbmRQb3NpdGlvbilcbiAgICAgICAgICAgIHN0YXJ0QmxvY2tLZXkgPSBwYXJzZVN0YXJ0UmVnaW9uQ29kZUJsb2NrSUQoY29kZUJsb2NrVGV4dClcblxuICAgICAgICAgICAgbGluZXNBYm92ZVN0ciA9IGxpbmVzQWJvdmVTdHIuc2xpY2Uoc3RhcnRDb2RlQmxvY2tEYXRhLmVuZFBvc2l0aW9uKTtcbiAgICAgICAgICAgIHN0YXJ0Q29kZUJsb2NrRGF0YSA9IGZpbmRTdGFydENvZGVibG9jayhsaW5lc0Fib3ZlU3RyKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGxldCByZXRMaW5lc0Fib3ZlQXJyYXkgPSBsaW5lc0Fib3ZlU3RyLnNwbGl0KFwiXFxuXCIpO1xuICAgIHJldHVybiB7IHN0YXJ0QmxvY2tLZXksIGxpbmVzQWJvdmVBcnJheTogcmV0TGluZXNBYm92ZUFycmF5IH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRFbmRCbG9ja0JlbG93KGxpbmVzQmVsb3c6IHN0cmluZ1tdKTogc3RyaW5nW10ge1xuXG4gICAgLy8gUmVkdWNlIHRoZSBhcnJheSBkb3duIGludG8gYSBzaW5nbGUgc3RyaW5nIHNvIHRoYXQgd2UgY2FuXG4gICAgLy8gZWFzaWx5IFJlZ0V4IG92ZXIgdGhlIHN0cmluZyBhbmQgZmluZCB0aGUgaW5kaWNpZXMgd2UncmUgbG9va2luZyBmb3IuXG4gICAgbGV0IGxpbmVzQmVsb3dTdHIgPSBsaW5lc0JlbG93LnJlZHVjZSgocHJldiwgY3VycmVudCkgPT4ge1xuICAgICAgICByZXR1cm4gcHJldiArIFwiXFxuXCIgICsgY3VycmVudDtcbiAgICB9LCBcIlwiKTtcbiAgICBsZXQgZW5kVGFnU2VyYWNoRGF0YSA9IGZpbmRFbmRUYWcobGluZXNCZWxvd1N0cik7XG4gICAgbGV0IHN0YXJ0VGFnU2VhcmNoRGF0YSA9IGZpbmRTdGFydFRhZyhsaW5lc0JlbG93U3RyKTtcblxuICAgIGxldCBzbGljZUVuZEluZGV4ID0gLTE7IC8vIElmIG5laXRoZXIgc3RhcnQgb3IgZW5kIGZvdW5kIHdlIHJldHVybiB0aGUgZW50aXJlIGFycmF5LlxuICAgIGlmKGVuZFRhZ1NlcmFjaERhdGEuZm91bmQgPT09IHRydWUgJiYgc3RhcnRUYWdTZWFyY2hEYXRhLmZvdW5kID09PSBmYWxzZSkge1xuXG4gICAgICAgIHNsaWNlRW5kSW5kZXggPSBlbmRUYWdTZXJhY2hEYXRhLnN0YXJ0UG9zaXRpb247XG4gICAgfVxuICAgIGVsc2UgaWYoZW5kVGFnU2VyYWNoRGF0YS5mb3VuZCA9PT0gZmFsc2UgJiYgc3RhcnRUYWdTZWFyY2hEYXRhLmZvdW5kID09PSB0cnVlKSB7XG5cbiAgICAgICAgc2xpY2VFbmRJbmRleCA9IHN0YXJ0VGFnU2VhcmNoRGF0YS5zdGFydFBvc2l0aW9uO1xuICAgIH1cbiAgICBlbHNlIGlmKGVuZFRhZ1NlcmFjaERhdGEuZm91bmQgPT09IHRydWUgJiYgc3RhcnRUYWdTZWFyY2hEYXRhLmZvdW5kID09PSB0cnVlKSB7XG5cbiAgICAgICAgc2xpY2VFbmRJbmRleCA9IGVuZFRhZ1NlcmFjaERhdGEuc3RhcnRQb3NpdGlvbjtcbiAgICAgICAgaWYoc3RhcnRUYWdTZWFyY2hEYXRhLnN0YXJ0UG9zaXRpb24gPCBlbmRUYWdTZXJhY2hEYXRhLnN0YXJ0UG9zaXRpb24pIHtcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBJZiB3ZSBmb3VuZCBhIHN0YXJ0IHRhZyBiZWZvcmUgYW4gZW5kIHRhZyB3ZSB3YW50IHRvIHVzZSB0aGUgc3RhcnQgdGFnXG4gICAgICAgICAgICAgKiBvdXIgY3VycmVudCBibG9jayBpcyBub3QgcHJvcGVybHkgZW5kZWQgYW5kIHdlIHVzZSB0aGUgbmV4dCBzdGFydCB0YWcgXG4gICAgICAgICAgICAgKiBhcyBvdXIgbGltaXRcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgc2xpY2VFbmRJbmRleCA9IHN0YXJ0VGFnU2VhcmNoRGF0YS5zdGFydFBvc2l0aW9uO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGxpbmVzQmVsb3cuc2xpY2UoMCwgc2xpY2VFbmRJbmRleCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRTdGFydFRhZ0tleShzdGFydFRhZzogc3RyaW5nKTogc3RyaW5nIHwgbnVsbCB7XG5cbiAgICBsZXQga2V5U3BsaXQgPSBzdGFydFRhZy5zcGxpdChcIjpcIik7XG4gICAgaWYoa2V5U3BsaXQubGVuZ3RoID4gMSl7XG4gICAgICAgIHJldHVybiBrZXlTcGxpdFsxXS5yZXBsYWNlKFwiIFwiLCBcIlwiKVxuICAgIH1cblxuICAgIHJldHVybiBudWxsO1xufVxuXG5cbmNvbnN0IFRBQl9IRUFERVJfRU5EX1JFR0VYX1NUUiA9IFwiXmBgYCRcIjtcbmNvbnN0IFRBQl9IRUFERVJfRU5EX1JFR0VYOiBSZWdFeHAgPSBuZXcgUmVnRXhwKFRBQl9IRUFERVJfRU5EX1JFR0VYX1NUUik7XG5leHBvcnQgZnVuY3Rpb24gcGFyc2VDb2RlQmxvY2tTdGFydChjb2RlQmxvY2tMaW5lczogc3RyaW5nW10pOiB7IGlkOiBzdHJpbmcsIGluZGV4OiBudW1iZXJ9IHwgbnVsbCB7XG5cbiAgICBsZXQgaWQgPSBudWxsO1xuICAgIGZvcihsZXQgaSA9IDA7IGkgPCBjb2RlQmxvY2tMaW5lcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBsZXQgbGluZSA9IGNvZGVCbG9ja0xpbmVzW2ldO1xuXG4gICAgICAgIGlmKGlkID09PSBudWxsKSB7XG4gICAgICAgICAgICBsZXQga2V5ID0gbGluZS5zcGxpdChcIjpcIilbMF07XG4gICAgICAgICAgICBpZihrZXkudG9Mb3dlckNhc2UoKSA9PT0gXCJyZWdpb24gaWRcIikge1xuICAgICAgICAgICAgICAgIGlkID0gbGluZS5zcGxpdChcIjpcIilbMV0udHJpbSgpXG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBpZihUQUJfSEVBREVSX0VORF9SRUdFWC50ZXN0KGxpbmUpKSB7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4geyBpZDogaWQsIGluZGV4OiBpIH07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZihpZCA9PT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHJldHVybiB7IGlkOiBpZCwgaW5kZXg6IC0xIH1cbiAgICB9XG59XG5jb25zdCBDT0RFQkxPQ0tfRU5EX1JFR0VYX1NUUiA9IFwiYGBgXCI7XG5jb25zdCBDT0RFQkxPQ0tfRU5EX1JFR0VYOiBSZWdFeHAgPSBuZXcgUmVnRXhwKENPREVCTE9DS19FTkRfUkVHRVhfU1RSKTtcbmV4cG9ydCBmdW5jdGlvbiBmaW5kRW5kT2ZDb2RlQmxvY2sodGV4dDogc3RyaW5nKTogeyBmb3VuZDogYm9vbGVhbiwgc3RhcnRQb3NpdGlvbjogbnVtYmVyLCBlbmRQb3NpdGlvbjogbnVtYmVyLCBtYXRjaExlbmd0aDogbnVtYmVyIH0ge1xuXG4gICAgbGV0IGZvdW5kID0gZmFsc2U7XG4gICAgbGV0IHN0YXJ0UG9zaXRpb24gPSAtMTtcbiAgICBsZXQgbWF0Y2hMZW5ndGggPSAwO1xuICAgIGxldCBlbmRQb3NpdGlvbiA9IC0xO1xuXG4gICAgbGV0IHJlZ2V4RGF0YSA9IENPREVCTE9DS19FTkRfUkVHRVguZXhlYyh0ZXh0KVxuICAgIGlmKHJlZ2V4RGF0YSAhPT0gbnVsbCAmJiByZWdleERhdGEubGVuZ3RoID4gMCkge1xuICAgICAgICBmb3VuZCA9IHRydWU7XG4gICAgICAgIHN0YXJ0UG9zaXRpb24gPSByZWdleERhdGEuaW5kZXhcbiAgICAgICAgbWF0Y2hMZW5ndGggPSByZWdleERhdGFbMF0ubGVuZ3RoXG4gICAgfVxuICAgIGVuZFBvc2l0aW9uID0gc3RhcnRQb3NpdGlvbiArIG1hdGNoTGVuZ3RoO1xuXG4gICAgcmV0dXJuIHsgZm91bmQsIHN0YXJ0UG9zaXRpb24sIGVuZFBvc2l0aW9uLCBtYXRjaExlbmd0aCB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VDb2RlQmxvY2tTZXR0aW5ncyhjb2RlQmxvY2tMaW5lczogc3RyaW5nW10pOiBzdHJpbmcge1xuXG4gICAgbGV0IHNldHRpbmdzTGluZXMgPSBbXTtcbiAgICBmb3IobGV0IGkgPSAwOyBpIDwgY29kZUJsb2NrTGluZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgbGV0IGxpbmUgPSBjb2RlQmxvY2tMaW5lc1tpXTtcblxuICAgICAgICBsZXQga2V5ID0gbGluZS5zcGxpdChcIjpcIilbMF07XG4gICAgICAgIGlmKGtleS50b0xvd2VyQ2FzZSgpICE9PSBcInJlZ2lvbiBpZFwiKSB7XG4gICAgICAgICAgICBzZXR0aW5nc0xpbmVzLnB1c2gobGluZSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gc2V0dGluZ3NMaW5lcy5qb2luKFwiXFxuXCIpO1xufSIsIi8qXG4gKiBGaWxlbmFtZTogbXVsdGktY29sdW1uLW1hcmtkb3duL3NyYy91dGlsaXRpZXMvdXRpbHMudHNcbiAqIENyZWF0ZWQgRGF0ZTogVHVlc2RheSwgSmFudWFyeSAzMHRoIDIwMjIsIDQ6MDI6MTkgcG1cbiAqIEF1dGhvcjogQ2FtZXJvbiBSb2JpbnNvblxuICogXG4gKiBDb3B5cmlnaHQgKGMpIDIwMjIgQ2FtZXJvbiBSb2JpbnNvblxuICovXG5cbmltcG9ydCB7IFdvcmtzcGFjZUxlYWYgfSBmcm9tIFwib2JzaWRpYW5cIjtcblxuZXhwb3J0IGZ1bmN0aW9uIGdldFVJRChsZW5ndGg6IG51bWJlciA9IDEwKTogc3RyaW5nIHtcblxuICAgIGlmKGxlbmd0aCA+IDEwKSB7XG4gICAgICAgIGxlbmd0aCA9IDEwO1xuICAgIH1cbiAgICBsZXQgVUlEID0gTWF0aC5yYW5kb20oKS50b1N0cmluZygzNikuc3Vic3RyaW5nKDIpO1xuICAgIFVJRCA9IFVJRC5zbGljZSgwLCBsZW5ndGgpO1xuICAgIFxuICAgIHJldHVybiBVSUQ7XG59XG5cbi8qKlxuICogQkZTIG9uIHRoZSBjaGlsZCBub2RlcyBvZiB0aGUgcGFzc2VkIGVsZW1lbnQgc2VhcmNoaW5nIGZvciB0aGUgZmlyc3QgaW5zdGFuY2Ugb2YgdGhlXG4gKiBub2RlIHR5cGUgcGFzc2VkLiBSZXR1cm5pbmcgdGhlIGVsZW1lbnQgZm91bmQgb3IgbnVsbCBpZiBub25lIGZvdW5kLlxuICogXG4gKiBAcGFyYW0gcm9vdCBcbiAqIEBwYXJhbSBub2RlVHlwZU5hbWVcbiAqIEByZXR1cm5zIFxuICovXG5leHBvcnQgZnVuY3Rpb24gc2VhcmNoQ2hpbGRyZW5Gb3JOb2RlVHlwZShyb290OiBIVE1MRWxlbWVudCwgbm9kZVR5cGVOYW1lOiBzdHJpbmcpOiBIVE1MRWxlbWVudCB8IG51bGwge1xuXG4gICAgbm9kZVR5cGVOYW1lID0gbm9kZVR5cGVOYW1lLnRvTG93ZXJDYXNlKCk7XG4gICAgXG4gICAgbGV0IHF1ZXVlOiBIVE1MRWxlbWVudFtdID0gW3Jvb3RdXG4gICAgd2hpbGUocXVldWUubGVuZ3RoID4gMCl7XG4gICAgICAgIFxuICAgICAgICBmb3IobGV0IGkgPSAwOyBpIDwgcXVldWUubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgbGV0IG5vZGUgPSBxdWV1ZS5zaGlmdCgpXG5cbiAgICAgICAgICAgIGxldCBub2RlTmFtZSA9IG5vZGUubm9kZU5hbWUudG9Mb3dlckNhc2UoKVxuICAgICAgICAgICAgaWYobm9kZU5hbWUgPT09IG5vZGVUeXBlTmFtZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBub2RlIGFzIEhUTUxFbGVtZW50O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmb3IobGV0IGkgPSAwOyBpIDwgbm9kZS5jaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHF1ZXVlLnB1c2gobm9kZS5jaGlsZHJlbltpXSBhcyBIVE1MRWxlbWVudClcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBudWxsO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0RmlsZVNvdXJjZU1vZGUoc291cmNlUGF0aDogc3RyaW5nKTogc3RyaW5nIHtcblxuICAgIGxldCBmaWxlTGVhZiA9IGdldEZpbGVMZWFmKHNvdXJjZVBhdGgpO1xuICAgIGlmKGZpbGVMZWFmID09PSBudWxsKSB7XG4gICAgICAgIHJldHVybiBcIlwiO1xuICAgIH1cbiAgICByZXR1cm4gZmlsZUxlYWYuZ2V0Vmlld1N0YXRlKCkuc3RhdGUubW9kZTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBnZXRMZWFmU291cmNlTW9kZShmaWxlTGVhZjogV29ya3NwYWNlTGVhZik6IHN0cmluZyB7XG5cbiAgICByZXR1cm4gZmlsZUxlYWYuZ2V0Vmlld1N0YXRlKCkuc3RhdGUubW9kZTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGZpbGVTdGlsbEluVmlldyhzb3VyY2VQYXRoOiBzdHJpbmcpOmJvb2xlYW4ge1xuXG4gICAgbGV0IGZpbGVMZWFmID0gZ2V0RmlsZUxlYWYoc291cmNlUGF0aCk7XG4gICAgaWYoZmlsZUxlYWYgPT09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldEZpbGVMZWFmKHNvdXJjZVBhdGg6IHN0cmluZyk6IFdvcmtzcGFjZUxlYWYgfCBudWxsIHtcblxuICAgIGxldCBtYXJrZG93bkxlYXZlcyA9IGFwcC53b3Jrc3BhY2UuZ2V0TGVhdmVzT2ZUeXBlKFwibWFya2Rvd25cIik7XG4gICAgaWYobWFya2Rvd25MZWF2ZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIGZvcihsZXQgaSA9IDA7IGkgPCBtYXJrZG93bkxlYXZlcy5sZW5ndGg7IGkrKykge1xuXG4gICAgICAgIGlmKG1hcmtkb3duTGVhdmVzW2ldLmdldFZpZXdTdGF0ZSgpLnN0YXRlLmZpbGUgPT09IHNvdXJjZVBhdGgpIHtcbiAgICAgICAgICAgIHJldHVybiBtYXJrZG93bkxlYXZlc1tpXTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBudWxsO1xufSIsImltcG9ydCB7IHNlYXJjaENoaWxkcmVuRm9yTm9kZVR5cGUgfSBmcm9tIFwiLi91dGlsc1wiO1xuXG5leHBvcnQgZW51bSBFbGVtZW50UmVuZGVyVHlwZSB7XG4gICAgdW5kZWZpbmVkLFxuICAgIG5vcm1hbFJlbmRlcixcbiAgICBzcGVjaWFsUmVuZGVyLFxuICAgIHNwZWNpYWxTaW5nbGVFbGVtZW50UmVuZGVyLFxuICAgIGNhbnZhc1JlbmRlckVsZW1lbnQsXG4gICAgdW5SZW5kZXJlZFxufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0RWxlbWVudFJlbmRlclR5cGUoZWxlbWVudDogSFRNTEVsZW1lbnQpOiBFbGVtZW50UmVuZGVyVHlwZSB7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgRGF0YXZpZXcgcGx1Z2luIG5lZWRzIHRvIGJlIGNvbnN0YW50bHkgY2hlY2tlZCBpZiB0aGUgY2xvbmUgc2hvdWxkIGJlXG4gICAgICogdXBkYXRlZCBidXQgc2hvdWxkIG5vdCBhbHdheXMgdXBkYXRlIHRoZSBcImR1YWwgcmVuZGVyXCIgYXNwZWN0LCBzbyB3ZSBhZGRcbiAgICAgKiBhIHNwZWNpYWwgY2FzZSBmb3IgdGhhdCBwbHVnaW4gYW5kIG1heWJlIG90aGVycyBpbiB0aGUgZnV0dXJlLlxuICAgICAqL1xuICAgIGlmKGhhc0RhdGF2aWV3KGVsZW1lbnQpID09PSB0cnVlIHx8XG4gICAgICAgaXNJbnRlcm5hbEVtYmVkKGVsZW1lbnQpKSB7XG4gICAgICAgIHJldHVybiBFbGVtZW50UmVuZGVyVHlwZS5zcGVjaWFsU2luZ2xlRWxlbWVudFJlbmRlcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTb21lIHR5cGVzIG9mIGNvbnRlbnQgYXJlIHJlbmRlcmVkIGluIGNhbnZhc2VzIHdoaWNoIGFyZSBub3QgcmVuZGVyZWQgcHJvcGVybHlcbiAgICAgKiB3aGVuIHdlIGNsb25lIHRoZSBvcmlnaW5hbCBub2RlLiBIZXJlIHdlIGFyZSBmbGFnZ2luZyB0aGUgZWxlbWVudCBhcyBhIGNhbnZhc1xuICAgICAqIGVsZW1lbnQgc28gd2UgY2FuIGNsb25lIHRoZSBjYW52YXMgdG8gYSBjb3B5IGVsZW1lbnQgd2l0aGluIHRoZSByZWdpb24uXG4gICAgICogXG4gICAgICovXG4gICAgaWYoIGhhc0RhdGF2aWV3SlMoZWxlbWVudCkgPT09IHRydWUpIHtcbiAgICAgICAgcmV0dXJuIEVsZW1lbnRSZW5kZXJUeXBlLmNhbnZhc1JlbmRlckVsZW1lbnQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTG9vayBmb3Igc3BlY2lmaWMga2luZHMgb2YgZWxlbWVudHMgYnkgdGhlaXIgQ1NTIGNsYXNzIG5hbWVzIGhlcmUuIFRoZXNlIFxuICAgICAqIGFyZSBnb2luZyB0byBiZSBicml0dGxlIGxpbmtzIGFzIHRoZXkgcmVseSBvbiBvdGhlciBwbHVnaW4gZGVmaW5pdGlvbnMgYnV0XG4gICAgICogYXMgdGhpcyBpcyBvbmx5IGFkZGluZyBpbiBleHRyYSBjb21wYXRhYmlsaXR5IHRvIHRoZSBwbHVnaW5zIGRlZmluZWQgaGVyZSBcbiAgICAgKiBpdCBzaG91bGQgYmUgb2suXG4gICAgICogXG4gICAgICogVGhlc2UgbWF5IGJlIGNsYXNzZXMgb24gb25lIG9mIHRoZSBzaW1wbGUgZWxlbWVudHMgKHN1Y2ggYXMgYSBwYXJhZ3JhcGgpXG4gICAgICogdGhhdCB3ZSBzZWFyY2ggZm9yIGJlbG93IHNvIG5lZWQgdG8gbG9vayBmb3IgdGhlc2UgZmlyc3QuXG4gICAgICovXG4gICAgaWYoaGFzRGljZVJvbGxlcihlbGVtZW50KSA9PT0gdHJ1ZSB8fFxuICAgICAgIGhhc0NvcHlCdXR0b24oZWxlbWVudCkgPT09IHRydWUgfHxcbiAgICAgICBoYXNBZG1vbml0aW9uRm9sZChlbGVtZW50KSA9PT0gdHJ1ZSkge1xuXG4gICAgICAgIHJldHVybiBFbGVtZW50UmVuZGVyVHlwZS5zcGVjaWFsUmVuZGVyXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBjaGVja3MgZm9yIHNwZWNpYWwgdHlwZXMgb2YgZWxlbWVudHMgdGhhdCBzaG91bGQgYmUgcmVuZGVyZWQgbm9ybWFsbHkuIElzXG4gICAgICogc2xpZ2h0bHkgcmVkdW5kYW50IHdpdGggbmV4dCBjaGVjayBidXQgZGlmZmVyZW50aWF0ZXMgYmV0d2VlbiB0eXBlcyBvZiBlbWVudHMgXG4gICAgICogYmVpbmcgY2hlY2tlZC5cbiAgICAgKi9cbiAgICBpZihoYXNBZG1vbml0aW9uKGVsZW1lbnQpID09PSB0cnVlIHx8XG4gICAgICAgaXNJRnJhbWUoZWxlbWVudCkgPT09IHRydWUpIHtcbiAgICAgICAgXG4gICAgICAgIHJldHVybiBFbGVtZW50UmVuZGVyVHlwZS5ub3JtYWxSZW5kZXJcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJZiB3ZSBkaWRudCBmaW5kIGEgc3BlY2lhbCBlbGVtZW50IHdlIHdhbnQgdG8gY2hlY2sgZm9yIHNpbXBsZSBlbGVtZW50c1xuICAgICAqIHN1Y2ggYXMgcGFyYWdyYXBocyBvciBsaXN0cy4gSW4gdGhlIGN1cnJlbnQgaW1wbGVtZW50YXRpb24gd2Ugb25seSBzZXQgdXBcbiAgICAgKiB0aGUgc3BlY2lhbCBjYXNlIGZvciBcInNwZWNpYWxSZW5kZXJcIiBlbGVtZW50cyBzbyB0aGlzICpzaG91bGQqIGJlIHNhdmluZ1xuICAgICAqIHNvbWUgcmVuZGVyaW5nIHRpbWUgYnkgc2V0dGluZyB0aGVzZSB0YWdzIHByb3Blcmx5LlxuICAgICAqL1xuICAgIGlmKGhhc1BhcmFncmFwaChlbGVtZW50KSB8fCBcbiAgICAgICBoYXNIZWFkZXIoZWxlbWVudCkgICAgfHxcbiAgICAgICBoYXNMaXN0KGVsZW1lbnQpIHx8XG4gICAgICAgaXNIb3Jpem9udGFsUnVsZShlbGVtZW50KSB8fFxuICAgICAgIGlzVGFibGUoZWxlbWVudCkpIHtcblxuICAgICAgICByZXR1cm4gRWxlbWVudFJlbmRlclR5cGUubm9ybWFsUmVuZGVyO1xuICAgIH1cblxuICAgIC8vIElmIHN0aWxsIG5vdGhpbmcgZm91bmQgd2UgcmV0dXJuIG90aGVyIGFzIHRoZSBkZWZhdWx0IHJlc3BvbnNlIGlmIG5vdGhpbmcgZWxzZSBmb3VuZC5cbiAgICByZXR1cm4gRWxlbWVudFJlbmRlclR5cGUuc3BlY2lhbFJlbmRlcjtcbn1cblxuZnVuY3Rpb24gaGFzUGFyYWdyYXBoKGVsZW1lbnQ6IEhUTUxFbGVtZW50KTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIGVsZW1lbnQuaW5uZXJIVE1MLnN0YXJ0c1dpdGgoXCI8cFwiKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGhhc0hlYWRlcihlbGVtZW50OiBIVE1MRWxlbWVudCk6IGJvb2xlYW4ge1xuXG4gICAgaWYoZWxlbWVudC5pbm5lckhUTUwuc3RhcnRzV2l0aChcIjxoMVwiKSB8fCBcbiAgICAgICBlbGVtZW50LmlubmVySFRNTC5zdGFydHNXaXRoKFwiPGgyXCIpIHx8IFxuICAgICAgIGVsZW1lbnQuaW5uZXJIVE1MLnN0YXJ0c1dpdGgoXCI8aDNcIikgfHwgXG4gICAgICAgZWxlbWVudC5pbm5lckhUTUwuc3RhcnRzV2l0aChcIjxoNFwiKSB8fFxuICAgICAgIGVsZW1lbnQuaW5uZXJIVE1MLnN0YXJ0c1dpdGgoXCI8aDVcIikgfHxcbiAgICAgICBlbGVtZW50LmlubmVySFRNTC5zdGFydHNXaXRoKFwiPGg2XCIpKSB7XG5cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBoYXNMaXN0KGVsZW1lbnQ6IEhUTUxFbGVtZW50KTogYm9vbGVhbiB7XG4gICAgXG4gICAgaWYoZWxlbWVudC5pbm5lckhUTUwuc3RhcnRzV2l0aChcIjx1bFwiKSB8fCBcbiAgICAgICBlbGVtZW50LmlubmVySFRNTC5zdGFydHNXaXRoKFwiPG9sXCIpKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gaGFzQ29weUJ1dHRvbihlbGVtZW50OiBIVE1MRWxlbWVudCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBlbGVtZW50LmdldEVsZW1lbnRzQnlDbGFzc05hbWUoXCJjb3B5LWNvZGUtYnV0dG9uXCIpLmxlbmd0aCAhPT0gMCB8fCBcbiAgICAgICAgICAgIGVsZW1lbnQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZShcImFkbW9uaXRpb24tY29udGVudC1jb3B5XCIpLmxlbmd0aCAhPT0gMDtcbn1cblxuZnVuY3Rpb24gaGFzRGljZVJvbGxlcihlbGVtZW50OiBIVE1MRWxlbWVudCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBlbGVtZW50LmdldEVsZW1lbnRzQnlDbGFzc05hbWUoXCJkaWNlLXJvbGxlclwiKS5sZW5ndGggIT09IDA7XG59XG5cbmZ1bmN0aW9uIGhhc0FkbW9uaXRpb24oZWxlbWVudDogSFRNTEVsZW1lbnQpOiBib29sZWFuIHtcbiAgICByZXR1cm4gZWxlbWVudC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKFwiYWRtb25pdGlvblwiKS5sZW5ndGggIT09IDA7XG59XG5cbmZ1bmN0aW9uIGlzSUZyYW1lKGVsZW1lbnQ6IEhUTUxFbGVtZW50KTogYm9vbGVhbiB7XG5cbiAgICBpZihlbGVtZW50LmNoaWxkcmVuLmxlbmd0aCA+IDApIHtcblxuICAgICAgICByZXR1cm4gZWxlbWVudC5maXJzdENoaWxkLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCkgPT09IFwiaWZyYW1lXCI7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlXG59XG5cbmZ1bmN0aW9uIGlzSG9yaXpvbnRhbFJ1bGUoZWxlbWVudDogSFRNTEVsZW1lbnQpOiBib29sZWFuIHtcbiAgICByZXR1cm4gZWxlbWVudC5pbm5lckhUTUwuc3RhcnRzV2l0aChcIjxoclwiKVxufVxuXG5mdW5jdGlvbiBpc1RhYmxlKGVsZW1lbnQ6IEhUTUxFbGVtZW50KTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIGVsZW1lbnQuaW5uZXJIVE1MLnN0YXJ0c1dpdGgoXCI8dGFibGVcIilcbn1cblxuZnVuY3Rpb24gaGFzQWRtb25pdGlvbkZvbGQoZWxlbWVudDogSFRNTEVsZW1lbnQpIHtcbiAgICByZXR1cm4gZWxlbWVudC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKFwiY2FsbG91dC1mb2xkXCIpLmxlbmd0aCAhPT0gMDtcbn1cblxuZnVuY3Rpb24gaGFzRGF0YXZpZXcoZWxlbWVudDogSFRNTEVsZW1lbnQpIHtcblxuICAgIGxldCBpc0RhdGF2aWV3ID0gZWxlbWVudC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKFwiYmxvY2stbGFuZ3VhZ2UtZGF0YXZpZXdcIikubGVuZ3RoICE9PSAwO1xuICAgIHJldHVybiBpc0RhdGF2aWV3O1xufVxuXG5mdW5jdGlvbiBoYXNEYXRhdmlld0pTKGVsZW1lbnQ6IEhUTUxFbGVtZW50KSB7XG5cbiAgICBsZXQgaXNEYXRhdmlld0pTID0gZWxlbWVudC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKFwiYmxvY2stbGFuZ3VhZ2UtZGF0YXZpZXdqc1wiKS5sZW5ndGggIT09IDA7XG4gICAgbGV0IGNhbnZhcyA9IHNlYXJjaENoaWxkcmVuRm9yTm9kZVR5cGUoZWxlbWVudCwgXCJjYW52YXNcIik7XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIG1lYW5zIG9ubHkgZGF0YXZpZXdKUyBjaGFydCBjYW52YXMgZWxlbWVudHMgc2hvdWxkIGJlIHJlbmRlcmVkIHByb3Blcmx5LiBPdGhlciBjYW52YXNlcyB3aWxsIFxuICAgICAqIG5lZWQgdGhpZXIgb3duIGNhc2UgcHV0IGluIG9yIHRoZSByZXN0cmljdGlvbiByZW1vdmVkIGFmdGVyIHRlc3RpbmcuXG4gICAgICovXG4gICAgcmV0dXJuIGNhbnZhcyAhPT0gbnVsbCAmJiBpc0RhdGF2aWV3SlMgXG59XG5cbmZ1bmN0aW9uIGlzSW50ZXJuYWxFbWJlZChlbGVtZW50OiBIVE1MRWxlbWVudCkge1xuICAgIGxldCBpc0VtYmVkID0gZWxlbWVudC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKFwiaW50ZXJuYWwtZW1iZWRcIikubGVuZ3RoICE9PSAwO1xuICAgIHJldHVybiBpc0VtYmVkO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0SGVhZGluZ0NvbGxhcHNlRWxlbWVudChlbGVtZW50OiBIVE1MRWxlbWVudCk6IEVsZW1lbnQgfCBudWxsIHtcblxuICAgIGlmKGVsZW1lbnQgPT09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgbGV0IGNoaWxkRWxlbWVudHMgPSBlbGVtZW50LmdldEVsZW1lbnRzQnlDbGFzc05hbWUoXCJoZWFkaW5nLWNvbGxhcHNlLWluZGljYXRvclwiKVxuICAgIGlmKGNoaWxkRWxlbWVudHMubGVuZ3RoID09PSAxKSB7XG4gICAgICAgIHJldHVybiBjaGlsZEVsZW1lbnRzWzBdO1xuICAgIH1cbiAgICBpZihjaGlsZEVsZW1lbnRzLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgY29uc29sZS5kZWJ1ZyhcIkZvdW5kIG11bHRpcGxlIGhlYWRpbmcgY29sbGFwc2UgaW5kaWNhdG9ycyBpbiBlbGVtZW50LlwiKVxuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbn0iLCIvKlxuICogRmlsZW5hbWU6IG11bHRpLWNvbHVtbi1tYXJrZG93bi9zcmMvZG9tT2JqZWN0LnRzXG4gKiBDcmVhdGVkIERhdGU6IFR1ZXNkYXksIEZlYnJ1YXJ5IDFzdCAyMDIyLCAxMjowNDowMCBwbVxuICogQXV0aG9yOiBDYW1lcm9uIFJvYmluc29uXG4gKiBcbiAqIENvcHlyaWdodCAoYykgMjAyMiBDYW1lcm9uIFJvYmluc29uXG4gKi9cblxuaW1wb3J0IHsgZ2V0VUlEIH0gZnJvbSBcIi4uL3V0aWxpdGllcy91dGlsc1wiO1xuaW1wb3J0IHsgRWxlbWVudFJlbmRlclR5cGUgfSBmcm9tIFwiLi4vdXRpbGl0aWVzL2VsZW1lbnRSZW5kZXJUeXBlUGFyc2VyXCI7XG5pbXBvcnQgeyBjaGVja0ZvclBhcmFncmFwaElubmVyQ29sRW5kVGFnLCBjb250YWluc0NvbEVuZFRhZywgY29udGFpbnNDb2xTZXR0aW5nc1RhZywgY29udGFpbnNFbmRUYWcsIGNvbnRhaW5zU3RhcnRUYWcsIGVsSW5uZXJUZXh0Q29udGFpbnNDb2xFbmRUYWcgfSBmcm9tIFwic3JjL3V0aWxpdGllcy90ZXh0UGFyc2VyXCI7XG5cbmNvbnN0IFVQREFURV9USU1FUzogbnVtYmVyW10gPSBbMTI1LCAxMjUsIDI1MCwgMjAwMDBdO1xuY29uc3QgTUlEX0JSRUFLX0VSUk9SX01FU1NBR0U6IHN0cmluZyA9IFwiRGV0ZWN0ZWQgaW52YWxpZCBjb2x1bW4gYnJlYWsgc3ludGF4LlxcblBsZWFzZSBtYWtlIHN1cmUgY29sdW1uIGJyZWFrIHRhZ3MgYXJlIG5vdCBpbiB0aGUgbWlkZGxlIG9mIGEgcGFyYWdyYXBoIGJsb2NrXCJcblxuZXhwb3J0IGVudW0gRE9NT2JqZWN0VGFnIHtcbiAgICBub25lLFxuICAgIHN0YXJ0UmVnaW9uLFxuICAgIHJlZ2lvblNldHRpbmdzLFxuICAgIGNvbHVtbkJyZWFrLFxuICAgIGVuZFJlZ2lvblxufVxuXG5leHBvcnQgZW51bSBFbGVtZW50Q29sdW1uQnJlYWtUeXBlIHtcbiAgICBub25lID0gMCxcbiAgICBwcmVCcmVhayxcbiAgICBwb3N0QnJlYWssXG4gICAgbWlkQnJlYWtcbn1cblxuZXhwb3J0IGNsYXNzIERPTU9iamVjdCB7XG4gICAgbm9kZUtleTogc3RyaW5nO1xuICAgIG9yaWdpbmFsRWxlbWVudDogSFRNTEVsZW1lbnQ7XG4gICAgY2xvbmVkRWxlbWVudDogSFRNTEVsZW1lbnQgPSBudWxsO1xuICAgIFVJRDogc3RyaW5nO1xuICAgIHRhZzogRE9NT2JqZWN0VGFnO1xuICAgIGVsZW1lbnRJc0NvbHVtbkJyZWFrOiBFbGVtZW50Q29sdW1uQnJlYWtUeXBlID0gRWxlbWVudENvbHVtbkJyZWFrVHlwZS5ub25lO1xuICAgIHVzaW5nT3JpZ2luYWxFbGVtZW50OiBib29sZWFuXG4gICAgZWxlbWVudFR5cGU6IEVsZW1lbnRSZW5kZXJUeXBlID0gRWxlbWVudFJlbmRlclR5cGUudW5kZWZpbmVkO1xuICAgIGVsZW1lbnRDb250YWluZXI6IEhUTUxEaXZFbGVtZW50ID0gbnVsbDtcbiAgICBlbGVtZW50UmVuZGVyZWRIZWlnaHQgPSAwO1xuICAgIGxpbmVzT2ZFbGVtZW50OiBzdHJpbmdbXVxuXG4gICAgY2FudmFzRWxlbWVudFVwZGF0ZVRpbWU6IG51bWJlciA9IERhdGUubm93KCk7XG4gICAgY2FudmFzVGltZXJJbmRleCA9IDA7XG5cbiAgICBsYXN0Q2xvbmVkRWxlbWVudFVwZGF0ZVRpbWU6IG51bWJlciA9IERhdGUubm93KCk7XG4gICAgdXBkYXRlVGltZXJJbmRleCA9IDA7XG5cbiAgICBjb25zdHJ1Y3RvcihlbGVtZW50OiBIVE1MRWxlbWVudCxcbiAgICAgICAgICAgICAgICBsaW5lc09mRWxlbWVudDogc3RyaW5nW10sXG4gICAgICAgICAgICAgICAgcmFuZG9tSUQ6c3RyaW5nID0gZ2V0VUlEKCksIFxuICAgICAgICAgICAgICAgIHRhZzogRE9NT2JqZWN0VGFnID0gRE9NT2JqZWN0VGFnLm5vbmUgKSB7XG4gICAgICAgIHRoaXMubm9kZUtleSA9IGVsZW1lbnQuaW5uZXJUZXh0LnRyaW0oKTtcbiAgICAgICAgdGhpcy5vcmlnaW5hbEVsZW1lbnQgPSBlbGVtZW50O1xuICAgICAgICB0aGlzLlVJRCA9IHJhbmRvbUlEO1xuICAgICAgICB0aGlzLnRhZyA9IHRhZztcbiAgICAgICAgdGhpcy51c2luZ09yaWdpbmFsRWxlbWVudCA9IGZhbHNlXG4gICAgICAgIHRoaXMubGluZXNPZkVsZW1lbnQgPSBsaW5lc09mRWxlbWVudDtcblxuICAgICAgICBpZih0aGlzLnRhZyA9PT0gRE9NT2JqZWN0VGFnLm5vbmUpIHtcbiAgICAgICAgICAgIHRoaXMuc2V0RG9tT2JqZWN0VGFnKClcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIElmIG91ciB0YWcgaXMgc3RpbGwgbm9uZSBoZXJlLCB3ZSBub3cgd2FudCB0byBjaGVjayBmb3JcbiAgICAgICAgLy8gYW4gaW4gcGFyYWdyYXBoIGNvbHVtbiBicmVhayBmbGFnLlxuICAgICAgICBpZih0aGlzLnRhZyA9PT0gRE9NT2JqZWN0VGFnLm5vbmUpIHtcbiAgICAgICAgICAgIHRoaXMuY2hlY2tGb3JQcmVQb3N0Q29sdW1uQnJlYWsoKVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgc2V0TWFpbkRPTUVsZW1lbnQoZG9tRWxlbWVudDogSFRNTEVsZW1lbnQpIHtcbiAgICAgICAgdGhpcy5vcmlnaW5hbEVsZW1lbnQgPSBkb21FbGVtZW50O1xuICAgICAgICB0aGlzLnVzaW5nT3JpZ2luYWxFbGVtZW50ID0gdHJ1ZVxuICAgIH1cblxuICAgIGNsb25lZEVsZW1lbnRSZWFkeUZvclVwZGF0ZSgpOiBib29sZWFuIHtcblxuICAgICAgICBsZXQgZGVsdGFUaW1lID0gRGF0ZS5ub3coKSAtIHRoaXMubGFzdENsb25lZEVsZW1lbnRVcGRhdGVUaW1lO1xuICAgICAgICBpZihkZWx0YVRpbWUgPiBVUERBVEVfVElNRVNbdGhpcy51cGRhdGVUaW1lckluZGV4XSkge1xuXG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBjYW52YXNSZWFkeUZvclVwZGF0ZSgpOiBib29sZWFuIHtcblxuICAgICAgICBsZXQgZGVsdGFUaW1lID0gRGF0ZS5ub3coKSAtIHRoaXMuY2FudmFzRWxlbWVudFVwZGF0ZVRpbWVcbiAgICAgICAgaWYoZGVsdGFUaW1lID4gVVBEQVRFX1RJTUVTW3RoaXMuY2FudmFzVGltZXJJbmRleF0pIHtcblxuICAgICAgICAgICAgdGhpcy5jYW52YXNFbGVtZW50VXBkYXRlVGltZSA9IERhdGUubm93KCk7XG4gICAgICAgICAgICB0aGlzLmNhbnZhc1RpbWVySW5kZXggPSBNYXRoLmNsYW1wKHRoaXMuY2FudmFzVGltZXJJbmRleCArIDEsIDAsIFVQREFURV9USU1FUy5sZW5ndGggLSAxKTtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHVwZGF0ZUNsb25lZEVsZW1lbnQobmV3Q2xvbmVkRWxlbWVudDogSFRNTEVsZW1lbnQpIHtcblxuICAgICAgICB0aGlzLmNsb25lZEVsZW1lbnQgPSBuZXdDbG9uZWRFbGVtZW50O1xuXG4gICAgICAgIHRoaXMubGFzdENsb25lZEVsZW1lbnRVcGRhdGVUaW1lID0gRGF0ZS5ub3coKTtcbiAgICAgICAgdGhpcy51cGRhdGVUaW1lckluZGV4ID0gTWF0aC5jbGFtcCh0aGlzLnVwZGF0ZVRpbWVySW5kZXggKyAxLCAwLCBVUERBVEVfVElNRVMubGVuZ3RoIC0gMSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzZXREb21PYmplY3RUYWcoKSB7XG5cbiAgICAgICAgbGV0IGVsZW1lbnRUZXh0U3BhY2VkID0gdGhpcy5saW5lc09mRWxlbWVudC5yZWR1Y2UoKHByZXYsIGN1cnIpID0+IHtcbiAgICAgICAgICAgIHJldHVybiBwcmV2ICsgXCJcXG5cIiArIGN1cnI7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmKGNvbnRhaW5zRW5kVGFnKHRoaXMub3JpZ2luYWxFbGVtZW50LnRleHRDb250ZW50KSA9PT0gdHJ1ZSkge1xuXG4gICAgICAgICAgICB0aGlzLmVsZW1lbnRUeXBlID0gRWxlbWVudFJlbmRlclR5cGUudW5SZW5kZXJlZDtcbiAgICAgICAgICAgIHRoaXMudGFnID0gRE9NT2JqZWN0VGFnLmVuZFJlZ2lvbjtcbiAgICAgICAgICAgIC8vIGVsLmFkZENsYXNzKE11bHRpQ29sdW1uU3R5bGVDU1MuUmVnaW9uRW5kVGFnKVxuICAgICAgICAgICAgLy8gcmVnaW9uYWxNYW5hZ2VyLnVwZGF0ZUVsZW1lbnRUYWcoY3VycmVudE9iamVjdC5VSUQsIERPTU9iamVjdFRhZy5lbmRSZWdpb24pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYoY29udGFpbnNDb2xFbmRUYWcodGhpcy5vcmlnaW5hbEVsZW1lbnQudGV4dENvbnRlbnQpID09PSB0cnVlIHx8IFxuICAgICAgICAodGhpcy5vcmlnaW5hbEVsZW1lbnQuaW5uZXJIVE1MLnN0YXJ0c1dpdGgoXCI8bWFyaz5cIikpICYmIGVsSW5uZXJUZXh0Q29udGFpbnNDb2xFbmRUYWcodGhpcy5vcmlnaW5hbEVsZW1lbnQudGV4dENvbnRlbnQpKSB7XG5cbiAgICAgICAgICAgIHRoaXMuZWxlbWVudFR5cGUgPSBFbGVtZW50UmVuZGVyVHlwZS51blJlbmRlcmVkXG4gICAgICAgICAgICB0aGlzLnRhZyA9IERPTU9iamVjdFRhZy5jb2x1bW5CcmVhaztcbiAgICAgICAgICAgIC8vIGVsLmFkZENsYXNzKE11bHRpQ29sdW1uU3R5bGVDU1MuQ29sdW1uRW5kVGFnKVxuICAgICAgICAgICAgLy8gcmVnaW9uYWxNYW5hZ2VyLnVwZGF0ZUVsZW1lbnRUYWcoY3VycmVudE9iamVjdC5VSUQsIERPTU9iamVjdFRhZy5jb2x1bW5CcmVhayk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZihjb250YWluc1N0YXJ0VGFnKHRoaXMub3JpZ2luYWxFbGVtZW50LnRleHRDb250ZW50KSA9PT0gdHJ1ZSkge1xuXG4gICAgICAgICAgICB0aGlzLmVsZW1lbnRUeXBlID0gRWxlbWVudFJlbmRlclR5cGUudW5SZW5kZXJlZFxuICAgICAgICAgICAgdGhpcy50YWcgPSBET01PYmplY3RUYWcuc3RhcnRSZWdpb247XG4gICAgICAgICAgICAvLyBlbC5hZGRDbGFzcyhNdWx0aUNvbHVtblN0eWxlQ1NTLkNvbHVtbkVuZFRhZylcbiAgICAgICAgICAgIC8vIHJlZ2lvbmFsTWFuYWdlci51cGRhdGVFbGVtZW50VGFnKGN1cnJlbnRPYmplY3QuVUlELCBET01PYmplY3RUYWcuY29sdW1uQnJlYWspO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYoY29udGFpbnNDb2xTZXR0aW5nc1RhZyhlbGVtZW50VGV4dFNwYWNlZCkgPT09IHRydWUpIHtcblxuICAgICAgICAgICAgdGhpcy5lbGVtZW50VHlwZSA9IEVsZW1lbnRSZW5kZXJUeXBlLnVuUmVuZGVyZWRcbiAgICAgICAgICAgIC8vIGVsLmFkZENsYXNzKE11bHRpQ29sdW1uU3R5bGVDU1MuUmVnaW9uU2V0dGluZ3MpXG4gICAgICAgICAgICAvLyByZWdpb25hbE1hbmFnZXIgPSByZWdpb25hbENvbnRhaW5lci5zZXRSZWdpb25TZXR0aW5ncyhlbGVtZW50VGV4dFNwYWNlZClcbiAgICAgICAgICAgIC8vIHJlZ2lvbmFsTWFuYWdlci51cGRhdGVFbGVtZW50VGFnKGN1cnJlbnRPYmplY3QuVUlELCBET01PYmplY3RUYWcucmVnaW9uU2V0dGluZ3MpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgY2hlY2tGb3JQcmVQb3N0Q29sdW1uQnJlYWsoKSB7XG5cbiAgICAgICAgbGV0IHRleHRPZkVsZW1lbnQgPSB0aGlzLm9yaWdpbmFsRWxlbWVudC5pbm5lclRleHQ7XG4gICAgICAgIGxldCBjb250YWluc0NvbHVtbkJyZWFrID0gY2hlY2tGb3JQYXJhZ3JhcGhJbm5lckNvbEVuZFRhZyh0ZXh0T2ZFbGVtZW50KTtcbiAgICAgICAgaWYoY29udGFpbnNDb2x1bW5CcmVhayAhPT0gbnVsbCkge1xuXG4gICAgICAgICAgICBsZXQgdGV4dCA9IHRoaXMub3JpZ2luYWxFbGVtZW50LmlubmVyVGV4dDtcbiAgICAgICAgICAgIGxldCBzdGFydEluZGV4ID0gY29udGFpbnNDb2x1bW5CcmVhay5pbmRleDtcbiAgICAgICAgICAgIGxldCBlbmRJbmRleCA9IHN0YXJ0SW5kZXggKyBjb250YWluc0NvbHVtbkJyZWFrWzBdLmxlbmd0aDtcbiAgICAgICAgICAgIGxldCBwcmUgPSB0ZXh0LnNsaWNlKDAsIHN0YXJ0SW5kZXgpO1xuICAgICAgICAgICAgbGV0IHBvc3QgPSB0ZXh0LnNsaWNlKGVuZEluZGV4KVxuXG4gICAgICAgICAgICBsZXQgcGFyYWdyYXBoID0gdGhpcy5vcmlnaW5hbEVsZW1lbnQuY2hpbGRyZW5bMF0gYXMgSFRNTEVsZW1lbnQ7XG4gICAgICAgICAgICBpZih0aGlzLm9yaWdpbmFsRWxlbWVudC5ub2RlTmFtZSA9PT0gXCJQXCIpIHtcbiAgICAgICAgICAgICAgICBwYXJhZ3JhcGggPSB0aGlzLm9yaWdpbmFsRWxlbWVudDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gY29uc29sZS5kZWJ1ZyhcIkNoZWNraW5nIHdoZXJlIGNvbHVtbiBicmVhayBpc1wiLCBzdGFydEluZGV4LCBlbmRJbmRleCwgdGV4dC5sZW5ndGgpO1xuICAgICAgICAgICAgaWYoc3RhcnRJbmRleCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIC8vIGNvbnNvbGUuZGVidWcoXCJjb2x1bW4gYnJlYWsgYXQgc3RhcnQgb2YgZWxlbWVudC5cIilcbiAgICAgICAgICAgICAgICB0aGlzLmVsZW1lbnRJc0NvbHVtbkJyZWFrID0gRWxlbWVudENvbHVtbkJyZWFrVHlwZS5wcmVCcmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYoZW5kSW5kZXggPT09IHRleHQubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgLy8gY29uc29sZS5kZWJ1ZyhcIkNvbHVtbiBicmVhayBhdCBlbmQgb2YgZWxlbWVudC5cIilcbiAgICAgICAgICAgICAgICB0aGlzLmVsZW1lbnRJc0NvbHVtbkJyZWFrID0gRWxlbWVudENvbHVtbkJyZWFrVHlwZS5wb3N0QnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmRlYnVnKFwiQ29sdW1uIGJyZWFrIGluIHRoZSBtaWRkbGUgb2YgZWxlbWVudD9cIilcbiAgICAgICAgICAgICAgICB0aGlzLmVsZW1lbnRJc0NvbHVtbkJyZWFrID0gRWxlbWVudENvbHVtbkJyZWFrVHlwZS5taWRCcmVhaztcblxuICAgICAgICAgICAgICAgIGNvbnN0IEVSUk9SX0NPTE9SX0NTUyA9IFwibWNtLWVycm9yLW1lc3NhZ2UtY29sb3JcIjtcbiAgICAgICAgICAgICAgICBjb25zdCBDRU5URVJfQUxJR05fU1BBTl9DU1MgPSBcIm1jbS1zcGFuLWNvbnRlbnQtYWxpZ25tZW50LWNlbnRlclwiO1xuICAgICAgICAgICAgICAgIGlmKHBhcmFncmFwaCkge1xuICAgICAgICAgICAgICAgICAgICBwYXJhZ3JhcGguaW5uZXJIVE1MID0gYCR7cHJlfVxcbjxzcGFuIGNsYXNzPVwiJHtFUlJPUl9DT0xPUl9DU1N9ICR7Q0VOVEVSX0FMSUdOX1NQQU5fQ1NTfVwiPiR7TUlEX0JSRUFLX0VSUk9SX01FU1NBR0V9PC9zcGFuPlxcblxcbiR7cG9zdH1gLnNwbGl0KFwiXFxuXCIpLmpvaW4oXCI8YnI+XCIpO1xuXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYocGFyYWdyYXBoKSB7XG4gICAgICAgICAgICAgICAgcGFyYWdyYXBoLmlubmVyVGV4dCA9IGAke3ByZX0ke3Bvc3R9YDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbn1cblxuZXhwb3J0IGNsYXNzIERPTVN0YXJ0UmVnaW9uT2JqZWN0IGV4dGVuZHMgRE9NT2JqZWN0IHtcblxuICAgIHJlZ2lvbkVsZW1lbnQ6IEhUTUxFbGVtZW50O1xuXG4gICAgY29uc3RydWN0b3IoYmFzZURPTU9iamVjdDogRE9NT2JqZWN0LCByZWdpb25FbGVtZW50OiBIVE1MRWxlbWVudCkge1xuXG4gICAgICAgIHN1cGVyKGJhc2VET01PYmplY3Qub3JpZ2luYWxFbGVtZW50LCBiYXNlRE9NT2JqZWN0LmxpbmVzT2ZFbGVtZW50LCBiYXNlRE9NT2JqZWN0LlVJRCwgRE9NT2JqZWN0VGFnLnN0YXJ0UmVnaW9uKTtcbiAgICAgICAgdGhpcy5yZWdpb25FbGVtZW50ID0gcmVnaW9uRWxlbWVudDtcbiAgICB9XG59XG5cbmV4cG9ydCBjbGFzcyBUYXNrTGlzdERPTU9iamVjdCBleHRlbmRzIERPTU9iamVjdCB7XG5cbiAgICBvcmlnaW5hbENoZWNrYm94ZXM6IEhUTUxFbGVtZW50W10gPSBbXTtcbiAgICBjaGVja2JveEVsZW1lbnRzOiBNYXA8bnVtYmVyLCBIVE1MSW5wdXRFbGVtZW50PiA9IG5ldyBNYXAoKTtcbiAgICBjb25zdHJ1Y3RvcihiYXNlRE9NT2JqZWN0OiBET01PYmplY3QpIHtcblxuICAgICAgICBzdXBlcihiYXNlRE9NT2JqZWN0Lm9yaWdpbmFsRWxlbWVudCwgYmFzZURPTU9iamVjdC5saW5lc09mRWxlbWVudCwgYmFzZURPTU9iamVjdC5VSUQsIERPTU9iamVjdFRhZy5ub25lKTtcbiAgICB9XG5cbiAgICBjaGVja2JveENsaWNrZWQoaW5kZXg6IG51bWJlcikge1xuXG4gICAgICAgIGlmKHRoaXMuY2hlY2tib3hFbGVtZW50cy5oYXMoaW5kZXgpKSB7XG4gICAgICAgICAgICB0aGlzLmNoZWNrYm94RWxlbWVudHMuZ2V0KGluZGV4KS5jbGljaygpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoaW5kZXggPCB0aGlzLm9yaWdpbmFsQ2hlY2tib3hlcy5sZW5ndGgpIHtcblxuICAgICAgICAgICAgbGV0IG9yaWdpbmFsSW5wdXQgPSB0aGlzLm9yaWdpbmFsQ2hlY2tib3hlc1tpbmRleF0uZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSgndGFzay1saXN0LWl0ZW0tY2hlY2tib3gnKVxuICAgICAgICAgICAgaWYob3JpZ2luYWxJbnB1dC5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgICAgICAgICAob3JpZ2luYWxJbnB1dFswXSBhcyBIVE1MSW5wdXRFbGVtZW50KS5jbGljaygpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIkNvdWxkIG5vdCBmaW5kIGNoZWNrYm94IHRvIGNsaWNrLlwiKVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgZ2V0Q2hlY2tib3hFbGVtZW50KGluZGV4OiBudW1iZXIpOiBIVE1MSW5wdXRFbGVtZW50IHwgdW5kZWZpbmVkIHtcblxuXG4gICAgICAgIGlmKHRoaXMuY2hlY2tib3hFbGVtZW50cy5oYXMoaW5kZXgpID09PSBmYWxzZSkge1xuXG4gICAgICAgICAgICBpZihpbmRleCA8IHRoaXMub3JpZ2luYWxDaGVja2JveGVzLmxlbmd0aCkge1xuXG4gICAgICAgICAgICAgICAgbGV0IG9yaWdpbmFsSW5wdXQgPSB0aGlzLm9yaWdpbmFsQ2hlY2tib3hlc1tpbmRleF0/LmdldEVsZW1lbnRzQnlDbGFzc05hbWUoJ3Rhc2stbGlzdC1pdGVtLWNoZWNrYm94JylcbiAgICAgICAgICAgICAgICBpZihvcmlnaW5hbElucHV0Py5sZW5ndGggPT09IDEpIHtcblxuICAgICAgICAgICAgICAgICAgICB0aGlzLmNoZWNrYm94RWxlbWVudHMuc2V0KGluZGV4LCAob3JpZ2luYWxJbnB1dFswXSBhcyBIVE1MSW5wdXRFbGVtZW50KSlcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJDb3VsZCBub3QgZmluZCBjaGVja2JveCBlbGVtZW50IHRvIHJldHVybi5cIiwgdGhpcy5vcmlnaW5hbENoZWNrYm94ZXMsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuY2hlY2tib3hFbGVtZW50cy5nZXQoaW5kZXgpO1xuICAgIH1cblxuICAgIHN0YXRpYyBjaGVja0ZvclRhc2tMaXN0RWxlbWVudChkb21FbGVtZW50OiBET01PYmplY3QpIHtcblxuICAgICAgICBpZihkb21FbGVtZW50Lm9yaWdpbmFsRWxlbWVudC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKFwidGFzay1saXN0LWl0ZW1cIikubGVuZ3RoID4gMCApIHtcblxuICAgICAgICAgICAgcmV0dXJuIG5ldyBUYXNrTGlzdERPTU9iamVjdChkb21FbGVtZW50KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBkb21FbGVtZW50O1xuICAgIH1cblxuICAgIHN0YXRpYyBnZXRDaGlsZENoZWNrYm94KGVsOiBIVE1MRWxlbWVudCk6IEhUTUxFbGVtZW50IHtcblxuICAgICAgICBsZXQgY2hlY2tib3hFbGVtZW50cyA9IGVsLmdldEVsZW1lbnRzQnlDbGFzc05hbWUoJ3Rhc2stbGlzdC1pdGVtLWNoZWNrYm94JylcbiAgICAgICAgaWYoY2hlY2tib3hFbGVtZW50cy5sZW5ndGggPT09IDEpIHtcblxuICAgICAgICAgICAgcmV0dXJuIGNoZWNrYm94RWxlbWVudHNbMF0gYXMgSFRNTEVsZW1lbnQ7XG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgIHJldHVybiBlbC5jaGlsZHJlblswXSBhcyBIVE1MRWxlbWVudFxuICAgIH1cbn0iLCIvKlxuICogRmlsZTogbXVsdGktY29sdW1uLW1hcmtkb3duL3NyYy91dGlsaXRpZXMvY3NzRGVmaW5pdGlvbnMudHNcbiAqIENyZWF0ZWQgRGF0ZTogV2VkbmVzZGF5LCBGZWJydWFyeSAxNnRoIDIwMjIsIDExOjA5OjA2IGFtXG4gKiBBdXRob3I6IENhbWVyb24gUm9iaW5zb25cbiAqIFxuICogQ29weXJpZ2h0IChjKSAyMDIyIENhbWVyb24gUm9iaW5zb25cbiAqL1xuXG5leHBvcnQgZW51bSBNdWx0aUNvbHVtbkxheW91dENTUyB7XG5cbiAgICBSZWdpb25Sb290Q29udGFpbmVyRGl2ID0gXCJtY20tY29sdW1uLXJvb3QtY29udGFpbmVyXCIsXG4gICAgUmVnaW9uRXJyb3JDb250YWluZXJEaXYgPSBcIm1jbS1jb2x1bW4tZXJyb3ItcmVnaW9uLXdyYXBwZXJcIixcbiAgICBSZWdpb25Db250ZW50Q29udGFpbmVyRGl2ID0gXCJtY20tY29sdW1uLXJlZ2lvbi13cmFwcGVyXCIsXG4gICAgUmVnaW9uQ29sdW1uQ29udGFpbmVyRGl2ID0gXCJtY20tY29sdW1uLXBhcmVudC1jb250YWluZXJcIixcbiAgICBDb2x1bW5EdWFsRWxlbWVudENvbnRhaW5lciA9IFwibWNtLWNvbHVtbi1lbGVtZW50LXdyYXBwZXJcIixcbiAgICBPcmlnaW5hbEVsZW1lbnRUeXBlID0gXCJtY20tb3JpZ2luYWwtY29sdW1uLWVsZW1lbnRcIixcbiAgICBDbG9uZWRFbGVtZW50VHlwZSA9IFwibWNtLWNsb25lZC1jb2x1bW4tZWxlbWVudFwiLFxuXG4gICAgQ29udGVudE92ZXJmbG93QXV0b1Njcm9sbCA9IFwibWNtLWNvbnRlbnQtb3ZlcmZsb3ctYXV0by1zY3JvbGxcIixcbiAgICBDb250ZW50T3ZlcmZsb3dIaWRkZW4gPSBcIm1jbS1jb250ZW50LW92ZXJmbG93LWhpZGRlblwiLFxuXG4gICAgQWxpZ25tZW50TGVmdCA9IFwibWNtLWNvbnRlbnQtYWxpZ25tZW50LWxlZnRcIixcbiAgICBBbGlnbm1lbnRDZW50ZXIgPSBcIm1jbS1jb250ZW50LWFsaWdubWVudC1jZW50ZXJcIixcbiAgICBBbGlnbm1lbnRSaWdodCA9IFwibWNtLWNvbnRlbnQtYWxpZ25tZW50LXJpZ2h0XCIsXG5cbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gLy9cblxuICAgIFNpbmdsZUNvbHVtblNtYWxsID0gXCJtY20tc2luZ2xlLWNvbHVtbi1zbWFsbFwiLFxuICAgIFNpbmdsZUNvbHVtbk1lZCA9IFwibWNtLXNpbmdsZS1jb2x1bW4tbWVkaXVtXCIsXG4gICAgU2luZ2xlQ29sdW1uTGFyZ2UgPSBcIm1jbS1zaW5nbGUtY29sdW1uLWxhcmdlXCIsXG4gICAgU2luZ2xlQ29sdW1uRnVsbCA9IFwibWNtLXNpbmdsZS1jb2x1bW4tZnVsbFwiLFxuXG4gICAgU2luZ2xlQ29sdW1uTGVmdExheW91dCA9IFwibWNtLXNpbmdsZWNvbC1sYXlvdXQtbGVmdFwiLFxuICAgIFNpbmdsZUNvbHVtbkNlbnRlckxheW91dCA9IFwibWNtLXNpbmdsZWNvbC1sYXlvdXQtY2VudGVyXCIsXG4gICAgU2luZ2xlQ29sdW1uUmlnaHRMYXlvdXQgPSBcIm1jbS1zaW5nbGVjb2wtbGF5b3V0LXJpZ2h0XCIsXG5cbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gLy9cblxuICAgIFR3b0VxdWFsQ29sdW1ucyA9IFwibWNtLXR3by1lcXVhbC1jb2x1bW5zXCIsXG5cbiAgICBUd29Db2x1bW5TbWFsbCA9IFwibWNtLXR3by1jb2x1bW4tc21hbGxcIixcbiAgICBUd29Db2x1bW5MYXJnZSA9IFwibWNtLXR3by1jb2x1bW4tbGFyZ2VcIixcblxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAvL1xuXG4gICAgVGhyZWVFcXVhbENvbHVtbnMgPSBcIm1jbS10aHJlZS1lcXVhbC1jb2x1bW5zXCIsXG5cbiAgICBUaHJlZUNvbHVtbl9MYXJnZSA9IFwibWNtLXRocmVlLWNvbHVtbi1sYXJnZVwiLFxuICAgIFRocmVlQ29sdW1uX1NtYWxsID0gXCJtY20tdGhyZWUtY29sdW1uLXNtYWxsXCIsXG59XG5cbmV4cG9ydCBlbnVtIE11bHRpQ29sdW1uU3R5bGVDU1Mge1xuXG4gICAgUmVnaW9uRXJyb3JNZXNzYWdlID0gXCJtY20tY29sdW1uLWVycm9yLW1lc3NhZ2VcIixcbiAgICBSZWdpb25TZXR0aW5ncyA9IFwibWNtLWNvbHVtbi1zZXR0aW5ncy13cmFwcGVyXCIsXG4gICAgUmVnaW9uQ29udGVudCA9IFwibWNtLWNvbHVtbi1jb250ZW50LXdyYXBwZXJcIixcbiAgICBSZWdpb25FbmRUYWcgPSBcIm1jbS1jb2x1bW4tZW5kLXRhZy13cmFwcGVyXCIsXG4gICAgQ29sdW1uRW5kVGFnID0gXCJtY20tY29sdW1uLWJyZWFrLXRhZy13cmFwcGVyXCIsXG4gICAgUmVnaW9uU2hhZG93ID0gXCJtY20tcmVnaW9uLXNoYWRvd1wiLFxuICAgIENvbHVtblNoYWRvdyA9IFwibWNtLWNvbHVtbi1zaGFkb3dcIixcbiAgICBDb2x1bW5Cb3JkZXIgPSBcIm1jbS1jb2x1bW4tYm9yZGVyXCIsXG4gICAgQ29sdW1uQ29udGVudCA9IFwibWNtLWNvbHVtbi1kaXZcIlxufSIsIi8qKlxuICogRmlsZTogL3NyYy9kb21fbWFuYWdlci9yZWdpb25hbF9tYW5hZ2Vycy9SZWdpb25NYW5hZ2VyLnRzICAgICAgICAgICAgICAgICAgICpcbiAqIENyZWF0ZWQgRGF0ZTogU3VuZGF5LCBNYXkgMjJuZCAyMDIyLCA3OjQ5IHBtICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gKiBBdXRob3I6IENhbWVyb24gUm9iaW5zb24gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpcbiAqIENvcHlyaWdodCAoYykgMjAyMiBDYW1lcm9uIFJvYmluc29uICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gKi9cblxuaW1wb3J0IHsgRE9NT2JqZWN0LCBET01PYmplY3RUYWcsIFRhc2tMaXN0RE9NT2JqZWN0IH0gZnJvbSAnLi4vZG9tT2JqZWN0JztcbmltcG9ydCB7IE11bHRpQ29sdW1uU2V0dGluZ3MsIENvbHVtbkxheW91dCwgZ2V0RGVmYXVsdE11bHRpQ29sdW1uU2V0dGluZ3MgfSBmcm9tIFwiLi4vLi4vcmVnaW9uU2V0dGluZ3NcIjtcbmltcG9ydCB7IE11bHRpQ29sdW1uTGF5b3V0Q1NTLCBNdWx0aUNvbHVtblN0eWxlQ1NTIH0gZnJvbSAnLi4vLi4vdXRpbGl0aWVzL2Nzc0RlZmluaXRpb25zJztcbmltcG9ydCB7IEZpbGVET01NYW5hZ2VyIH0gZnJvbSAnLi4vZG9tTWFuYWdlcic7XG5pbXBvcnQgeyBFbGVtZW50UmVuZGVyVHlwZSwgZ2V0RWxlbWVudFJlbmRlclR5cGUgfSBmcm9tICdzcmMvdXRpbGl0aWVzL2VsZW1lbnRSZW5kZXJUeXBlUGFyc2VyJztcbmltcG9ydCB7IFJlZ2lvbk1hbmFnZXJEYXRhIH0gZnJvbSAnLi9yZWdpb25NYW5hZ2VyQ29udGFpbmVyJztcbmltcG9ydCB7IHNlYXJjaENoaWxkcmVuRm9yTm9kZVR5cGUgfSBmcm9tICdzcmMvdXRpbGl0aWVzL3V0aWxzJztcblxuZXhwb3J0IHR5cGUgTXVsdGlDb2x1bW5SZW5kZXJEYXRhID0geyBcbiAgICBwYXJlbnRSZW5kZXJFbGVtZW50OiBIVE1MRWxlbWVudCwgXG4gICAgcGFyZW50UmVuZGVyU2V0dGluZ3M6IE11bHRpQ29sdW1uU2V0dGluZ3MsXG4gICAgZG9tT2JqZWN0czogRE9NT2JqZWN0W11cbn1cblxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIFJlZ2lvbk1hbmFnZXIge1xuXG4gICAgcHJvdGVjdGVkIGRvbUxpc3Q6IERPTU9iamVjdFtdID0gW107XG4gICAgcHVibGljIGdldCBudW1iZXJPZkNoaWxkcmVuKCk6IG51bWJlciB7XG4gICAgICAgIHJldHVybiB0aGlzLmRvbUxpc3QubGVuZ3RoO1xuICAgIH1cbiAgICBwcm90ZWN0ZWQgZG9tT2JqZWN0TWFwOiBNYXA8c3RyaW5nLCBET01PYmplY3Q+ID0gbmV3IE1hcCgpO1xuICAgIHByaXZhdGUgX3JlZ2lvblBhcmVudDogSFRNTEVsZW1lbnQ7XG4gICAgcHVibGljIGdldCByZWdpb25QYXJlbnQoKTogSFRNTEVsZW1lbnQge1xuICAgICAgICByZXR1cm4gdGhpcy5fcmVnaW9uUGFyZW50O1xuICAgIH1cbiAgICBwdWJsaWMgc2V0IHJlZ2lvblBhcmVudCh2YWx1ZTogSFRNTEVsZW1lbnQpIHtcbiAgICAgICAgdGhpcy5fcmVnaW9uUGFyZW50ID0gdmFsdWU7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIGZpbGVNYW5hZ2VyOiBGaWxlRE9NTWFuYWdlcjtcbiAgICBwcm90ZWN0ZWQgcmVnaW9uYWxTZXR0aW5nczogTXVsdGlDb2x1bW5TZXR0aW5ncyA9IGdldERlZmF1bHRNdWx0aUNvbHVtblNldHRpbmdzKCk7XG5cbiAgICBwcm90ZWN0ZWQgcmVnaW9uS2V5OiBzdHJpbmc7XG5cbiAgICBjb25zdHJ1Y3RvcihkYXRhOiBSZWdpb25NYW5hZ2VyRGF0YSkge1xuXG4gICAgICAgIHRoaXMuZG9tTGlzdCA9IGRhdGEuZG9tTGlzdDtcbiAgICAgICAgdGhpcy5kb21PYmplY3RNYXAgPSBkYXRhLmRvbU9iamVjdE1hcDtcbiAgICAgICAgdGhpcy5yZWdpb25QYXJlbnQgPSBkYXRhLnJlZ2lvblBhcmVudDtcblxuICAgICAgICB0aGlzLmZpbGVNYW5hZ2VyID0gZGF0YS5maWxlTWFuYWdlcjtcbiAgICAgICAgdGhpcy5yZWdpb25hbFNldHRpbmdzID0gZGF0YS5yZWdpb25hbFNldHRpbmdzO1xuXG4gICAgICAgIHRoaXMucmVnaW9uS2V5ID0gZGF0YS5yZWdpb25LZXk7XG4gICAgfVxuXG4gICAgcHVibGljIGdldFJlZ2lvbkRhdGEoKTogUmVnaW9uTWFuYWdlckRhdGEge1xuXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBkb21MaXN0OiB0aGlzLmRvbUxpc3QsXG4gICAgICAgICAgICBkb21PYmplY3RNYXA6IHRoaXMuZG9tT2JqZWN0TWFwLFxuICAgICAgICAgICAgcmVnaW9uUGFyZW50OiB0aGlzLnJlZ2lvblBhcmVudCxcblxuICAgICAgICAgICAgZmlsZU1hbmFnZXI6IHRoaXMuZmlsZU1hbmFnZXIsXG4gICAgICAgICAgICByZWdpb25hbFNldHRpbmdzOiB0aGlzLnJlZ2lvbmFsU2V0dGluZ3MsXG5cbiAgICAgICAgICAgIHJlZ2lvbktleTogdGhpcy5yZWdpb25LZXksXG4gICAgICAgICAgICByb290RWxlbWVudDogbnVsbFxuICAgICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFkZHMgYSBuZXcgb2JqZWN0IHRvIHRoZSByZWdpb24gYnkgZmluZGluZyB3aGVyZSBpdCBzaG91bGQgYmUgcmVsYXRpdmUgdG8gaXRzIHNpYmxpbmdzLlxuICAgICAqIEBwYXJhbSBzaWJsaW5nc0Fib3ZlIFRoZSBNYXJrZG93biB0ZXh0IHJlbmRlcmVkIGVsZW1lbnRzIGZvciBzaWJpbGluZ3MgYWJvdmUgdGhpcyBlbGVtZW50IGluIHRoZSBkb21cbiAgICAgKiBAcGFyYW0gc2libGluZ3NCZWxvdyBUaGUgTWFya2Rvd24gdGV4dCByZW5kZXJlZCBlbGVtZW50cyBmb3Igc2liaWxpbmdzIGJlbG93IHRoaXMgZWxlbWVudCBpbiB0aGUgZG9tXG4gICAgICogQHBhcmFtIG9iaiBUaGUgb2JqZWN0IHRvIGFkZC5cbiAgICAgKiBAcmV0dXJucyBSZXR1cm5zIHRoZSBpbmRleCBhdCB3aGljaCB0aGUgb2JqZWN0IGhhcyBiZWVuIGFkZGVkLlxuICAgICAqL1xuICAgIHB1YmxpYyBhZGRPYmplY3Qoc2libGluZ3NBYm92ZTogSFRNTERpdkVsZW1lbnQsIHNpYmxpbmdzQmVsb3c6IEhUTUxEaXZFbGVtZW50LCBvYmo6IERPTU9iamVjdCk6IG51bWJlciB7XG5cbiAgICAgICAgbGV0IG5leHRPYmogPSBzaWJsaW5nc0JlbG93LmNoaWxkcmVuWzBdIGFzIEhUTUxFbGVtZW50O1xuXG4gICAgICAgIGxldCBhZGRBdEluZGV4ID0gc2libGluZ3NBYm92ZS5jaGlsZHJlbi5sZW5ndGg7XG5cbiAgICAgICAgaWYgKHNpYmxpbmdzQWJvdmUuY2hpbGRyZW4ubGVuZ3RoID4gMCkge1xuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFdlIHdhbnQgdG8gZmluZCB0aGUgZmlyc3Qgc2libGluZyB3aXRob3V0aCBcIlwiIGZvciBhbiBpbm5lciB0ZXh0IHNvIHdlIGNhbiB1c2UgdGhhdCB0byBhbmNob3Igb3VyXG4gICAgICAgICAgICAgKiBlbGVtZW50IGludG8gdGhlIGRvbUxpc3QuIEZvciBtb3N0IGl0ZW1zIHRoZSBmaXJzdCBlbGVtZW50IGJlZm9yZSBvdXIgbmV3IGVsZW1lbnQgd2lsbCBoYXZlIHRoZSBwcm9wZXJcbiAgICAgICAgICAgICAqIGlubmVyVGV4dC4gU29tZXRpbWVzIG90aGVyIGVsZW1lbnRzIGFyZSBlbXB0eSBhbmQgd2VyZSBjYXVzaW5nIGlzc3Vlcy5cbiAgICAgICAgICAgICAqIFxuICAgICAgICAgICAgICogTm93IHdlIGxvb3AgYmFjayB0aHJvdWdoIHRoZSBwcmV2aW91cyBzaWJsaW5ncyBsb29raW5nIGZvciB0aGUgZmlyc3Qgb25lIHdpdGggYSB2YWxpZCBpbm5lciB0ZXh0IGFuZCB1c2luZyB0aGF0IFxuICAgICAgICAgICAgICogYXMgdGhlIGFuY2hvciBhbmQgb2Zmc2V0dGluZyBvdXIgYWRkQXRJbmRleCBieSB0aGUgbnVtYmVyIG9mIGVtcHR5IHN0cmluZyBlbGVtZW50cyB3ZSBmb3VuZC5cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgbGV0IHByZXZTaWJsaW5nSW5uZXJUZXh0ID0gXCJcIlxuICAgICAgICAgICAgbGV0IHByZXZTaWJsaW5nT2Zmc2V0ID0gMDtcbiAgICAgICAgICAgIGZvcihsZXQgaSA9IHNpYmxpbmdzQWJvdmUuY2hpbGRyZW4ubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcblxuICAgICAgICAgICAgICAgIGxldCBvYmogPSBzaWJsaW5nc0Fib3ZlLmNoaWxkcmVuW2ldIGFzIEhUTUxFbGVtZW50O1xuICAgICAgICAgICAgICAgIGlmKG9iai5pbm5lclRleHQgIT09IFwiXCIpIHtcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICAgICAgcHJldlNpYmxpbmdJbm5lclRleHQgPSBvYmouaW5uZXJUZXh0O1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBwcmV2U2libGluZ09mZnNldCsrO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmb3IgKGxldCBpID0gdGhpcy5kb21MaXN0Lmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuZG9tTGlzdFtpXS5ub2RlS2V5ID09PSBwcmV2U2libGluZ0lubmVyVGV4dCkge1xuICAgICAgICAgICAgICAgICAgICBhZGRBdEluZGV4ID0gaSArIDEgKyBwcmV2U2libGluZ09mZnNldDtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgbGV0IG5leHRFbEluZGV4ID0gYWRkQXRJbmRleDtcbiAgICAgICAgbGV0IG5leHRPYmpUZXh0ID0gXCJcIjtcbiAgICAgICAgaWYgKG5leHRPYmogIT09IHVuZGVmaW5lZCkge1xuXG4gICAgICAgICAgICBsZXQgZm91bmROZXh0ID0gZmFsc2U7XG4gICAgICAgICAgICBuZXh0T2JqVGV4dCA9IG5leHRPYmouaW5uZXJUZXh0O1xuXG4gICAgICAgICAgICBmb3IgKGxldCBpID0gYWRkQXRJbmRleDsgaSA8IHRoaXMuZG9tTGlzdC5sZW5ndGg7IGkrKykge1xuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuZG9tTGlzdFtpXS5ub2RlS2V5ID09PSBuZXh0T2JqLmlubmVyVGV4dC50cmltKCkpIHtcblxuICAgICAgICAgICAgICAgICAgICBuZXh0RWxJbmRleCA9IGk7XG4gICAgICAgICAgICAgICAgICAgIGZvdW5kTmV4dCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGNvbnNvbGUubG9nKFwiIFByZXY6IFwiLCBBcnJheS5mcm9tKHNpYmxpbmdzQWJvdmUuY2hpbGRyZW4pLnNsaWNlKC0zKSwgXCJBZGRpbmc6IFwiLCBvYmoub3JpZ2luYWxFbGVtZW50LCBcIiBOZXh0OiBcIiwgc2libGluZ3NCZWxvdy5jaGlsZHJlblswXSwgXCJPdmVyd3JpdGluZzpcIiwgdGhpcy5kb21MaXN0LnNsaWNlKGFkZEF0SW5kZXgsIG5leHRFbEluZGV4KSk7XG4gICAgICAgIHRoaXMuZG9tTGlzdC5zcGxpY2UoYWRkQXRJbmRleCwgbmV4dEVsSW5kZXggLSBhZGRBdEluZGV4LCBvYmopO1xuICAgICAgICB0aGlzLmRvbU9iamVjdE1hcC5zZXQob2JqLlVJRCwgb2JqKTtcblxuICAgICAgICAvLyAvKipcbiAgICAgICAgLy8gICogTWFrZSBhIGNvcHkgb2YgdGhlIGxpc3QgdG8gbG9nLCBvbmx5IGJlY2F1c2VcbiAgICAgICAgLy8gICogY29uc29sZSBsb2cgdXBkYXRlcyBpdHMgcmVmZXJlbmNlcyB3aXRoIHVwZGF0ZXMgaW4gbWVtb3J5LlxuICAgICAgICAvLyAgKi9cbiAgICAgICAgLy8gbGV0IHggPSB0aGlzLmRvbUxpc3Quc2xpY2UoMCk7XG4gICAgICAgIC8vIGNvbnNvbGUubG9nKHgpO1xuICAgICAgICByZXR1cm4gYWRkQXRJbmRleDtcbiAgICB9XG5cbiAgICBwdWJsaWMgYWRkT2JqZWN0QXRJbmRleChvYmo6IERPTU9iamVjdCwgaW5kZXg6IG51bWJlcikge1xuXG4gICAgICAgIHRoaXMuZG9tTGlzdC5zcGxpY2UoaW5kZXgsIDAsIG9iaik7XG4gICAgICAgIHRoaXMuZG9tT2JqZWN0TWFwLnNldChvYmouVUlELCBvYmopO1xuICAgIH1cblxuICAgIHB1YmxpYyByZW1vdmVPYmplY3Qob2JqZWN0VUlEOiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgLy8gLyoqXG4gICAgICAgIC8vICAqIE1ha2UgYSBjb3B5IG9mIHRoZSBsaXN0IHRvIGxvZ1xuICAgICAgICAvLyAgKi9cbiAgICAgICAgLy8gbGV0IHggPSBkb21MaXN0LnNsaWNlKDApO1xuICAgICAgICAvLyBjb25zb2xlLmxvZyh4KTtcbiAgICAgICAgLy8gR2V0IHRoZSBvYmplY3QgYnkga2V5LCByZW1vdmUgaXQgZnJvbSB0aGUgbWFwIGFuZCB0aGVuXG4gICAgICAgIC8vIGZyb20gdGhlIGxpc3QuXG4gICAgICAgIGxldCBvYmogPSB0aGlzLmRvbU9iamVjdE1hcC5nZXQob2JqZWN0VUlEKTtcbiAgICAgICAgdGhpcy5kb21PYmplY3RNYXAuZGVsZXRlKG9iamVjdFVJRCk7XG5cbiAgICAgICAgaWYgKG9iaiA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5kb21MaXN0LmNvbnRhaW5zKG9iaikpIHtcbiAgICAgICAgICAgIHRoaXMuZG9tTGlzdC5yZW1vdmUob2JqKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLmRvbUxpc3QubGVuZ3RoID09PSAwICYmIHRoaXMuZmlsZU1hbmFnZXIgIT09IG51bGwpIHtcbiAgICAgICAgICAgIHRoaXMuZmlsZU1hbmFnZXIucmVtb3ZlUmVnaW9uKHRoaXMucmVnaW9uS2V5KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHggPSBkb21MaXN0LnNsaWNlKDApO1xuICAgICAgICAvLyBjb25zb2xlLmxvZyh4KTtcbiAgICB9XG5cbiAgICBwdWJsaWMgdXBkYXRlRWxlbWVudFRhZyhvYmplY3RVSUQ6IHN0cmluZywgbmV3VGFnOiBET01PYmplY3RUYWcpOiB2b2lkIHtcblxuICAgICAgICBsZXQgb2JqID0gdGhpcy5kb21PYmplY3RNYXAuZ2V0KG9iamVjdFVJRCk7XG4gICAgICAgIG9iai50YWcgPSBuZXdUYWc7XG4gICAgfVxuXG4gICAgcHVibGljIHNldFJlZ2lvbmFsU2V0dGluZ3MocmVnaW9uU2V0dGluZ3M6IE11bHRpQ29sdW1uU2V0dGluZ3MpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5yZWdpb25hbFNldHRpbmdzID0gcmVnaW9uU2V0dGluZ3M7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBvYmplY3QgY29udGFpbmluZyBhbGwgbmVjZXNzYXJ5IGluZm9ybWF0aW9uIGZvciB0aGUgcmVnaW9uXG4gICAgICogdG8gYmUgcmVuZGVyZWQgdG8gdGhlIHByZXZpZXcgcGFuZS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIGEgTXVsdGlDb2x1bW5SZW5kZXJEYXRhIG9iamVjdCB3aXRoIHRoZSByb290IERPTSBlbGVtZW50LCBzZXR0aW5ncyBvYmplY3QsIGFuZFxuICAgICAqIGFsbCBjaGlsZCBvYmplY3RzIGluIHRoZSBvcmRlciB0aGV5IHNob3VsZCBiZSByZW5kZXJlZC5cbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0UmVnaW9uUmVuZGVyRGF0YSgpOiBNdWx0aUNvbHVtblJlbmRlckRhdGEge1xuXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBwYXJlbnRSZW5kZXJFbGVtZW50OiB0aGlzLnJlZ2lvblBhcmVudCxcbiAgICAgICAgICAgIHBhcmVudFJlbmRlclNldHRpbmdzOiB0aGlzLnJlZ2lvbmFsU2V0dGluZ3MsXG4gICAgICAgICAgICBkb21PYmplY3RzOiB0aGlzLmRvbUxpc3RcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIGZ1Y3Rpb24gaXMgY2FsbGVkIHdoZW4gYSBzdGFydCB0YWcgaXMgcmVtb3ZlZCBmcm9tIHZpZXcgbWVhbmluZ1xuICAgICAqIG91ciBwYXJlbnQgZWxlbWVudCBzdG9yaW5nIHRoZSBtdWx0aS1jb2x1bW4gcmVnaW9uIGlzIHJlbW92ZWQuIEl0XG4gICAgICogcmVtb3ZlcyB0aGUgQ1NTIGNsYXNzIGZyb20gYWxsIG9mIHRoZSBlbGVtZW50cyBzbyB0aGV5IHdpbGwgYmVcbiAgICAgKiByZS1yZW5kZXJlZCBpbiB0aGUgcHJldmlldyB3aW5kb3cuXG4gICAgICovXG4gICAgcHVibGljIGRpc3BsYXlPcmlnaW5hbEVsZW1lbnRzKCkge1xuXG5cbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLmRvbUxpc3QubGVuZ3RoOyBpKyspIHtcblxuICAgICAgICAgICAgaWYgKHRoaXMuZG9tTGlzdFtpXS5vcmlnaW5hbEVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmRvbUxpc3RbaV0ub3JpZ2luYWxFbGVtZW50LnJlbW92ZUNsYXNzZXMoW011bHRpQ29sdW1uU3R5bGVDU1MuUmVnaW9uRW5kVGFnLFxuICAgICAgICAgICAgICAgIE11bHRpQ29sdW1uU3R5bGVDU1MuQ29sdW1uRW5kVGFnLFxuICAgICAgICAgICAgICAgIE11bHRpQ29sdW1uU3R5bGVDU1MuUmVnaW9uU2V0dGluZ3MsXG4gICAgICAgICAgICAgICAgTXVsdGlDb2x1bW5TdHlsZUNTUy5SZWdpb25Db250ZW50XSk7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuZG9tTGlzdFtpXS5vcmlnaW5hbEVsZW1lbnQucGFyZW50RWxlbWVudCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRvbUxpc3RbaV0ub3JpZ2luYWxFbGVtZW50LnBhcmVudEVsZW1lbnQucmVtb3ZlQ2hpbGQodGhpcy5kb21MaXN0W2ldLm9yaWdpbmFsRWxlbWVudCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIFxuICAgIHB1YmxpYyBnZXRJRCgpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gdGhpcy5yZWdpb25LZXk7XG4gICAgfVxuXG4gICAgcHVibGljIHVwZGF0ZVJlbmRlcmVkTWFya2Rvd24oKSB7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBUaGlzIGZ1bmN0aW9uIGFjdHMgYXMgdGhlIHVwZGF0ZSBsb29wIGZvciB0aGUgbXVsdGktY29sdW1uIHJlZ2lvbnMuXG4gICAgICAgICAqIEhlcmUgd2UgbG9vcCB0aHJvdWdoIGFsbCBvZiB0aGUgZWxlbWVudHMgd2l0aGluIHRoZSByZW5kZXJlZCByZWdpb24gYW5kXG4gICAgICAgICAqIHBvdGVudGlhbGx5IHVwZGF0ZSBob3cgdGhpbmdzIGFyZSByZW5kZXJlZC4gV2UgbmVlZCB0byBkbyB0aGlzIGZvclxuICAgICAgICAgKiBjb21wYXRhYmlsaXR5IHdpdGggb3RoZXIgcGx1Z2lucy5cbiAgICAgICAgICpcbiAgICAgICAgICogSWYgdGhlIG11bHRpLWNvbHVtbiByZWdpb24gaXMgcmVuZGVyZWQgYmVmb3JlIG90aGVyIHBsdWdpbnMgdGhhdCBlZmZlY3RcbiAgICAgICAgICogY29udGVudCB3aXRoaW4gdGhlIHJlZ2lvbiBvdXIgcmVuZGVyZWQgZGF0YSBtYXkgbm90IHByb3Blcmx5IGRpc3BsYXlcbiAgICAgICAgICogdGhlIGNvbnRlbnQgZnJvbSB0aGUgb3RoZXIgcGx1Z2luLiBIZXJlIHdlIGxvb3AgdGhyb3VnaCB0aGUgZWxlbWVudHNcbiAgICAgICAgICogYWZ0ZXIgYWxsIHBsdWdpbnMgaGF2ZSBoYWQgYSBjaGFuY2UgdG8gcnVuIGFuZCBjYW4gbWFrZSBjaGFuZ2VzIHRvIHRoZVxuICAgICAgICAgKiBET00gYXQgdGhpcyBwb2ludC5cbiAgICAgICAgICovXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5kb21MaXN0Lmxlbmd0aDsgaSsrKSB7XG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogSGVyZSB3ZSBjaGVjayBmb3Igc3BlY2lhbCBjYXNlc1xuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBpZiAodGhpcy5kb21MaXN0W2ldIGluc3RhbmNlb2YgVGFza0xpc3RET01PYmplY3QpIHtcblxuICAgICAgICAgICAgICAgIHRoaXMuZml4Q2xvbmVkQ2hlY2tMaXN0QnV0dG9ucyh0aGlzLmRvbUxpc3RbaV0gYXMgVGFza0xpc3RET01PYmplY3QpO1xuICAgICAgICAgICAgfVxuXG5cbiAgICAgICAgICAgIGxldCBlbGVtZW50VHlwZSA9IHRoaXMuZG9tTGlzdFtpXS5lbGVtZW50VHlwZTtcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBJZiB0aGUgZWxlbWVudCBpcyBub3QgY3VycmVudGx5IGEgc3BlY2lhbCByZW5kZXIgZWxlbWVudCB3ZSBjaGVjayBhZ2FpblxuICAgICAgICAgICAgICogYXMgdGhlIG9yaWdpbmFsIGVsZW1lbnQgbWF5IGhhdmUgYmVlbiB1cGRhdGVkLlxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIFRPRE86IGZpbmQgYSB3YXkgdG8gXCJPZmZpY2lhbGx5XCIgbWFyayBub3JtYWwgZWxlbWVudHMgcmF0aGVyIHRoYW5cbiAgICAgICAgICAgICAqIGNvbnRpbnVvdXNseSBzZWFyY2ggZm9yIHNwZWNpYWwgcmVuZGVyIHR5cGVzLlxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBpZiAoZWxlbWVudFR5cGUgIT09IEVsZW1lbnRSZW5kZXJUeXBlLnNwZWNpYWxSZW5kZXIgJiZcbiAgICAgICAgICAgICAgICBlbGVtZW50VHlwZSAhPT0gRWxlbWVudFJlbmRlclR5cGUuc3BlY2lhbFNpbmdsZUVsZW1lbnRSZW5kZXIgJiYgXG4gICAgICAgICAgICAgICAgZWxlbWVudFR5cGUgIT09IEVsZW1lbnRSZW5kZXJUeXBlLnVuUmVuZGVyZWQpIHtcblxuICAgICAgICAgICAgICAgIC8vIElmIHRoZSBuZXcgcmVzdWx0IHJldHVybnMgYXMgYSBzcGVjaWFsIHJlbmRlcmVyIHdlIHVwZGF0ZSBzb1xuICAgICAgICAgICAgICAgIC8vIHRoaXMgd29udCBydW4gYWdhaW4gZm9yIHRoaXMgaXRlbS5cbiAgICAgICAgICAgICAgICBlbGVtZW50VHlwZSA9IGdldEVsZW1lbnRSZW5kZXJUeXBlKHRoaXMuZG9tTGlzdFtpXS5vcmlnaW5hbEVsZW1lbnQpO1xuICAgICAgICAgICAgICAgIHRoaXMuZG9tTGlzdFtpXS5vcmlnaW5hbEVsZW1lbnQuY2xpZW50SGVpZ2h0O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoZWxlbWVudFR5cGUgPT09IEVsZW1lbnRSZW5kZXJUeXBlLnNwZWNpYWxSZW5kZXIgfHxcbiAgICAgICAgICAgICAgICBlbGVtZW50VHlwZSA9PT0gRWxlbWVudFJlbmRlclR5cGUuc3BlY2lhbFNpbmdsZUVsZW1lbnRSZW5kZXIgfHwgXG4gICAgICAgICAgICAgICAgZWxlbWVudFR5cGUgPT09IEVsZW1lbnRSZW5kZXJUeXBlLmNhbnZhc1JlbmRlckVsZW1lbnQpIHtcblxuICAgICAgICAgICAgICAgIHRoaXMuZG9tTGlzdFtpXS5lbGVtZW50VHlwZSA9IGVsZW1lbnRUeXBlO1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0VXBEdWFsUmVuZGVyKHRoaXMuZG9tTGlzdFtpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIGZ1bmN0aW9uIHRha2VzIGluIHRoZSBvcmlnaW5hbCBlbGVtZW50IGFuZCBpdHMgY2xvbmUgYW5kIGNoZWNrcyBpZlxuICAgICAqIHRoZSBlbGVtZW50IGNvbnRhaW5zIGEgdGFzay1saXN0LWl0ZW0gY2xhc3MuIElmIHNvIGl0IGxvb3BzIHRocm91Z2ggYWxsXG4gICAgICogaXRlbXMgaW4gdGhlIGxpc3QgYW5kIGZpeGVzIHRoZWlyIGNoZWNrYm94ZXMgdG8gcHJvcGVybHkgZmlyZSBhbiBldmVudC5cbiAgICAgKiBUaGUgbmV3IGNoZWNrYm94IGNhbGxzIHRoZSBjbGljayBmdW5jdGlvbiBvbiB0aGUgb3JpZ2luYWwgY2hlY2tib3ggc29cbiAgICAgKiBjb21wYXRhYmlsaXR5IHdpdGggb3RoZXIgcGx1Z2lucyAqc2hvdWxkKiByZW1haW4uXG4gICAgICogQHBhcmFtIGRvbUVsZW1lbnRcbiAgICAgKiBAcGFyYW0gaW5pdGFsaXplQ2hlY2tib3hlc1xuICAgICAqL1xuICAgIHByb3RlY3RlZCBmaXhDbG9uZWRDaGVja0xpc3RCdXR0b25zKGRvbUVsZW1lbnQ6IFRhc2tMaXN0RE9NT2JqZWN0LCBpbml0YWxpemVDaGVja2JveGVzOiBib29sZWFuID0gZmFsc2UpIHtcblxuICAgICAgICBpZihkb21FbGVtZW50Lm9yaWdpbmFsRWxlbWVudCA9PT0gbnVsbCB8fCBkb21FbGVtZW50LmNsb25lZEVsZW1lbnQgPT09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBlbGVtZW50OiBIVE1MRWxlbWVudCA9IGRvbUVsZW1lbnQub3JpZ2luYWxFbGVtZW50O1xuICAgICAgICBsZXQgY2xvbmVkRWxlbWVudDogSFRNTEVsZW1lbnQgPSBkb21FbGVtZW50LmNsb25lZEVsZW1lbnQ7XG5cbiAgICAgICAgbGV0IGNsb25lZExpc3RDaGVja2JveGVzID0gQXJyYXkuZnJvbShjbG9uZWRFbGVtZW50LmdldEVsZW1lbnRzQnlDbGFzc05hbWUoXCJ0YXNrLWxpc3QtaXRlbVwiKSkgYXMgSFRNTEVsZW1lbnRbXTtcbiAgICAgICAgbGV0IG9yaWdpbmFsTGlzdENoZWNrYm94ZXMgPSBBcnJheS5mcm9tKGVsZW1lbnQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZShcInRhc2stbGlzdC1pdGVtXCIpKSBhcyBIVE1MRWxlbWVudFtdO1xuXG4gICAgICAgIGlmIChpbml0YWxpemVDaGVja2JveGVzID09PSB0cnVlKSB7XG5cbiAgICAgICAgICAgIGRvbUVsZW1lbnQub3JpZ2luYWxDaGVja2JveGVzID0gb3JpZ2luYWxMaXN0Q2hlY2tib3hlcztcbiAgICAgICAgICAgIC8vIFdoZW4gd2UgaW5pdGFsaXplIHdlIHJlbW92ZSB0aGUgb2xkIGlucHV0IGNoZWNrYm94IHRoYXQgY29udGFpbnNcbiAgICAgICAgICAgIC8vIHRoZSB3ZWlyZCBjYWxsYmFjayBzaXR1YXRpb24gY2F1c2luZyB0aGUgYnVnLiBUaGVuIHdlIGNyZWF0ZSBhIG5ld1xuICAgICAgICAgICAgLy8gY2hlY2tib3ggdG8gcmVwbGFjZSBpdCBhbmQgc2V0IGl0IHVwIHRvIGZpcmUgdGhlIGNsaWNrIGV2ZW50IG9uXG4gICAgICAgICAgICAvLyB0aGUgb3JpZ2luYWwgY2hlY2tib3ggc28gZnVuY3Rpb25hbGl0eSBpcyByZXN0b3JlZC5cbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgb3JpZ2luYWxMaXN0Q2hlY2tib3hlcy5sZW5ndGg7IGkrKykge1xuXG4gICAgICAgICAgICAgICAgY29uc3QgY2hlY2tib3ggPSBjcmVhdGVFbCgnaW5wdXQnKTtcblxuICAgICAgICAgICAgICAgIGxldCBvcmlnaW5hbElucHV0ID0gZG9tRWxlbWVudC5nZXRDaGVja2JveEVsZW1lbnQoaSk7XG4gICAgICAgICAgICAgICAgY2hlY2tib3guY2hlY2tlZCA9IG9yaWdpbmFsSW5wdXQ/LmNoZWNrZWQ7XG4gICAgICAgICAgICAgICAgY2xvbmVkTGlzdENoZWNrYm94ZXNbaV0ucmVwbGFjZUNoaWxkKGNoZWNrYm94LCBUYXNrTGlzdERPTU9iamVjdC5nZXRDaGlsZENoZWNrYm94KGNsb25lZExpc3RDaGVja2JveGVzW2ldKSk7XG5cbiAgICAgICAgICAgICAgICBjaGVja2JveC5hZGRDbGFzcygndGFzay1saXN0LWl0ZW0tY2hlY2tib3gnKTtcbiAgICAgICAgICAgICAgICBjaGVja2JveC50eXBlID0gJ2NoZWNrYm94JztcbiAgICAgICAgICAgICAgICBjaGVja2JveC5vbkNsaWNrRXZlbnQoKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBkb21FbGVtZW50LmNoZWNrYm94Q2xpY2tlZChpKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcblxuICAgICAgICAgICAgLy8gV2hlbmV2ZXIgd2UgcmVhY2ggdGhpcyBwb2ludCB3ZSB1cGRhdGUgb3VyIGxpc3Qgb2Ygb3JpZ2luYWwgY2hlY2tib3hlc1xuICAgICAgICAgICAgLy8gdGhhdCBtYXkgYmUgZGlmZmVyZW50IGZyb20gb3VyIGNhY2hlLiBUaGlzIGlzIGR1ZSB0byBob3cgb2JzaWRpYW5cbiAgICAgICAgICAgIC8vIGNoYW5nZXMgdGhlIERPTSB1bmRlcm5lYXRoIHVzIHNvIHdlIG5lZWQgdG8gY29uc3RhbnRseSB1cGRhdGUgb3VyIGNhY2hlLlxuICAgICAgICAgICAgZG9tRWxlbWVudC5vcmlnaW5hbENoZWNrYm94ZXMgPSBvcmlnaW5hbExpc3RDaGVja2JveGVzO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gV2hlbiB0aGUgVGFza3MgcGx1Z2luIGlzIGluc3RhbGxlZCB0aGUgY2xvbmVkIGNvcHkgb2YgdGhlIG9yaWdpbmFsIGVsZW1lbnQgY29udGFpbnNcbiAgICAgICAgLy8gYW4gZXh0cmEgZWxlbWVudCBmb3Igc29tZSByZWFzb24uIElmIHRoaXMgb2NjdXJzIGZvciBvdGhlciByZWFzb25zIGhlcmUgd2UgYWRqdXN0XG4gICAgICAgIC8vIHRoYXQgdG8ga2VlcCB0aGUgY2xvbmUgdGhlIHNhbWUgYXMgdGhlIG9yaWdpbmFsLlxuICAgICAgICBpZiAoY2xvbmVkTGlzdENoZWNrYm94ZXMubGVuZ3RoID4gb3JpZ2luYWxMaXN0Q2hlY2tib3hlcy5sZW5ndGgpIHtcblxuICAgICAgICAgICAgZm9yIChsZXQgaSA9IG9yaWdpbmFsTGlzdENoZWNrYm94ZXMubGVuZ3RoOyBpIDwgY2xvbmVkTGlzdENoZWNrYm94ZXMubGVuZ3RoOyBpKyspIHtcblxuICAgICAgICAgICAgICAgIGRvbUVsZW1lbnQuY2xvbmVkRWxlbWVudC5yZW1vdmVDaGlsZChjbG9uZWRMaXN0Q2hlY2tib3hlc1tpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgc2V0VXBEdWFsUmVuZGVyKGRvbUVsZW1lbnQ6IERPTU9iamVjdCkge1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBJZiBvdXIgZWxlbWVudCBpcyBvZiBcInNwZWNpYWxSZW5kZXJcIiB0eXBlIGl0ICptYXkqIG5lZWQgdG8gYmUgcmVuZGVyZWRcbiAgICAgICAgICogdXNpbmcgdGhlIG9yaWdpbmFsIGVsZW1lbnQgcmF0aGVyIHRoYW4gYSBjb3B5LiBGb3IgZXhhbXBsZSwgYW4gZWxlbWVudFxuICAgICAgICAgKiBtYXkgaGF2ZSBhbiBvbkNsaWNrIGV2ZW50IHRoYXQgd291bGQgbm90IGdldCBjb3BwaWVkIHRvIHRoZSBjbG9uZS5cbiAgICAgICAgICpcbiAgICAgICAgICogSWYgd2UganVzdCBtb3ZlZCB0aGVzZSBlbGVtZW50cyBpbnRvIHRoZSByZWdpb24gaXQgd291bGQgZ2V0XG4gICAgICAgICAqIG1vdmVkIGJhY2sgb3V0IGludG8gdGhlIG9yaWdpbmFsIGxvY2F0aW9uIGluIHRoZSBET00gYnkgb2JzaWRpYW5cbiAgICAgICAgICogd2hlbiBzY3JvbGxpbmcgb3Igd2hlbiB0aGUgZmlsZSBpcyB1cGRhdGVkLiBPbiB0aGUgbmV4dCByZWZyZXNoIGl0XG4gICAgICAgICAqIHdvdWxkIGJlIG1vdmVkIGJhY2sgYnV0IHRoYXQgY2FuIGxlYWQgdG8gYSByZWdpb24ganVtcGluZ1xuICAgICAgICAgKiBhcm91bmQgYXMgdGhlIGl0ZW0gaXMgbW92ZWQgaW4gYW5kIG91dC5cbiAgICAgICAgICpcbiAgICAgICAgICogSGVyZSB3ZSBzZXQgdXAgdGhlIGRpdiB0byBjb250YWluIHRoZSBlbGVtZW50IGFuZCBjcmVhdGVcbiAgICAgICAgICogYSB2aXN1YWwgb25seSBjbG9uZSBvZiBpdC4gVGhlIGNsb25lIHdpbGwgb25seSBiZSB2aXNpYmxlXG4gICAgICAgICAqIHdoZW4gdGhlIG9yaWdpbmFsIGlzIG5vdCBpbiB0aGUgbXVsdGktY29sdW1uIHJlZ2lvbiBzbyBpdFxuICAgICAgICAgKiBzYXZlcyB1cyBmcm9tIHRoZSB2aXN1YWwgbm9pc2Ugb2YgdGhlIHJlZ2lvbiBqdW1waW5nIGFyb3VuZC5cbiAgICAgICAgICovXG5cbiAgICAgICAgIGxldCBvcmlnaW5hbEVsZW1lbnQgPSBkb21FbGVtZW50Lm9yaWdpbmFsRWxlbWVudDtcbiAgICAgICAgIGxldCBjbG9uZWRFbGVtZW50ID0gZG9tRWxlbWVudC5jbG9uZWRFbGVtZW50O1xuICAgICAgICAgbGV0IGNvbnRhaW5lckVsZW1lbnQ6IEhUTUxEaXZFbGVtZW50ID0gZG9tRWxlbWVudC5lbGVtZW50Q29udGFpbmVyO1xuXG4gICAgICAgIC8vIEdldCBoZWlnaHQgb2YgdGhlIG9yaWdpbmFsIGFuZCBjbG9uZWQgZWxlbWVudC4gSWYgdGhlIGVsZW1lbnQgaXMgbm90IGN1cnJlbnRseSByZW5kZXJlZFxuICAgICAgICAvLyBpdCB3aWxsIGhhdmUgMCBoZWlnaHQgc28gd2UgbmVlZCB0byB0ZW1wb3JhcmlseSByZW5kZXIgaXQgdG8gZ2V0IHRoZSBoZWlnaHQuXG4gICAgICAgIGxldCBvcmlnaW5hbEVsZW1lbnRIZWlnaHQgPSBnZXRFbGVtZW50Q2xpZW50SGVpZ2h0KG9yaWdpbmFsRWxlbWVudCwgY29udGFpbmVyRWxlbWVudCk7XG4gICAgICAgIGxldCBjbG9uZWRFbGVtZW50SGVpZ2h0ID0gZ2V0RWxlbWVudENsaWVudEhlaWdodChjbG9uZWRFbGVtZW50LCBjb250YWluZXJFbGVtZW50KTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogV2Ugb25seSB3YW50IHRvIGNsb25lIHRoZSBlbGVtZW50IG9uY2UgdG8gcmVkdWNlIEdDLiBCdXQgaWYgdGhlIGNsb25lZCBcbiAgICAgICAgICogZWxlbWVudCdzIGhlaWdodCBpcyBub3QgZXF1YWwgdG8gdGhlIG9yaWdpbmFsIGVsZW1lbnQsIHRoaXMgbWVhbnMgdGhlXG4gICAgICAgICAqIGl0ZW0gZWxlbWVudCBoYXMgYmVlbiB1cGRhdGVkIHNvbWV3aGVyZSBlbHNlIHdpdGhvdXQgdGhlIGRvbSBiZWluZyBcbiAgICAgICAgICogcmVmcmVzaGVkLiBUaGlzIGNhbiBvY2N1ciB3aGVuIGVsZW1lbnRzIGFyZSB1cGRhdGVkIGJ5IG90aGVyIHBsdWdpbnMsIFxuICAgICAgICAgKiBzdWNoIGFzIERhdGF2aWV3LlxuICAgICAgICAgKi9cbiAgICAgICAgaWYoKGNsb25lZEVsZW1lbnQgPT09IG51bGwgIHx8IFxuICAgICAgICAgICBNYXRoLmFicyhjbG9uZWRFbGVtZW50SGVpZ2h0IC0gb3JpZ2luYWxFbGVtZW50SGVpZ2h0KSA+IDEwIHx8XG4gICAgICAgICAgIGRvbUVsZW1lbnQuY2xvbmVkRWxlbWVudFJlYWR5Rm9yVXBkYXRlKCkgPT09IHRydWUpICYmXG4gICAgICAgICAgIGRvbUVsZW1lbnQuZWxlbWVudFR5cGUgIT09IEVsZW1lbnRSZW5kZXJUeXBlLmNhbnZhc1JlbmRlckVsZW1lbnQpIHtcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgLy8gY29uc29sZS5sb2coXCJVcGRhdGluZyBDbG9uZWQgRWxlbWVudC5cIiwgRWxlbWVudFJlbmRlclR5cGVbZG9tRWxlbWVudC5lbGVtZW50VHlwZV0sIGNsb25lZEVsZW1lbnRIZWlnaHQsIG9yaWdpbmFsRWxlbWVudEhlaWdodClcbiAgICAgICAgICAgIC8vIFVwZGF0ZSBjbG9uZSBhbmQgcmVmZXJlbmNlLlxuICAgICAgICAgICAgY2xvbmVFbGVtZW50KCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZihkb21FbGVtZW50LmVsZW1lbnRUeXBlID09PSBFbGVtZW50UmVuZGVyVHlwZS5jYW52YXNSZW5kZXJFbGVtZW50ICYmIFxuICAgICAgICAgICBkb21FbGVtZW50LmNhbnZhc1JlYWR5Rm9yVXBkYXRlKCkpIHtcblxuICAgICAgICAgICAgLy8gY29uc29sZS5sb2coXCJVcGRhdGluZyBjYW52YXMgcmUtcmVuZGVyXCIpXG4gICAgICAgICAgICBjb250YWluZXJFbGVtZW50LmFwcGVuZENoaWxkKG9yaWdpbmFsRWxlbWVudCk7XG4gICAgICAgICAgICBpZihjbG9uZWRFbGVtZW50ICE9PSBudWxsICYmIGNsb25lZEVsZW1lbnQucGFyZW50RWxlbWVudCA9PT0gY29udGFpbmVyRWxlbWVudCkge1xuICAgICAgICAgICAgICAgIGNvbnRhaW5lckVsZW1lbnQucmVtb3ZlQ2hpbGQoY2xvbmVkRWxlbWVudCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGNsb25lQ2FudmFzKG9yaWdpbmFsQ2FudmFzOiBIVE1MQ2FudmFzRWxlbWVudCk6IEhUTUxDYW52YXNFbGVtZW50IHtcblxuICAgICAgICAgICAgICAgIC8vY3JlYXRlIGEgbmV3IGNhbnZhc1xuICAgICAgICAgICAgICAgIGxldCBjbG9uZWRDYW52YXM6IEhUTUxDYW52YXNFbGVtZW50ID0gb3JpZ2luYWxDYW52YXMuY2xvbmVOb2RlKHRydWUpIGFzIEhUTUxDYW52YXNFbGVtZW50O1xuICAgICAgICAgICAgICAgIGxldCBjb250ZXh0OiBDYW52YXNSZW5kZXJpbmdDb250ZXh0MkQgPSBjbG9uZWRDYW52YXMuZ2V0Q29udGV4dCgnMmQnKTtcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgIC8vc2V0IGRpbWVuc2lvbnNcbiAgICAgICAgICAgICAgICBjbG9uZWRDYW52YXMud2lkdGggPSBvcmlnaW5hbENhbnZhcy53aWR0aDtcbiAgICAgICAgICAgICAgICBjbG9uZWRDYW52YXMuaGVpZ2h0ID0gb3JpZ2luYWxDYW52YXMuaGVpZ2h0O1xuXG4gICAgICAgICAgICAgICAgaWYoY2xvbmVkQ2FudmFzLndpZHRoID09PSAwIHx8IGNsb25lZENhbnZhcy5oZWlnaHQgPT09IDApe1xuICAgICAgICAgICAgICAgICAgICAvLyBEb250IHdhbnQgdG8gcmVuZGVyIGlmIHRoZSB3aWR0aCBpcyAwIGFzIGl0IHRocm93cyBhbiBlcnJvclxuICAgICAgICAgICAgICAgICAgICAvLyB3b3VsZCBoYXBwZW4gaWYgdGhlIG9sZCBjYW52YXMgaGFzbnQgYmVlbiByZW5kZXJlZCB5ZXQuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBjbG9uZWRDYW52YXM7XG4gICAgICAgICAgICAgICAgfSBcblxuICAgICAgICAgICAgICAgIC8vYXBwbHkgdGhlIG9sZCBjYW52YXMgdG8gdGhlIG5ldyBvbmVcbiAgICAgICAgICAgICAgICBjb250ZXh0LmRyYXdJbWFnZShvcmlnaW5hbENhbnZhcywgMCwgMCk7XG4gICAgICAgICAgICBcbiAgICAgICAgICAgICAgICAvL3JldHVybiB0aGUgbmV3IGNhbnZhc1xuICAgICAgICAgICAgICAgIHJldHVybiBjbG9uZWRDYW52YXM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGxldCBjYW52YXMgPSBzZWFyY2hDaGlsZHJlbkZvck5vZGVUeXBlKG9yaWdpbmFsRWxlbWVudCwgXCJjYW52YXNcIik7XG4gICAgICAgICAgICBpZihjYW52YXMgIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICBkb21FbGVtZW50LnVwZGF0ZUNsb25lZEVsZW1lbnQob3JpZ2luYWxFbGVtZW50LmNsb25lTm9kZSh0cnVlKSBhcyBIVE1MRGl2RWxlbWVudCk7XG4gICAgICAgICAgICAgICAgY2xvbmVkRWxlbWVudCA9IGRvbUVsZW1lbnQuY2xvbmVkRWxlbWVudDtcbiAgICAgICAgICAgICAgICBjbG9uZWRFbGVtZW50LmFkZENsYXNzKE11bHRpQ29sdW1uTGF5b3V0Q1NTLkNsb25lZEVsZW1lbnRUeXBlKTtcbiAgICAgICAgICAgICAgICBjbG9uZWRFbGVtZW50LnJlbW92ZUNsYXNzZXMoW011bHRpQ29sdW1uU3R5bGVDU1MuUmVnaW9uQ29udGVudCwgTXVsdGlDb2x1bW5MYXlvdXRDU1MuT3JpZ2luYWxFbGVtZW50VHlwZV0pO1xuICAgICAgICAgICAgICAgIGNvbnRhaW5lckVsZW1lbnQuYXBwZW5kQ2hpbGQoY2xvbmVkRWxlbWVudCk7XG5cbiAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gY2xvbmVkRWxlbWVudC5jaGlsZHJlbi5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICAgICAgICAgICAgICBjbG9uZWRFbGVtZW50LmNoaWxkcmVuW2ldLmRldGFjaCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjbG9uZWRFbGVtZW50LmFwcGVuZENoaWxkKGNsb25lQ2FudmFzKGNhbnZhcyBhcyBIVE1MQ2FudmFzRWxlbWVudCkpXG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnRhaW5lckVsZW1lbnQucmVtb3ZlQ2hpbGQob3JpZ2luYWxFbGVtZW50KTtcbiAgICAgICAgICAgIGNvbnRhaW5lckVsZW1lbnQuYXBwZW5kQ2hpbGQoY2xvbmVkRWxlbWVudCk7XG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgIC8qKiBcbiAgICAgICAgICogSWYgdGhlIGNvbnRhaW5lciBlbGVtZW50IGhhcyBsZXNzIHRoYW4gMiBjaGlsZHJlbiB3ZSBuZWVkIHRvIG1vdmUgdGhlXG4gICAgICAgICAqIG9yaWdpbmFsIGVsZW1lbnQgYmFjayBpbnRvIGl0LiBIb3dldmVyIHNvbWUgZWxlbWVudHMgY29uc3RhbnRseSBnZXQgbW92ZWRcbiAgICAgICAgICogaW4gYW5kIG91dCBjYXVzaW5nIHNvbWUgdW53YW50ZWQgYmVoYXZpb3IuIFRob3NlIGVsZW1lbnQgd2lsbCBiZSB0YWdnZWRcbiAgICAgICAgICogYXMgc3BlY2lhbFNpbmdsZUVsZW1lbnRSZW5kZXIgc28gd2UgaWdub3JlIHRob3NlIGVsZW1lbnRzIGhlcmUuXG4gICAgICAgICAqL1xuICAgICAgICBpZihkb21FbGVtZW50LmVsZW1lbnRDb250YWluZXIuY2hpbGRyZW4ubGVuZ3RoIDwgMiAmJiBcbiAgICAgICAgICAgZG9tRWxlbWVudC5lbGVtZW50VHlwZSAhPT0gRWxlbWVudFJlbmRlclR5cGUuc3BlY2lhbFNpbmdsZUVsZW1lbnRSZW5kZXIgJiZcbiAgICAgICAgICAgZG9tRWxlbWVudC5lbGVtZW50VHlwZSAhPT0gRWxlbWVudFJlbmRlclR5cGUuY2FudmFzUmVuZGVyRWxlbWVudCkge1xuXG4gICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhcIlVwZGF0aW5nIGR1YWwgcmVuZGVyaW5nLlwiLCBkb21FbGVtZW50LCBkb21FbGVtZW50Lm9yaWdpbmFsRWxlbWVudC5wYXJlbnRFbGVtZW50LCBkb21FbGVtZW50Lm9yaWdpbmFsRWxlbWVudC5wYXJlbnRFbGVtZW50Py5jaGlsZEVsZW1lbnRDb3VudCk7XG5cbiAgICAgICAgICAgIC8vIE1ha2Ugc3VyZSBvdXIgQ1NTIGlzIHVwIHRvIGRhdGUuXG4gICAgICAgICAgICBvcmlnaW5hbEVsZW1lbnQuYWRkQ2xhc3MoTXVsdGlDb2x1bW5MYXlvdXRDU1MuT3JpZ2luYWxFbGVtZW50VHlwZSk7XG4gICAgICAgICAgICBjbG9uZWRFbGVtZW50LmFkZENsYXNzKE11bHRpQ29sdW1uTGF5b3V0Q1NTLkNsb25lZEVsZW1lbnRUeXBlKTtcbiAgICAgICAgICAgIGNsb25lZEVsZW1lbnQucmVtb3ZlQ2xhc3NlcyhbTXVsdGlDb2x1bW5TdHlsZUNTUy5SZWdpb25Db250ZW50LCBNdWx0aUNvbHVtbkxheW91dENTUy5PcmlnaW5hbEVsZW1lbnRUeXBlXSk7XG4gICAgXG4gICAgICAgICAgICBmb3IgKGxldCBpID0gY29udGFpbmVyRWxlbWVudC5jaGlsZHJlbi5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICAgICAgICAgIGNvbnRhaW5lckVsZW1lbnQuY2hpbGRyZW5baV0uZGV0YWNoKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb250YWluZXJFbGVtZW50LmFwcGVuZENoaWxkKG9yaWdpbmFsRWxlbWVudCk7XG4gICAgICAgICAgICBjb250YWluZXJFbGVtZW50LmFwcGVuZENoaWxkKGNsb25lZEVsZW1lbnQpO1xuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gY2xvbmVFbGVtZW50KCkge1xuICAgICAgICAgICAgZG9tRWxlbWVudC51cGRhdGVDbG9uZWRFbGVtZW50KG9yaWdpbmFsRWxlbWVudC5jbG9uZU5vZGUodHJ1ZSkgYXMgSFRNTERpdkVsZW1lbnQpO1xuICAgICAgICAgICAgY2xvbmVkRWxlbWVudCA9IGRvbUVsZW1lbnQuY2xvbmVkRWxlbWVudDtcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBJZiB3ZSB1cGRhdGVkIHRoZSBjbG9uZWQgZWxlbWVudCwgd2Ugd2FudCB0byBhbHNvIHVwZGF0ZSB0aGVcbiAgICAgICAgICAgICAqIGVsZW1lbnQgcmVuZGVyZWQgaW4gdGhlIHBhcmVudCBjb250YWluZXIuXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGZvciAobGV0IGkgPSBjb250YWluZXJFbGVtZW50LmNoaWxkcmVuLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgICAgICAgICAgY29udGFpbmVyRWxlbWVudC5jaGlsZHJlbltpXS5kZXRhY2goKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gVXBkYXRlIENTUywgd2UgYWRkIGNsb25lZCBjbGFzcyBhbmQgcmVtb3ZlIGNsYXNzZXMgZnJvbSBvcmlnaW5hbEVsZW1lbnQgdGhhdCBkbyBub3QgYXBwbHkuXG4gICAgICAgICAgICBjbG9uZWRFbGVtZW50LmFkZENsYXNzKE11bHRpQ29sdW1uTGF5b3V0Q1NTLkNsb25lZEVsZW1lbnRUeXBlKTtcbiAgICAgICAgICAgIGNsb25lZEVsZW1lbnQucmVtb3ZlQ2xhc3NlcyhbTXVsdGlDb2x1bW5TdHlsZUNTUy5SZWdpb25Db250ZW50LCBNdWx0aUNvbHVtbkxheW91dENTUy5PcmlnaW5hbEVsZW1lbnRUeXBlXSk7XG4gICAgICAgICAgICBjb250YWluZXJFbGVtZW50LmFwcGVuZENoaWxkKGNsb25lZEVsZW1lbnQpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB1cCB0aGUgQ1NTIGNsYXNzZXMgYW5kIHRoZSBudW1iZXIgb2YgY29sdW1ucyBiYXNlZCBvbiB0aGUgcGFzc2VkIHNldHRpbmdzLlxuICAgICAqIEBwYXJhbSBzZXR0aW5ncyBUaGUgdXNlciBkZWZpbmVkIHNldHRpbmdzIHRoYXQgZGV0ZXJtaW5lIHdoYXQgQ1NTIGlzIHNldCBoZXJlLlxuICAgICAqIEBwYXJhbSBtdWx0aUNvbHVtblBhcmVudCBUaGUgcGFyZW50IG9iamVjdCB0aGF0IHRoZSBjb2x1bW4gZGl2cyB3aWxsIGJlIGNyZWF0ZWQgdW5kZXIuXG4gICAgICogQHJldHVybnMgVGhlIGxpc3Qgb2YgY29sdW1uIGRpdnMgY3JlYXRlZCB1bmRlciB0aGUgcGFzc2VkIHBhcmVudCBlbGVtZW50LlxuICAgICAqL1xuICAgIGdldENvbHVtbkNvbnRlbnREaXZzKHNldHRpbmdzOiBNdWx0aUNvbHVtblNldHRpbmdzLCBtdWx0aUNvbHVtblBhcmVudDogSFRNTERpdkVsZW1lbnQpOiBIVE1MRGl2RWxlbWVudFtdIHtcblxuICAgICAgICBsZXQgY29sdW1uQ29udGVudERpdnM6IEhUTUxEaXZFbGVtZW50W10gPSBbXVxuICAgICAgICBsZXQgc3R5bGVTdHI6IHN0cmluZyA9IFwiXCJcbiAgICAgICAgaWYoc2V0dGluZ3MuY29sdW1uU3BhY2luZyAhPT0gXCJcIikge1xuXG4gICAgICAgICAgICBzdHlsZVN0ciA9IGBtYXJnaW4taW5saW5lOiAke3NldHRpbmdzLmNvbHVtblNwYWNpbmd9O2BcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKHNldHRpbmdzLm51bWJlck9mQ29sdW1ucyA9PT0gMikge1xuXG4gICAgICAgICAgICBzd2l0Y2goc2V0dGluZ3MuY29sdW1uTGF5b3V0KSB7XG4gICAgICAgICAgICAgICAgY2FzZShDb2x1bW5MYXlvdXQuc3RhbmRhcmQpOlxuICAgICAgICAgICAgICAgIGNhc2UoQ29sdW1uTGF5b3V0Lm1pZGRsZSk6XG4gICAgICAgICAgICAgICAgY2FzZShDb2x1bW5MYXlvdXQuY2VudGVyKTpcbiAgICAgICAgICAgICAgICBjYXNlKENvbHVtbkxheW91dC50aGlyZCk6XG4gICAgICAgICAgICAgICAgICAgIGNvbHVtbkNvbnRlbnREaXZzLnB1c2gobXVsdGlDb2x1bW5QYXJlbnQuY3JlYXRlRGl2KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsczogYCR7TXVsdGlDb2x1bW5TdHlsZUNTUy5Db2x1bW5Db250ZW50fSAke011bHRpQ29sdW1uTGF5b3V0Q1NTLlR3b0VxdWFsQ29sdW1uc31gXG4gICAgICAgICAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgICAgICAgICAgbXVsdGlDb2x1bW5QYXJlbnQuY3JlYXRlRGl2KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsczogYG1jbS1jb2x1bW4tc3BhY2VyYCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGF0dHI6IHtcInN0eWxlXCI6IHN0eWxlU3RyfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgY29sdW1uQ29udGVudERpdnMucHVzaChtdWx0aUNvbHVtblBhcmVudC5jcmVhdGVEaXYoe1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xzOiBgJHtNdWx0aUNvbHVtblN0eWxlQ1NTLkNvbHVtbkNvbnRlbnR9ICR7TXVsdGlDb2x1bW5MYXlvdXRDU1MuVHdvRXF1YWxDb2x1bW5zfWBcbiAgICAgICAgICAgICAgICAgICAgfSkpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgIGNhc2UoQ29sdW1uTGF5b3V0LmxlZnQpOlxuICAgICAgICAgICAgICAgIGNhc2UoQ29sdW1uTGF5b3V0LmZpcnN0KTpcbiAgICAgICAgICAgICAgICAgICAgY29sdW1uQ29udGVudERpdnMucHVzaChtdWx0aUNvbHVtblBhcmVudC5jcmVhdGVEaXYoe1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xzOiBgJHtNdWx0aUNvbHVtblN0eWxlQ1NTLkNvbHVtbkNvbnRlbnR9ICR7TXVsdGlDb2x1bW5MYXlvdXRDU1MuVHdvQ29sdW1uTGFyZ2V9YFxuICAgICAgICAgICAgICAgICAgICB9KSk7XG4gICAgICAgICAgICAgICAgICAgIG11bHRpQ29sdW1uUGFyZW50LmNyZWF0ZURpdih7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbHM6IGBtY20tY29sdW1uLXNwYWNlcmAsXG4gICAgICAgICAgICAgICAgICAgICAgICBhdHRyOiB7XCJzdHlsZVwiOiBzdHlsZVN0cn1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIGNvbHVtbkNvbnRlbnREaXZzLnB1c2gobXVsdGlDb2x1bW5QYXJlbnQuY3JlYXRlRGl2KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsczogYCR7TXVsdGlDb2x1bW5TdHlsZUNTUy5Db2x1bW5Db250ZW50fSAke011bHRpQ29sdW1uTGF5b3V0Q1NTLlR3b0NvbHVtblNtYWxsfWBcbiAgICAgICAgICAgICAgICAgICAgfSkpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgIGNhc2UoQ29sdW1uTGF5b3V0LnJpZ2h0KTpcbiAgICAgICAgICAgICAgICBjYXNlKENvbHVtbkxheW91dC5zZWNvbmQpOlxuICAgICAgICAgICAgICAgIGNhc2UoQ29sdW1uTGF5b3V0Lmxhc3QpOlxuICAgICAgICAgICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2cy5wdXNoKG11bHRpQ29sdW1uUGFyZW50LmNyZWF0ZURpdih7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbHM6IGAke011bHRpQ29sdW1uU3R5bGVDU1MuQ29sdW1uQ29udGVudH0gJHtNdWx0aUNvbHVtbkxheW91dENTUy5Ud29Db2x1bW5TbWFsbH1gXG4gICAgICAgICAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgICAgICAgICAgbXVsdGlDb2x1bW5QYXJlbnQuY3JlYXRlRGl2KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsczogYG1jbS1jb2x1bW4tc3BhY2VyYCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGF0dHI6IHtcInN0eWxlXCI6IHN0eWxlU3RyfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgY29sdW1uQ29udGVudERpdnMucHVzaChtdWx0aUNvbHVtblBhcmVudC5jcmVhdGVEaXYoe1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xzOiBgJHtNdWx0aUNvbHVtblN0eWxlQ1NTLkNvbHVtbkNvbnRlbnR9ICR7TXVsdGlDb2x1bW5MYXlvdXRDU1MuVHdvQ29sdW1uTGFyZ2V9YFxuICAgICAgICAgICAgICAgICAgICB9KSk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYoc2V0dGluZ3MubnVtYmVyT2ZDb2x1bW5zID09PSAzKSB7XG5cbiAgICAgICAgICAgIHN3aXRjaChzZXR0aW5ncy5jb2x1bW5MYXlvdXQpIHtcbiAgICAgICAgICAgICAgICBjYXNlKENvbHVtbkxheW91dC5zdGFuZGFyZCk6XG4gICAgICAgICAgICAgICAgICAgIGNvbHVtbkNvbnRlbnREaXZzLnB1c2gobXVsdGlDb2x1bW5QYXJlbnQuY3JlYXRlRGl2KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsczogYCR7TXVsdGlDb2x1bW5TdHlsZUNTUy5Db2x1bW5Db250ZW50fSAke011bHRpQ29sdW1uTGF5b3V0Q1NTLlRocmVlRXF1YWxDb2x1bW5zfWBcbiAgICAgICAgICAgICAgICAgICAgfSkpO1xuICAgICAgICAgICAgICAgICAgICBtdWx0aUNvbHVtblBhcmVudC5jcmVhdGVEaXYoe1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xzOiBgbWNtLWNvbHVtbi1zcGFjZXJgLFxuICAgICAgICAgICAgICAgICAgICAgICAgYXR0cjoge1wic3R5bGVcIjogc3R5bGVTdHJ9XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2cy5wdXNoKG11bHRpQ29sdW1uUGFyZW50LmNyZWF0ZURpdih7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbHM6IGAke011bHRpQ29sdW1uU3R5bGVDU1MuQ29sdW1uQ29udGVudH0gJHtNdWx0aUNvbHVtbkxheW91dENTUy5UaHJlZUVxdWFsQ29sdW1uc31gXG4gICAgICAgICAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgICAgICAgICAgbXVsdGlDb2x1bW5QYXJlbnQuY3JlYXRlRGl2KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsczogYG1jbS1jb2x1bW4tc3BhY2VyYCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGF0dHI6IHtcInN0eWxlXCI6IHN0eWxlU3RyfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgY29sdW1uQ29udGVudERpdnMucHVzaChtdWx0aUNvbHVtblBhcmVudC5jcmVhdGVEaXYoe1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xzOiBgJHtNdWx0aUNvbHVtblN0eWxlQ1NTLkNvbHVtbkNvbnRlbnR9ICR7TXVsdGlDb2x1bW5MYXlvdXRDU1MuVGhyZWVFcXVhbENvbHVtbnN9YFxuICAgICAgICAgICAgICAgICAgICB9KSk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgY2FzZShDb2x1bW5MYXlvdXQubGVmdCk6XG4gICAgICAgICAgICAgICAgY2FzZShDb2x1bW5MYXlvdXQuZmlyc3QpOlxuICAgICAgICAgICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2cy5wdXNoKG11bHRpQ29sdW1uUGFyZW50LmNyZWF0ZURpdih7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbHM6IGAke011bHRpQ29sdW1uU3R5bGVDU1MuQ29sdW1uQ29udGVudH0gJHtNdWx0aUNvbHVtbkxheW91dENTUy5UaHJlZUNvbHVtbl9MYXJnZX1gXG4gICAgICAgICAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgICAgICAgICAgbXVsdGlDb2x1bW5QYXJlbnQuY3JlYXRlRGl2KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsczogYG1jbS1jb2x1bW4tc3BhY2VyYCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGF0dHI6IHtcInN0eWxlXCI6IHN0eWxlU3RyfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgY29sdW1uQ29udGVudERpdnMucHVzaChtdWx0aUNvbHVtblBhcmVudC5jcmVhdGVEaXYoe1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xzOiBgJHtNdWx0aUNvbHVtblN0eWxlQ1NTLkNvbHVtbkNvbnRlbnR9ICR7TXVsdGlDb2x1bW5MYXlvdXRDU1MuVGhyZWVDb2x1bW5fU21hbGx9YFxuICAgICAgICAgICAgICAgICAgICB9KSk7XG4gICAgICAgICAgICAgICAgICAgIG11bHRpQ29sdW1uUGFyZW50LmNyZWF0ZURpdih7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbHM6IGBtY20tY29sdW1uLXNwYWNlcmAsXG4gICAgICAgICAgICAgICAgICAgICAgICBhdHRyOiB7XCJzdHlsZVwiOiBzdHlsZVN0cn1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIGNvbHVtbkNvbnRlbnREaXZzLnB1c2gobXVsdGlDb2x1bW5QYXJlbnQuY3JlYXRlRGl2KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsczogYCR7TXVsdGlDb2x1bW5TdHlsZUNTUy5Db2x1bW5Db250ZW50fSAke011bHRpQ29sdW1uTGF5b3V0Q1NTLlRocmVlQ29sdW1uX1NtYWxsfWBcbiAgICAgICAgICAgICAgICAgICAgfSkpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgIGNhc2UoQ29sdW1uTGF5b3V0Lm1pZGRsZSk6XG4gICAgICAgICAgICAgICAgY2FzZShDb2x1bW5MYXlvdXQuY2VudGVyKTpcbiAgICAgICAgICAgICAgICBjYXNlKENvbHVtbkxheW91dC5zZWNvbmQpOlxuICAgICAgICAgICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2cy5wdXNoKG11bHRpQ29sdW1uUGFyZW50LmNyZWF0ZURpdih7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbHM6IGAke011bHRpQ29sdW1uU3R5bGVDU1MuQ29sdW1uQ29udGVudH0gJHtNdWx0aUNvbHVtbkxheW91dENTUy5UaHJlZUNvbHVtbl9TbWFsbH1gXG4gICAgICAgICAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgICAgICAgICAgbXVsdGlDb2x1bW5QYXJlbnQuY3JlYXRlRGl2KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsczogYG1jbS1jb2x1bW4tc3BhY2VyYCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGF0dHI6IHtcInN0eWxlXCI6IHN0eWxlU3RyfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgY29sdW1uQ29udGVudERpdnMucHVzaChtdWx0aUNvbHVtblBhcmVudC5jcmVhdGVEaXYoe1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xzOiBgJHtNdWx0aUNvbHVtblN0eWxlQ1NTLkNvbHVtbkNvbnRlbnR9ICR7TXVsdGlDb2x1bW5MYXlvdXRDU1MuVGhyZWVDb2x1bW5fTGFyZ2V9YFxuICAgICAgICAgICAgICAgICAgICB9KSk7XG4gICAgICAgICAgICAgICAgICAgIG11bHRpQ29sdW1uUGFyZW50LmNyZWF0ZURpdih7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbHM6IGBtY20tY29sdW1uLXNwYWNlcmAsXG4gICAgICAgICAgICAgICAgICAgICAgICBhdHRyOiB7XCJzdHlsZVwiOiBzdHlsZVN0cn1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIGNvbHVtbkNvbnRlbnREaXZzLnB1c2gobXVsdGlDb2x1bW5QYXJlbnQuY3JlYXRlRGl2KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsczogYCR7TXVsdGlDb2x1bW5TdHlsZUNTUy5Db2x1bW5Db250ZW50fSAke011bHRpQ29sdW1uTGF5b3V0Q1NTLlRocmVlQ29sdW1uX1NtYWxsfWBcbiAgICAgICAgICAgICAgICAgICAgfSkpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgIGNhc2UoQ29sdW1uTGF5b3V0LnJpZ2h0KTpcbiAgICAgICAgICAgICAgICBjYXNlKENvbHVtbkxheW91dC50aGlyZCk6XG4gICAgICAgICAgICAgICAgY2FzZShDb2x1bW5MYXlvdXQubGFzdCk6XG4gICAgICAgICAgICAgICAgICAgIGNvbHVtbkNvbnRlbnREaXZzLnB1c2gobXVsdGlDb2x1bW5QYXJlbnQuY3JlYXRlRGl2KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsczogYCR7TXVsdGlDb2x1bW5TdHlsZUNTUy5Db2x1bW5Db250ZW50fSAke011bHRpQ29sdW1uTGF5b3V0Q1NTLlRocmVlQ29sdW1uX1NtYWxsfWBcbiAgICAgICAgICAgICAgICAgICAgfSkpO1xuICAgICAgICAgICAgICAgICAgICBtdWx0aUNvbHVtblBhcmVudC5jcmVhdGVEaXYoe1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xzOiBgbWNtLWNvbHVtbi1zcGFjZXJgLFxuICAgICAgICAgICAgICAgICAgICAgICAgYXR0cjoge1wic3R5bGVcIjogc3R5bGVTdHJ9XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2cy5wdXNoKG11bHRpQ29sdW1uUGFyZW50LmNyZWF0ZURpdih7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbHM6IGAke011bHRpQ29sdW1uU3R5bGVDU1MuQ29sdW1uQ29udGVudH0gJHtNdWx0aUNvbHVtbkxheW91dENTUy5UaHJlZUNvbHVtbl9TbWFsbH1gXG4gICAgICAgICAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgICAgICAgICAgbXVsdGlDb2x1bW5QYXJlbnQuY3JlYXRlRGl2KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsczogYG1jbS1jb2x1bW4tc3BhY2VyYCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGF0dHI6IHtcInN0eWxlXCI6IHN0eWxlU3RyfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgY29sdW1uQ29udGVudERpdnMucHVzaChtdWx0aUNvbHVtblBhcmVudC5jcmVhdGVEaXYoe1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xzOiBgJHtNdWx0aUNvbHVtblN0eWxlQ1NTLkNvbHVtbkNvbnRlbnR9ICR7TXVsdGlDb2x1bW5MYXlvdXRDU1MuVGhyZWVDb2x1bW5fTGFyZ2V9YFxuICAgICAgICAgICAgICAgICAgICB9KSk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGNvbHVtbkNvbnRlbnREaXZzO1xuICAgIH1cblxuICAgIHB1YmxpYyBhYnN0cmFjdCByZW5kZXJSZWdpb25FbGVtZW50c1RvU2NyZWVuKCk6IHZvaWQ7XG4gICAgcHVibGljIGFic3RyYWN0IGV4cG9ydFJlZ2lvbkVsZW1lbnRzVG9QREYocGRmUGFyZW50RWxlbWVudDogSFRNTEVsZW1lbnQpOiB2b2lkO1xuICAgIHB1YmxpYyBhYnN0cmFjdCByZW5kZXJSZWdpb25FbGVtZW50c1RvTGl2ZVByZXZpZXcocGFyZW50RWxlbWVudDogSFRNTEVsZW1lbnQpOiB2b2lkXG59XG5cblxuZnVuY3Rpb24gZ2V0RWxlbWVudENsaWVudEhlaWdodChlbGVtZW50OiBIVE1MRWxlbWVudCwgcGFyZW50UmVuZGVyRWxlbWVudDogSFRNTERpdkVsZW1lbnQpOiBudW1iZXIge1xuXG4gICAgbGV0IGhlaWdodCA9IGVsZW1lbnQuY2xpZW50SGVpZ2h0O1xuICAgIGlmKGhlaWdodCA9PT0gMCkge1xuICAgICAgICBwYXJlbnRSZW5kZXJFbGVtZW50LmFwcGVuZENoaWxkKGVsZW1lbnQpO1xuICAgICAgICBoZWlnaHQgPSBlbGVtZW50LmNsaWVudEhlaWdodFxuICAgICAgICBwYXJlbnRSZW5kZXJFbGVtZW50LnJlbW92ZUNoaWxkKGVsZW1lbnQpO1xuICAgIH1cbiAgICByZXR1cm4gaGVpZ2h0XG59IiwiLyoqXG4gKiBGaWxlOiAvc3JjL2RvbV9tYW5hZ2VyL3JlZ2lvbmFsX21hbmFnZXJzL3JlZ2lvbkRPTU1hbmFnZXIudHMgICAgICAgICAgICAgICAgKlxuICogQ3JlYXRlZCBEYXRlOiBTdW5kYXksIE1heSAyMm5kIDIwMjIsIDc6NDYgcG0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpcbiAqIEF1dGhvcjogQ2FtZXJvbiBSb2JpbnNvbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICogQ29weXJpZ2h0IChjKSAyMDIyIENhbWVyb24gUm9iaW5zb24gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpcbiAqL1xuXG5pbXBvcnQgeyBET01PYmplY3QsIERPTU9iamVjdFRhZywgRWxlbWVudENvbHVtbkJyZWFrVHlwZSwgVGFza0xpc3RET01PYmplY3QgfSBmcm9tICcuLi9kb21PYmplY3QnO1xuaW1wb3J0IHsgTXVsdGlDb2x1bW5TZXR0aW5ncywgQ29udGVudE92ZXJmbG93VHlwZSwgQWxpZ25tZW50VHlwZSB9IGZyb20gXCIuLi8uLi9yZWdpb25TZXR0aW5nc1wiO1xuaW1wb3J0IHsgTXVsdGlDb2x1bW5MYXlvdXRDU1MsIE11bHRpQ29sdW1uU3R5bGVDU1MgfSBmcm9tICcuLi8uLi91dGlsaXRpZXMvY3NzRGVmaW5pdGlvbnMnO1xuaW1wb3J0IHsgTWFya2Rvd25SZW5kZXJDaGlsZCB9IGZyb20gJ29ic2lkaWFuJztcbmltcG9ydCB7IFJlZ2lvbk1hbmFnZXIgfSBmcm9tICcuL3JlZ2lvbk1hbmFnZXInO1xuaW1wb3J0IHsgZ2V0SGVhZGluZ0NvbGxhcHNlRWxlbWVudCB9IGZyb20gJ3NyYy91dGlsaXRpZXMvZWxlbWVudFJlbmRlclR5cGVQYXJzZXInO1xuXG5leHBvcnQgY2xhc3MgU3RhbmRhcmRNdWx0aUNvbHVtblJlZ2lvbk1hbmFnZXIgZXh0ZW5kcyBSZWdpb25NYW5hZ2VyIHtcblxuXG4gICAgcHVibGljIHJlbmRlclJlZ2lvbkVsZW1lbnRzVG9TY3JlZW4oKTogdm9pZCB7XG5cbiAgICAgICAgdGhpcy5yZW5kZXJDb2x1bW5NYXJrZG93bih0aGlzLnJlZ2lvblBhcmVudCwgdGhpcy5kb21MaXN0LCB0aGlzLnJlZ2lvbmFsU2V0dGluZ3MpO1xuICAgIH1cbiAgICBwdWJsaWMgZXhwb3J0UmVnaW9uRWxlbWVudHNUb1BERihwZGZQYXJlbnRFbGVtZW50OiBIVE1MRWxlbWVudCk6IHZvaWQge1xuXG4gICAgICAgIC8vIERlZmF1bHQgc2V0IHNoYWRvdyB0byBvZmYgZm9yIGV4cG9ydGluZyBQREZzXG4gICAgICAgIGxldCByZW5kZXJTZXR0aW5ncyA9IHRoaXMucmVnaW9uYWxTZXR0aW5ncztcbiAgICAgICAgcmVuZGVyU2V0dGluZ3MuZHJhd1NoYWRvdyA9IGZhbHNlO1xuICAgICAgICB0aGlzLnJlbmRlckNvbHVtbk1hcmtkb3duKHBkZlBhcmVudEVsZW1lbnQsIHRoaXMuZG9tTGlzdC5zbGljZSgpLCByZW5kZXJTZXR0aW5ncyk7XG4gICAgfVxuICAgIHB1YmxpYyByZW5kZXJSZWdpb25FbGVtZW50c1RvTGl2ZVByZXZpZXcocGFyZW50RWxlbWVudDogSFRNTEVsZW1lbnQpOiB2b2lkIHtcblxuICAgICAgICB0aGlzLnJlbmRlckNvbHVtbk1hcmtkb3duKHBhcmVudEVsZW1lbnQsIHRoaXMuZG9tTGlzdCwgdGhpcy5yZWdpb25hbFNldHRpbmdzKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogVGhpcyBmdW5jdGlvbiB0YWtlcyBpbiB0aGUgZGF0YSBmb3IgdGhlIG11bHRpLWNvbHVtbiByZWdpb24gYW5kIHNldHMgdXAgdGhlIFxuICAgICAqIHVzZXIgZGVmaW5lZCBudW1iZXIgb2YgY2hpbGRyZW4gd2l0aCB0aGUgcHJvcGVyIGNzcyBjbGFzc2VzIHRvIGJlIHJlbmRlcmVkIHByb3Blcmx5LlxuICAgICAqIFxuICAgICAqIEBwYXJhbSBwYXJlbnRFbGVtZW50IFRoZSBlbGVtZW50IHRoYXQgdGhlIG11bHRpLWNvbHVtbiByZWdpb24gd2lsbCBiZSByZW5kZXJlZCB1bmRlci5cbiAgICAgKiBAcGFyYW0gcmVnaW9uRWxlbWVudHMgVGhlIGxpc3Qgb2YgRE9NIG9iamVjdHMgdGhhdCB3aWxsIGJlIGNvcHBpZWQgdW5kZXIgdGhlIHBhcmVudCBvYmplY3RcbiAgICAgKiBAcGFyYW0gc2V0dGluZ3MgVGhlIHNldHRpbmdzIHRoZSB1c2VyIGhhcyBkZWZpbmVkIGZvciB0aGUgcmVnaW9uLlxuICAgICAqL1xuICAgIHByaXZhdGUgcmVuZGVyQ29sdW1uTWFya2Rvd24ocGFyZW50RWxlbWVudDogSFRNTEVsZW1lbnQsIHJlZ2lvbkVsZW1lbnRzOiBET01PYmplY3RbXSwgc2V0dGluZ3M6IE11bHRpQ29sdW1uU2V0dGluZ3MpIHtcblxuICAgICAgICBsZXQgbXVsdGlDb2x1bW5QYXJlbnQgPSBjcmVhdGVEaXYoe1xuICAgICAgICAgICAgY2xzOiBNdWx0aUNvbHVtbkxheW91dENTUy5SZWdpb25Db2x1bW5Db250YWluZXJEaXYsXG4gICAgICAgIH0pO1xuXG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFBhc3Mgb3VyIHBhcmVudCBkaXYgYW5kIHNldHRpbmdzIHRvIHBhcnNlciB0byBjcmVhdGUgdGhlIHJlcXVpcmVkXG4gICAgICAgICAqIGNvbHVtbiBkaXZzIGFzIGNoaWxkcmVuIG9mIHRoZSBwYXJlbnQuXG4gICAgICAgICAqL1xuICAgICAgICBsZXQgY29sdW1uQ29udGVudERpdnMgPSB0aGlzLmdldENvbHVtbkNvbnRlbnREaXZzKHNldHRpbmdzLCBtdWx0aUNvbHVtblBhcmVudCk7XG4gICAgICAgIGlmKHNldHRpbmdzLmRyYXdTaGFkb3cgPT09IHRydWUpIHtcbiAgICAgICAgICAgIG11bHRpQ29sdW1uUGFyZW50LmFkZENsYXNzKE11bHRpQ29sdW1uU3R5bGVDU1MuUmVnaW9uU2hhZG93KTtcbiAgICAgICAgfVxuICAgICAgICBmb3IobGV0IGkgPSAwOyBpIDwgY29sdW1uQ29udGVudERpdnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmKHNldHRpbmdzLmRyYXdCb3JkZXIgPT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2c1tpXS5hZGRDbGFzcyhNdWx0aUNvbHVtblN0eWxlQ1NTLkNvbHVtbkJvcmRlcik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmKHNldHRpbmdzLmRyYXdTaGFkb3cgPT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2c1tpXS5hZGRDbGFzcyhNdWx0aUNvbHVtblN0eWxlQ1NTLkNvbHVtblNoYWRvdyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDcmVhdGUgbWFya2Rvd24gcmVuZGVyZXIgdG8gcGFyc2UgdGhlIHBhc3NlZCBtYXJrZG93blxuICAgICAgICAvLyBiZXR3ZWVuIHRoZSB0YWdzLlxuICAgICAgICBsZXQgbWFya2Rvd25SZW5kZXJDaGlsZCA9IG5ldyBNYXJrZG93blJlbmRlckNoaWxkKFxuICAgICAgICAgICAgbXVsdGlDb2x1bW5QYXJlbnRcbiAgICAgICAgKTtcblxuICAgICAgICAvLyBSZW1vdmUgZXZlcnkgb3RoZXIgY2hpbGQgZnJvbSB0aGUgcGFyZW50IHNvIFxuICAgICAgICAvLyB3ZSBkb250IGVuZCB1cCB3aXRoIG11bHRpcGxlIHNldHMgb2YgZGF0YS4gVGhpcyBzaG91bGRcbiAgICAgICAgLy8gcmVhbGx5IG9ubHkgbmVlZCB0byBsb29wIG9uY2UgZm9yIGkgPSAwIGJ1dCBsb29wIGp1c3RcbiAgICAgICAgLy8gaW4gY2FzZS5cbiAgICAgICAgZm9yKGxldCBpID0gcGFyZW50RWxlbWVudC5jaGlsZHJlbi5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICAgICAgcGFyZW50RWxlbWVudC5jaGlsZHJlbltpXS5kZXRhY2goKTtcbiAgICAgICAgfVxuICAgICAgICBwYXJlbnRFbGVtZW50LmFwcGVuZENoaWxkKG1hcmtkb3duUmVuZGVyQ2hpbGQuY29udGFpbmVyRWwpO1xuXG4gICAgICAgIHRoaXMuYXBwZW5kRWxlbWVudHNUb0NvbHVtbnMocmVnaW9uRWxlbWVudHMsIGNvbHVtbkNvbnRlbnREaXZzLCBzZXR0aW5ncyk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhcHBlbmRFbGVtZW50c1RvQ29sdW1ucyhyZWdpb25FbGVtZW50czogRE9NT2JqZWN0W10sIGNvbHVtbkNvbnRlbnREaXZzOiBIVE1MRGl2RWxlbWVudFtdLCBzZXR0aW5nczogTXVsdGlDb2x1bW5TZXR0aW5ncykge1xuXG4gICAgICAgIGxldCBjb2x1bW5JbmRleCA9IDA7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcmVnaW9uRWxlbWVudHMubGVuZ3RoOyBpKyspIHtcblxuICAgICAgICAgICAgaWYgKHJlZ2lvbkVsZW1lbnRzW2ldLnRhZyA9PT0gRE9NT2JqZWN0VGFnLm5vbmUgfHxcbiAgICAgICAgICAgICAgICByZWdpb25FbGVtZW50c1tpXS50YWcgPT09IERPTU9iamVjdFRhZy5jb2x1bW5CcmVhaykge1xuXG4gICAgICAgICAgICAgICAgLy8gSWYgYSBzdGFuZGFyZCBlbGVtZW50IGNvbnRhaW5zIGEgY29sdW1uIGJyZWFrIHRhZyBhbmQgaXQgaXMgc2V0IGFzIGEgcHJlIGNvbnRlbnQgYnJlYWsgdGFnIHdlIGZsaXAgb3VyIGluZGV4IGhlcmUuXG4gICAgICAgICAgICAgICAgaWYocmVnaW9uRWxlbWVudHNbaV0udGFnID09PSBET01PYmplY3RUYWcubm9uZSAmJiBcbiAgICAgICAgICAgICAgICAgICByZWdpb25FbGVtZW50c1tpXS5lbGVtZW50SXNDb2x1bW5CcmVhayA9PT0gRWxlbWVudENvbHVtbkJyZWFrVHlwZS5wcmVCcmVhayAmJiBcbiAgICAgICAgICAgICAgICAgICAoY29sdW1uSW5kZXggKyAxKSA8IHNldHRpbmdzLm51bWJlck9mQ29sdW1ucykge1xuICAgICAgICAgICAgICAgICAgICBjb2x1bW5JbmRleCsrO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIFdlIHN0b3JlIHRoZSBlbGVtZW50cyBpbiBhIHdyYXBwZXIgY29udGFpbmVyIHVudGlsIHdlIGRldGVybWluZVxuICAgICAgICAgICAgICAgIGxldCBlbGVtZW50ID0gY3JlYXRlRGl2KHtcbiAgICAgICAgICAgICAgICAgICAgY2xzOiBNdWx0aUNvbHVtbkxheW91dENTUy5Db2x1bW5EdWFsRWxlbWVudENvbnRhaW5lcixcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIGlmKHNldHRpbmdzLmNvbnRlbnRPdmVyZmxvdyA9PT0gQ29udGVudE92ZXJmbG93VHlwZS5oaWRkZW4pIHtcbiAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5hZGRDbGFzcyhNdWx0aUNvbHVtbkxheW91dENTUy5Db250ZW50T3ZlcmZsb3dIaWRkZW4pXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBlbGVtZW50LmFkZENsYXNzKE11bHRpQ29sdW1uTGF5b3V0Q1NTLkNvbnRlbnRPdmVyZmxvd0F1dG9TY3JvbGwpXG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYoc2V0dGluZ3MuYWxpZ25tZW50ID09PSBBbGlnbm1lbnRUeXBlLmNlbnRlcikge1xuICAgICAgICAgICAgICAgICAgICBlbGVtZW50LmFkZENsYXNzKE11bHRpQ29sdW1uTGF5b3V0Q1NTLkFsaWdubWVudENlbnRlcilcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoc2V0dGluZ3MuYWxpZ25tZW50ID09PSBBbGlnbm1lbnRUeXBlLnJpZ2h0KSB7XG4gICAgICAgICAgICAgICAgICAgIGVsZW1lbnQuYWRkQ2xhc3MoTXVsdGlDb2x1bW5MYXlvdXRDU1MuQWxpZ25tZW50UmlnaHQpXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBlbGVtZW50LmFkZENsYXNzKE11bHRpQ29sdW1uTGF5b3V0Q1NTLkFsaWdubWVudExlZnQpXG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmVnaW9uRWxlbWVudHNbaV0uZWxlbWVudENvbnRhaW5lciA9IGVsZW1lbnQ7XG5cbiAgICAgICAgICAgICAgICAvLyBPdGhlcndpc2Ugd2UganVzdCBtYWtlIGEgY29weSBvZiB0aGUgb3JpZ2luYWwgZWxlbWVudCB0byBkaXNwbGF5LlxuICAgICAgICAgICAgICAgIGxldCBjbG9uZWRFbGVtZW50ID0gcmVnaW9uRWxlbWVudHNbaV0ub3JpZ2luYWxFbGVtZW50LmNsb25lTm9kZSh0cnVlKSBhcyBIVE1MRGl2RWxlbWVudDtcbiAgICAgICAgICAgICAgICBsZXQgaGVhZGluZ0NvbGxhcHNlRWxlbWVudCA9IGdldEhlYWRpbmdDb2xsYXBzZUVsZW1lbnQoY2xvbmVkRWxlbWVudCk7XG4gICAgICAgICAgICAgICAgaWYoaGVhZGluZ0NvbGxhcHNlRWxlbWVudCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIHJlbW92ZXMgdGhlIGNvbGxhcHNlIGFycm93IGZyb20gdGhlIHZpZXcgaWYgaXQgZXhpc3RzLlxuICAgICAgICAgICAgICAgICAgICBoZWFkaW5nQ29sbGFwc2VFbGVtZW50LmRldGFjaCgpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJlZ2lvbkVsZW1lbnRzW2ldLmNsb25lZEVsZW1lbnQgPSBjbG9uZWRFbGVtZW50O1xuICAgICAgICAgICAgICAgIGVsZW1lbnQuYXBwZW5kQ2hpbGQoY2xvbmVkRWxlbWVudCk7XG5cbiAgICAgICAgICAgICAgICBpZiAocmVnaW9uRWxlbWVudHNbaV0gaW5zdGFuY2VvZiBUYXNrTGlzdERPTU9iamVjdCkge1xuXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZml4Q2xvbmVkQ2hlY2tMaXN0QnV0dG9ucyhyZWdpb25FbGVtZW50c1tpXSBhcyBUYXNrTGlzdERPTU9iamVjdCwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGVsZW1lbnQgIT09IG51bGwgJiYgcmVnaW9uRWxlbWVudHNbaV0udGFnICE9PSBET01PYmplY3RUYWcuY29sdW1uQnJlYWspIHtcblxuICAgICAgICAgICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2c1tjb2x1bW5JbmRleF0uYXBwZW5kQ2hpbGQoZWxlbWVudCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgICAgICogSWYgdGhlIHRhZyBpcyBhIGNvbHVtbiBicmVhayB3ZSB1cGRhdGUgdGhlIGNvbHVtbiBpbmRleCBhZnRlclxuICAgICAgICAgICAgICAgICAqIGFwcGVuZGluZyB0aGUgaXRlbSB0byB0aGUgY29sdW1uIGRpdi4gVGhpcyBrZWVwcyB0aGUgbWFpbiBET01cbiAgICAgICAgICAgICAgICAgKiBjbGVhbmVyIGJ5IHJlbW92aW5nIG90aGVyIGl0ZW1zIGFuZCBwbGFjaW5nIHRoZW0gYWxsIHdpdGhpblxuICAgICAgICAgICAgICAgICAqIGEgcmVnaW9uIGNvbnRhaW5lci5cbiAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICBpZiAocmVnaW9uRWxlbWVudHNbaV0udGFnID09PSBET01PYmplY3RUYWcuY29sdW1uQnJlYWsgJiZcbiAgICAgICAgICAgICAgICAgICAgKGNvbHVtbkluZGV4ICsgMSkgPCBzZXR0aW5ncy5udW1iZXJPZkNvbHVtbnMpIHtcblxuICAgICAgICAgICAgICAgICAgICBjb2x1bW5JbmRleCsrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmKHJlZ2lvbkVsZW1lbnRzW2ldLnRhZyA9PT0gRE9NT2JqZWN0VGFnLm5vbmUgJiYgXG4gICAgICAgICAgICAgICAgICAgICAgICByZWdpb25FbGVtZW50c1tpXS5lbGVtZW50SXNDb2x1bW5CcmVhayA9PT0gRWxlbWVudENvbHVtbkJyZWFrVHlwZS5wb3N0QnJlYWsgJiYgXG4gICAgICAgICAgICAgICAgICAgICAgICAoY29sdW1uSW5kZXggKyAxKSA8IHNldHRpbmdzLm51bWJlck9mQ29sdW1ucykge1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIElmIGEgc3RhbmRhcmQgZWxlbWVudCBjb250YWlucyBhIGNvbHVtbiBicmVhayB0YWcgYW5kIGl0IGlzIHNldCBhcyBhIHBvc3QgY29udGVudCBicmVhayB0YWcgd2UgZmxpcCBvdXIgaW5kZXggaGVyZS5cbiAgICAgICAgICAgICAgICAgICAgY29sdW1uSW5kZXgrKztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59XG5cbiIsImltcG9ydCB7IERPTU9iamVjdCwgRE9NT2JqZWN0VGFnLCBUYXNrTGlzdERPTU9iamVjdCB9IGZyb20gJy4uL2RvbU9iamVjdCc7XG5pbXBvcnQgeyBNdWx0aUNvbHVtblNldHRpbmdzLCBDb2x1bW5MYXlvdXQsIFNpbmdsZUNvbHVtblNpemUsIENvbnRlbnRPdmVyZmxvd1R5cGUsIEFsaWdubWVudFR5cGUgfSBmcm9tIFwiLi4vLi4vcmVnaW9uU2V0dGluZ3NcIjtcbmltcG9ydCB7IE11bHRpQ29sdW1uTGF5b3V0Q1NTLCBNdWx0aUNvbHVtblN0eWxlQ1NTIH0gZnJvbSAnLi4vLi4vdXRpbGl0aWVzL2Nzc0RlZmluaXRpb25zJztcbmltcG9ydCB7IE1hcmtkb3duUmVuZGVyQ2hpbGQgfSBmcm9tICdvYnNpZGlhbic7XG5pbXBvcnQgeyBSZWdpb25NYW5hZ2VyIH0gZnJvbSAnLi9yZWdpb25NYW5hZ2VyJztcbmltcG9ydCB7IGdldEhlYWRpbmdDb2xsYXBzZUVsZW1lbnQgfSBmcm9tICdzcmMvdXRpbGl0aWVzL2VsZW1lbnRSZW5kZXJUeXBlUGFyc2VyJztcblxuXG5leHBvcnQgY2xhc3MgU2luZ2xlQ29sdW1uUmVnaW9uTWFuYWdlciBleHRlbmRzIFJlZ2lvbk1hbmFnZXIge1xuXG5cbiAgICBwdWJsaWMgcmVuZGVyUmVnaW9uRWxlbWVudHNUb1NjcmVlbigpOiB2b2lkIHtcblxuICAgICAgICB0aGlzLnJlbmRlckNvbHVtbk1hcmtkb3duKHRoaXMucmVnaW9uUGFyZW50LCB0aGlzLmRvbUxpc3QsIHRoaXMucmVnaW9uYWxTZXR0aW5ncyk7XG4gICAgfVxuICAgIHB1YmxpYyBleHBvcnRSZWdpb25FbGVtZW50c1RvUERGKHBkZlBhcmVudEVsZW1lbnQ6IEhUTUxFbGVtZW50KTogdm9pZCB7XG5cbiAgICAgICAgLy8gRGVmYXVsdCBzZXQgc2hhZG93IHRvIG9mZiBmb3IgZXhwb3J0aW5nIFBERnNcbiAgICAgICAgbGV0IHJlbmRlclNldHRpbmdzID0gdGhpcy5yZWdpb25hbFNldHRpbmdzO1xuICAgICAgICByZW5kZXJTZXR0aW5ncy5kcmF3U2hhZG93ID0gZmFsc2U7XG4gICAgICAgIHRoaXMucmVuZGVyQ29sdW1uTWFya2Rvd24ocGRmUGFyZW50RWxlbWVudCwgdGhpcy5kb21MaXN0LnNsaWNlKCksIHJlbmRlclNldHRpbmdzKTtcbiAgICB9XG4gICAgcHVibGljIHJlbmRlclJlZ2lvbkVsZW1lbnRzVG9MaXZlUHJldmlldyhwYXJlbnRFbGVtZW50OiBIVE1MRWxlbWVudCk6IHZvaWQge1xuXG4gICAgICAgIHRoaXMucmVuZGVyQ29sdW1uTWFya2Rvd24ocGFyZW50RWxlbWVudCwgdGhpcy5kb21MaXN0LCB0aGlzLnJlZ2lvbmFsU2V0dGluZ3MpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBUaGlzIGZ1bmN0aW9uIHRha2VzIGluIHRoZSBkYXRhIGZvciB0aGUgbXVsdGktY29sdW1uIHJlZ2lvbiBhbmQgc2V0cyB1cCB0aGVcbiAgICAgKiB1c2VyIGRlZmluZWQgbnVtYmVyIG9mIGNoaWxkcmVuIHdpdGggdGhlIHByb3BlciBjc3MgY2xhc3NlcyB0byBiZSByZW5kZXJlZCBwcm9wZXJseS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBwYXJlbnRFbGVtZW50IFRoZSBlbGVtZW50IHRoYXQgdGhlIG11bHRpLWNvbHVtbiByZWdpb24gd2lsbCBiZSByZW5kZXJlZCB1bmRlci5cbiAgICAgKiBAcGFyYW0gcmVnaW9uRWxlbWVudHMgVGhlIGxpc3Qgb2YgRE9NIG9iamVjdHMgdGhhdCB3aWxsIGJlIGNvcHBpZWQgdW5kZXIgdGhlIHBhcmVudCBvYmplY3RcbiAgICAgKiBAcGFyYW0gc2V0dGluZ3MgVGhlIHNldHRpbmdzIHRoZSB1c2VyIGhhcyBkZWZpbmVkIGZvciB0aGUgcmVnaW9uLlxuICAgICAqL1xuICAgIHByb3RlY3RlZCByZW5kZXJDb2x1bW5NYXJrZG93bihwYXJlbnRFbGVtZW50OiBIVE1MRWxlbWVudCwgcmVnaW9uRWxlbWVudHM6IERPTU9iamVjdFtdLCBzZXR0aW5nczogTXVsdGlDb2x1bW5TZXR0aW5ncykge1xuXG4gICAgICAgIGxldCBtdWx0aUNvbHVtblBhcmVudCA9IGNyZWF0ZURpdih7XG4gICAgICAgICAgICBjbHM6IE11bHRpQ29sdW1uTGF5b3V0Q1NTLlJlZ2lvbkNvbHVtbkNvbnRhaW5lckRpdixcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYoaXNMZWZ0TGF5b3V0KHRoaXMucmVnaW9uYWxTZXR0aW5ncy5jb2x1bW5Qb3NpdGlvbikpe1xuICAgICAgICAgICAgbXVsdGlDb2x1bW5QYXJlbnQuYWRkQ2xhc3MoTXVsdGlDb2x1bW5MYXlvdXRDU1MuU2luZ2xlQ29sdW1uTGVmdExheW91dClcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmKGlzUmlnaHRMYXlvdXQodGhpcy5yZWdpb25hbFNldHRpbmdzLmNvbHVtblBvc2l0aW9uKSkge1xuICAgICAgICAgICAgbXVsdGlDb2x1bW5QYXJlbnQuYWRkQ2xhc3MoTXVsdGlDb2x1bW5MYXlvdXRDU1MuU2luZ2xlQ29sdW1uUmlnaHRMYXlvdXQpXG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBtdWx0aUNvbHVtblBhcmVudC5hZGRDbGFzcyhNdWx0aUNvbHVtbkxheW91dENTUy5TaW5nbGVDb2x1bW5DZW50ZXJMYXlvdXQpXG4gICAgICAgIH1cblxuICAgICAgICAvKipcbiAgICAgICAgICogUGFzcyBvdXIgcGFyZW50IGRpdiBhbmQgc2V0dGluZ3MgdG8gcGFyc2VyIHRvIGNyZWF0ZSB0aGUgcmVxdWlyZWRcbiAgICAgICAgICogY29sdW1uIGRpdnMgYXMgY2hpbGRyZW4gb2YgdGhlIHBhcmVudC5cbiAgICAgICAgICovXG4gICAgICAgIGxldCBjb2x1bW5Db250ZW50RGl2ID0gdGhpcy5jcmVhdGVDb2x1bW5Db250ZW50RGl2cyhtdWx0aUNvbHVtblBhcmVudCk7XG4gICAgICAgIGlmIChzZXR0aW5ncy5kcmF3Qm9yZGVyID09PSB0cnVlKSB7XG4gICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2LmFkZENsYXNzKE11bHRpQ29sdW1uU3R5bGVDU1MuQ29sdW1uQm9yZGVyKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoc2V0dGluZ3MuZHJhd1NoYWRvdyA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgY29sdW1uQ29udGVudERpdi5hZGRDbGFzcyhNdWx0aUNvbHVtblN0eWxlQ1NTLkNvbHVtblNoYWRvdyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDcmVhdGUgbWFya2Rvd24gcmVuZGVyZXIgdG8gcGFyc2UgdGhlIHBhc3NlZCBtYXJrZG93blxuICAgICAgICAvLyBiZXR3ZWVuIHRoZSB0YWdzLlxuICAgICAgICBsZXQgbWFya2Rvd25SZW5kZXJDaGlsZCA9IG5ldyBNYXJrZG93blJlbmRlckNoaWxkKFxuICAgICAgICAgICAgbXVsdGlDb2x1bW5QYXJlbnRcbiAgICAgICAgKTtcblxuICAgICAgICAvLyBSZW1vdmUgZXZlcnkgb3RoZXIgY2hpbGQgZnJvbSB0aGUgcGFyZW50IHNvIFxuICAgICAgICAvLyB3ZSBkb250IGVuZCB1cCB3aXRoIG11bHRpcGxlIHNldHMgb2YgZGF0YS4gVGhpcyBzaG91bGRcbiAgICAgICAgLy8gcmVhbGx5IG9ubHkgbmVlZCB0byBsb29wIG9uY2UgZm9yIGkgPSAwIGJ1dCBsb29wIGp1c3RcbiAgICAgICAgLy8gaW4gY2FzZS5cbiAgICAgICAgZm9yIChsZXQgaSA9IHBhcmVudEVsZW1lbnQuY2hpbGRyZW4ubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICAgIHBhcmVudEVsZW1lbnQuY2hpbGRyZW5baV0uZGV0YWNoKCk7XG4gICAgICAgIH1cbiAgICAgICAgcGFyZW50RWxlbWVudC5hcHBlbmRDaGlsZChtYXJrZG93blJlbmRlckNoaWxkLmNvbnRhaW5lckVsKTtcblxuICAgICAgICB0aGlzLmFwcGVuZEVsZW1lbnRzVG9Db2x1bW5zKHJlZ2lvbkVsZW1lbnRzLCBjb2x1bW5Db250ZW50RGl2LCBzZXR0aW5ncyk7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIGFwcGVuZEVsZW1lbnRzVG9Db2x1bW5zKHJlZ2lvbkVsZW1lbnRzOiBET01PYmplY3RbXSwgY29sdW1uQ29udGVudERpdjogSFRNTERpdkVsZW1lbnQsIHNldHRpbmdzOiBNdWx0aUNvbHVtblNldHRpbmdzKSB7XG5cblxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHJlZ2lvbkVsZW1lbnRzLmxlbmd0aDsgaSsrKSB7XG5cbiAgICAgICAgICAgIGlmIChyZWdpb25FbGVtZW50c1tpXS50YWcgPT09IERPTU9iamVjdFRhZy5ub25lIHx8XG4gICAgICAgICAgICAgICAgcmVnaW9uRWxlbWVudHNbaV0udGFnID09PSBET01PYmplY3RUYWcuY29sdW1uQnJlYWspIHtcblxuICAgICAgICAgICAgICAgIC8vIFdlIHN0b3JlIHRoZSBlbGVtZW50cyBpbiBhIHdyYXBwZXIgY29udGFpbmVyIHVudGlsIHdlIGRldGVybWluZVxuICAgICAgICAgICAgICAgIGxldCBlbGVtZW50ID0gY3JlYXRlRGl2KHtcbiAgICAgICAgICAgICAgICAgICAgY2xzOiBNdWx0aUNvbHVtbkxheW91dENTUy5Db2x1bW5EdWFsRWxlbWVudENvbnRhaW5lcixcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICByZWdpb25FbGVtZW50c1tpXS5lbGVtZW50Q29udGFpbmVyID0gZWxlbWVudDtcblxuICAgICAgICAgICAgICAgIGlmKHNldHRpbmdzLmNvbnRlbnRPdmVyZmxvdyA9PT0gQ29udGVudE92ZXJmbG93VHlwZS5oaWRkZW4pIHtcbiAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5hZGRDbGFzcyhNdWx0aUNvbHVtbkxheW91dENTUy5Db250ZW50T3ZlcmZsb3dIaWRkZW4pXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBlbGVtZW50LmFkZENsYXNzKE11bHRpQ29sdW1uTGF5b3V0Q1NTLkNvbnRlbnRPdmVyZmxvd0F1dG9TY3JvbGwpXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgIGlmKHNldHRpbmdzLmFsaWdubWVudCA9PT0gQWxpZ25tZW50VHlwZS5jZW50ZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5hZGRDbGFzcyhNdWx0aUNvbHVtbkxheW91dENTUy5BbGlnbm1lbnRDZW50ZXIpXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKHNldHRpbmdzLmFsaWdubWVudCA9PT0gQWxpZ25tZW50VHlwZS5yaWdodCkge1xuICAgICAgICAgICAgICAgICAgICBlbGVtZW50LmFkZENsYXNzKE11bHRpQ29sdW1uTGF5b3V0Q1NTLkFsaWdubWVudFJpZ2h0KVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5hZGRDbGFzcyhNdWx0aUNvbHVtbkxheW91dENTUy5BbGlnbm1lbnRMZWZ0KVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIE90aGVyd2lzZSB3ZSBqdXN0IG1ha2UgYSBjb3B5IG9mIHRoZSBvcmlnaW5hbCBlbGVtZW50IHRvIGRpc3BsYXkuXG4gICAgICAgICAgICAgICAgbGV0IGNsb25lZEVsZW1lbnQgPSByZWdpb25FbGVtZW50c1tpXS5vcmlnaW5hbEVsZW1lbnQuY2xvbmVOb2RlKHRydWUpIGFzIEhUTUxEaXZFbGVtZW50O1xuICAgICAgICAgICAgICAgIGxldCBoZWFkaW5nQ29sbGFwc2VFbGVtZW50ID0gZ2V0SGVhZGluZ0NvbGxhcHNlRWxlbWVudChjbG9uZWRFbGVtZW50KTtcbiAgICAgICAgICAgICAgICBpZihoZWFkaW5nQ29sbGFwc2VFbGVtZW50ICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgcmVtb3ZlcyB0aGUgY29sbGFwc2UgYXJyb3cgZnJvbSB0aGUgdmlldyBpZiBpdCBleGlzdHMuXG4gICAgICAgICAgICAgICAgICAgIGhlYWRpbmdDb2xsYXBzZUVsZW1lbnQuZGV0YWNoKCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmVnaW9uRWxlbWVudHNbaV0uY2xvbmVkRWxlbWVudCA9IGNsb25lZEVsZW1lbnQ7XG4gICAgICAgICAgICAgICAgZWxlbWVudC5hcHBlbmRDaGlsZChjbG9uZWRFbGVtZW50KTtcblxuICAgICAgICAgICAgICAgIGlmIChyZWdpb25FbGVtZW50c1tpXSBpbnN0YW5jZW9mIFRhc2tMaXN0RE9NT2JqZWN0KSB7XG5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5maXhDbG9uZWRDaGVja0xpc3RCdXR0b25zKHJlZ2lvbkVsZW1lbnRzW2ldIGFzIFRhc2tMaXN0RE9NT2JqZWN0LCB0cnVlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoZWxlbWVudCAhPT0gbnVsbCkge1xuXG4gICAgICAgICAgICAgICAgICAgIGNvbHVtbkNvbnRlbnREaXYuYXBwZW5kQ2hpbGQoZWxlbWVudCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgY3JlYXRlQ29sdW1uQ29udGVudERpdnMobXVsdGlDb2x1bW5QYXJlbnQ6IEhUTUxEaXZFbGVtZW50KTogSFRNTERpdkVsZW1lbnQge1xuXG4gICAgICAgIGxldCBjb250ZW50RGl2ID0gbXVsdGlDb2x1bW5QYXJlbnQuY3JlYXRlRGl2KHtcbiAgICAgICAgICAgIGNsczogYCR7TXVsdGlDb2x1bW5TdHlsZUNTUy5Db2x1bW5Db250ZW50fWBcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYodGhpcy5yZWdpb25hbFNldHRpbmdzLmNvbHVtblNpemUgPT09IFNpbmdsZUNvbHVtblNpemUuc21hbGwpIHtcbiAgICAgICAgICAgIGNvbnRlbnREaXYuYWRkQ2xhc3MoYCR7TXVsdGlDb2x1bW5MYXlvdXRDU1MuU2luZ2xlQ29sdW1uU21hbGx9YClcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmKHRoaXMucmVnaW9uYWxTZXR0aW5ncy5jb2x1bW5TaXplID09PSBTaW5nbGVDb2x1bW5TaXplLmxhcmdlKSB7XG4gICAgICAgICAgICBjb250ZW50RGl2LmFkZENsYXNzKGAke011bHRpQ29sdW1uTGF5b3V0Q1NTLlNpbmdsZUNvbHVtbkxhcmdlfWApXG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZih0aGlzLnJlZ2lvbmFsU2V0dGluZ3MuY29sdW1uU2l6ZSA9PT0gU2luZ2xlQ29sdW1uU2l6ZS5mdWxsKSB7XG4gICAgICAgICAgICBjb250ZW50RGl2LmFkZENsYXNzKGAke011bHRpQ29sdW1uTGF5b3V0Q1NTLlNpbmdsZUNvbHVtbkZ1bGx9YClcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGNvbnRlbnREaXYuYWRkQ2xhc3MoYCR7TXVsdGlDb2x1bW5MYXlvdXRDU1MuU2luZ2xlQ29sdW1uTWVkfWApXG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gY29udGVudERpdjtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGlzQ2VudGVyZWQobGF5b3V0OiBDb2x1bW5MYXlvdXQpOiBib29sZWFuIHtcblxuICAgIGlmKGxheW91dCA9PT0gQ29sdW1uTGF5b3V0LnN0YW5kYXJkIHx8XG4gICAgICAgbGF5b3V0ID09PSBDb2x1bW5MYXlvdXQubWlkZGxlICAgfHxcbiAgICAgICBsYXlvdXQgPT09IENvbHVtbkxheW91dC5jZW50ZXIgICB8fFxuICAgICAgIGxheW91dCA9PT0gQ29sdW1uTGF5b3V0LnNlY29uZCAgICApIHtcblxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2Vcbn1cblxuZnVuY3Rpb24gaXNMZWZ0TGF5b3V0KGxheW91dDogQ29sdW1uTGF5b3V0KTogYm9vbGVhbiB7XG5cbiAgICBpZihsYXlvdXQgPT09IENvbHVtbkxheW91dC5sZWZ0IHx8XG4gICAgICAgbGF5b3V0ID09PSBDb2x1bW5MYXlvdXQuZmlyc3QgKSB7XG4gXG4gICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgfVxuIFxuICAgICByZXR1cm4gZmFsc2Vcbn1cblxuZnVuY3Rpb24gaXNSaWdodExheW91dChsYXlvdXQ6IENvbHVtbkxheW91dCk6IGJvb2xlYW4ge1xuXG4gICAgaWYobGF5b3V0ID09PSBDb2x1bW5MYXlvdXQucmlnaHQgfHxcbiAgICAgICBsYXlvdXQgPT09IENvbHVtbkxheW91dC50aGlyZCB8fFxuICAgICAgIGxheW91dCA9PT0gQ29sdW1uTGF5b3V0Lmxhc3QgKSB7XG4gXG4gICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgfVxuIFxuICAgICByZXR1cm4gZmFsc2Vcbn0iLCIvKipcbiAqIEZpbGU6IC9zcmMvZG9tX21hbmFnZXIvcmVnaW9uYWxfbWFuYWdlcnMvYXV0b0xheW91dFJlZ2lvbk1hbmFnZXIudHMgICAgICAgICAqXG4gKiBDcmVhdGVkIERhdGU6IFN1bmRheSwgTWF5IDIybmQgMjAyMiwgMTA6MjMgcG0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICogQXV0aG9yOiBDYW1lcm9uIFJvYmluc29uICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpcbiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMjIgQ2FtZXJvbiBSb2JpbnNvbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICovXG5cbmltcG9ydCB7IERPTU9iamVjdCwgRE9NT2JqZWN0VGFnLCBUYXNrTGlzdERPTU9iamVjdCB9IGZyb20gJy4uL2RvbU9iamVjdCc7XG5pbXBvcnQgeyBBbGlnbm1lbnRUeXBlLCBDb250ZW50T3ZlcmZsb3dUeXBlLCBNdWx0aUNvbHVtblNldHRpbmdzIH0gZnJvbSBcIi4uLy4uL3JlZ2lvblNldHRpbmdzXCI7XG5pbXBvcnQgeyBNdWx0aUNvbHVtbkxheW91dENTUywgTXVsdGlDb2x1bW5TdHlsZUNTUyB9IGZyb20gJy4uLy4uL3V0aWxpdGllcy9jc3NEZWZpbml0aW9ucyc7XG5pbXBvcnQgeyBSZWdpb25NYW5hZ2VyIH0gZnJvbSAnLi9yZWdpb25NYW5hZ2VyJztcbmltcG9ydCB7IGdldEhlYWRpbmdDb2xsYXBzZUVsZW1lbnQsIGhhc0hlYWRlciB9IGZyb20gJ3NyYy91dGlsaXRpZXMvZWxlbWVudFJlbmRlclR5cGVQYXJzZXInO1xuXG5leHBvcnQgY2xhc3MgQXV0b0xheW91dFJlZ2lvbk1hbmFnZXIgZXh0ZW5kcyBSZWdpb25NYW5hZ2VyIHtcblxuICAgIHByaXZhdGUgcHJldmlvdXNDb2x1bW5IZWlnaHRzOiBudW1iZXJbXSA9IFtdXG5cbiAgICBwcml2YXRlIGNvbHVtblBhcmVudDogSFRNTERpdkVsZW1lbnQ7XG4gICAgcHJpdmF0ZSBjb2x1bW5EaXZzOiBIVE1MRGl2RWxlbWVudFtdO1xuXG4gICAgcHVibGljIHJlbmRlclJlZ2lvbkVsZW1lbnRzVG9TY3JlZW4oKTogdm9pZCB7XG5cbiAgICAgICAgIHRoaXMucmVuZGVyQ29sdW1uTWFya2Rvd24odGhpcy5yZWdpb25QYXJlbnQsIHRoaXMuZG9tTGlzdCwgdGhpcy5yZWdpb25hbFNldHRpbmdzKTtcbiAgICB9XG4gICAgcHVibGljIGV4cG9ydFJlZ2lvbkVsZW1lbnRzVG9QREYocGRmUGFyZW50RWxlbWVudDogSFRNTEVsZW1lbnQpOiB2b2lkIHtcblxuICAgICAgICAvLyBEZWZhdWx0IHNldCBzaGFkb3cgdG8gb2ZmIGZvciBleHBvcnRpbmcgUERGc1xuICAgICAgICBsZXQgcmVuZGVyU2V0dGluZ3MgPSB0aGlzLnJlZ2lvbmFsU2V0dGluZ3M7XG4gICAgICAgIHJlbmRlclNldHRpbmdzLmRyYXdTaGFkb3cgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5yZW5kZXJDb2x1bW5NYXJrZG93bihwZGZQYXJlbnRFbGVtZW50LCB0aGlzLmRvbUxpc3Quc2xpY2UoKSwgcmVuZGVyU2V0dGluZ3MpO1xuICAgIH1cbiAgICBwdWJsaWMgcmVuZGVyUmVnaW9uRWxlbWVudHNUb0xpdmVQcmV2aWV3KHBhcmVudEVsZW1lbnQ6IEhUTUxFbGVtZW50KTogdm9pZCB7XG5cbiAgICAgICAgdGhpcy5yZW5kZXJDb2x1bW5NYXJrZG93bihwYXJlbnRFbGVtZW50LCB0aGlzLmRvbUxpc3QsIHRoaXMucmVnaW9uYWxTZXR0aW5ncyk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFRoaXMgZnVuY3Rpb24gdGFrZXMgaW4gdGhlIGRhdGEgZm9yIHRoZSBtdWx0aS1jb2x1bW4gcmVnaW9uIGFuZCBzZXRzIHVwIHRoZSBcbiAgICAgKiB1c2VyIGRlZmluZWQgbnVtYmVyIG9mIGNoaWxkcmVuIHdpdGggdGhlIHByb3BlciBjc3MgY2xhc3NlcyB0byBiZSByZW5kZXJlZCBwcm9wZXJseS5cbiAgICAgKiBcbiAgICAgKiBAcGFyYW0gcGFyZW50RWxlbWVudCBUaGUgZWxlbWVudCB0aGF0IHRoZSBtdWx0aS1jb2x1bW4gcmVnaW9uIHdpbGwgYmUgcmVuZGVyZWQgdW5kZXIuXG4gICAgICogQHBhcmFtIHJlZ2lvbkVsZW1lbnRzIFRoZSBsaXN0IG9mIERPTSBvYmplY3RzIHRoYXQgd2lsbCBiZSBjb3BwaWVkIHVuZGVyIHRoZSBwYXJlbnQgb2JqZWN0XG4gICAgICogQHBhcmFtIHNldHRpbmdzIFRoZSBzZXR0aW5ncyB0aGUgdXNlciBoYXMgZGVmaW5lZCBmb3IgdGhlIHJlZ2lvbi5cbiAgICAgKi9cbiAgICBwcml2YXRlIHJlbmRlckNvbHVtbk1hcmtkb3duKHBhcmVudEVsZW1lbnQ6IEhUTUxFbGVtZW50LCByZWdpb25FbGVtZW50czogRE9NT2JqZWN0W10sIHNldHRpbmdzOiBNdWx0aUNvbHVtblNldHRpbmdzKSB7XG5cbiAgICAgICAgbGV0IG11bHRpQ29sdW1uUGFyZW50ID0gY3JlYXRlRGl2KHtcbiAgICAgICAgICAgIGNsczogTXVsdGlDb2x1bW5MYXlvdXRDU1MuUmVnaW9uQ29sdW1uQ29udGFpbmVyRGl2LFxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5jb2x1bW5QYXJlbnQgPSBtdWx0aUNvbHVtblBhcmVudDtcblxuICAgICAgICAvKipcbiAgICAgICAgICogUGFzcyBvdXIgcGFyZW50IGRpdiBhbmQgc2V0dGluZ3MgdG8gcGFyc2VyIHRvIGNyZWF0ZSB0aGUgcmVxdWlyZWRcbiAgICAgICAgICogY29sdW1uIGRpdnMgYXMgY2hpbGRyZW4gb2YgdGhlIHBhcmVudC5cbiAgICAgICAgICovXG4gICAgICAgIHRoaXMuY29sdW1uRGl2cyA9IHRoaXMuZ2V0Q29sdW1uQ29udGVudERpdnMoc2V0dGluZ3MsIG11bHRpQ29sdW1uUGFyZW50KTtcblxuICAgICAgICBpZiAoc2V0dGluZ3MuZHJhd1NoYWRvdyA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgbXVsdGlDb2x1bW5QYXJlbnQuYWRkQ2xhc3MoTXVsdGlDb2x1bW5TdHlsZUNTUy5SZWdpb25TaGFkb3cpO1xuICAgICAgICB9XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5jb2x1bW5EaXZzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBpZiAoc2V0dGluZ3MuZHJhd0JvcmRlciA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuY29sdW1uRGl2c1tpXS5hZGRDbGFzcyhNdWx0aUNvbHVtblN0eWxlQ1NTLkNvbHVtbkJvcmRlcik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChzZXR0aW5ncy5kcmF3U2hhZG93ID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jb2x1bW5EaXZzW2ldLmFkZENsYXNzKE11bHRpQ29sdW1uU3R5bGVDU1MuQ29sdW1uU2hhZG93KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFJlbW92ZSBldmVyeSBvdGhlciBjaGlsZCBmcm9tIHRoZSBwYXJlbnQgc28gXG4gICAgICAgIC8vIHdlIGRvbnQgZW5kIHVwIHdpdGggbXVsdGlwbGUgc2V0cyBvZiBkYXRhLiBUaGlzIHNob3VsZFxuICAgICAgICAvLyByZWFsbHkgb25seSBuZWVkIHRvIGxvb3Agb25jZSBmb3IgaSA9IDAgYnV0IGxvb3AganVzdFxuICAgICAgICAvLyBpbiBjYXNlLlxuICAgICAgICBmb3IgKGxldCBpID0gcGFyZW50RWxlbWVudC5jaGlsZHJlbi5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICAgICAgcGFyZW50RWxlbWVudC5jaGlsZHJlbltpXS5kZXRhY2goKTtcbiAgICAgICAgfVxuICAgICAgICBwYXJlbnRFbGVtZW50LmFwcGVuZENoaWxkKG11bHRpQ29sdW1uUGFyZW50KTtcblxuICAgICAgICB0aGlzLmFwcGVuZEVsZW1lbnRzVG9Db2x1bW5zKHJlZ2lvbkVsZW1lbnRzLCB0aGlzLmNvbHVtbkRpdnMsIHNldHRpbmdzKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFwcGVuZEVsZW1lbnRzVG9Db2x1bW5zKHJlZ2lvbkVsZW1lbnRzOiBET01PYmplY3RbXSwgY29sdW1uQ29udGVudERpdnM6IEhUTUxEaXZFbGVtZW50W10sIHNldHRpbmdzOiBNdWx0aUNvbHVtblNldHRpbmdzKSB7XG5cbiAgICAgICAgZnVuY3Rpb24gYmFsYW5jZUVsZW1lbnRzKCkge1xuXG4gICAgICAgICAgICBsZXQgdG90YWxIZWlnaHQgPSByZWdpb25FbGVtZW50cy5tYXAoKGVsOiBET01PYmplY3QsIGluZGV4OiBudW1iZXIpID0+IHsgXG5cbiAgICAgICAgICAgICAgICAvLyBXZSBvbmx5IHdhbnQgdG8gYXR0ZW1wdCB0byB1cGRhdGUgdGhlIGVsZW1lbnRSZW5kZXJlZEhlaWdodCBpZiBpdCBpcyAwIGFuZCBpZiBpdCBpcyBub3QgYW4gdW5yZW5kZXJlZCBlbGVtZW50IHN1Y2ggYXMgYSBlbmRyZWdpb24gdGFnLlxuICAgICAgICAgICAgICAgIGlmKGVsLmVsZW1lbnRSZW5kZXJlZEhlaWdodCA9PT0gMCAmJlxuICAgICAgICAgICAgICAgICAgICBlbC50YWcgIT09IERPTU9iamVjdFRhZy5jb2x1bW5CcmVhayAmJlxuICAgICAgICAgICAgICAgICAgICBlbC50YWcgIT09IERPTU9iamVjdFRhZy5lbmRSZWdpb24gJiZcbiAgICAgICAgICAgICAgICAgICAgZWwudGFnICE9PSBET01PYmplY3RUYWcucmVnaW9uU2V0dGluZ3MgJiZcbiAgICAgICAgICAgICAgICAgICAgZWwudGFnICE9PSBET01PYmplY3RUYWcuc3RhcnRSZWdpb24pIHtcbiAgICBcbiAgICAgICAgICAgICAgICAgICAgLy8gQWRkIGVsZW1lbnQgdG8gcmVuZGVyZWQgZGl2IHNvIHdlIGNhbiBleHRyYWN0IHRoZSByZW5kZXJlZCBoZWlnaHQuXG4gICAgICAgICAgICAgICAgICAgIGNvbHVtbkNvbnRlbnREaXZzWzBdLmFwcGVuZENoaWxkKGVsLm9yaWdpbmFsRWxlbWVudClcbiAgICAgICAgICAgICAgICAgICAgZWwuZWxlbWVudFJlbmRlcmVkSGVpZ2h0ID0gZWwub3JpZ2luYWxFbGVtZW50LmNsaWVudEhlaWdodFxuICAgICAgICAgICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2c1swXS5yZW1vdmVDaGlsZChlbC5vcmlnaW5hbEVsZW1lbnQpXG4gICAgICAgICAgICAgICAgfVxuICAgIFxuICAgICAgICAgICAgICAgIHJldHVybiBlbC5lbGVtZW50UmVuZGVyZWRIZWlnaHQgXG4gICAgICAgICAgICB9KS5yZWR1Y2UoKHByZXY6IG51bWJlciwgY3VycjogbnVtYmVyKSA9PiB7IHJldHVybiBwcmV2ICsgY3VyciB9LCAwKTtcbiAgICAgICAgICAgIGxldCBtYXhDb2x1bW5Db250ZW50SGVpZ2h0ID0gTWF0aC50cnVuYyh0b3RhbEhlaWdodCAvIHNldHRpbmdzLm51bWJlck9mQ29sdW1ucyk7XG5cbiAgICAgICAgICAgIGZvcihsZXQgaSA9IDA7IGkgPCBjb2x1bW5Db250ZW50RGl2cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGogPSBjb2x1bW5Db250ZW50RGl2c1tpXS5jaGlsZHJlbi5sZW5ndGggLSAxOyBqID49IDA7IGotLSkge1xuICAgICAgICAgICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2c1tpXS5jaGlsZHJlbltqXS5kZXRhY2goKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGxldCBjb2x1bW5JbmRleCA9IDA7XG4gICAgICAgICAgICBsZXQgY3VycmVudENvbHVtbkhlaWdodCA9IDA7XG4gICAgICAgICAgICBmdW5jdGlvbiBjaGVja1Nob3VsZFN3aXRjaENvbHVtbnMobmV4dEVsZW1lbnRIZWlnaHQ6IG51bWJlcikge1xuICAgIFxuICAgICAgICAgICAgICAgIGlmIChjdXJyZW50Q29sdW1uSGVpZ2h0ICsgbmV4dEVsZW1lbnRIZWlnaHQgPiBtYXhDb2x1bW5Db250ZW50SGVpZ2h0ICYmXG4gICAgICAgICAgICAgICAgICAgIChjb2x1bW5JbmRleCArIDEpIDwgc2V0dGluZ3MubnVtYmVyT2ZDb2x1bW5zKSB7XG4gICAgXG4gICAgICAgICAgICAgICAgICAgIGNvbHVtbkluZGV4Kys7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRDb2x1bW5IZWlnaHQgPSAwO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCByZWdpb25FbGVtZW50cy5sZW5ndGg7IGkrKykge1xuXG4gICAgICAgICAgICAgICAgaWYgKHJlZ2lvbkVsZW1lbnRzW2ldLnRhZyA9PT0gRE9NT2JqZWN0VGFnLm5vbmUgfHxcbiAgICAgICAgICAgICAgICAgICAgcmVnaW9uRWxlbWVudHNbaV0udGFnID09PSBET01PYmplY3RUYWcuY29sdW1uQnJlYWspIHtcbiAgICBcbiAgICAgICAgICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgICAgICAgICAqIEhlcmUgd2UgY2hlY2sgaWYgd2UgbmVlZCB0byBzd2FwIHRvIHRoZSBuZXh0IGNvbHVtbiBmb3IgdGhlIGN1cnJlbnQgZWxlbWVudC5cbiAgICAgICAgICAgICAgICAgICAgICogSWYgdGhlIHVzZXIgd2FudHMgdG8ga2VlcCBoZWFkaW5ncyB3aXRoIHRoZSBjb250ZW50IGJlbG93IGl0IHdlIGFsc28gbWFrZSBzdXJlXG4gICAgICAgICAgICAgICAgICAgICAqIHRoYXQgdGhlIGxhc3QgaXRlbSBpbiBhIGNvbHVtbiBpcyBub3QgYSBoZWFkZXIgZWxlbWVudCBieSB1c2luZyB0aGUgaGVhZGVyIGFuZFxuICAgICAgICAgICAgICAgICAgICAgKiB0aGUgbmV4dCBlbGVtZW50J3MgaGVpZ2h0IGFzIHRoZSBoZWlnaHQgdmFsdWUuIFxuICAgICAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICAgICAgaWYoaGFzSGVhZGVyKHJlZ2lvbkVsZW1lbnRzW2ldLm9yaWdpbmFsRWxlbWVudCkgPT09IHRydWUpIHsgLy8gVE9ETzogQWRkIHRoaXMgYXMgc2VsZWN0YWJsZSBvcHRpb24uXG4gICAgXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgaGVhZGVyQW5kTmV4dEVsZW1lbnRIZWlnaHQgPSByZWdpb25FbGVtZW50c1tpXS5lbGVtZW50UmVuZGVyZWRIZWlnaHQ7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZihpIDwgcmVnaW9uRWxlbWVudHMubGVuZ3RoIC0gMSkge1xuICAgIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhlYWRlckFuZE5leHRFbGVtZW50SGVpZ2h0ICs9IHJlZ2lvbkVsZW1lbnRzW2kgKyAxXS5lbGVtZW50UmVuZGVyZWRIZWlnaHQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgXG4gICAgICAgICAgICAgICAgICAgICAgICBjaGVja1Nob3VsZFN3aXRjaENvbHVtbnMoaGVhZGVyQW5kTmV4dEVsZW1lbnRIZWlnaHQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgIFxuICAgICAgICAgICAgICAgICAgICAgICAgY2hlY2tTaG91bGRTd2l0Y2hDb2x1bW5zKHJlZ2lvbkVsZW1lbnRzW2ldLmVsZW1lbnRSZW5kZXJlZEhlaWdodCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgY3VycmVudENvbHVtbkhlaWdodCArPSByZWdpb25FbGVtZW50c1tpXS5lbGVtZW50UmVuZGVyZWRIZWlnaHRcbiAgICBcbiAgICBcbiAgICAgICAgICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgICAgICAgICAqIFdlIHN0b3JlIHRoZSBlbGVtZW50cyBpbiBhIHdyYXBwZXIgY29udGFpbmVyIHVudGlsIHdlIGRldGVybWluZSBpZiB3ZSB3YW50IHRvIFxuICAgICAgICAgICAgICAgICAgICAgKiB1c2UgdGhlIG9yaWdpbmFsIGVsZW1lbnQgb3IgYSBjbG9uZSBvZiB0aGUgZWxlbWVudC4gVGhpcyBoZWxwcyB1cyBieSBhbGxvd2luZyBcbiAgICAgICAgICAgICAgICAgICAgICogdXMgdG8gY3JlYXRlIGEgdmlzdWFsIG9ubHkgY2xvbmUgd2hpbGUgdGhlIHVwZGF0ZSBsb29wIG1vdmVzIHRoZSBvcmlnaW5hbCBlbGVtZW50IFxuICAgICAgICAgICAgICAgICAgICAgKiBpbnRvIHRoZSBjb2x1bW5zLlxuICAgICAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICAgICAgbGV0IGVsZW1lbnQgPSBjcmVhdGVEaXYoe1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xzOiBNdWx0aUNvbHVtbkxheW91dENTUy5Db2x1bW5EdWFsRWxlbWVudENvbnRhaW5lcixcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIHJlZ2lvbkVsZW1lbnRzW2ldLmVsZW1lbnRDb250YWluZXIgPSBlbGVtZW50O1xuICAgIFxuICAgICAgICAgICAgICAgICAgICBpZihzZXR0aW5ncy5jb250ZW50T3ZlcmZsb3cgPT09IENvbnRlbnRPdmVyZmxvd1R5cGUuaGlkZGVuKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50LmFkZENsYXNzKE11bHRpQ29sdW1uTGF5b3V0Q1NTLkNvbnRlbnRPdmVyZmxvd0hpZGRlbilcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnQuYWRkQ2xhc3MoTXVsdGlDb2x1bW5MYXlvdXRDU1MuQ29udGVudE92ZXJmbG93QXV0b1Njcm9sbClcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICAgICAgaWYoc2V0dGluZ3MuYWxpZ25tZW50ID09PSBBbGlnbm1lbnRUeXBlLmNlbnRlcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5hZGRDbGFzcyhNdWx0aUNvbHVtbkxheW91dENTUy5BbGlnbm1lbnRDZW50ZXIpXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoc2V0dGluZ3MuYWxpZ25tZW50ID09PSBBbGlnbm1lbnRUeXBlLnJpZ2h0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50LmFkZENsYXNzKE11bHRpQ29sdW1uTGF5b3V0Q1NTLkFsaWdubWVudFJpZ2h0KVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5hZGRDbGFzcyhNdWx0aUNvbHVtbkxheW91dENTUy5BbGlnbm1lbnRMZWZ0KVxuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgbGV0IGNsb25lZEVsZW1lbnQgPSByZWdpb25FbGVtZW50c1tpXS5jbG9uZWRFbGVtZW50O1xuICAgICAgICAgICAgICAgICAgICBpZihyZWdpb25FbGVtZW50c1tpXS5jbG9uZWRFbGVtZW50ID09PSBudWxsKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNsb25lZEVsZW1lbnQgPSByZWdpb25FbGVtZW50c1tpXS5vcmlnaW5hbEVsZW1lbnQuY2xvbmVOb2RlKHRydWUpIGFzIEhUTUxEaXZFbGVtZW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGhlYWRpbmdDb2xsYXBzZUVsZW1lbnQgPSBnZXRIZWFkaW5nQ29sbGFwc2VFbGVtZW50KGNsb25lZEVsZW1lbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYoaGVhZGluZ0NvbGxhcHNlRWxlbWVudCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgcmVtb3ZlcyB0aGUgY29sbGFwc2UgYXJyb3cgZnJvbSB0aGUgdmlldyBpZiBpdCBleGlzdHMuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVhZGluZ0NvbGxhcHNlRWxlbWVudC5kZXRhY2goKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgICAgICAgICAgICAgICAgICByZWdpb25FbGVtZW50c1tpXS5jbG9uZWRFbGVtZW50ID0gY2xvbmVkRWxlbWVudDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbGVtZW50LmFwcGVuZENoaWxkKGNsb25lZEVsZW1lbnQpO1xuICAgIFxuICAgICAgICAgICAgICAgICAgICBpZiAocmVnaW9uRWxlbWVudHNbaV0gaW5zdGFuY2VvZiBUYXNrTGlzdERPTU9iamVjdCkge1xuICAgIFxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5maXhDbG9uZWRDaGVja0xpc3RCdXR0b25zKHJlZ2lvbkVsZW1lbnRzW2ldIGFzIFRhc2tMaXN0RE9NT2JqZWN0LCB0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgIFxuICAgICAgICAgICAgICAgICAgICBpZiAoZWxlbWVudCAhPT0gbnVsbCAmJiBcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbHVtbkNvbnRlbnREaXZzW2NvbHVtbkluZGV4XSAmJiBcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlZ2lvbkVsZW1lbnRzW2ldLnRhZyAhPT0gRE9NT2JqZWN0VGFnLmNvbHVtbkJyZWFrKSB7XG4gICAgXG4gICAgICAgICAgICAgICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2c1tjb2x1bW5JbmRleF0uYXBwZW5kQ2hpbGQoZWxlbWVudCk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWdpb25FbGVtZW50c1tpXS5lbGVtZW50UmVuZGVyZWRIZWlnaHQgPSBlbGVtZW50LmNsaWVudEhlaWdodDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgIFxuICAgICAgICAgICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAgICAgICAgICogSWYgdGhlIHRhZyBpcyBhIGNvbHVtbiBicmVhayB3ZSB1cGRhdGUgdGhlIGNvbHVtbiBpbmRleCBhZnRlclxuICAgICAgICAgICAgICAgICAgICAgKiBhcHBlbmRpbmcgdGhlIGl0ZW0gdG8gdGhlIGNvbHVtbiBkaXYuIFRoaXMga2VlcHMgdGhlIG1haW4gRE9NXG4gICAgICAgICAgICAgICAgICAgICAqIGNsZWFuZXIgYnkgcmVtb3Zpbmcgb3RoZXIgaXRlbXMgYW5kIHBsYWNpbmcgdGhlbSBhbGwgd2l0aGluXG4gICAgICAgICAgICAgICAgICAgICAqIGEgcmVnaW9uIGNvbnRhaW5lci5cbiAgICAgICAgICAgICAgICAgICAgICogXG4gICAgICAgICAgICAgICAgICAgICAqIFJlbW92aW5nIHRoZSBlbmQgY29sdW1uIHRhZyBhcyBhbiBvcHRpb24gZm9yIG5vdy5cbiAgICAgICAgICAgICAgICAgICAgICovXG4gICAgICAgICAgICAgICAgICAgIC8vIGlmIChyZWdpb25FbGVtZW50c1tpXS50YWcgPT09IERPTU9iamVjdFRhZy5jb2x1bW5CcmVhayAmJlxuICAgICAgICAgICAgICAgICAgICAvLyAgICAoY29sdW1uSW5kZXggKyAxKSA8IHNldHRpbmdzLm51bWJlck9mQ29sdW1ucykge1xuICAgIFxuICAgICAgICAgICAgICAgICAgICAvLyAgICAgY29sdW1uSW5kZXgrKztcbiAgICAgICAgICAgICAgICAgICAgLy8gICAgIGN1cnJlbnRDb2x1bW5IZWlnaHQgPSAwO1xuICAgICAgICAgICAgICAgICAgICAvLyB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEF0dGVtcHQgdG8gYmFsYW5jZWQgdGhlIGVsZW1lbnRzLiBXZSBuZWVkIHRvIGl0ZXJhdGUgb3ZlciB0aGUgZWxlbWVudHMgbXVsdGlwbGUgdGltZXMgYmVjYXVzZVxuICAgICAgICAgKiBvdXIgaW5pdGlhbCBiYWxhbmNlIGVzdGltYXRlIG1heSBub3QgYmUgcGVyZmVjdGx5IGJhbGFuY2VkIGR1ZSB0byBkaWZmZXJlbnQgY29sdW1uIHdpZHRocyBjYXVzaW5nIFxuICAgICAgICAgKiBlbGVtZW50cyB3aXRoaW4gdGhlbSB0byBiZSBvZiBkaWZmZXJlbnQgaGVpZ2h0cy4gVGhpcyBjYW4gY2F1c2UgdGhlIGVsZW1lbnRzIHRvIGp1bXAgYXJvdW5kIG9uIFxuICAgICAgICAgKiBzdWJzaXF1ZW50IHVwZGF0ZSBsb29wcyB3aGljaCBpcyBub3QgaWRlYWwuIEhlcmUgd2UgcmVuZGVyIHRoZSBlbGVtZW50cyB0byB0aGUgc2NyZWVuIGFuZCB1cGRhdGUgXG4gICAgICAgICAqIHRoZWlyIGhlaWdodCBhZnRlciBiZWluZyByZW5kZXJlZCBpbnRvIHRoZSBlc3RpbWF0ZWQgcG9zaXRpb24uIFxuICAgICAgICAgKiBcbiAgICAgICAgICogT25jZSBldmVyeXRoaW5nIGlzIHJlbmRlcmVkIHdlIGNoZWNrIGFsbCBvZiB0aGUgY29sdW1uIGhlaWdodHMgYWdhaW5zdCBvdXIgbGFzdCBpdGVyYXRpb24gYW5kIFxuICAgICAgICAgKiBpZiBub3RoaW5nIGhhcyBjaGFuZ2VkIHdlIGtub3cgd2UgYXJlIGJhbGFuY2VkLlxuICAgICAgICAgKiBcbiAgICAgICAgICogVGhlcmUgaXMgcHJvYmFibHkgYSBiZXR0ZXIgd2F5IG9mIGFjY29tcGxpc2hpbmcgdGhpcyB0YXNrIGJ1dCB0aGlzIHdvcmtzIGZvciB0aGUgdGltZSBiZWluZy5cbiAgICAgICAgICovXG4gICAgICAgIGZvcihsZXQgaSA9IDA7IGkgPCA1OyBpKyspIHtcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgYmFsYW5jZUVsZW1lbnRzKClcblxuICAgICAgICAgICAgbGV0IGJhbGFuY2VkID0gdHJ1ZTtcbiAgICAgICAgICAgIGZvcihsZXQgaiA9IDA7IGogPCBjb2x1bW5Db250ZW50RGl2cy5sZW5ndGg7IGorKykge1xuXG4gICAgICAgICAgICAgICAgLy8gSWYgdGhlIGNvbHVtbiBoZWlnaHRzIGFyZSB1bmRlZmluZWQgd2Ugc2V0IGRlZmF1bHQgdG8gemVybyBzbyBub3QgdG8gZW5jb3VudGVyIGFuIGVycm9yLlxuICAgICAgICAgICAgICAgIGlmKCF0aGlzLnByZXZpb3VzQ29sdW1uSGVpZ2h0c1tqXSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnByZXZpb3VzQ29sdW1uSGVpZ2h0cy5wdXNoKDApXG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gaWYgdGhpcyByZW5kZXIgaGVpZ2h0IGlzIG5vdCB0aGUgc2FtZSBhcyB0aGUgcHJldmlvdXMgaGVpZ2h0IHdlIGFyZSBzdGlsbCBiYWxhbmNpbmcuXG4gICAgICAgICAgICAgICAgaWYodGhpcy5wcmV2aW91c0NvbHVtbkhlaWdodHNbal0gIT09IGNvbHVtbkNvbnRlbnREaXZzW2pdLmNsaWVudEhlaWdodCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnByZXZpb3VzQ29sdW1uSGVpZ2h0c1tqXSA9IGNvbHVtbkNvbnRlbnREaXZzW2pdLmNsaWVudEhlaWdodFxuICAgICAgICAgICAgICAgICAgICBiYWxhbmNlZCA9IGZhbHNlXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBpZiB3ZSBtYWRlIGl0IG91dCBvZiB0aGUgbG9vcCBhbmQgYWxsIG9mIHRoZSBjb2x1bW5zIGFyZSB0aGUgc2FtZSBoZWlnaHQgYXMgbGFzdCB1cGRhdGVcbiAgICAgICAgICAgIC8vIHdlJ3JlIGJhbGFuY2VkIHNvIHdlIGNhbiBicmVhayBvdXQgb2YgdGhlIGxvb3AuXG4gICAgICAgICAgICBpZihiYWxhbmNlZCA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHVibGljIHVwZGF0ZVJlbmRlcmVkTWFya2Rvd24oKSB7XG5cbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLmRvbUxpc3QubGVuZ3RoOyBpKyspIHtcblxuICAgICAgICAgICAgbGV0IGVsID0gdGhpcy5kb21MaXN0W2ldXG4gICAgICAgICAgICBsZXQgb3JpZ2luYWxDbGllbnRIZWlnaHQgPSAwO1xuICAgICAgICAgICAgaWYgKGVsLm9yaWdpbmFsRWxlbWVudCkge1xuICAgICAgICAgICAgICAgIG9yaWdpbmFsQ2xpZW50SGVpZ2h0ID0gZWwub3JpZ2luYWxFbGVtZW50LmNsaWVudEhlaWdodFxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IGNsb25lZENsaWVudEhlaWdodCA9IDA7XG4gICAgICAgICAgICBpZiAoZWwuY2xvbmVkRWxlbWVudCkge1xuICAgICAgICAgICAgICAgIGNsb25lZENsaWVudEhlaWdodCA9IGVsLmNsb25lZEVsZW1lbnQuY2xpZW50SGVpZ2h0XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChvcmlnaW5hbENsaWVudEhlaWdodCA8IGNsb25lZENsaWVudEhlaWdodCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZG9tTGlzdFtpXS5lbGVtZW50UmVuZGVyZWRIZWlnaHQgPSBjbG9uZWRDbGllbnRIZWlnaHQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLmRvbUxpc3RbaV0uZWxlbWVudFJlbmRlcmVkSGVpZ2h0ID0gb3JpZ2luYWxDbGllbnRIZWlnaHQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgdmFsaWRDb2x1bW5zID0gdHJ1ZTtcbiAgICAgICAgaWYodGhpcy5jb2x1bW5QYXJlbnQgIT09IG51bGwgJiYgdGhpcy5jb2x1bW5EaXZzICE9PSBudWxsICYmIHRoaXMuY29sdW1uRGl2cyAhPT0gdW5kZWZpbmVkICYmXG4gICAgICAgICAgICB0aGlzLmNvbHVtbkRpdnMubGVuZ3RoID09PSB0aGlzLnJlZ2lvbmFsU2V0dGluZ3MubnVtYmVyT2ZDb2x1bW5zKSB7XG5cbiAgICAgICAgICAgIGxldCB0b3RhbEhlaWdodCA9IHRoaXMuZG9tTGlzdC5tYXAoKGVsOiBET01PYmplY3QsIGluZGV4OiBudW1iZXIpID0+IHsgXG5cbiAgICAgICAgICAgICAgICAvLyBXZSBvbmx5IHdhbnQgdG8gYXR0ZW1wdCB0byB1cGRhdGUgdGhlIGVsZW1lbnRSZW5kZXJlZEhlaWdodCBpZiBpdCBpcyAwIGFuZCBpZiBpdCBpcyBub3QgYW4gdW5yZW5kZXJlZCBlbGVtZW50IHN1Y2ggYXMgYSBlbmRyZWdpb24gdGFnLlxuICAgICAgICAgICAgICAgIGlmKGVsLmVsZW1lbnRSZW5kZXJlZEhlaWdodCA9PT0gMCAmJlxuICAgICAgICAgICAgICAgICAgICBlbC50YWcgIT09IERPTU9iamVjdFRhZy5jb2x1bW5CcmVhayAmJlxuICAgICAgICAgICAgICAgICAgICBlbC50YWcgIT09IERPTU9iamVjdFRhZy5lbmRSZWdpb24gJiZcbiAgICAgICAgICAgICAgICAgICAgZWwudGFnICE9PSBET01PYmplY3RUYWcucmVnaW9uU2V0dGluZ3MgJiZcbiAgICAgICAgICAgICAgICAgICAgZWwudGFnICE9PSBET01PYmplY3RUYWcuc3RhcnRSZWdpb24pIHtcbiAgICBcbiAgICAgICAgICAgICAgICAgICAgLy8gQWRkIGVsZW1lbnQgdG8gcmVuZGVyZWQgZGl2IHNvIHdlIGNhbiBleHRyYWN0IHRoZSByZW5kZXJlZCBoZWlnaHQuXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY29sdW1uUGFyZW50LmFwcGVuZENoaWxkKGVsLm9yaWdpbmFsRWxlbWVudClcbiAgICAgICAgICAgICAgICAgICAgZWwuZWxlbWVudFJlbmRlcmVkSGVpZ2h0ID0gZWwub3JpZ2luYWxFbGVtZW50LmNsaWVudEhlaWdodFxuICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbHVtblBhcmVudC5yZW1vdmVDaGlsZChlbC5vcmlnaW5hbEVsZW1lbnQpXG4gICAgICAgICAgICAgICAgfVxuICAgIFxuICAgICAgICAgICAgICAgIHJldHVybiBlbC5lbGVtZW50UmVuZGVyZWRIZWlnaHQgXG4gICAgICAgICAgICB9KS5yZWR1Y2UoKHByZXY6IG51bWJlciwgY3VycjogbnVtYmVyKSA9PiB7IHJldHVybiBwcmV2ICsgY3VyciB9LCAwKTtcbiAgICAgICAgICAgIGxldCBtYXhDb2x1bW5Db250ZW50SGVpZ2h0ID0gTWF0aC50cnVuYyh0b3RhbEhlaWdodCAvIHRoaXMucmVnaW9uYWxTZXR0aW5ncy5udW1iZXJPZkNvbHVtbnMpO1xuXG4gICAgICAgICAgICBmb3IobGV0IGkgPSAwOyBpIDwgdGhpcy5jb2x1bW5EaXZzLmxlbmd0aCAtIDE7IGkrKykge1xuXG4gICAgICAgICAgICAgICAgbGV0IGNvbHVtbkhlaWdodCA9IDBcbiAgICAgICAgICAgICAgICBmb3IobGV0IGogPSAwOyBqIDwgdGhpcy5jb2x1bW5EaXZzW2ldLmNoaWxkcmVuLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbHVtbkhlaWdodCArPSB0aGlzLmNvbHVtbkRpdnNbaV0uY2hpbGRyZW5bal0uY2xpZW50SGVpZ2h0XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYoY29sdW1uSGVpZ2h0ID4gbWF4Q29sdW1uQ29udGVudEhlaWdodCkge1xuICAgICAgICAgICAgICAgICAgICB2YWxpZENvbHVtbnMgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYodmFsaWRDb2x1bW5zID09PSBmYWxzZSkge1xuXG4gICAgICAgICAgICB0aGlzLnJlbmRlckNvbHVtbk1hcmtkb3duKHRoaXMucmVnaW9uUGFyZW50LCB0aGlzLmRvbUxpc3QsIHRoaXMucmVnaW9uYWxTZXR0aW5ncyk7XG4gICAgICAgIH1cblxuICAgICAgICBzdXBlci51cGRhdGVSZW5kZXJlZE1hcmtkb3duKCk7XG4gICAgfVxufVxuXG4iLCIvKipcbiAqIEZpbGU6IC9zcmMvZG9tX21hbmFnZXIvcmVnaW9uYWxfbWFuYWdlcnMvcmVnaW9uTWFuYWdlckNvbnRhaW5lci50cyAgICAgICAgICAqXG4gKiBDcmVhdGVkIERhdGU6IFN1bmRheSwgTWF5IDIybmQgMjAyMiwgNzo1MCBwbSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICogQXV0aG9yOiBDYW1lcm9uIFJvYmluc29uICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpcbiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMjIgQ2FtZXJvbiBSb2JpbnNvbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKlxuICovXG5cbmltcG9ydCB7IHBhcnNlQ29sdW1uU2V0dGluZ3MsIHBhcnNlU2luZ2xlQ29sdW1uU2V0dGluZ3MgfSBmcm9tIFwiLi4vLi4vdXRpbGl0aWVzL3NldHRpbmdzUGFyc2VyXCI7XG5pbXBvcnQgeyBET01PYmplY3QgfSBmcm9tICcuLi9kb21PYmplY3QnO1xuaW1wb3J0IHsgTXVsdGlDb2x1bW5TZXR0aW5ncywgZ2V0RGVmYXVsdE11bHRpQ29sdW1uU2V0dGluZ3MgfSBmcm9tIFwiLi4vLi4vcmVnaW9uU2V0dGluZ3NcIjtcbmltcG9ydCB7IEZpbGVET01NYW5hZ2VyIH0gZnJvbSAnLi4vZG9tTWFuYWdlcic7XG5pbXBvcnQgeyBTdGFuZGFyZE11bHRpQ29sdW1uUmVnaW9uTWFuYWdlciBhcyBTdGFuZGFyZE11bHRpQ29sdW1uUmVnaW9uTWFuYWdlciB9IGZyb20gJy4vc3RhbmRhcmRNdWx0aUNvbHVtblJlZ2lvbk1hbmFnZXInO1xuaW1wb3J0IHsgU2luZ2xlQ29sdW1uUmVnaW9uTWFuYWdlciB9IGZyb20gXCIuL3NpbmdsZUNvbHVtblJlZ2lvbk1hbmFnZXJcIjtcbmltcG9ydCB7IFJlZ2lvbk1hbmFnZXIgfSBmcm9tIFwiLi9yZWdpb25NYW5hZ2VyXCI7XG5pbXBvcnQgeyBBdXRvTGF5b3V0UmVnaW9uTWFuYWdlciB9IGZyb20gJy4vYXV0b0xheW91dFJlZ2lvbk1hbmFnZXInO1xuXG4vKipcbiAqIFRoaXMgY2xhc3MgYWN0cyBhcyBhbiBhYnN0cmFjdGlvbiBmb3IgdGhlIGFjdHVhbCByZWdpb25hbCBtYW5hZ2VyLiBJdCBpcyB1c2VkIHRvIHVwZGF0ZSB0aGVcbiAqIHN1YmNsYXNzIG9mIFJlZ2lvbmFsTWFuYWdlciBkZXBlbmRpbmcgb24gdXNlciBwcmVmZXJlbmNlcyB0byBtYWtlIHJlbmRlcmluZyBtb3JlIHNpbXBsaWZpZWQuXG4gKi9cbmV4cG9ydCBjbGFzcyBSZWdpb25NYW5hZ2VyQ29udGFpbmVyIHtcblxuICAgIHByb3RlY3RlZCByZWdpb246IFJlZ2lvbk1hbmFnZXI7XG4gICAgY29uc3RydWN0b3IocGFyZW50RmlsZU1hbmFnZXI6IEZpbGVET01NYW5hZ2VyLCByZWdpb25LZXk6IHN0cmluZywgcm9vdEVsZW1lbnQ6IEhUTUxFbGVtZW50LCByZWdpb25QYXJlbnQ6IEhUTUxFbGVtZW50KSB7XG4gICAgICAgIHRoaXMucmVnaW9uID0gbmV3IFN0YW5kYXJkTXVsdGlDb2x1bW5SZWdpb25NYW5hZ2VyKGNyZWF0ZURlZmF1bHRSZWdpb25NYW5hZ2VyRGF0YShyZWdpb25QYXJlbnQsIHBhcmVudEZpbGVNYW5hZ2VyLCByZWdpb25LZXksIHJvb3RFbGVtZW50KSk7XG4gICAgfVxuXG4gICAgcHVibGljIGdldFJlZ2lvbigpOiBSZWdpb25NYW5hZ2VyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucmVnaW9uO1xuICAgIH1cblxuICAgIHB1YmxpYyBzZXRSZWdpb25TZXR0aW5ncyhzZXR0aW5nc1RleHQ6IHN0cmluZyk6IFJlZ2lvbk1hbmFnZXIge1xuXG4gICAgICAgIGxldCByZWdpb25hbFNldHRpbmdzID0gcGFyc2VDb2x1bW5TZXR0aW5ncyhzZXR0aW5nc1RleHQpO1xuICAgICAgICBpZiAocmVnaW9uYWxTZXR0aW5ncy5udW1iZXJPZkNvbHVtbnMgPT09IDEpIHtcblxuICAgICAgICAgICAgcmVnaW9uYWxTZXR0aW5ncyA9IHBhcnNlU2luZ2xlQ29sdW1uU2V0dGluZ3Moc2V0dGluZ3NUZXh0LCByZWdpb25hbFNldHRpbmdzKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnJlZ2lvbi5zZXRSZWdpb25hbFNldHRpbmdzKHJlZ2lvbmFsU2V0dGluZ3MpO1xuXG4gICAgICAgIGlmIChyZWdpb25hbFNldHRpbmdzLm51bWJlck9mQ29sdW1ucyA9PT0gMSkge1xuXG4gICAgICAgICAgICBpZih0aGlzLnJlZ2lvbiBpbnN0YW5jZW9mIFNpbmdsZUNvbHVtblJlZ2lvbk1hbmFnZXIgPT09IGZhbHNlKSB7XG5cbiAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmRlYnVnKFwiQ29udmVydGluZyByZWdpb24gdG8gc2luZ2xlIGNvbHVtbi5cIilcbiAgICAgICAgICAgICAgICB0aGlzLmNvbnZlcnRUb1NpbmdsZUNvbHVtbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYocmVnaW9uYWxTZXR0aW5ncy5hdXRvTGF5b3V0ID09PSB0cnVlKSB7XG5cbiAgICAgICAgICAgIGlmKHRoaXMucmVnaW9uIGluc3RhbmNlb2YgQXV0b0xheW91dFJlZ2lvbk1hbmFnZXIgPT09IGZhbHNlKSB7XG5cbiAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmRlYnVnKFwiQ29udmVydGluZyByZWdpb24gdG8gYXV0byBsYXlvdXQuXCIpXG4gICAgICAgICAgICAgICAgdGhpcy5jb252ZXJ0VG9BdXRvTGF5b3V0KClcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChyZWdpb25hbFNldHRpbmdzLm51bWJlck9mQ29sdW1ucyA+PSAyKSB7XG5cbiAgICAgICAgICAgIGlmKHRoaXMucmVnaW9uIGluc3RhbmNlb2YgU3RhbmRhcmRNdWx0aUNvbHVtblJlZ2lvbk1hbmFnZXIgPT09IGZhbHNlKSB7XG5cbiAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmRlYnVnKFwiQ29udmVydGluZyByZWdpb24gdG8gc3RhbmRhcmQgbXVsdGktY29sdW1uXCIpXG4gICAgICAgICAgICAgICAgdGhpcy5jb252ZXJ0VG9TdGFuZGFyZE11bHRpQ29sdW1uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcy5yZWdpb247XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBjb252ZXJ0VG9TaW5nbGVDb2x1bW4oKTogU2luZ2xlQ29sdW1uUmVnaW9uTWFuYWdlciB7XG5cbiAgICAgICAgbGV0IGRhdGEgPSB0aGlzLnJlZ2lvbi5nZXRSZWdpb25EYXRhKCk7XG4gICAgICAgIHRoaXMucmVnaW9uID0gbmV3IFNpbmdsZUNvbHVtblJlZ2lvbk1hbmFnZXIoZGF0YSk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXMucmVnaW9uIGFzIFNpbmdsZUNvbHVtblJlZ2lvbk1hbmFnZXI7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBjb252ZXJ0VG9TdGFuZGFyZE11bHRpQ29sdW1uKCk6IFN0YW5kYXJkTXVsdGlDb2x1bW5SZWdpb25NYW5hZ2VyIHtcblxuICAgICAgICBsZXQgZGF0YSA9IHRoaXMucmVnaW9uLmdldFJlZ2lvbkRhdGEoKTtcbiAgICAgICAgdGhpcy5yZWdpb24gPSBuZXcgU3RhbmRhcmRNdWx0aUNvbHVtblJlZ2lvbk1hbmFnZXIoZGF0YSk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXMucmVnaW9uIGFzIFN0YW5kYXJkTXVsdGlDb2x1bW5SZWdpb25NYW5hZ2VyO1xuICAgIH1cblxuICAgIHByaXZhdGUgY29udmVydFRvQXV0b0xheW91dCgpOiBBdXRvTGF5b3V0UmVnaW9uTWFuYWdlciB7XG5cbiAgICAgICAgbGV0IGRhdGEgPSB0aGlzLnJlZ2lvbi5nZXRSZWdpb25EYXRhKCk7XG4gICAgICAgIHRoaXMucmVnaW9uID0gbmV3IEF1dG9MYXlvdXRSZWdpb25NYW5hZ2VyKGRhdGEpO1xuXG4gICAgICAgIHJldHVybiB0aGlzLnJlZ2lvbiBhcyBBdXRvTGF5b3V0UmVnaW9uTWFuYWdlcjtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZURlZmF1bHRSZWdpb25NYW5hZ2VyRGF0YShyZWdpb25QYXJlbnQ6IEhUTUxFbGVtZW50LCBmaWxlTWFuYWdlcjogRmlsZURPTU1hbmFnZXIsIHJlZ2lvbktleTogc3RyaW5nLCByb290RWxlbWVudDogSFRNTEVsZW1lbnQpOiBSZWdpb25NYW5hZ2VyRGF0YSB7XG5cbiAgICByZXR1cm4ge1xuICAgICAgICBkb21MaXN0OiBbXSxcbiAgICAgICAgZG9tT2JqZWN0TWFwOiBuZXcgTWFwKCksXG4gICAgICAgIHJlZ2lvblBhcmVudDogcmVnaW9uUGFyZW50LFxuICAgICAgICBmaWxlTWFuYWdlcjogZmlsZU1hbmFnZXIsXG4gICAgICAgIHJlZ2lvbmFsU2V0dGluZ3M6IGdldERlZmF1bHRNdWx0aUNvbHVtblNldHRpbmdzKCksXG4gICAgICAgIHJlZ2lvbktleTogcmVnaW9uS2V5LFxuICAgICAgICByb290RWxlbWVudDogcm9vdEVsZW1lbnRcbiAgICB9O1xufVxuXG5leHBvcnQgdHlwZSBSZWdpb25NYW5hZ2VyRGF0YSA9IHtcbiAgICBkb21MaXN0OiBET01PYmplY3RbXTtcbiAgICBkb21PYmplY3RNYXA6IE1hcDxzdHJpbmcsIERPTU9iamVjdD47XG4gICAgcmVnaW9uUGFyZW50OiBIVE1MRWxlbWVudDtcblxuICAgIGZpbGVNYW5hZ2VyOiBGaWxlRE9NTWFuYWdlcjtcbiAgICByZWdpb25hbFNldHRpbmdzOiBNdWx0aUNvbHVtblNldHRpbmdzO1xuXG4gICAgcmVnaW9uS2V5OiBzdHJpbmc7XG4gICAgcm9vdEVsZW1lbnQ6IEhUTUxFbGVtZW50O1xufTtcbiIsIi8qXG4gKiBGaWxlOiBtdWx0aS1jb2x1bW4tbWFya2Rvd24vc3JjL2RvbU1hbmFnZXIudHNcbiAqIENyZWF0ZWQgRGF0ZTogU2F0dXJkYXksIEphbnVhcnkgMzB0aCAyMDIyLCAzOjE2OjMyIHBtXG4gKiBBdXRob3I6IENhbWVyb24gUm9iaW5zb25cbiAqIFxuICogQ29weXJpZ2h0IChjKSAyMDIyIENhbWVyb24gUm9iaW5zb25cbiAqL1xuXG5pbXBvcnQgeyBSZWdpb25NYW5hZ2VyIH0gZnJvbSBcIi4vcmVnaW9uYWxfbWFuYWdlcnMvcmVnaW9uTWFuYWdlclwiO1xuaW1wb3J0IHsgUmVnaW9uTWFuYWdlckNvbnRhaW5lciB9IGZyb20gXCIuL3JlZ2lvbmFsX21hbmFnZXJzL3JlZ2lvbk1hbmFnZXJDb250YWluZXJcIjtcblxuLyoqXG4gKiBUaGlzIGNsYXNzIGhhbmRsZXMgdGhlIGdsb2JhbCBtYW5hZ2VycyBrZWVwaW5nIHRyYWNrIG9mIGFsbCBvcGVuIGZpbGVzIHRoYXRcbiAqIGNvbnRhaW4gTUNNLVJlZ2lvbnMuXG4gKi9cbmV4cG9ydCBjbGFzcyBHbG9iYWxET01NYW5hZ2VyIHtcbiAgICBtYW5hZ2VyczogTWFwPHN0cmluZywgRmlsZURPTU1hbmFnZXI+O1xuXG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHRoaXMubWFuYWdlcnMgPSBuZXcgTWFwKCk7XG4gICAgfVxuXG4gICAgcHVibGljIHJlbW92ZUZpbGVNYW5hZ2VyQ2FsbGJhY2soa2V5OiBzdHJpbmcpIHtcbiAgICAgICAgaWYodGhpcy5tYW5hZ2Vycy5oYXMoa2V5KSA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgdGhpcy5tYW5hZ2Vycy5kZWxldGUoa2V5KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyBnZXRGaWxlTWFuYWdlcihrZXk6IHN0cmluZykge1xuXG4gICAgICAgIGxldCBmaWxlTWFuYWdlciA9IG51bGw7XG4gICAgICAgIGlmKHRoaXMubWFuYWdlcnMuaGFzKGtleSkgPT09IHRydWUpIHtcbiAgICAgICAgICAgIGZpbGVNYW5hZ2VyID0gdGhpcy5tYW5hZ2Vycy5nZXQoa2V5KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGZpbGVNYW5hZ2VyID0gY3JlYXRlRmlsZURPTU1hbmFnZXIodGhpcywga2V5KTtcbiAgICAgICAgICAgIHRoaXMubWFuYWdlcnMuc2V0KGtleSwgZmlsZU1hbmFnZXIpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGZpbGVNYW5hZ2VyO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXRBbGxGaWxlTWFuYWdlcnMoKSB7XG4gICAgICAgIHJldHVybiBBcnJheS5mcm9tKHRoaXMubWFuYWdlcnMudmFsdWVzKCkpO1xuICAgIH1cbn1cblxuZXhwb3J0IHR5cGUgRmlsZURPTU1hbmFnZXIgPSB7XG4gICAgcmVnaW9uTWFwOiBNYXA8c3RyaW5nLCBSZWdpb25NYW5hZ2VyQ29udGFpbmVyPixcbiAgICBoYXNTdGFydFRhZzogYm9vbGVhbixcbiAgICBjcmVhdGVSZWdpb25hbE1hbmFnZXI6IChyZWdpb25LZXk6IHN0cmluZywgcm9vdEVsZW1lbnQ6IEhUTUxFbGVtZW50LCBlcnJvckVsZW1lbnQ6IEhUTUxFbGVtZW50LCByZW5kZXJSZWdpb25FbGVtZW50OiBIVE1MRWxlbWVudCkgPT4gUmVnaW9uTWFuYWdlclxuICAgIGdldFJlZ2lvbmFsQ29udGFpbmVyOiAocmVnaW9uS2V5OiBzdHJpbmcpID0+IFJlZ2lvbk1hbmFnZXJDb250YWluZXIgfCBudWxsLFxuICAgIGdldEFsbFJlZ2lvbmFsTWFuYWdlcnM6ICgpID0+IFJlZ2lvbk1hbmFnZXJbXSxcbiAgICByZW1vdmVSZWdpb246IChyZWdpb25LZXk6IHN0cmluZykgPT4gdm9pZCxcbiAgICBzZXRIYXNTdGFydFRhZzogKCkgPT4gdm9pZCxcbiAgICBnZXRIYXNTdGFydFRhZzogKCkgPT4gYm9vbGVhbixcbiAgICBnZXROdW1iZXJPZlJlZ2lvbnM6ICgpID0+IG51bWJlcixcbiAgICBjaGVja0tleUV4aXN0czogKGNoZWNrS2V5OiBzdHJpbmcpID0+IGJvb2xlYW5cbn1cbmZ1bmN0aW9uIGNyZWF0ZUZpbGVET01NYW5hZ2VyKHBhcmVudE1hbmFnZXI6IEdsb2JhbERPTU1hbmFnZXIsIGZpbGVLZXk6IHN0cmluZyk6IEZpbGVET01NYW5hZ2VyIHtcbiAgICBcbiAgICBsZXQgcmVnaW9uTWFwOiBNYXA8c3RyaW5nLCBSZWdpb25NYW5hZ2VyQ29udGFpbmVyPiA9IG5ldyBNYXAoKTtcbiAgICBsZXQgaGFzU3RhcnRUYWc6IGJvb2xlYW4gPSBmYWxzZTtcblxuICAgIGZ1bmN0aW9uIHJlbW92ZVJlZ2lvbihyZWdpb25LZXk6IHN0cmluZyk6IHZvaWQge1xuXG4gICAgICAgIGxldCByZWdpb25Db250YWluZXIgPSByZWdpb25NYXAuZ2V0KHJlZ2lvbktleSk7XG4gICAgICAgIGlmKHJlZ2lvbkNvbnRhaW5lcikge1xuICAgICAgICAgICAgbGV0IHJlZ2lvbmFsTWFuYWdlciA9IHJlZ2lvbkNvbnRhaW5lci5nZXRSZWdpb24oKTtcbiAgICAgICAgICAgIHJlZ2lvbmFsTWFuYWdlci5kaXNwbGF5T3JpZ2luYWxFbGVtZW50cygpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmVnaW9uTWFwLmRlbGV0ZShyZWdpb25LZXkpO1xuICAgICAgICBcbiAgICAgICAgaWYocmVnaW9uTWFwLnNpemUgPT09IDApIHtcbiAgICAgICAgICAgIHBhcmVudE1hbmFnZXIucmVtb3ZlRmlsZU1hbmFnZXJDYWxsYmFjayhmaWxlS2V5KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNyZWF0ZVJlZ2lvbmFsTWFuYWdlcihyZWdpb25LZXk6IHN0cmluZywgcm9vdEVsZW1lbnQ6IEhUTUxFbGVtZW50LCBlcnJvckVsZW1lbnQ6IEhUTUxFbGVtZW50LCByZW5kZXJSZWdpb25FbGVtZW50OiBIVE1MRWxlbWVudCk6IFJlZ2lvbk1hbmFnZXIge1xuXG4gICAgICAgIC8vVE9ETzogVXNlIHRoZSBlcnJvciBlbGVtZW50IHdoZW5ldmVyIHRoZXJlIGlzIGFuIGVycm9yLlxuXG4gICAgICAgIGxldCByZWdvbmFsQ29udGFpbmVyID0gbmV3IFJlZ2lvbk1hbmFnZXJDb250YWluZXIodGhpcywgcmVnaW9uS2V5LCByb290RWxlbWVudCwgcmVuZGVyUmVnaW9uRWxlbWVudCk7XG4gICAgICAgIHJlZ2lvbk1hcC5zZXQocmVnaW9uS2V5LCByZWdvbmFsQ29udGFpbmVyKTtcbiAgICAgICAgcmV0dXJuIHJlZ29uYWxDb250YWluZXIuZ2V0UmVnaW9uKCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0UmVnaW9uYWxDb250YWluZXIocmVnaW9uS2V5OiBzdHJpbmcpOiBSZWdpb25NYW5hZ2VyQ29udGFpbmVyIHwgbnVsbCB7XG5cbiAgICAgICAgbGV0IHJlZ29uYWxNYW5hZ2VyID0gbnVsbDtcbiAgICAgICAgaWYocmVnaW9uTWFwLmhhcyhyZWdpb25LZXkpID09PSB0cnVlKSB7XG4gICAgICAgICAgICByZWdvbmFsTWFuYWdlciA9IHJlZ2lvbk1hcC5nZXQocmVnaW9uS2V5KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByZWdvbmFsTWFuYWdlcjtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBnZXRBbGxSZWdpb25hbE1hbmFnZXJzKCk6IFJlZ2lvbk1hbmFnZXJbXSB7XG5cbiAgICAgICAgbGV0IGNvbnRhaW5lcnMgPSBBcnJheS5mcm9tKHJlZ2lvbk1hcC52YWx1ZXMoKSlcbiAgICAgICAgbGV0IHJlZ2lvbnM6IFJlZ2lvbk1hbmFnZXJbXSA9IGNvbnRhaW5lcnMubWFwKChjdXJyKSA9PiB7IHJldHVybiBjdXJyLmdldFJlZ2lvbigpIH0pO1xuICAgICAgICByZXR1cm4gcmVnaW9ucztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBzZXRIYXNTdGFydFRhZygpIHtcbiAgICAgICAgaGFzU3RhcnRUYWcgPSB0cnVlO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldEhhc1N0YXJ0VGFnKCkge1xuICAgICAgICByZXR1cm4gaGFzU3RhcnRUYWc7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0TnVtYmVyT2ZSZWdpb25zKCkge1xuICAgICAgICByZXR1cm4gcmVnaW9uTWFwLnNpemVcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjaGVja0tleUV4aXN0cyhjaGVja0tleTogc3RyaW5nKSB7XG4gICAgICAgIHJldHVybiByZWdpb25NYXAuaGFzKGNoZWNrS2V5KTtcbiAgICB9XG5cbiAgICByZXR1cm4geyByZWdpb25NYXA6IHJlZ2lvbk1hcCwgXG4gICAgICAgIGhhc1N0YXJ0VGFnOiBoYXNTdGFydFRhZywgIFxuICAgICAgICBjcmVhdGVSZWdpb25hbE1hbmFnZXI6IGNyZWF0ZVJlZ2lvbmFsTWFuYWdlciwgXG4gICAgICAgIGdldFJlZ2lvbmFsQ29udGFpbmVyOiBnZXRSZWdpb25hbENvbnRhaW5lcixcbiAgICAgICAgZ2V0QWxsUmVnaW9uYWxNYW5hZ2VyczogZ2V0QWxsUmVnaW9uYWxNYW5hZ2VycyxcbiAgICAgICAgcmVtb3ZlUmVnaW9uOiByZW1vdmVSZWdpb24sIFxuICAgICAgICBzZXRIYXNTdGFydFRhZzogc2V0SGFzU3RhcnRUYWcsIFxuICAgICAgICBnZXRIYXNTdGFydFRhZzogZ2V0SGFzU3RhcnRUYWcsXG4gICAgICAgIGdldE51bWJlck9mUmVnaW9uczogZ2V0TnVtYmVyT2ZSZWdpb25zLFxuICAgICAgICBjaGVja0tleUV4aXN0czogY2hlY2tLZXlFeGlzdHNcbiAgICB9XG59IiwiLypcbiAqIEZpbGVuYW1lOiBtdWx0aS1jb2x1bW4tbWFya2Rvd24vc3JjL2xpdmVfcHJldmlldy9NdWx0aUNvbHVtbk1hcmtkb3duX1dpZGdldC50c1xuICogQ3JlYXRlZCBEYXRlOiBUdWVzZGF5LCBBdWd1c3QgMTZ0aCAyMDIyLCA0OjM4OjQzIHBtXG4gKiBBdXRob3I6IENhbWVyb24gUm9iaW5zb25cbiAqIFxuICogQ29weXJpZ2h0IChjKSAyMDIyIENhbWVyb24gUm9iaW5zb25cbiAqL1xuXG5pbXBvcnQgeyBNYXJrZG93blJlbmRlckNoaWxkLCBNYXJrZG93blJlbmRlcmVyLCBURmlsZSwgV29ya3NwYWNlTGVhZiB9IGZyb20gXCJvYnNpZGlhblwiO1xuaW1wb3J0IHsgV2lkZ2V0VHlwZSB9IGZyb20gXCJAY29kZW1pcnJvci92aWV3XCI7XG5pbXBvcnQgeyBnZXREZWZhdWx0TXVsdGlDb2x1bW5TZXR0aW5ncywgTXVsdGlDb2x1bW5TZXR0aW5ncyB9IGZyb20gXCIuLi9yZWdpb25TZXR0aW5nc1wiO1xuaW1wb3J0IHsgZmluZFNldHRpbmdzQ29kZWJsb2NrLCBmaW5kU3RhcnRDb2RlYmxvY2sgfSBmcm9tIFwiLi4vdXRpbGl0aWVzL3RleHRQYXJzZXJcIjtcbmltcG9ydCB7IHBhcnNlQ29sdW1uU2V0dGluZ3MsIHBhcnNlU2luZ2xlQ29sdW1uU2V0dGluZ3MgfSBmcm9tIFwiLi4vdXRpbGl0aWVzL3NldHRpbmdzUGFyc2VyXCI7XG5pbXBvcnQgeyBTdGFuZGFyZE11bHRpQ29sdW1uUmVnaW9uTWFuYWdlciB9IGZyb20gXCIuLi9kb21fbWFuYWdlci9yZWdpb25hbF9tYW5hZ2Vycy9zdGFuZGFyZE11bHRpQ29sdW1uUmVnaW9uTWFuYWdlclwiO1xuaW1wb3J0IHsgUmVnaW9uTWFuYWdlckRhdGEgfSBmcm9tIFwiLi4vZG9tX21hbmFnZXIvcmVnaW9uYWxfbWFuYWdlcnMvcmVnaW9uTWFuYWdlckNvbnRhaW5lclwiO1xuaW1wb3J0IHsgZ2V0VUlEIH0gZnJvbSBcIi4uL3V0aWxpdGllcy91dGlsc1wiO1xuaW1wb3J0IHsgRE9NT2JqZWN0IH0gZnJvbSBcIi4uL2RvbV9tYW5hZ2VyL2RvbU9iamVjdFwiO1xuaW1wb3J0IHsgUmVnaW9uTWFuYWdlciB9IGZyb20gXCIuLi9kb21fbWFuYWdlci9yZWdpb25hbF9tYW5hZ2Vycy9yZWdpb25NYW5hZ2VyXCI7XG5pbXBvcnQgeyBTaW5nbGVDb2x1bW5SZWdpb25NYW5hZ2VyIH0gZnJvbSBcIi4uL2RvbV9tYW5hZ2VyL3JlZ2lvbmFsX21hbmFnZXJzL3NpbmdsZUNvbHVtblJlZ2lvbk1hbmFnZXJcIjtcbmltcG9ydCB7IEF1dG9MYXlvdXRSZWdpb25NYW5hZ2VyIH0gZnJvbSBcIi4uL2RvbV9tYW5hZ2VyL3JlZ2lvbmFsX21hbmFnZXJzL2F1dG9MYXlvdXRSZWdpb25NYW5hZ2VyXCI7XG5cbmV4cG9ydCBjbGFzcyBNdWx0aUNvbHVtbk1hcmtkb3duX0xpdmVQcmV2aWV3X1dpZGdldCBleHRlbmRzIFdpZGdldFR5cGUge1xuXG4gICAgY29udGVudERhdGE6IHN0cmluZztcbiAgICB0ZW1wUGFyZW50OiBIVE1MRGl2RWxlbWVudDtcbiAgICBkb21MaXN0OiBET01PYmplY3RbXSA9IFtdO1xuICAgIHNldHRpbmdzVGV4dDogc3RyaW5nO1xuICAgIHJlZ2lvblNldHRpbmdzOiBNdWx0aUNvbHVtblNldHRpbmdzID0gZ2V0RGVmYXVsdE11bHRpQ29sdW1uU2V0dGluZ3MoKTtcbiAgICByZWdpb25NYW5hZ2VyOiBSZWdpb25NYW5hZ2VyO1xuXG4gICAgY29uc3RydWN0b3IoY29udGVudERhdGE6IHN0cmluZykge1xuICAgICAgICBzdXBlcigpO1xuICAgICAgICB0aGlzLmNvbnRlbnREYXRhID0gY29udGVudERhdGE7XG5cbiAgICAgICAgLy8gRmluZCB0aGUgc2V0dGluZ3MgZGVmaW5lZCBpbiB0aGUgY29udGVudCwgaWYgaXQgZXhpc3RzLlxuICAgICAgICAvLyBJZiB0aGUgc2V0dGluZ3MgY29kZWJsb2NrIGlzbnQgZGVmaW5lZCBhdHRlbXB0IHRvIGdldCB0aGUgcmVnaW9uIGNvZGVibG9jayB0eXBlLlxuICAgICAgICBsZXQgc2V0dGluZ3NTdGFydERhdGEgPSBmaW5kU2V0dGluZ3NDb2RlYmxvY2sodGhpcy5jb250ZW50RGF0YSk7XG4gICAgICAgIGlmKHNldHRpbmdzU3RhcnREYXRhLmZvdW5kID09PSBmYWxzZSkge1xuICAgICAgICAgICAgc2V0dGluZ3NTdGFydERhdGEgPSBmaW5kU3RhcnRDb2RlYmxvY2sodGhpcy5jb250ZW50RGF0YSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHNldHRpbmdzU3RhcnREYXRhLmZvdW5kID09PSB0cnVlKSB7XG5cbiAgICAgICAgICAgIHRoaXMuc2V0dGluZ3NUZXh0ID0gdGhpcy5jb250ZW50RGF0YS5zbGljZShzZXR0aW5nc1N0YXJ0RGF0YS5zdGFydFBvc2l0aW9uLCBzZXR0aW5nc1N0YXJ0RGF0YS5lbmRQb3NpdGlvbik7XG4gICAgICAgICAgICB0aGlzLmNvbnRlbnREYXRhID0gdGhpcy5jb250ZW50RGF0YS5yZXBsYWNlKHRoaXMuc2V0dGluZ3NUZXh0LCBcIlwiKTtcblxuICAgICAgICAgICAgLy8gUGFyc2UgdGhlIHNldHRpbmdzLCB1cGRhdGluZyB0aGUgZGVmYXVsdCBzZXR0aW5ncy5cbiAgICAgICAgICAgIHRoaXMucmVnaW9uU2V0dGluZ3MgPSBwYXJzZUNvbHVtblNldHRpbmdzKHRoaXMuc2V0dGluZ3NUZXh0KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFJlbmRlciB0aGUgbWFya2Rvd24gY29udGVudCB0byBvdXIgdGVtcCBwYXJlbnQgZWxlbWVudC5cbiAgICAgICAgdGhpcy50ZW1wUGFyZW50ID0gY3JlYXRlRGl2KCk7XG4gICAgICAgIGxldCBlbGVtZW50TWFya2Rvd25SZW5kZXJlciA9IG5ldyBNYXJrZG93blJlbmRlckNoaWxkKHRoaXMudGVtcFBhcmVudCk7XG4gICAgICAgIE1hcmtkb3duUmVuZGVyZXIucmVuZGVyTWFya2Rvd24odGhpcy5jb250ZW50RGF0YSwgdGhpcy50ZW1wUGFyZW50LCBcIlwiLCBlbGVtZW50TWFya2Rvd25SZW5kZXJlcik7XG5cbiAgICAgICAgLy8gdGFrZSBhbGwgZWxlbWVudHMsIGluIG9yZGVyLCBhbmQgY3JlYXRlIG91ciBET00gbGlzdC5cbiAgICAgICAgbGV0IGFyciA9IEFycmF5LmZyb20odGhpcy50ZW1wUGFyZW50LmNoaWxkcmVuKTtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBhcnIubGVuZ3RoOyBpKyspIHtcblxuICAgICAgICAgICAgbGV0IGVsID0gdGhpcy5maXhFbGVtZW50UmVuZGVyKGFycltpXSk7XG4gICAgICAgICAgICB0aGlzLmRvbUxpc3QucHVzaChuZXcgRE9NT2JqZWN0KGVsIGFzIEhUTUxFbGVtZW50LCBbXCJcIl0pKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFNldCB1cCB0aGUgcmVnaW9uIG1hbmFnZXIgZGF0YSBiZWZvcmUgdGhlbiBjcmVhdGluZyBvdXIgcmVnaW9uIG1hbmFnZXIuXG4gICAgICAgIGxldCByZWdpb25EYXRhOiBSZWdpb25NYW5hZ2VyRGF0YSA9IHtcbiAgICAgICAgICAgIGRvbUxpc3Q6IHRoaXMuZG9tTGlzdCxcbiAgICAgICAgICAgIGRvbU9iamVjdE1hcDogbmV3IE1hcDxzdHJpbmcsIERPTU9iamVjdD4oKSxcbiAgICAgICAgICAgIHJlZ2lvblBhcmVudDogY3JlYXRlRGl2KCksXG4gICAgICAgICAgICBmaWxlTWFuYWdlcjogbnVsbCxcbiAgICAgICAgICAgIHJlZ2lvbmFsU2V0dGluZ3M6IHRoaXMucmVnaW9uU2V0dGluZ3MsXG4gICAgICAgICAgICByZWdpb25LZXk6IGdldFVJRCgpLFxuICAgICAgICAgICAgcm9vdEVsZW1lbnQ6IGNyZWF0ZURpdigpXG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gRmluYWxseSBzZXR1cCB0aGUgdHlwZSBvZiByZWdpb24gbWFuYWdlciByZXF1aXJlZC5cbiAgICAgICAgaWYgKHRoaXMucmVnaW9uU2V0dGluZ3MubnVtYmVyT2ZDb2x1bW5zID09PSAxKSB7XG4gICAgICAgICAgICB0aGlzLnJlZ2lvblNldHRpbmdzID0gcGFyc2VTaW5nbGVDb2x1bW5TZXR0aW5ncyh0aGlzLnNldHRpbmdzVGV4dCwgdGhpcy5yZWdpb25TZXR0aW5ncyk7XG4gICAgICAgICAgICB0aGlzLnJlZ2lvbk1hbmFnZXIgPSBuZXcgU2luZ2xlQ29sdW1uUmVnaW9uTWFuYWdlcihyZWdpb25EYXRhKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh0aGlzLnJlZ2lvblNldHRpbmdzLmF1dG9MYXlvdXQgPT09IHRydWUpIHtcbiAgICAgICAgICAgIHRoaXMucmVnaW9uTWFuYWdlciA9IG5ldyBBdXRvTGF5b3V0UmVnaW9uTWFuYWdlcihyZWdpb25EYXRhKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMucmVnaW9uTWFuYWdlciA9IG5ldyBTdGFuZGFyZE11bHRpQ29sdW1uUmVnaW9uTWFuYWdlcihyZWdpb25EYXRhKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZpeEVsZW1lbnRSZW5kZXIoZWw6IEVsZW1lbnQpOiBFbGVtZW50IHtcblxuICAgICAgICBsZXQgZml4ZWRFbCA9IGZpeEltYWdlUmVuZGVyKGVsKTtcbiAgICAgICAgcmV0dXJuIGZpeGVkRWw7XG4gICAgfVxuXG4gICAgdG9ET00oKSB7XG4gICAgICAgIC8vIENyZWF0ZSBvdXIgZWxlbWVudCB0byBob2xkIGFsbCBvZiB0aGUgbGl2ZSBwcmV2aWV3IGVsZW1lbnRzLlxuICAgICAgICBsZXQgZWwgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiZGl2XCIpO1xuICAgICAgICBlbC5jbGFzc05hbWUgPSBcIm1jbS1jbS1wcmV2aWV3XCI7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEZvciBzaXR1YXRpb25zIHdoZXJlIHdlIG5lZWQgdG8ga25vdyB0aGUgcmVuZGVyZWQgaGVpZ2h0LCBBdXRvTGF5b3V0LCBcbiAgICAgICAgICogdGhlIGVsZW1lbnQgbXVzdCBiZSByZW5kZXJlZCBvbnRvIHRoZSBzY3JlZW4gdG8gZ2V0IHRoZSBpbmZvLCBldmVuIGlmIFxuICAgICAgICAgKiBvbmx5IGZvciBhIG1vbWVudC4gSGVyZSB3ZSBhdHRlbXB0IHRvIGdldCBhIGxlYWYgZnJvbSB0aGUgYXBwIHNvIHdlIFxuICAgICAgICAgKiBjYW4gYnJpZWZseSBhcHBlbmQgb3VyIGVsZW1lbnQsIGNoZWNrIGFueSBkYXRhIGlmIHJlcXVpcmVkLCBhbmQgdGhlblxuICAgICAgICAgKiByZW1vdmUgaXQuXG4gICAgICAgICAqL1xuICAgICAgICBsZXQgbGVhZjogV29ya3NwYWNlTGVhZiA9IG51bGw7XG4gICAgICAgIGlmIChhcHApIHtcbiAgICAgICAgICAgIGxldCBsZWF2ZXMgPSBhcHAud29ya3NwYWNlLmdldExlYXZlc09mVHlwZShcIm1hcmtkb3duXCIpO1xuICAgICAgICAgICAgaWYgKGxlYXZlcy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgbGVhZiA9IGxlYXZlc1swXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLnJlZ2lvbk1hbmFnZXIpIHtcblxuICAgICAgICAgICAgaWYgKGxlYWYpIHtcbiAgICAgICAgICAgICAgICBsZWFmLnZpZXcuY29udGFpbmVyRWwuYXBwZW5kQ2hpbGQoZWwpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLnJlZ2lvbk1hbmFnZXIucmVuZGVyUmVnaW9uRWxlbWVudHNUb0xpdmVQcmV2aWV3KGVsKTtcblxuICAgICAgICAgICAgaWYgKGxlYWYpIHtcbiAgICAgICAgICAgICAgICBsZWFmLnZpZXcuY29udGFpbmVyRWwucmVtb3ZlQ2hpbGQoZWwpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgZml4RXh0ZXJuYWxMaW5rcyhlbClcblxuICAgICAgICByZXR1cm4gZWw7XG4gICAgfVxufVxuXG5leHBvcnQgY2xhc3MgTXVsdGlDb2x1bW5NYXJrZG93bl9EZWZpbmVkU2V0dGluZ3NfTGl2ZVByZXZpZXdfV2lkZ2V0IGV4dGVuZHMgV2lkZ2V0VHlwZSB7XG5cbiAgICBjb250ZW50RGF0YTogc3RyaW5nO1xuXG4gICAgY29uc3RydWN0b3IoY29udGVudERhdGE6IHN0cmluZykge1xuICAgICAgICBzdXBlcigpO1xuXG4gICAgICAgIHRoaXMuY29udGVudERhdGEgPSBjb250ZW50RGF0YTtcbiAgICB9XG5cbiAgICB0b0RPTSgpIHtcbiAgICAgICAgLy8gQ3JlYXRlIG91ciBlbGVtZW50IHRvIGhvbGQgYWxsIG9mIHRoZSBsaXZlIHByZXZpZXcgZWxlbWVudHMuXG4gICAgICAgIGxldCBlbCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIik7XG4gICAgICAgIGVsLmNsYXNzTmFtZSA9IFwibWNtLWNtLXNldHRpbmdzLXByZXZpZXdcIjtcblxuICAgICAgICBsZXQgbGFiZWxEaXYgPSBlbC5jcmVhdGVEaXYoKVxuICAgICAgICBsZXQgbGFiZWwgPSBsYWJlbERpdi5jcmVhdGVTcGFuKHtcbiAgICAgICAgICAgIGNsczogXCJtY20tY29sLXNldHRpbmdzLXByZXZpZXdcIlxuICAgICAgICB9KVxuICAgICAgICBsYWJlbC50ZXh0Q29udGVudCA9IFwiQ29sdW1uIFNldHRpbmdzOlwiO1xuXG4gICAgICAgIGxldCBsaXN0ID0gZWwuY3JlYXRlRWwoXCJ1bFwiKVxuICAgICAgICBsZXQgbGluZXMgPSB0aGlzLmNvbnRlbnREYXRhLnNwbGl0KFwiXFxuXCIpXG4gICAgICAgIGZvcihsZXQgaSA9IDE7IGkgPCBsaW5lcy5sZW5ndGggLSAxOyBpKyspIHtcbiAgICAgICAgICAgIGxldCBpdGVtID0gbGlzdC5jcmVhdGVFbChcImxpXCIpXG4gICAgICAgICAgICBpdGVtLnRleHRDb250ZW50ID0gbGluZXNbaV1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBlbDtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGZpeEltYWdlUmVuZGVyKGVsOiBFbGVtZW50KTogRWxlbWVudCB7XG5cbiAgICBsZXQgZW1iZWQgPSBudWxsO1xuICAgIGxldCBmaXhlZEVsID0gZWw7XG5cbiAgICAvLyBpbWFnZSBlbWJlZHMgY2FuIGVpdGhlciBiZSBhIDxkaXYgY2xhc3M9XCJpbnRlcm5hbC1lbWJlZFwiIG9yIDxwPjxkaXYgY2xhc3M9XCJpbnRlcm5hbC1lbWJlZFwiXG4gICAgLy8gZGVwZW5kaW5nIG9uIHRoZSBzeW50YXggdGhpcyBhZGRpdGlvbmFsIGNoZWNrIGlzIHRvIGZpeCBmYWxzZSBuZWdhdGl2ZXMgd2hlbiBlbWJlZCBpc1xuICAgIC8vIHRoZSBmaXJzdCBjYXNlLlxuICAgIGlmKGVsLmhhc0NsYXNzKFwiaW50ZXJuYWwtZW1iZWRcIikpIHtcbiAgICAgICAgZW1iZWQgPSBlbDtcbiAgICB9XG4gICAgZWxzZSB7XG5cbiAgICAgICAgbGV0IGl0ZW1zID0gZWwuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZShcImludGVybmFsLWVtYmVkXCIpO1xuICAgICAgICBpZihpdGVtcy5sZW5ndGggIT09IDEpIHtcbiAgICAgICAgICAgIHJldHVybiBlbDtcbiAgICAgICAgfVxuICAgICAgICBlbWJlZCA9IGl0ZW1zWzBdO1xuICAgIH1cblxuICAgIGxldCBjdXN0b21XaWR0aCA9IGVtYmVkLmF0dHJpYnV0ZXMuZ2V0TmFtZWRJdGVtKFwid2lkdGhcIilcbiAgICBsZXQgYWx0ID0gZW1iZWQuZ2V0QXR0cihcImFsdFwiKVxuICAgIGxldCBzcmMgPSBlbWJlZC5nZXRBdHRyKFwic3JjXCIpXG4gICAgXG4gICAgLy8gSWYgdGhlIGxpbmsgc291cmNlIGlzIG5vdCBhbiBpbWFnZSB3ZSBkb250IHdhbnQgdG8gbWFrZSBhbnkgYWRqdXN0bWVudHMuXG4gICAgaWYoZmlsZW5hbWVJc0ltYWdlKHNyYykgPT09IGZhbHNlKSB7XG4gICAgICAgIHJldHVybiBlbDtcbiAgICB9XG5cbiAgICAvLyBUcnkgdG8gZmluZCB0aGUgaW1hZ2UgZmlsZSBpbiB0aGUgdmF1bHQuIFRoaXMgaXMgdmVyeSBpbmVmZmljaWVudCBidXQgd29ya3MgZm9yIG5vdy5cbiAgICBsZXQgYVRGaWxlcyA9IGFwcC52YXVsdC5nZXRBbGxMb2FkZWRGaWxlcygpXG4gICAgbGV0IHJlc291cmNlUGF0aCA9IFwiXCJcbiAgICBmb3IobGV0IGkgPSAwOyBpIDwgYVRGaWxlcy5sZW5ndGg7IGkrKykge1xuXG4gICAgICAgIGxldCBhYnN0cmFjdEZpbGUgPSBhVEZpbGVzW2ldO1xuICAgICAgICBpZihhYnN0cmFjdEZpbGUgaW5zdGFuY2VvZiBURmlsZSA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGxldCBmaWxlID0gYWJzdHJhY3RGaWxlIGFzIFRGaWxlO1xuXG4gICAgICAgIGlmKGZpbGUubmFtZSA9PT0gc3JjICYmIGlzSW1hZ2VFeHRlbnNpb24oZmlsZS5leHRlbnNpb24pID09PSB0cnVlKSB7XG4gICAgICAgICAgICByZXNvdXJjZVBhdGggPSBhcHAudmF1bHQuZ2V0UmVzb3VyY2VQYXRoKGZpbGUpXG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIElmIHdlIGZvdW5kIHRoZSByZXNvdXJjZSBwYXRoIHRoZW4gd2UgdXBkYXRlIHRoZSBlbGVtZW50IHRvIGJlIGEgcHJvcGVyIGltYWdlIHJlbmRlci5cbiAgICBpZihyZXNvdXJjZVBhdGggIT09IFwiXCIpIHtcblxuICAgICAgICBmaXhlZEVsID0gY3JlYXRlRGl2KHtcbiAgICAgICAgICAgIGNsczogXCJpbnRlcm5hbC1lbWJlZCBpbWFnZS1lbWJlZCBpcy1sb2FkZWRcIixcbiAgICAgICAgfSlcbiAgICAgICAgZml4ZWRFbC5zZXRBdHRyKFwiYWx0XCIsIGFsdCk7XG5cbiAgICAgICAgbGV0IGltYWdlID0gZml4ZWRFbC5jcmVhdGVFbChcImltZ1wiKTtcbiAgICAgICAgaW1hZ2Uuc2V0QXR0cihcInNyY1wiLCByZXNvdXJjZVBhdGgpO1xuXG4gICAgICAgIGlmKGN1c3RvbVdpZHRoICE9PSBudWxsKSB7XG5cbiAgICAgICAgICAgIGltYWdlLnNldEF0dHIoXCJ3aWR0aFwiLCBjdXN0b21XaWR0aC52YWx1ZSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gZml4ZWRFbDtcbn1cblxuZnVuY3Rpb24gZml4RXh0ZXJuYWxMaW5rcyhlbDogRWxlbWVudCk6IEVsZW1lbnQge1xuXG4gICAgbGV0IGl0ZW1zID0gZWwuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZShcImV4dGVybmFsLWxpbmtcIik7XG4gICAgZm9yKGxldCBsaW5rRWwgb2YgQXJyYXkuZnJvbShpdGVtcykpIHtcblxuICAgICAgICBsZXQgbGluayA9IGxpbmtFbCBhcyBIVE1MRWxlbWVudDtcbiAgICAgICAgaWYobGluayA9PT0gdW5kZWZpbmVkIHx8XG4gICAgICAgICAgIGxpbmsgPT09IG51bGwgKSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFJlbW92ZSB0aGUgaHJlZiBmcm9tIHRoZSBsaW5rIGFuZCBzZXR1cCBhbiBldmVudCBsaXN0ZW5lciB0byBvcGVuIHRoZSBsaW5rIGluIHRoZSBkZWZhdWx0IGJyb3dzZXIuXG4gICAgICAgIGxldCBocmVmID0gbGluay5nZXRBdHRyKFwiaHJlZlwiKVxuICAgICAgICBsaW5rLnJlbW92ZUF0dHJpYnV0ZShcImhyZWZcIik7XG5cbiAgICAgICAgbGluay5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgKGV2KSA9PiB7XG5cbiAgICAgICAgICAgIHdpbmRvdy5vcGVuKGhyZWYpOyBcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgaXRlbXMgPSBlbC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKFwiaW50ZXJuYWwtbGlua1wiKTtcbiAgICBmb3IobGV0IGxpbmtFbCBvZiBBcnJheS5mcm9tKGl0ZW1zKSkge1xuXG4gICAgICAgIGxldCBsaW5rID0gbGlua0VsIGFzIEhUTUxFbGVtZW50O1xuICAgICAgICBpZihsaW5rID09PSB1bmRlZmluZWQgfHxcbiAgICAgICAgICAgbGluayA9PT0gbnVsbCApIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gUmVtb3ZpbmcgdGhlIGhyZWYgZnJvbSBpbnRlcm5hbCBsaW5rcyBpcyBhbGwgdGhhdCBzZWVtcyB0byBiZSByZXF1aXJlZCB0byBmaXggdGhlIG9uY2xpY2suXG4gICAgICAgIGxpbmsucmVtb3ZlQXR0cmlidXRlKFwiaHJlZlwiKTtcbiAgICB9XG5cbiAgICByZXR1cm4gZWw7XG59XG5cbmZ1bmN0aW9uIGZpbGVuYW1lSXNJbWFnZShmaWxlbmFtZTogc3RyaW5nKTogYm9vbGVhbiB7XG5cbiAgICBsZXQgcGFydHMgPSBmaWxlbmFtZS5zcGxpdChcIi5cIik7XG4gICAgaWYocGFydHMubGVuZ3RoIDw9IDEpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGxldCBleHRlbnNpb24gPSBwYXJ0cy5sYXN0KCk7XG4gICAgcmV0dXJuIGlzSW1hZ2VFeHRlbnNpb24oZXh0ZW5zaW9uKTtcbn1cblxuZnVuY3Rpb24gaXNJbWFnZUV4dGVuc2lvbihleHRlbnNpb246IHN0cmluZyk6IGJvb2xlYW4ge1xuXG4gICAgZXh0ZW5zaW9uID0gZXh0ZW5zaW9uLnRvTG93ZXJDYXNlKCk7XG4gICAgc3dpdGNoKGV4dGVuc2lvbikge1xuICAgICAgICBjYXNlIFwicG5nXCI6XG4gICAgICAgIGNhc2UgXCJqcGdcIjpcbiAgICAgICAgY2FzZSBcImpwZWdcIjpcbiAgICAgICAgY2FzZSBcImdpZlwiOlxuICAgICAgICBjYXNlIFwiYm1wXCI6XG4gICAgICAgIGNhc2UgXCJzdmdcIjpcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG59IiwiLypcbiAqIEZpbGVuYW1lOiBtdWx0aS1jb2x1bW4tbWFya2Rvd24vc3JjL2xpdmVfcHJldmlldy9jbTZfbGl2ZVByZXZpZXcudHNcbiAqIENyZWF0ZWQgRGF0ZTogTW9uZGF5LCBBdWd1c3QgMXN0IDIwMjIsIDE6NTE6MTYgcG1cbiAqIEF1dGhvcjogQ2FtZXJvbiBSb2JpbnNvblxuICogXG4gKiBDb3B5cmlnaHQgKGMpIDIwMjIgQ2FtZXJvbiBSb2JpbnNvblxuICovXG5cbmltcG9ydCB7IEV4dGVuc2lvbiwgTGluZSwgUmFuZ2VTZXRCdWlsZGVyLCBTdGF0ZUZpZWxkLCBUcmFuc2FjdGlvbiB9IGZyb20gXCJAY29kZW1pcnJvci9zdGF0ZVwiO1xuaW1wb3J0IHsgRGVjb3JhdGlvbiwgRGVjb3JhdGlvblNldCwgRWRpdG9yVmlldyB9IGZyb20gXCJAY29kZW1pcnJvci92aWV3XCI7XG5pbXBvcnQgeyBzeW50YXhUcmVlLCB0b2tlbkNsYXNzTm9kZVByb3AgfSBmcm9tIFwiQGNvZGVtaXJyb3IvbGFuZ3VhZ2VcIjtcbmltcG9ydCB7IGNvbnRhaW5zUmVnaW9uU3RhcnQsIGZpbmRFbmRUYWcsIGZpbmRTZXR0aW5nc0NvZGVibG9jaywgZmluZFN0YXJ0Q29kZWJsb2NrLCBmaW5kU3RhcnRUYWcgfSBmcm9tIFwiLi4vdXRpbGl0aWVzL3RleHRQYXJzZXJcIjtcbmltcG9ydCB7IE11bHRpQ29sdW1uTWFya2Rvd25fRGVmaW5lZFNldHRpbmdzX0xpdmVQcmV2aWV3X1dpZGdldCwgTXVsdGlDb2x1bW5NYXJrZG93bl9MaXZlUHJldmlld19XaWRnZXQgfSBmcm9tIFwiLi9tY21fbGl2ZVByZXZpZXdfd2lkZ2V0XCI7XG5pbXBvcnQgeyBlZGl0b3JMaXZlUHJldmlld0ZpZWxkIH0gZnJvbSBcIm9ic2lkaWFuXCI7XG5cbmV4cG9ydCBjb25zdCBtdWx0aUNvbHVtbk1hcmtkb3duX1N0YXRlRmllbGQgPSBTdGF0ZUZpZWxkLmRlZmluZTxEZWNvcmF0aW9uU2V0Pih7XG5cdGNyZWF0ZShzdGF0ZSk6IERlY29yYXRpb25TZXQge1xuXHRcdHJldHVybiBEZWNvcmF0aW9uLm5vbmU7XG5cdH0sXG5cdHVwZGF0ZShvbGRTdGF0ZTogRGVjb3JhdGlvblNldCwgdHJhbnNhY3Rpb246IFRyYW5zYWN0aW9uKTogRGVjb3JhdGlvblNldCB7XG5cdFx0Y29uc3QgYnVpbGRlciA9IG5ldyBSYW5nZVNldEJ1aWxkZXI8RGVjb3JhdGlvbj4oKTtcbiAgICAgICAgbGV0IGlnbm9yZUZ1cnRoZXJJdGVyYXRpb25zID0gZmFsc2U7XG5cblx0XHRzeW50YXhUcmVlKHRyYW5zYWN0aW9uLnN0YXRlKS5pdGVyYXRlKHtcblx0XHRcdGVudGVyKG5vZGUpIHtcblxuXHRcdFx0XHQvLyBJZiB3ZSBmaW5kIHRoYXQgdGhlIGZpbGUgZG9lcyBub3QgY29udGFpbiBhbnkgTUNNIHJlZ2lvbnMgd2UgY2FuIGZsaXAgdGhpc1xuXHRcdFx0XHQvLyBmbGFnIGFuZCBza2lwIGFsbCBvdGhlciBub2RlIGl0ZXJhdGlvbnMsIHBvdGVudGlhbGx5IHNhdmluZyBhIGxvdCBvZiBjb21wdXRlIHRpbWUuXG5cdFx0XHRcdC8vIFxuICAgICAgICAgICAgICAgIC8vIFdlIG9ubHkgd2FudCB0byBydW4gdGhlIGdlbmVyYXRpb24gb25jZSBwZXIgc3RhdGUgY2hhbmdlLiBJZlxuICAgICAgICAgICAgICAgIC8vIGEgcHJldmlvdXMgbm9kZSBoYXMgc3VjZXNzZnVsbHkgZ2VuZXJhdGVkIHJlZ2lvbnMgd2UgaWdub3JlIGFsbFxuICAgICAgICAgICAgICAgIC8vIG90aGVyIG5vZGVzIGluIHRoZSBzdGF0ZS5cbiAgICAgICAgICAgICAgICBpZihpZ25vcmVGdXJ0aGVySXRlcmF0aW9ucyA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG5cdFx0XHRcdC8vIENoZWNrIGlmIHZpZXcgaXMgaW4gbGl2ZSBwcmV2aWV3IHN0YXRlLlxuICAgICAgICAgICAgICAgIGlmKHRyYW5zYWN0aW9uLnN0YXRlLmZpZWxkKGVkaXRvckxpdmVQcmV2aWV3RmllbGQpID09PSBmYWxzZSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmRlYnVnKFwiVXNlciBkaXNhYmxlZCBsaXZlIHByZXZpZXcuXCIpXG5cdFx0XHRcdFx0aWdub3JlRnVydGhlckl0ZXJhdGlvbnMgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG5cdFx0XHRcdC8vIFdlIHdhbnQgdG8gcnVuIG9uIHRoZSB3aG9sZSBmaWxlIHNvIHdlIGRvbnQganVzdCBsb29rIGZvciBhIHNpbmdsZSB0b2tlbi5cblx0XHRcdFx0Y29uc3QgdG9rZW5Qcm9wcyA9IG5vZGUudHlwZS5wcm9wPHN0cmluZz4odG9rZW5DbGFzc05vZGVQcm9wKTtcblx0XHRcdFx0aWYgKHRva2VuUHJvcHMgIT09IHVuZGVmaW5lZCkge1xuXHRcdFx0XHRcdHJldHVybjtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8qKlxuXHRcdFx0XHQgKiBXaGVuIHdlIGhhdmUgdGhlIHdoaWxlIGZpbGUgd2UgdGhlbiBnZXQgdGhlIGVudGlyZSBkb2MgdGV4dCBhbmQgY2hlY2sgaWYgaXQgXG5cdFx0XHRcdCAqIGNvbnRhaW5zIGEgTUNNIHJlZ2lvbiBzbyB3ZSBrbm93IHRvIGJyZWFrIG9yIG5vdC5cblx0XHRcdFx0ICovXG4gICAgICAgICAgICAgICAgbGV0IGRvY0xlbmd0aCA9IHRyYW5zYWN0aW9uLnN0YXRlLmRvYy5sZW5ndGhcbiAgICAgICAgICAgICAgICBsZXQgZG9jVGV4dCA9IHRyYW5zYWN0aW9uLnN0YXRlLmRvYy5zbGljZVN0cmluZygwLCBkb2NMZW5ndGgpO1xuXHRcdFx0XHRpZiAoY29udGFpbnNSZWdpb25TdGFydChkb2NUZXh0KSA9PT0gZmFsc2UpIHtcblx0XHRcdFx0XHQvLyBjb25zb2xlLmRlYnVnKFwiTm8gc3RhcnQgdGFnIGluIGRvY3VtZW50LlwiKVxuXHRcdFx0XHRcdGlnbm9yZUZ1cnRoZXJJdGVyYXRpb25zID0gdHJ1ZTtcblx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBXZSB3YW50IHRvIGtub3cgd2hlcmUgdGhlIHVzZXIncyBjdXJzb3IgaXMsIGl0IGNhbiBiZVxuXHRcdFx0XHQvLyBzZWxlY3RpbmcgbXVsdGlwbGUgcmVnaW9ucyBvZiB0ZXh0IGFzIHdlbGwgc28gd2UgbmVlZCB0byBrbm93XG5cdFx0XHRcdC8vIGFsbCBsb2NhdGlvbnMuIFVzZWQgdG8ga25vdyBpZiB3ZSBzaG91bGQgcmVuZGVyIHJlZ2lvbiBhcyB0ZXh0IG9yIGFzIHByZXZpZXcuXG5cdFx0XHRcdGxldCByYW5nZXMgPSBnZXRDdXJzb3JMaW5lTG9jYXRpb25zKCk7XG5cblx0XHRcdFx0Ly8gU2V0dXAgb3VyIGxvb3AgdG8gcmVuZGVyIHRoZSByZWdpb25zIGFzIE1DTS4gXG5cdFx0XHRcdGxldCB3b3JraW5nRmlsZVRleHQgPSBkb2NUZXh0O1xuXG5cdFx0XHRcdGxldCBsb29wSW5kZXggPSAwO1xuXHRcdFx0XHRsZXQgc3RhcnRJbmRleE9mZnNldCA9IDA7XG5cdFx0XHRcdHdoaWxlICh0cnVlKSB7XG5cblx0XHRcdFx0XHQvLyBJZiB0aGVyZSBhcmUgbXVsdGlwbGUga2luZHMgb2Ygc3RhcnQgYmxvY2tzLCB0aGUgb2xkIHdheSBvZiBwYXJzaW5nIHdvdWxkIGNhdXNlIGlzc3Vlcy5cblx0XHRcdFx0XHQvLyBOb3cgc2VhcmNoIGZvciBib3RoIGtpbmRzIGFuZCBkZXRlcm1pbmUgd2hhdCB0byBkbyBhZnRlciBzZWFyY2guXG5cdFx0XHRcdFx0bGV0IHN0YXJ0VGFnRGF0YV9jb2RlYmxvY2tTdGFydCA9IGZpbmRTdGFydENvZGVibG9jayh3b3JraW5nRmlsZVRleHQpO1xuXHRcdFx0XHRcdGxldCBzdGFydFRhZ0RhdGFfZGVwcmVjaWF0ZWRTdGFydCA9IGZpbmRTdGFydFRhZyh3b3JraW5nRmlsZVRleHQpO1xuXG5cdFx0XHRcdFx0Ly8gRGVmYXVsdCB0byBjb2RlYmxvY2sgU3R5bGUuIFRoZW4gY2hlY2ssIGlmIGNvZGVibG9jayB3YXMgbm90IGZvdW5kIGFuZCBkZXByZWNpYXRlZCBTdGFydCB3YXMsIHNldCBzdGFydFRhZyB0byBkZXByZWNpYXRlZC5cblx0XHRcdFx0XHRsZXQgc3RhcnRUYWdEYXRhID0gc3RhcnRUYWdEYXRhX2NvZGVibG9ja1N0YXJ0O1xuXHRcdFx0XHRcdGlmKHN0YXJ0VGFnRGF0YV9jb2RlYmxvY2tTdGFydC5mb3VuZCA9PT0gZmFsc2UgJiYgc3RhcnRUYWdEYXRhX2RlcHJlY2lhdGVkU3RhcnQuZm91bmQgPT09IHRydWUpIHtcblx0XHRcdFx0XHRcdFxuXHRcdFx0XHRcdFx0c3RhcnRUYWdEYXRhID0gc3RhcnRUYWdEYXRhX2RlcHJlY2lhdGVkU3RhcnRcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0ZWxzZSBpZihzdGFydFRhZ0RhdGFfY29kZWJsb2NrU3RhcnQuZm91bmQgPT09IHRydWUgJiYgc3RhcnRUYWdEYXRhX2RlcHJlY2lhdGVkU3RhcnQuZm91bmQgPT09IHRydWUpIHtcblxuXHRcdFx0XHRcdFx0Ly8gSWYgYm90aCBraW5kcyB3ZXJlIGZvdW5kIHdlIHdhbnQgdG8gc3RhcnQgd2l0aCB0aGUgb25lIGNsb3NlciB0byB0aGUgdG9wIG9mIHRoZSBkb2N1bWVudCBhcyBDTTYgcmVxdWlyZXMgd2Ugd29yayBpbiBvcmRlci5cblx0XHRcdFx0XHRcdGlmIChzdGFydFRhZ0RhdGFfY29kZWJsb2NrU3RhcnQuc3RhcnRQb3NpdGlvbiA+IHN0YXJ0VGFnRGF0YV9kZXByZWNpYXRlZFN0YXJ0LnN0YXJ0UG9zaXRpb24pIHtcblxuXHRcdFx0XHRcdFx0XHRzdGFydFRhZ0RhdGEgPSBzdGFydFRhZ0RhdGFfZGVwcmVjaWF0ZWRTdGFydFxuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XG5cdFx0XHRcdFx0aWYoc3RhcnRUYWdEYXRhLmZvdW5kID09PSBmYWxzZSkge1xuXHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0Ly8gU2VhcmNoIGZvciB0aGUgZmlyc3QgZW5kIHRhZyBhZnRlciBhIHN0YXJ0IGJsb2NrLiAoTm8gcmVjdXJzaXZlIGNvbHVtbnMuKVxuXHRcdFx0XHRcdGxldCBlbmRUYWdEYXRhID0gZmluZEVuZFRhZyh3b3JraW5nRmlsZVRleHQuc2xpY2Uoc3RhcnRUYWdEYXRhLnN0YXJ0UG9zaXRpb24pKTtcblx0XHRcdFx0XHRpZihlbmRUYWdEYXRhLmZvdW5kID09PSBmYWxzZSkge1xuXHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0LyoqXG5cdFx0XHRcdFx0ICogRm9yIHRoZSByZWdpb24gd2UgZm91bmQgZ2V0IHRoZSBzdGFydCBhbmQgZW5kIHBvc2l0aW9uIG9mIHRoZSB0YWdzIHNvIHdlIFxuXHRcdFx0XHRcdCAqIGNhbiBzbGljZSBpdCBvdXQgb2YgdGhlIGRvY3VtZW50LlxuXHRcdFx0XHRcdCAqL1xuXHRcdFx0XHRcdGxldCBzdGFydEluZGV4ID0gc3RhcnRJbmRleE9mZnNldCArIHN0YXJ0VGFnRGF0YS5zdGFydFBvc2l0aW9uXG5cdFx0XHRcdFx0bGV0IGVuZEluZGV4ID0gc3RhcnRJbmRleCArIGVuZFRhZ0RhdGEuc3RhcnRQb3NpdGlvbiArIGVuZFRhZ0RhdGEubWF0Y2hMZW5ndGggLy8gV2l0aG91dCB0aGUgbWF0Y2hMZW5ndGggd2lsbCBsZWF2ZSB0aGUgZW5kIHRhZyBvbiB0aGUgc2NyZWVuLlxuXG5cdFx0XHRcdFx0Ly8gVGhpcyB0ZXh0IGlzIHRoZSBlbnRpcmUgcmVnaW9uIGRhdGEgaW5jbHVkaW5nIHRoZSBzdGFydCBhbmQgZW5kIHRhZ3MuXG5cdFx0XHRcdFx0bGV0IGVsZW1lbnRUZXh0ID0gZG9jVGV4dC5zbGljZShzdGFydEluZGV4LCBlbmRJbmRleClcblxuXHRcdFx0XHRcdC8qKlxuXHRcdFx0XHRcdCAqIFVwZGF0ZSBvdXIgc3RhcnQgb2Zmc2V0IGFuZCB0aGUgd29ya2luZyB0ZXh0IG9mIHRoZSBmaWxlIHNvIG91ciBuZXh0IFxuXHRcdFx0XHRcdCAqIGl0ZXJhdGlvbiBrbm93cyB3aGVyZSB3ZSBsZWZ0IG9mZlxuXHRcdFx0XHRcdCAqL1xuXHRcdFx0XHRcdHN0YXJ0SW5kZXhPZmZzZXQgPSBlbmRJbmRleFxuXHRcdFx0XHRcdHdvcmtpbmdGaWxlVGV4dCA9IGRvY1RleHQuc2xpY2UoZW5kSW5kZXgpO1xuXG5cblx0XHRcdFx0XHQvLyBIZXJlIHdlIGNoZWNrIGlmIHRoZSBjdXJzb3IgaXMgaW4gdGhpcyBzcGVjaWZpYyByZWdpb24uXG5cdFx0XHRcdFx0bGV0IGN1cnNvckluUmVnaW9uID0gY2hlY2tDdXJzb3JJblJlZ2lvbihzdGFydEluZGV4LCBlbmRJbmRleCwgcmFuZ2VzKTtcblx0XHRcdFx0XHRpZihjdXJzb3JJblJlZ2lvbiA9PT0gdHJ1ZSkge1xuXHRcdFx0XHRcdFx0XG5cdFx0XHRcdFx0XHQvLyBJZiB0aGUgY3Vyc29yIGlzIHdpdGhpbiB0aGUgcmVnaW9uIHdlIHRoZW4gbmVlZCB0byBrbm93IGlmXG5cdFx0XHRcdFx0XHQvLyBpdCBpcyB3aXRoaW4gb3VyIHNldHRpbmdzIGJsb2NrIChpZiBpdCBleGlzdHMuKVxuXHRcdFx0XHRcdFx0bGV0IHNldHRpbmdzU3RhcnREYXRhID0gZmluZFN0YXJ0Q29kZWJsb2NrKGVsZW1lbnRUZXh0KTtcblx0XHRcdFx0XHRcdGlmKHNldHRpbmdzU3RhcnREYXRhLmZvdW5kID09PSBmYWxzZSkge1xuXHRcdFx0XHRcdFx0XHRzZXR0aW5nc1N0YXJ0RGF0YSA9IGZpbmRTZXR0aW5nc0NvZGVibG9jayhlbGVtZW50VGV4dCk7XG5cdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdGlmKHNldHRpbmdzU3RhcnREYXRhLmZvdW5kID09PSB0cnVlKSB7XG5cblx0XHRcdFx0XHRcdFx0Ly8gU2luY2UgdGhlIHNldHRpbmdzIGJsb2NrIGV4aXN0cyBjaGVjayBpZiB0aGUgY3Vyc29yIGlzIHdpdGhpbiB0aGF0IHJlZ2lvbi5cblx0XHRcdFx0XHRcdFx0bGV0IGNvZGVibG9ja1N0YXJ0SW5kZXggPSBzdGFydEluZGV4ICsgc2V0dGluZ3NTdGFydERhdGEuc3RhcnRQb3NpdGlvbjtcblx0XHRcdFx0XHRcdFx0bGV0IGNvZGVibG9ja0VuZEluZGV4ID0gc3RhcnRJbmRleCArIHNldHRpbmdzU3RhcnREYXRhLmVuZFBvc2l0aW9uO1xuXHRcdFx0XHRcdFx0XHRsZXQgc2V0dGluZ3NUZXh0ID0gZG9jVGV4dC5zbGljZShjb2RlYmxvY2tTdGFydEluZGV4LCBjb2RlYmxvY2tFbmRJbmRleCApXG5cblx0XHRcdFx0XHRcdFx0bGV0IGN1cnNvckluQ29kZWJsb2NrID0gY2hlY2tDdXJzb3JJblJlZ2lvbihjb2RlYmxvY2tTdGFydEluZGV4LCBjb2RlYmxvY2tFbmRJbmRleCwgcmFuZ2VzKTtcblx0XHRcdFx0XHRcdFx0aWYoY3Vyc29ySW5Db2RlYmxvY2sgPT09IGZhbHNlKSB7XG5cdFxuXHRcdFx0XHRcdFx0XHRcdC8vIElmIHRoZSBjdXJzb3IgaXMgbm90IHdpdGhpbiB0aGUgcmVnaW9uIHdlIHBhc3MgdGhlIGRhdGEgdG8gdGhlXG5cdFx0XHRcdFx0XHRcdFx0Ly8gc2V0dGluZ3MgdmlldyBzbyBpdCBjYW4gYmUgZGlzcGxheWVkIGluIHRoZSByZWdpb24uXG5cdFx0XHRcdFx0XHRcdFx0YnVpbGRlci5hZGQoXG5cdFx0XHRcdFx0XHRcdFx0XHRjb2RlYmxvY2tTdGFydEluZGV4LFxuXHRcdFx0XHRcdFx0XHRcdFx0Y29kZWJsb2NrRW5kSW5kZXggKyAxLFxuXHRcdFx0XHRcdFx0XHRcdFx0RGVjb3JhdGlvbi5yZXBsYWNlKHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0d2lkZ2V0OiBuZXcgTXVsdGlDb2x1bW5NYXJrZG93bl9EZWZpbmVkU2V0dGluZ3NfTGl2ZVByZXZpZXdfV2lkZ2V0KHNldHRpbmdzVGV4dCksXG5cdFx0XHRcdFx0XHRcdFx0XHR9KVxuXHRcdFx0XHRcdFx0XHRcdCk7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH1cdFx0XHRcdFx0XHRcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0ZWxzZSB7XG5cblx0XHRcdFx0XHRcdC8vIEF0IHRoaXMgcG9pbnQgaWYgdGhlIGN1cnNvciBpc250IGluIHRoZSByZWdpb24gd2UgcGFzcyB0aGUgZGF0YSB0byB0aGVcblx0XHRcdFx0XHRcdC8vIGVsZW1lbnQgdG8gYmUgcmVuZGVyZWQuXG5cdFx0XHRcdFx0XHRidWlsZGVyLmFkZChcblx0XHRcdFx0XHRcdFx0c3RhcnRJbmRleCxcblx0XHRcdFx0XHRcdFx0ZW5kSW5kZXgsXG5cdFx0XHRcdFx0XHRcdERlY29yYXRpb24ucmVwbGFjZSh7XG5cdFx0XHRcdFx0XHRcdFx0d2lkZ2V0OiBuZXcgTXVsdGlDb2x1bW5NYXJrZG93bl9MaXZlUHJldmlld19XaWRnZXQoZWxlbWVudFRleHQpLFxuXHRcdFx0XHRcdFx0XHR9KVxuXHRcdFx0XHRcdFx0KTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0aWdub3JlRnVydGhlckl0ZXJhdGlvbnMgPSB0cnVlO1xuXG5cdFx0XHRcdFx0Ly8gSW5maW5pdGUgbG9vcCBwcm90ZWN0aW9uLlxuXHRcdFx0XHRcdGxvb3BJbmRleCsrO1xuXHRcdFx0XHRcdGlmKGxvb3BJbmRleCA+IDEwMCkge1xuXHRcdFx0XHRcdFx0Y29uc29sZS53YXJuKFwiUG90ZW50aWFsIGlzc3VlIHdpdGggcmVuZGVyaW5nIE11bHRpLUNvbHVtbiBNYXJrZG93biBsaXZlIHByZXZpZXcgcmVnaW9ucy4gSWYgcHJvYmxlbSBwZXJzaXN0cyBwbGVhc2UgZmlsZSBhIGJ1ZyByZXBvcnQgd2l0aCBkZXZlbG9wZXIuXCIpXG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH0sXG5cdFx0fSk7XG4gXG5cdFx0cmV0dXJuIGJ1aWxkZXIuZmluaXNoKCk7XG5cblx0XHRmdW5jdGlvbiBnZXRDdXJzb3JMaW5lTG9jYXRpb25zKCk6IHsgbGluZTogTGluZSwgcG9zaXRpb246IG51bWJlciB9W10ge1xuXG5cdFx0XHRsZXQgcmFuZ2VzOiB7IGxpbmU6IExpbmUsIHBvc2l0aW9uOiBudW1iZXIgfVtdID0gW107XG5cblx0XHRcdGlmICh0cmFuc2FjdGlvbi5zdGF0ZS5zZWxlY3Rpb24ucmFuZ2VzKSB7XG5cblx0XHRcdFx0cmFuZ2VzID0gdHJhbnNhY3Rpb24uc3RhdGUuc2VsZWN0aW9uLnJhbmdlcy5maWx0ZXIoKHJhbmdlKSA9PiB7XG5cblx0XHRcdFx0XHRyZXR1cm4gcmFuZ2UuZW1wdHk7XG5cdFx0XHRcdH0pLm1hcCgocmFuZ2UpID0+IHtcblxuXHRcdFx0XHRcdGxldCBsaW5lID0gdHJhbnNhY3Rpb24uc3RhdGUuZG9jLmxpbmVBdChyYW5nZS5oZWFkKTtcblx0XHRcdFx0XHRsZXQgdGV4dCA9IGAke2xpbmUubnVtYmVyfToke3JhbmdlLmhlYWQgLSBsaW5lLmZyb219YDtcblxuXHRcdFx0XHRcdHJldHVybiB7XG5cdFx0XHRcdFx0XHRsaW5lOiBsaW5lLFxuXHRcdFx0XHRcdFx0cG9zaXRpb246IHJhbmdlLmhlYWRcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0pO1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gcmFuZ2VzO1xuXHRcdH1cblxuICAgICAgICBmdW5jdGlvbiB2YWx1ZUlzSW5SYW5nZSh2YWx1ZTogbnVtYmVyLCBtaW5WYWw6IG51bWJlciwgbWF4VmFsOiBudW1iZXIsIGluY2x1c2l2ZTogYm9vbGVhbiA9IHRydWUpIHtcblxuICAgICAgICAgICAgaWYoaW5jbHVzaXZlID09PSB0cnVlICYmICh2YWx1ZSA9PT0gbWluVmFsIHx8IHZhbHVlID09PSBtYXhWYWwpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChtaW5WYWwgPCB2YWx1ZSAmJiB2YWx1ZSA8IG1heFZhbCkge1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuXG5cdFx0ZnVuY3Rpb24gY2hlY2tDdXJzb3JJblJlZ2lvbihzdGFydEluZGV4OiBudW1iZXIsXG5cdFx0XHRcdFx0XHRcdFx0ZW5kSW5kZXg6IG51bWJlciwgXG5cdFx0XHRcdFx0XHRcdFx0cmFuZ2VzOiB7IGxpbmU6IExpbmUsIHBvc2l0aW9uOiBudW1iZXIgfVtdICk6IGJvb2xlYW4ge1xuXG5cdFx0XHRmb3IgKGxldCBpID0gMDsgaSA8IHJhbmdlcy5sZW5ndGg7IGkrKykge1xuXG5cdFx0XHRcdC8vIFRPRE86IE1heWJlIGxvb2sgaW50byBsaW1pdGluZyB0aGlzIHRvIHRoZSBzZWNvbmQgYW5kIHNlY29uZCB0byBsYXN0IGxpbmVcblx0XHRcdFx0Ly8gb2YgdGhlIHJlZ2lvbiBhcyBjbGlja2luZyByaWdodCBhdCB0aGUgdG9wIG9yIGJvdHRvbSBvZiB0aGUgcmVnaW9uXG5cdFx0XHRcdC8vIHN3YXBzIGl0IHRvIHVucmVuZGVyZWQuXG5cdFx0XHRcdGxldCByYW5nZSA9IHJhbmdlc1tpXTtcblx0XHRcdFx0aWYodmFsdWVJc0luUmFuZ2UocmFuZ2UucG9zaXRpb24sIHN0YXJ0SW5kZXgsIGVuZEluZGV4KSA9PT0gdHJ1ZSkge1xuXHRcdFx0XHRcdHJldHVybiB0cnVlO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdGlmKHRyYW5zYWN0aW9uLnN0YXRlLnNlbGVjdGlvbil7XG5cdFx0XHRcdGZvciAobGV0IGkgPSAwOyBpIDwgdHJhbnNhY3Rpb24uc3RhdGUuc2VsZWN0aW9uLnJhbmdlcy5sZW5ndGg7IGkrKykge1xuXG5cdFx0XHRcdFx0bGV0IHJhbmdlID0gdHJhbnNhY3Rpb24uc3RhdGUuc2VsZWN0aW9uLnJhbmdlc1tpXTtcblxuXHRcdFx0XHRcdC8vIElmIGVpdGhlciB0aGUgc3RhcnQgb3IgZW5kIG9mIHRoZSBzZWxlY3Rpb24gaXMgd2l0aGluIHRoZVxuXHRcdFx0XHRcdC8vIHJlZ2lvbiByYW5nZSB3ZSBkbyBub3QgcmVuZGVyIGxpdmUgcHJldmlldy5cblx0XHRcdFx0XHRpZih2YWx1ZUlzSW5SYW5nZShyYW5nZS5mcm9tLCBzdGFydEluZGV4LCBlbmRJbmRleCkgfHwgXG5cdFx0XHRcdFx0ICAgdmFsdWVJc0luUmFuZ2UocmFuZ2UudG8sIHN0YXJ0SW5kZXgsIGVuZEluZGV4KSkge1xuXHRcdFx0XHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0Ly8gLy8gT3IgaWYgdGhlIGVudGlyZSByZWdpb24gaXMgd2l0aGluIHRoZSBzZWxlY3Rpb24gcmFuZ2Vcblx0XHRcdFx0XHQvLyB3ZSBkbyBub3QgcmVuZGVyIHRoZSBsaXZlIHByZXZpZXcuXG5cdFx0XHRcdFx0aWYodmFsdWVJc0luUmFuZ2Uoc3RhcnRJbmRleCwgcmFuZ2UuZnJvbSwgcmFuZ2UudG8pICYmIFxuXHRcdFx0XHRcdCAgIHZhbHVlSXNJblJhbmdlKGVuZEluZGV4LCByYW5nZS5mcm9tLCByYW5nZS50bykpIHtcblx0XHRcdFx0XHRcdHJldHVybiB0cnVlO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXHR9LFxuXHRwcm92aWRlKGZpZWxkOiBTdGF0ZUZpZWxkPERlY29yYXRpb25TZXQ+KTogRXh0ZW5zaW9uIHtcblx0XHRyZXR1cm4gRWRpdG9yVmlldy5kZWNvcmF0aW9ucy5mcm9tKGZpZWxkKTtcblx0fSxcbn0pO1xuIiwiLypcclxuICogRmlsZTogbXVsdGktY29sdW1uLW1hcmtkb3duL3NyYy9tYWluLnRzXHJcbiAqIENyZWF0ZWQgRGF0ZTogVHVlc2RheSwgT2N0b2JlciA1dGggMjAyMSwgMTowOSBwbVxyXG4gKiBBdXRob3I6IENhbWVyb24gUm9iaW5zb25cclxuICogXHJcbiAqIENvcHlyaWdodCAoYykgMjAyMiBDYW1lcm9uIFJvYmluc29uXHJcbiAqL1xyXG5cclxuaW1wb3J0IHsgTm90aWNlLCBQbHVnaW4sICBNYXJrZG93blJlbmRlckNoaWxkLCBNYXJrZG93blJlbmRlcmVyLCBURmlsZSwgUGxhdGZvcm0gfSBmcm9tICdvYnNpZGlhbic7XHJcbmltcG9ydCAqIGFzIG11bHRpQ29sdW1uUGFyc2VyIGZyb20gJy4vdXRpbGl0aWVzL3RleHRQYXJzZXInO1xyXG5pbXBvcnQgeyBGaWxlRE9NTWFuYWdlciwgR2xvYmFsRE9NTWFuYWdlciB9IGZyb20gJy4vZG9tX21hbmFnZXIvZG9tTWFuYWdlcic7XHJcbmltcG9ydCB7IE11bHRpQ29sdW1uUmVuZGVyRGF0YSB9IGZyb20gXCIuL2RvbV9tYW5hZ2VyL3JlZ2lvbmFsX21hbmFnZXJzL3JlZ2lvbk1hbmFnZXJcIjtcclxuaW1wb3J0IHsgUmVnaW9uTWFuYWdlciB9IGZyb20gXCIuL2RvbV9tYW5hZ2VyL3JlZ2lvbmFsX21hbmFnZXJzL3JlZ2lvbk1hbmFnZXJcIjtcclxuaW1wb3J0IHsgUmVnaW9uTWFuYWdlckNvbnRhaW5lciB9IGZyb20gXCIuL2RvbV9tYW5hZ2VyL3JlZ2lvbmFsX21hbmFnZXJzL3JlZ2lvbk1hbmFnZXJDb250YWluZXJcIjtcclxuaW1wb3J0IHsgRE9NT2JqZWN0LCBET01PYmplY3RUYWcsIFRhc2tMaXN0RE9NT2JqZWN0IH0gZnJvbSAnLi9kb21fbWFuYWdlci9kb21PYmplY3QnO1xyXG5pbXBvcnQgeyBmaWxlU3RpbGxJblZpZXcsIGdldEZpbGVMZWFmLCBnZXRMZWFmU291cmNlTW9kZSwgZ2V0VUlEIH0gZnJvbSAnLi91dGlsaXRpZXMvdXRpbHMnO1xyXG5pbXBvcnQgeyBNdWx0aUNvbHVtbkxheW91dENTUywgTXVsdGlDb2x1bW5TdHlsZUNTUyB9IGZyb20gJy4vdXRpbGl0aWVzL2Nzc0RlZmluaXRpb25zJztcclxuaW1wb3J0IHsgRWxlbWVudFJlbmRlclR5cGUgfSBmcm9tICcuL3V0aWxpdGllcy9lbGVtZW50UmVuZGVyVHlwZVBhcnNlcic7XHJcbmltcG9ydCB7IG11bHRpQ29sdW1uTWFya2Rvd25fU3RhdGVGaWVsZCB9IGZyb20gJy4vbGl2ZV9wcmV2aWV3L2NtNl9saXZlUHJldmlldyc7XHJcbmltcG9ydCB7IHBhcnNlU3RhcnRSZWdpb25Db2RlQmxvY2tJRCB9IGZyb20gJy4vdXRpbGl0aWVzL3NldHRpbmdzUGFyc2VyJztcclxuXHJcbmludGVyZmFjZSBNQ01fU2V0dGluZ3Mge1xyXG4gICAgcmVuZGVyT25Nb2JpbGU6IGJvb2xlYW47XHJcbn1cclxuY29uc3QgREVGQVVMVF9TRVRUSU5HUzogTUNNX1NldHRpbmdzID0ge1xyXG4gICAgcmVuZGVyT25Nb2JpbGU6IHRydWVcclxufTtcclxuXHJcbmNvbnN0IENPREVCTE9DS19TVEFSVF9TVFJTID0gW1xyXG4gICAgXCJzdGFydC1tdWx0aS1jb2x1bW5cIixcclxuICAgIFwibXVsdGktY29sdW1uLXN0YXJ0XCJcclxuXVxyXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBNdWx0aUNvbHVtbk1hcmtkb3duIGV4dGVuZHMgUGx1Z2luIHtcclxuXHJcbiAgICBzZXR0aW5nczogTUNNX1NldHRpbmdzID0gREVGQVVMVF9TRVRUSU5HUztcclxuICAgIGdsb2JhbE1hbmFnZXI6IEdsb2JhbERPTU1hbmFnZXIgPSBuZXcgR2xvYmFsRE9NTWFuYWdlcigpO1xyXG5cclxuXHRhc3luYyBvbmxvYWQoKSB7XHJcblxyXG4gICAgICAgIGNvbnNvbGUubG9nKFwiTG9hZGluZyBtdWx0aS1jb2x1bW4gbWFya2Rvd25cIik7XHJcblxyXG4gICAgICAgIGF3YWl0IHRoaXMubG9hZFNldHRpbmdzKCk7XHJcblxyXG4gICAgICAgIHRoaXMuZ2xvYmFsTWFuYWdlciA9IG5ldyBHbG9iYWxET01NYW5hZ2VyKCk7XHJcblxyXG4gICAgICAgIHRoaXMucmVnaXN0ZXJFZGl0b3JFeHRlbnNpb24obXVsdGlDb2x1bW5NYXJrZG93bl9TdGF0ZUZpZWxkKVxyXG5cclxuICAgICAgICBmb3IobGV0IGkgPSAwOyBpIDwgQ09ERUJMT0NLX1NUQVJUX1NUUlMubGVuZ3RoOyBpKyspIHtcclxuXHJcbiAgICAgICAgICAgIGxldCBzdGFydFN0ciA9IENPREVCTE9DS19TVEFSVF9TVFJTW2ldXHJcbiAgICAgICAgICAgIHRoaXMuc2V0dXBNYXJrZG93bkNvZGVibG9ja1Bvc3RQcm9jZXNzb3Ioc3RhcnRTdHIpO1xyXG4gICAgICAgIH1cclxuICAgICAgICB0aGlzLnNldHVwTWFya2Rvd25Qb3N0UHJvY2Vzc29yKCk7XHJcblxyXG4gICAgICAgIHRoaXMuYWRkQ29tbWFuZCh7ICAgICAgICAgICAgXHJcbiAgICAgICAgICAgIGlkOiBgdG9nZ2xlLW1vYmlsZS1yZW5kZXJpbmctbWNtYCxcclxuICAgICAgICAgICAgbmFtZTogYFRvZ2dsZSBNb2JpbGUgUmVuZGVyaW5nIC0gTXVsdGktQ29sdW1uIE1hcmtkb3duYCxcclxuICAgICAgICAgICAgY2FsbGJhY2s6IGFzeW5jICgpID0+IHtcclxuXHJcbiAgICAgICAgICAgICAgICB0aGlzLnNldHRpbmdzLnJlbmRlck9uTW9iaWxlID0gIXRoaXMuc2V0dGluZ3MucmVuZGVyT25Nb2JpbGU7IFxyXG4gICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5zYXZlU2V0dGluZ3MoKTtcclxuXHJcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcInJlbmRlciBvbiBtb2JpbGU6XCIsIHRoaXMuc2V0dGluZ3MucmVuZGVyT25Nb2JpbGUpO1xyXG5cclxuICAgICAgICAgICAgICAgIGxldCBub3RpY2VTdHJpbmcgPSBgVG9nZ2xlZCBtb2JpbGUgcmVuZGVyaW5nICR7dGhpcy5zZXR0aW5ncy5yZW5kZXJPbk1vYmlsZSA/IFwib25cIiA6IFwib2ZmXCJ9LmBcclxuICAgICAgICAgICAgICAgIGlmKFBsYXRmb3JtLmlzTW9iaWxlID09PSB0cnVlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgbm90aWNlU3RyaW5nICs9IGAgUGxlYXNlIHJlbG9hZCBhbnkgb3BlbiBmaWxlcyBmb3IgY2hhbmdlIHRvIHRha2UgZWZmZWN0LmBcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIG5ldyBOb3RpY2UgKG5vdGljZVN0cmluZyk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgLy9UT0RPOiBTZXQgdXAgdGhpcyBhcyBhIG1vZGFsIHRvIHNldCBzZXR0aW5ncyBhdXRvbWF0aWNhbGx5XHJcbiAgICAgICAgdGhpcy5hZGRDb21tYW5kKHsgICAgICAgICAgICBcclxuICAgICAgICAgICAgaWQ6IGBpbnNlcnQtbXVsdGktY29sdW1uLXJlZ2lvbmAsXHJcbiAgICAgICAgICAgIG5hbWU6IGBJbnNlcnQgTXVsdGktQ29sdW1uIFJlZ2lvbmAsXHJcbiAgICAgICAgICAgIGVkaXRvckNhbGxiYWNrOiAoZWRpdG9yLCB2aWV3KSA9PiB7XHJcblxyXG4gICAgICAgICAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgICAgICAgICBsZXQgY3Vyc29yU3RhcnRQb3NpdGlvbiA9IGVkaXRvci5nZXRDdXJzb3IoXCJmcm9tXCIpO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICBlZGl0b3IuZ2V0RG9jKCkucmVwbGFjZVNlbGVjdGlvbihcclxuYFxyXG5cXGBcXGBcXGBzdGFydC1tdWx0aS1jb2x1bW5cclxuSUQ6IElEXyR7Z2V0VUlEKDQpfVxyXG5OdW1iZXIgb2YgQ29sdW1uczogMlxyXG5MYXJnZXN0IENvbHVtbjogc3RhbmRhcmRcclxuXFxgXFxgXFxgXHJcblxyXG5cclxuXHJcbi0tLSBjb2x1bW4tZW5kIC0tLVxyXG5cclxuXHJcblxyXG49PT0gZW5kLW11bHRpLWNvbHVtblxyXG5cclxuJHtlZGl0b3IuZ2V0RG9jKCkuZ2V0U2VsZWN0aW9uKCl9YFxyXG4gICAgICAgICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgICAgICAgICAgXHJcbiAgICAgICAgICAgICAgICAgICAgY3Vyc29yU3RhcnRQb3NpdGlvbi5saW5lID0gY3Vyc29yU3RhcnRQb3NpdGlvbi5saW5lICsgN1xyXG4gICAgICAgICAgICAgICAgICAgIGN1cnNvclN0YXJ0UG9zaXRpb24uY2ggPSAwO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICBlZGl0b3Iuc2V0Q3Vyc29yKGN1cnNvclN0YXJ0UG9zaXRpb24pO1xyXG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xyXG4gICAgICAgICAgICAgICAgICAgIG5ldyBOb3RpY2UoXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIFwiRW5jb3VudGVyZWQgYW4gZXJyb3IgaW5zZXJ0aW5nIGEgbXVsdGktY29sdW1uIHJlZ2lvbi4gUGxlYXNlIHRyeSBhZ2FpbiBsYXRlci5cIlxyXG4gICAgICAgICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgdGhpcy5hZGRDb21tYW5kKHsgICAgICAgICAgICBcclxuICAgICAgICAgICAgaWQ6IGBhZGQtSURzLVRvLW11bHRpLWNvbHVtbi1yZWdpb25gLFxyXG4gICAgICAgICAgICBuYW1lOiBgRml4IE1pc3NpbmcgSURzIGZvciBNdWx0aS1Db2x1bW4gUmVnaW9uc2AsXHJcbiAgICAgICAgICAgIGVkaXRvckNhbGxiYWNrOiAoZWRpdG9yLCB2aWV3KSA9PiB7XHJcblxyXG4gICAgICAgICAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgICAgICAgICAvKipcclxuICAgICAgICAgICAgICAgICAgICAgKiBOb3Qgc3VyZSBpZiB0aGVyZSBpcyBhbiBlYXNpZXIgd2F5IHRvIGRvIHRoaXMuXHJcbiAgICAgICAgICAgICAgICAgICAgICogXHJcbiAgICAgICAgICAgICAgICAgICAgICogR2V0IGFsbCBvZiB0aGUgbGluZXMgb2YgdGhlIGRvY3VtZW50IHNwbGl0IGJ5IG5ld2xpbmVzLlxyXG4gICAgICAgICAgICAgICAgICAgICAqL1xyXG4gICAgICAgICAgICAgICAgICAgIGxldCBkb2NUZXh0ID0gZWRpdG9yLmdldFJhbmdlKHsgbGluZTogMCwgY2g6IDAgfSwgeyBsaW5lOiBlZGl0b3IuZ2V0RG9jKCkubGluZUNvdW50KCksIGNoOiAwfSk7XHJcbiAgICAgICAgICAgICAgICAgICAgbGV0IGxpbmVzID0gZG9jVGV4dC5zcGxpdChcIlxcblwiKTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgbGV0IHN0YXJ0Q29kZWJsb2NrID0gbXVsdGlDb2x1bW5QYXJzZXIuZmluZFN0YXJ0Q29kZWJsb2NrKGRvY1RleHQpO1xyXG4gICAgICAgICAgICAgICAgICAgIGxldCBsaW5lT2Zmc2V0ID0gMDtcclxuICAgICAgICAgICAgICAgICAgICBsZXQgbnVtQ29kZWJsb2Nrc1VwZGF0ZWQgPSAwO1xyXG4gICAgICAgICAgICAgICAgICAgIHdoaWxlKHN0YXJ0Q29kZWJsb2NrLmZvdW5kID09PSB0cnVlKSB7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBHZXQgdGhlIHRleHQgb2YgdGhlIHNldHRpbmdzIGJsb2NrIHNvIHdlIGNhbiBjaGVjayBpZiBpdCBjb250YWlucyBhbiBJRCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYWxzbyBzbyB3ZSBjYW4gZ2V0IHRoZSBsZW5ndGggb2YgdGhlIGZpcnN0IGxpbmUsIHVzZWQgdG8gY2FsY3VsYXRlIHdoZXJlIHRvIGFwcGVuZCBhIG5ldyBJRCBpZiBuZWVkZWRcclxuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHNldHRpbmdzVGV4dCA9IGRvY1RleHQuc2xpY2Uoc3RhcnRDb2RlYmxvY2suc3RhcnRQb3NpdGlvbiwgc3RhcnRDb2RlYmxvY2suZW5kUG9zaXRpb24pO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgZmlyc3RMaW5lT2ZDb2RlYmxvY2tMZW5ndGggPSBzZXR0aW5nc1RleHQuc3BsaXQoXCJcXG5cIilbMF0ubGVuZ3RoO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBcclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2UgbmVlZCB0aGUgbGluZXMgYmVmb3JlIHRoZSBibG9jayB0byBrbm93IHdoZXJlIHRvIHN0YXJ0IHJlcGxhY2luZyB0ZXh0XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGFuZCB0aGUgbGluZXMgaW5jbHVkaW5nIHRoZSBibG9jayB0byBrbm93IHdoZXJlIHRvIHNldCBvdXIgb2Zmc2V0IHRvIGFmdGVyIHRoaXMgaXRlcmF0aW9uLlxyXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgbGluZXNCZWZvcmUgPSBkb2NUZXh0LnNsaWNlKDAsIHN0YXJ0Q29kZWJsb2NrLnN0YXJ0UG9zaXRpb24pO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgc3RhcnRSZXBsYWNlbWVudExpbmVJbmRleCA9IChsaW5lc0JlZm9yZS5zcGxpdChcIlxcblwiKS5sZW5ndGggLSAxKSArIGxpbmVPZmZzZXQ7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBsaW5lc09mID0gZG9jVGV4dC5zbGljZSgwLCBzdGFydENvZGVibG9jay5lbmRQb3NpdGlvbik7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBlbmRSZXBsYWNlbWVudExpbmVJbmRleCA9ICAobGluZXNPZi5zcGxpdChcIlxcblwiKS5sZW5ndGggLSAxKSArIGxpbmVPZmZzZXQ7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgc2V0dGluZ3NJRCA9IHBhcnNlU3RhcnRSZWdpb25Db2RlQmxvY2tJRChzZXR0aW5nc1RleHQpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZihzZXR0aW5nc0lEID09PSBcIlwiKSB7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gY29weSB0aGUgZmlyc3QgbGluZSBvZiB0aGUgY29kZWJsb2NrIGFuZCBhcHBlbmQgYSBuZXcgSUQsIHRoZW4gcmVwbGFjZSB0aGUgZmlyc3QgbGluZSBvZiB0aGUgYmxvY2tcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCByZXBsYWNlbWVudFRleHQgPSBlZGl0b3IuZ2V0UmFuZ2UoeyBsaW5lOiBzdGFydFJlcGxhY2VtZW50TGluZUluZGV4LCBjaDogMCB9LCB7IGxpbmU6IHN0YXJ0UmVwbGFjZW1lbnRMaW5lSW5kZXgsIGNoOiBmaXJzdExpbmVPZkNvZGVibG9ja0xlbmd0aH0pICsgYFxcbklEOiBJRF8ke2dldFVJRCg0KX1gXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlZGl0b3IucmVwbGFjZVJhbmdlKHJlcGxhY2VtZW50VGV4dCwgeyBsaW5lOiBzdGFydFJlcGxhY2VtZW50TGluZUluZGV4LCBjaDogMCB9LCBcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7IGxpbmU6IHN0YXJ0UmVwbGFjZW1lbnRMaW5lSW5kZXgsIGNoOiBmaXJzdExpbmVPZkNvZGVibG9ja0xlbmd0aH0pO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZW5kUmVwbGFjZW1lbnRMaW5lSW5kZXggKz0gMTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG51bUNvZGVibG9ja3NVcGRhdGVkICs9IDE7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxpbmVPZmZzZXQgPSBlbmRSZXBsYWNlbWVudExpbmVJbmRleFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBkb2NUZXh0ID0gZG9jVGV4dC5zbGljZShzdGFydENvZGVibG9jay5lbmRQb3NpdGlvbik7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0YXJ0Q29kZWJsb2NrID0gbXVsdGlDb2x1bW5QYXJzZXIuZmluZFN0YXJ0Q29kZWJsb2NrKGRvY1RleHQpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgLyoqXHJcbiAgICAgICAgICAgICAgICAgICAgICogTG9vcCB0aHJvdWdoIGFsbCBvZiB0aGUgbGluZXMgY2hlY2tpbmcgaWYgdGhlIGxpbmUgaXMgYSBcclxuICAgICAgICAgICAgICAgICAgICAgKiBzdGFydCB0YWcgYW5kIGlmIHNvIGlzIGl0IG1pc3NpbmcgYW4gSUQuXHJcbiAgICAgICAgICAgICAgICAgICAgICovXHJcbiAgICAgICAgICAgICAgICAgICAgbGV0IGxpbmVzV2l0aG91dElEcyA9IFtdXHJcbiAgICAgICAgICAgICAgICAgICAgbGV0IHRleHRXaXRob3V0SURzID0gW11cclxuICAgICAgICAgICAgICAgICAgICBmb3IobGV0IGkgPSAwOyBpIDwgbGluZXMubGVuZ3RoOyBpKyspIHtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBkYXRhID0gbXVsdGlDb2x1bW5QYXJzZXIuaXNTdGFydFRhZ1dpdGhJRChsaW5lc1tpXSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKGRhdGEuaXNTdGFydFRhZyA9PT0gdHJ1ZSAmJiBkYXRhLmhhc0tleSA9PT0gZmFsc2UpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmVzV2l0aG91dElEcy5wdXNoKGkpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGV4dFdpdGhvdXRJRHMucHVzaChsaW5lc1tpXSlcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIH0gICAgICAgICAgICAgICAgICAgIFxyXG5cclxuICAgICAgICAgICAgICAgICAgICBpZihsaW5lc1dpdGhvdXRJRHMubGVuZ3RoID09PSAwICYmIG51bUNvZGVibG9ja3NVcGRhdGVkID09PSAwKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ldyBOb3RpY2UgKFwiRm91bmQgMCBtaXNzaW5nIElEcyBpbiB0aGUgY3VycmVudCBkb2N1bWVudC5cIik7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIC8qKlxyXG4gICAgICAgICAgICAgICAgICAgICAqIE5vdyBsb29wIHRocm91Z2ggZWFjaCBsaW5lIHRoYXQgaXMgbWlzc2luZyBhbiBJRCBhbmRcclxuICAgICAgICAgICAgICAgICAgICAgKiBnZW5lcmF0ZSBhIHJhbmRvbSBJRCBhbmQgcmVwbGFjZSB0aGUgb3JpZ2luYWwgdGV4dC5cclxuICAgICAgICAgICAgICAgICAgICAgKi9cclxuICAgICAgICAgICAgICAgICAgICBmb3IobGV0IGkgPSAwOyBpIDwgbGluZXNXaXRob3V0SURzLmxlbmd0aDsgaSsrKSB7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgb3JpZ2luYWxUZXh0ID0gdGV4dFdpdGhvdXRJRHNbaV1cclxuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHRleHQgPSBvcmlnaW5hbFRleHQ7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRleHQgPSB0ZXh0LnRyaW1FbmQoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYodGV4dC5jaGFyQXQodGV4dC5sZW5ndGggLSAxKSA9PT0gXCI6XCIpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRleHQgPSB0ZXh0LnNsaWNlKDAsIHRleHQubGVuZ3RoLTEpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRleHQgPSBgJHt0ZXh0fTogSURfJHtnZXRVSUQoNCl9YDtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGVkaXRvci5yZXBsYWNlUmFuZ2UodGV4dCwgeyBsaW5lOiBsaW5lc1dpdGhvdXRJRHNbaV0sIGNoOiAwIH0sIFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHsgbGluZTogbGluZXNXaXRob3V0SURzW2ldLCBjaDogb3JpZ2luYWxUZXh0Lmxlbmd0aH0pO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgbmV3IE5vdGljZSAoYFJlcGxhY2VkICR7bGluZXNXaXRob3V0SURzLmxlbmd0aCArIG51bUNvZGVibG9ja3NVcGRhdGVkfSBtaXNzaW5nIElEKHMpIGluIHRoZSBjdXJyZW50IGRvY3VtZW50LmApO1xyXG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xyXG4gICAgICAgICAgICAgICAgICAgIG5ldyBOb3RpY2UoXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIFwiRW5jb3VudGVyZWQgYW4gZXJyb3IgYWRkaWduIElEcyB0byBtdWx0aS1jb2x1bW4gcmVnaW9ucy4gUGxlYXNlIHRyeSBhZ2FpbiBsYXRlci5cIlxyXG4gICAgICAgICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgdGhpcy5yZWdpc3RlckludGVydmFsKHdpbmRvdy5zZXRJbnRlcnZhbCgoKSA9PiB7XHJcbiAgICAgICAgICAgIFxyXG4gICAgICAgICAgICB0aGlzLlVwZGF0ZU9wZW5GaWxlUHJldmlld3MoKTtcclxuICAgICAgICB9LCA1MDApKTtcclxuICAgIH1cclxuXHJcbiAgICBVcGRhdGVPcGVuRmlsZVByZXZpZXdzKCkge1xyXG5cclxuICAgICAgICBsZXQgZmlsZU1hbmFnZXJzID0gdGhpcy5nbG9iYWxNYW5hZ2VyLmdldEFsbEZpbGVNYW5hZ2VycygpO1xyXG4gICAgICAgIGZpbGVNYW5hZ2Vycy5mb3JFYWNoKGVsZW1lbnQgPT4ge1xyXG4gICAgICAgICAgICBcclxuICAgICAgICAgICAgbGV0IHJlZ2lvbmFsTWFuYWdlcnMgPSBlbGVtZW50LmdldEFsbFJlZ2lvbmFsTWFuYWdlcnMoKTtcclxuICAgICAgICAgICAgcmVnaW9uYWxNYW5hZ2Vycy5mb3JFYWNoKHJlZ2lvbk1hbmFnZXIgPT4ge1xyXG4gICAgICAgICAgICAgICAgXHJcbiAgICAgICAgICAgICAgICByZWdpb25NYW5hZ2VyLnVwZGF0ZVJlbmRlcmVkTWFya2Rvd24oKVxyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICBzZXR1cE1hcmtkb3duUG9zdFByb2Nlc3NvcigpIHtcclxuICAgICAgICB0aGlzLnJlZ2lzdGVyTWFya2Rvd25Qb3N0UHJvY2Vzc29yKGFzeW5jIChlbCwgY3R4KSA9PiB7XHJcblxyXG4gICAgICAgICAgICBpZih0aGlzLnNldHRpbmdzLnJlbmRlck9uTW9iaWxlID09PSBmYWxzZSAmJlxyXG4gICAgICAgICAgICAgICBQbGF0Zm9ybS5pc01vYmlsZSA9PT0gdHJ1ZSkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBjb25zdCBzb3VyY2VQYXRoID0gY3R4LnNvdXJjZVBhdGg7XHJcblxyXG4gICAgICAgICAgICBsZXQgZmlsZURPTU1hbmFnZXIgPSB0aGlzLmdsb2JhbE1hbmFnZXIuZ2V0RmlsZU1hbmFnZXIoc291cmNlUGF0aCk7XHJcbiAgICAgICAgICAgIGlmKGZpbGVET01NYW5hZ2VyID09PSBudWxsKSB7XHJcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcIkZvdW5kIG51bGwgRE9NIG1hbmFnZXIuIENvdWxkIG5vdCBwcm9jZXNzIG11bHRpLWNvbHVtbiBtYXJrZG93bi5cIilcclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgLyoqXHJcbiAgICAgICAgICAgICAqIEhlcmUgd2UgY2hlY2sgaWYgdGhlIGV4cG9ydCBcInByaW50XCIgZmxhZyBpcyBpbiB0aGUgRE9NIHNvIHdlIGNhbiBkZXRlcm1pbmUgaWYgd2VcclxuICAgICAgICAgICAgICogYXJlIGV4cG9ydGluZyBhbmQgaGFuZGxlIHRoYXQgY2FzZS5cclxuICAgICAgICAgICAgICovXHJcbiAgICAgICAgICAgIGlmKHRoaXMuY2hlY2tFeHBvcnRpbmcoZWwpKSB7XHJcblxyXG4gICAgICAgICAgICAgICAgdGhpcy5leHBvcnREb2N1bWVudFRvUERGKGVsLCBmaWxlRE9NTWFuYWdlciwgc291cmNlUGF0aCk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIC8vIEdldCB0aGUgaW5mbyBmb3Igb3VyIGN1cnJlbnQgY29udGV4dCBhbmQgdGhlbiBjaGVja1xyXG4gICAgICAgICAgICAvLyBpZiB0aGUgZW50aXJlIHRleHQgY29udGFpbnMgYSBzdGFydCB0YWcuIElmIHRoZXJlIGlzXHJcbiAgICAgICAgICAgIC8vIG5vIHN0YXJ0IHRhZyBpbiB0aGUgZG9jdW1lbnQgd2UgY2FuIGp1c3QgcmV0dXJuIGFuZFxyXG4gICAgICAgICAgICAvLyBpZ25vcmUgdGhlIHJlc3Qgb2YgdGhlIHBhcnNpbmcuXHJcbiAgICAgICAgICAgIGxldCBpbmZvID0gY3R4LmdldFNlY3Rpb25JbmZvKGVsKTtcclxuXHJcbiAgICAgICAgICAgIC8qKlxyXG4gICAgICAgICAgICAgKiBXZSBuZWVkIHRoZSBjb250ZXh0IGluZm8gdG8gcHJvcGVybHkgcGFyc2Ugc28gcmV0dXJuaW5nIGhlcmUgXHJcbiAgICAgICAgICAgICAqIGluZm8gaXMgbnVsbC4gVE9ETzogU2V0IGVycm9yIGluIHZpZXcgaWYgdGhpcyBvY2N1cnMuXHJcbiAgICAgICAgICAgICAqL1xyXG4gICAgICAgICAgICBpZighaW5mbykge1xyXG5cclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgbGV0IGRvY1N0cmluZyA9IGluZm8udGV4dDtcclxuICAgICAgICAgICAgbGV0IGRvY0xpbmVzID0gZG9jU3RyaW5nLnNwbGl0KFwiXFxuXCIpO1xyXG5cclxuICAgICAgICAgICAgLyoqXHJcbiAgICAgICAgICAgICAqIElmIHdlIGVuY291bnRlciBhIHN0YXJ0IHRhZyBvbiB0aGUgZG9jdW1lbnQgd2Ugc2V0IHRoZSBmbGFnIHRvIHN0YXJ0XHJcbiAgICAgICAgICAgICAqIHBhcnNpbmcgdGhlIHJlc3Qgb2YgdGhlIGRvY3VtZW50LlxyXG4gICAgICAgICAgICAgKi9cclxuICAgICAgICAgICAgaWYobXVsdGlDb2x1bW5QYXJzZXIuY29udGFpbnNTdGFydFRhZyhlbC50ZXh0Q29udGVudCkgfHwgXHJcbiAgICAgICAgICAgICAgIG11bHRpQ29sdW1uUGFyc2VyLmNvbnRhaW5zU3RhcnRDb2RlQmxvY2soZG9jU3RyaW5nKSkge1xyXG5cclxuICAgICAgICAgICAgICAgIGZpbGVET01NYW5hZ2VyLnNldEhhc1N0YXJ0VGFnKCk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIC8qKiBcclxuICAgICAgICAgICAgICogSWYgdGhlIGRvY3VtZW50IGRvZXMgbm90IGNvbnRhaW4gYW55IHN0YXJ0IHRhZ3Mgd2UgaWdub3JlIHRoZVxyXG4gICAgICAgICAgICAgKiByZXN0IG9mIHRoZSBwYXJzaW5nLiBUaGlzIGlzIG9ubHkgc2V0IHRvIHRydWUgb25jZSB0aGUgZmlyc3RcclxuICAgICAgICAgICAgICogc3RhcnQgdGFnIGVsZW1lbnQgaXMgcGFyc2VkIGFib3ZlLlxyXG4gICAgICAgICAgICAgKi9cclxuICAgICAgICAgICAgaWYoZmlsZURPTU1hbmFnZXIuZ2V0SGFzU3RhcnRUYWcoKSA9PT0gZmFsc2UpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgLyoqXHJcbiAgICAgICAgICAgICAqIFRha2UgdGhlIGluZm8gcHJvdmlkZWQgYW5kIGdlbmVyYXRlIHRoZSByZXF1aXJlZCB2YXJpYWJsZXMgZnJvbSBcclxuICAgICAgICAgICAgICogdGhlIGxpbmUgc3RhcnQgYW5kIGVuZCB2YWx1ZXMuXHJcbiAgICAgICAgICAgICAqL1xyXG4gICAgICAgICAgICBsZXQgbGluZXNBYm92ZUFycmF5ID0gZG9jTGluZXMuc2xpY2UoMCwgaW5mby5saW5lU3RhcnQpXHJcbiAgICAgICAgICAgIGxldCBsaW5lc09mRWxlbWVudCA9IGRvY0xpbmVzLnNsaWNlKGluZm8ubGluZVN0YXJ0LCBpbmZvLmxpbmVFbmQgKyAxKTtcclxuICAgICAgICAgICAgbGV0IHRleHRPZkVsZW1lbnQgPSBsaW5lc09mRWxlbWVudC5qb2luKFwiXFxuXCIpXHJcbiAgICAgICAgICAgIGxldCBsaW5lc0JlbG93QXJyYXkgPSBkb2NMaW5lcy5zbGljZShpbmZvLmxpbmVFbmQgKyAxKVxyXG5cclxuICAgICAgICAgICAgLy8jcmVnaW9uIERlcHJlY2lhdGVkIFN0YXJ0IFRhZ1xyXG4gICAgICAgICAgICAvKipcclxuICAgICAgICAgICAgICogSWYgdGhlIGN1cnJlbnQgbGluZSBpcyBhIHN0YXJ0IHRhZyB3ZSB3YW50IHRvIHNldCB1cCB0aGVcclxuICAgICAgICAgICAgICogcmVnaW9uIG1hbmFnZXIuIFRoZSByZWdpb25hbCBtYW5hZ2VyIHRha2VzIGNhcmVcclxuICAgICAgICAgICAgICogb2YgYWxsIGl0ZW1zIGJldHdlZW4gaXQncyBzdGFydCBhbmQgZW5kIHRhZ3Mgd2hpbGUgdGhlXHJcbiAgICAgICAgICAgICAqIGZpbGUgbWFuYWdlciB3ZSBnb3QgYWJvdmUgYWJvdmUgdGFrZXMgY2FyZSBvZiBhbGwgcmVnaW9uYWwgXHJcbiAgICAgICAgICAgICAqIG1hbmFnZXJzIGluIGVhY2ggZmlsZS5cclxuICAgICAgICAgICAgICovXHJcbiAgICAgICAgICAgIGlmKG11bHRpQ29sdW1uUGFyc2VyLmNvbnRhaW5zU3RhcnRUYWcodGV4dE9mRWxlbWVudCkpIHtcclxuXHJcbiAgICAgICAgICAgICAgICAvKiogXHJcbiAgICAgICAgICAgICAgICAgKiBTZXQgdXAgdGhlIGN1cnJlbnQgZWxlbWVudCB0byBhY3QgYXMgdGhlIHBhcmVudCBmb3IgdGhlIFxyXG4gICAgICAgICAgICAgICAgICogbXVsdGktY29sdW1uIHJlZ2lvbi5cclxuICAgICAgICAgICAgICAgICAqL1xyXG4gICAgICAgICAgICAgICAgZWwuY2hpbGRyZW5bMF0uZGV0YWNoKCk7XHJcbiAgICAgICAgICAgICAgICBlbC5jbGFzc0xpc3QuYWRkKE11bHRpQ29sdW1uTGF5b3V0Q1NTLlJlZ2lvblJvb3RDb250YWluZXJEaXYpXHJcbiAgICAgICAgICAgICAgICBsZXQgcmVuZGVyRXJyb3JSZWdpb24gPSBlbC5jcmVhdGVEaXYoe1xyXG4gICAgICAgICAgICAgICAgICAgIGNsczogYCR7TXVsdGlDb2x1bW5MYXlvdXRDU1MuUmVnaW9uRXJyb3JDb250YWluZXJEaXZ9ICR7TXVsdGlDb2x1bW5TdHlsZUNTUy5SZWdpb25FcnJvck1lc3NhZ2V9YCxcclxuICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgICAgbGV0IHJlbmRlckNvbHVtblJlZ2lvbiA9IGVsLmNyZWF0ZURpdih7XHJcbiAgICAgICAgICAgICAgICAgICAgY2xzOiBNdWx0aUNvbHVtbkxheW91dENTUy5SZWdpb25Db250ZW50Q29udGFpbmVyRGl2XHJcbiAgICAgICAgICAgICAgICB9KVxyXG5cclxuICAgICAgICAgICAgICAgIGxldCBzdGFydEJsb2NrRGF0YSA9IG11bHRpQ29sdW1uUGFyc2VyLmdldFN0YXJ0QmxvY2tBYm92ZUxpbmUobGluZXNPZkVsZW1lbnQpXHJcbiAgICAgICAgICAgICAgICBpZihzdGFydEJsb2NrRGF0YSA9PT0gbnVsbCkge1xyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIFxyXG4gICAgICAgICAgICAgICAgbGV0IHJlZ2lvbktleSA9IHN0YXJ0QmxvY2tEYXRhLnN0YXJ0QmxvY2tLZXk7XHJcbiAgICAgICAgICAgICAgICBpZihmaWxlRE9NTWFuYWdlci5jaGVja0tleUV4aXN0cyhyZWdpb25LZXkpID09PSB0cnVlKSB7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIGxldCB7IG51bWJlck9mVGFncywga2V5cyB9ID0gbXVsdGlDb2x1bW5QYXJzZXIuY291bnRTdGFydFRhZ3MoaW5mby50ZXh0KTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgbGV0IG51bU1hdGNoZXMgPSAwO1xyXG4gICAgICAgICAgICAgICAgICAgIGZvcihsZXQgaSA9IDA7IGkgPCBudW1iZXJPZlRhZ3M7IGkrKykge1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gQmVjYXVzZSB3ZSBjaGVja2VkIGlmIGtleSBleGlzdHMgb25lIG9mIHRoZXNlIGhhcyB0byBtYXRjaC5cclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYoa2V5c1tpXSA9PT0gcmVnaW9uS2V5KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBudW1NYXRjaGVzKys7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIC8vIFdlIG9ubHkgd2FudCB0byBkaXNwbGF5IGFuIGVycm9yIGlmIHRoZXJlIGFyZSBtb3JlIHRoYW4gMiBvZiB0aGUgc2FtZSBpZCBhY3Jvc3NcclxuICAgICAgICAgICAgICAgICAgICAvLyB0aGUgd2hvbGUgZG9jdW1lbnQuIFRoaXMgcHJldmVudHMgZXJyb3Mgd2hlbiBvYnNpZGlhbiByZWxvYWRzIHRoZSB3aG9sZSBkb2N1bWVudFxyXG4gICAgICAgICAgICAgICAgICAgIC8vIGFuZCB0aGVyZSBhcmUgdHdvIG9mIHRoZSBzYW1lIGtleSBpbiB0aGUgbWFwLlxyXG4gICAgICAgICAgICAgICAgICAgIGlmKG51bU1hdGNoZXMgPj0gMikge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZihyZWdpb25LZXkgPT09IFwiXCIpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbmRlckVycm9yUmVnaW9uLmlubmVyVGV4dCA9IFwiRm91bmQgbXVsdGlwbGUgcmVnaW9ucyB3aXRoIGVtcHR5IElEcy4gUGxlYXNlIHNldCBhIHVuaXF1ZSBJRCBhZnRlciBlYWNoIHN0YXJ0IHRhZy5cXG5FRzogJz09PSBtdWx0aS1jb2x1bW4tc3RhcnQ6IHJhbmRvbUlEJ1xcbk9yIHVzZSAnRml4IE1pc3NpbmcgSURzJyBpbiB0aGUgY29tbWFuZCBwYWxldHRlIGFuZCByZWxvYWQgdGhlIGRvY3VtZW50LlwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW5kZXJFcnJvclJlZ2lvbi5pbm5lclRleHQgPSBcIlJlZ2lvbiBJRCBhbHJlYWR5IGV4aXN0cyBpbiBkb2N1bWVudCwgcGxlYXNlIHNldCBhIHVuaXF1ZSBJRC5cXG5FRzogJz09PSBtdWx0aS1jb2x1bW4tc3RhcnQ6IHJhbmRvbUlEJ1wiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGVsLmlkID0gYE11bHRpQ29sdW1uSUQ6JHtyZWdpb25LZXl9YFxyXG5cclxuICAgICAgICAgICAgICAgIGxldCBlbGVtZW50TWFya2Rvd25SZW5kZXJlciA9IG5ldyBNYXJrZG93blJlbmRlckNoaWxkKGVsKTtcclxuICAgICAgICAgICAgICAgIGZpbGVET01NYW5hZ2VyLmNyZWF0ZVJlZ2lvbmFsTWFuYWdlcihyZWdpb25LZXksIGVsLCByZW5kZXJFcnJvclJlZ2lvbiwgcmVuZGVyQ29sdW1uUmVnaW9uKTtcclxuICAgICAgICAgICAgICAgIGVsZW1lbnRNYXJrZG93blJlbmRlcmVyLm9udW5sb2FkID0gKCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgIGlmKGZpbGVET01NYW5hZ2VyKSB7XHJcbiAgICBcclxuICAgICAgICAgICAgICAgICAgICAgICAgZmlsZURPTU1hbmFnZXIucmVtb3ZlUmVnaW9uKHN0YXJ0QmxvY2tEYXRhLnN0YXJ0QmxvY2tLZXkpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH07XHJcbiAgICAgICAgICAgICAgICBjdHguYWRkQ2hpbGQoZWxlbWVudE1hcmtkb3duUmVuZGVyZXIpO1xyXG5cclxuICAgICAgICAgICAgICAgIC8qKlxyXG4gICAgICAgICAgICAgICAgICogTm93IHdlIGhhdmUgY3JlYXRlZCBvdXIgcmVnaW9uYWwgbWFuYWdlciBhbmQgZGVmaW5lZCB3aGF0IGVsZW1lbnRzIFxyXG4gICAgICAgICAgICAgICAgICogbmVlZCB0byBiZSByZW5kZXJlZCBpbnRvLiBTbyB3ZSBjYW4gcmV0dXJuIHdpdGhvdXQgYW55IG1vcmUgcHJvY2Vzc2luZy5cclxuICAgICAgICAgICAgICAgICAqL1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuXHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgLy8jZW5kcmVnaW9uIERlcHJlY2lhdGVkIFN0YXJ0IFRhZ1xyXG5cclxuICAgICAgICAgICAgLyoqXHJcbiAgICAgICAgICAgICAqIENoZWNrIGlmIGFueSBvZiB0aGUgbGluZXMgYWJvdmUgdXMgY29udGFpbiBhIHN0YXJ0IGJsb2NrLCBhbmQgaWZcclxuICAgICAgICAgICAgICogc28gZ2V0IHRoZSBsaW5lcyBmcm9tIG91ciBjdXJyZW50IGVsZW1lbnQgdG8gdGhlIHN0YXJ0IGJsb2NrLlxyXG4gICAgICAgICAgICAgKi9cclxuICAgICAgICAgICAgbGV0IHN0YXJ0Qm9ja0Fib3ZlID0gbXVsdGlDb2x1bW5QYXJzZXIuZ2V0U3RhcnRCbG9ja09yQ29kZWJsb2NrQWJvdmVMaW5lKGxpbmVzQWJvdmVBcnJheSk7XHJcbiAgICAgICAgICAgIGlmKHN0YXJ0Qm9ja0Fib3ZlID09PSBudWxsKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgLyoqXHJcbiAgICAgICAgICAgICAqIFdlIG5vdyBrbm93IHdlJ3JlIHdpdGhpbiBhIG11bHRpLWNvbHVtbiByZWdpb24sIHNvIHdlIHVwZGF0ZSBvdXJcclxuICAgICAgICAgICAgICogbGlzdCBvZiBsaW5lcyBhYm92ZSB0byBqdXN0IGJlIHRoZSBpdGVtcyB3aXRoaW4gdGhpcyByZWdpb24uXHJcbiAgICAgICAgICAgICAqL1xyXG4gICAgICAgICAgICBsaW5lc0Fib3ZlQXJyYXkgPSBzdGFydEJvY2tBYm92ZS5saW5lc0Fib3ZlQXJyYXk7XHJcblxyXG4gICAgICAgICAgICAvKipcclxuICAgICAgICAgICAgICogV2UgdXNlIHRoZSBzdGFydCBibG9jaydzIGtleSB0byBnZXQgb3VyIHJlZ2lvbmFsIG1hbmFnZXIuIElmIHRoaXNcclxuICAgICAgICAgICAgICogbG9va3VwIGZhaWxzIHdlIGNhbiBub3QgY29udGludWUgcHJvY2Vzc2luZyB0aGlzIGVsZW1lbnQuXHJcbiAgICAgICAgICAgICAqL1xyXG4gICAgICAgICAgICBsZXQgcmVnaW9uYWxDb250YWluZXI6IFJlZ2lvbk1hbmFnZXJDb250YWluZXIgPSBmaWxlRE9NTWFuYWdlci5nZXRSZWdpb25hbENvbnRhaW5lcihzdGFydEJvY2tBYm92ZS5zdGFydEJsb2NrS2V5KTtcclxuICAgICAgICAgICAgaWYocmVnaW9uYWxDb250YWluZXIgPT09IG51bGwpIHtcclxuICAgICAgICAgICAgICAgIHJldHVyblxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGxldCByZWdpb25hbE1hbmFnZXI6IFJlZ2lvbk1hbmFnZXIgPSByZWdpb25hbENvbnRhaW5lci5nZXRSZWdpb24oKTtcclxuXHJcbiAgICAgICAgICAgIC8qKlxyXG4gICAgICAgICAgICAgKiBUbyBtYWtlIHN1cmUgd2UncmUgcGxhY2luZyB0aGUgaXRlbSBpbiB0aGUgcmlnaHQgbG9jYXRpb24gKGFuZCBcclxuICAgICAgICAgICAgICogb3ZlcndyaXRlIGVsZW1lbnRzIHRoYXQgYXJlIG5vdyBnb25lKSB3ZSBub3cgd2FudCBhbGwgb2YgdGhlXHJcbiAgICAgICAgICAgICAqIGxpbmVzIGFmdGVyIHRoaXMgZWxlbWVudCB1cCB0byB0aGUgZW5kIHRhZy5cclxuICAgICAgICAgICAgICovXHJcbiAgICAgICAgICAgIGxpbmVzQmVsb3dBcnJheSA9ICBtdWx0aUNvbHVtblBhcnNlci5nZXRFbmRCbG9ja0JlbG93KGxpbmVzQmVsb3dBcnJheSk7XHJcblxyXG4gICAgICAgICAgICAvKipcclxuICAgICAgICAgICAgICogTm93IHdlIHRha2UgdGhlIGxpbmVzIGFib3ZlIG91ciBjdXJyZW50IGVsZW1lbnQgdXAgdW50aWwgdGhlXHJcbiAgICAgICAgICAgICAqIHN0YXJ0IHJlZ2lvbiB0YWcgYW5kIHJlbmRlciB0aGF0IGludG8gYW4gSFRNTCBlbGVtZW50LiBXZSB3aWxsIFxyXG4gICAgICAgICAgICAgKiB1c2UgdGhlc2UgZWxlbWVudHMgdG8gZGV0ZXJtaW5lIHdoZXJlIHRvIHBsYWNlIG91ciBjdXJyZW50IGVsZW1lbnQuXHJcbiAgICAgICAgICAgICAqL1xyXG4gICAgICAgICAgICBsZXQgc2libGluZ3NBYm92ZTogSFRNTERpdkVsZW1lbnQgPSByZW5kZXJNYXJrZG93bkZyb21MaW5lcyhsaW5lc0Fib3ZlQXJyYXksIHNvdXJjZVBhdGgpO1xyXG5cclxuICAgICAgICAgICAgbGV0IHNpYmxpbmdzQmVsb3c6IEhUTUxEaXZFbGVtZW50ID0gcmVuZGVyTWFya2Rvd25Gcm9tTGluZXMobGluZXNCZWxvd0FycmF5LCBzb3VyY2VQYXRoKTtcclxuXHJcbiAgICAgICAgICAgIC8qKlxyXG4gICAgICAgICAgICAgKiBTZXQgdXAgb3VyIGRvbSBvYmplY3QgdG8gYmUgYWRkZWQgdG8gdGhlIG1hbmFnZXIuXHJcbiAgICAgICAgICAgICAqL1xyXG4gICAgICAgICAgICBsZXQgY3VycmVudE9iamVjdDogRE9NT2JqZWN0ID0gbmV3IERPTU9iamVjdChlbCwgbGluZXNPZkVsZW1lbnQpXHJcbiAgICAgICAgICAgIGVsLmlkID0gY3VycmVudE9iamVjdC5VSUQ7XHJcblxyXG4gICAgICAgICAgICBjdXJyZW50T2JqZWN0ID0gVGFza0xpc3RET01PYmplY3QuY2hlY2tGb3JUYXNrTGlzdEVsZW1lbnQoY3VycmVudE9iamVjdClcclxuXHJcbiAgICAgICAgICAgIC8qKlxyXG4gICAgICAgICAgICAgKiBOb3cgd2UgYWRkIHRoZSBvYmplY3QgdG8gdGhlIG1hbmFnZXIgYW5kIHRoZW4gc2V0dXAgdGhlXHJcbiAgICAgICAgICAgICAqIGNhbGxiYWNrIGZvciB3aGVuIHRoZSBvYmplY3QgaXMgcmVtb3ZlZCBmcm9tIHZpZXcgdGhhdCB3aWxsIHJlbW92ZSBcclxuICAgICAgICAgICAgICogdGhlIGl0ZW0gZnJvbSB0aGUgbWFuYWdlci5cclxuICAgICAgICAgICAgICovXHJcbiAgICAgICAgICAgIGxldCBhZGRJbmRleCA9IHJlZ2lvbmFsTWFuYWdlci5hZGRPYmplY3Qoc2libGluZ3NBYm92ZSwgc2libGluZ3NCZWxvdywgY3VycmVudE9iamVjdCk7XHJcblxyXG4gICAgICAgICAgICBsZXQgZWxlbWVudE1hcmtkb3duUmVuZGVyZXIgPSBuZXcgTWFya2Rvd25SZW5kZXJDaGlsZChlbCk7XHJcbiAgICAgICAgICAgIGVsZW1lbnRNYXJrZG93blJlbmRlcmVyLm9udW5sb2FkID0gKCkgPT4ge1xyXG5cclxuICAgICAgICAgICAgICAgIGlmKHJlZ2lvbmFsQ29udGFpbmVyID09PSBudWxsKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuXHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBcclxuICAgICAgICAgICAgICAgIGxldCByZWdpb25hbE1hbmFnZXI6IFJlZ2lvbk1hbmFnZXIgPSByZWdpb25hbENvbnRhaW5lci5nZXRSZWdpb24oKTtcclxuICAgICAgICAgICAgICAgIGlmKHJlZ2lvbmFsTWFuYWdlcikge1xyXG4gICAgICAgICAgICAgICAgICAgIFxyXG4gICAgICAgICAgICAgICAgICAgIC8vIFdlIGNhbiBhdHRlbXB0IHRvIHVwZGF0ZSB0aGUgdmlldyBoZXJlIGFmdGVyIHRoZSBpdGVtIGlzIHJlbW92ZWRcclxuICAgICAgICAgICAgICAgICAgICAvLyBidXQgbmVlZCB0byBnZXQgdGhlIGl0ZW0ncyBwYXJlbnQgZWxlbWVudCBiZWZvcmUgcmVtb3Zpbmcgb2JqZWN0IGZyb20gbWFuYWdlci5cclxuICAgICAgICAgICAgICAgICAgICBsZXQgcmVnaW9uUmVuZGVyRGF0YTogTXVsdGlDb2x1bW5SZW5kZXJEYXRhID0gcmVnaW9uYWxNYW5hZ2VyLmdldFJlZ2lvblJlbmRlckRhdGEoKTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgcmVnaW9uYWxNYW5hZ2VyLnJlbW92ZU9iamVjdChjdXJyZW50T2JqZWN0LlVJRCk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIC8qKlxyXG4gICAgICAgICAgICAgICAgICAgICAqIE5lZWQgdG8gY2hlY2sgaGVyZSBpZiBlbGVtZW50IGlzIG51bGwgYXMgdGhpcyBjbG9zdXJlIHdpbGwgYmUgY2FsbGVkXHJcbiAgICAgICAgICAgICAgICAgICAgICogcmVwZWF0ZWRseSBvbiBmaWxlIGNoYW5nZS5cclxuICAgICAgICAgICAgICAgICAgICAgKi9cclxuICAgICAgICAgICAgICAgICAgICBpZihyZWdpb25SZW5kZXJEYXRhLnBhcmVudFJlbmRlckVsZW1lbnQgPT09IG51bGwpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICByZWdpb25hbE1hbmFnZXIucmVuZGVyUmVnaW9uRWxlbWVudHNUb1NjcmVlbigpXHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH07XHJcbiAgICAgICAgICAgIGN0eC5hZGRDaGlsZChlbGVtZW50TWFya2Rvd25SZW5kZXJlcik7XHJcblxyXG4gICAgICAgICAgICAvKipcclxuICAgICAgICAgICAgICogTm93IHdlIGNoZWNrIGlmIG91ciBjdXJyZW50IGVsZW1lbnQgaXMgYSBzcGVjaWFsIGZsYWcgc28gd2UgY2FuXHJcbiAgICAgICAgICAgICAqIHByb3Blcmx5IHNldCB0aGUgZWxlbWVudCB0YWcgd2l0aGluIHRoZSByZWdpb25hbCBtYW5hZ2VyLlxyXG4gICAgICAgICAgICAgKi9cclxuICAgICAgICAgICAgaWYobXVsdGlDb2x1bW5QYXJzZXIuY29udGFpbnNFbmRUYWcoZWwudGV4dENvbnRlbnQpID09PSB0cnVlKSB7XHJcblxyXG4gICAgICAgICAgICAgICAgY3VycmVudE9iamVjdC5lbGVtZW50VHlwZSA9IEVsZW1lbnRSZW5kZXJUeXBlLnVuUmVuZGVyZWRcclxuICAgICAgICAgICAgICAgIGVsLmFkZENsYXNzKE11bHRpQ29sdW1uU3R5bGVDU1MuUmVnaW9uRW5kVGFnKVxyXG4gICAgICAgICAgICAgICAgcmVnaW9uYWxNYW5hZ2VyLnVwZGF0ZUVsZW1lbnRUYWcoY3VycmVudE9iamVjdC5VSUQsIERPTU9iamVjdFRhZy5lbmRSZWdpb24pO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGVsc2UgaWYobXVsdGlDb2x1bW5QYXJzZXIuY29udGFpbnNDb2xFbmRUYWcodGV4dE9mRWxlbWVudCkgPT09IHRydWUpIHtcclxuXHJcbiAgICAgICAgICAgICAgICBjdXJyZW50T2JqZWN0LmVsZW1lbnRUeXBlID0gRWxlbWVudFJlbmRlclR5cGUudW5SZW5kZXJlZFxyXG4gICAgICAgICAgICAgICAgZWwuYWRkQ2xhc3MoTXVsdGlDb2x1bW5TdHlsZUNTUy5Db2x1bW5FbmRUYWcpXHJcbiAgICAgICAgICAgICAgICByZWdpb25hbE1hbmFnZXIudXBkYXRlRWxlbWVudFRhZyhjdXJyZW50T2JqZWN0LlVJRCwgRE9NT2JqZWN0VGFnLmNvbHVtbkJyZWFrKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBlbHNlIGlmKG11bHRpQ29sdW1uUGFyc2VyLmNvbnRhaW5zQ29sU2V0dGluZ3NUYWcodGV4dE9mRWxlbWVudCkgPT09IHRydWUpIHtcclxuXHJcbiAgICAgICAgICAgICAgICBjdXJyZW50T2JqZWN0LmVsZW1lbnRUeXBlID0gRWxlbWVudFJlbmRlclR5cGUudW5SZW5kZXJlZFxyXG4gICAgICAgICAgICAgICAgZWwuYWRkQ2xhc3MoTXVsdGlDb2x1bW5TdHlsZUNTUy5SZWdpb25TZXR0aW5ncylcclxuICAgICAgICAgICAgICAgIHJlZ2lvbmFsTWFuYWdlciA9IHJlZ2lvbmFsQ29udGFpbmVyLnNldFJlZ2lvblNldHRpbmdzKHRleHRPZkVsZW1lbnQpXHJcbiAgICAgICAgICAgICAgICByZWdpb25hbE1hbmFnZXIudXBkYXRlRWxlbWVudFRhZyhjdXJyZW50T2JqZWN0LlVJRCwgRE9NT2JqZWN0VGFnLnJlZ2lvblNldHRpbmdzKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgICAgIGVsLmFkZENsYXNzKE11bHRpQ29sdW1uU3R5bGVDU1MuUmVnaW9uQ29udGVudClcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBcclxuICAgICAgICAgICAgcmVnaW9uYWxNYW5hZ2VyLnJlbmRlclJlZ2lvbkVsZW1lbnRzVG9TY3JlZW4oKVxyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBpc1N0YXJ0Q29kZWJsb2NrSW5FeHBvcnQobm9kZTogSFRNTEVsZW1lbnQpOiBib29sZWFuIHtcclxuXHJcbiAgICAgICAgZm9yKGxldCBpID0gMDsgaSA8IENPREVCTE9DS19TVEFSVF9TVFJTLmxlbmd0aDsgaSsrKSB7XHJcblxyXG4gICAgICAgICAgICBpZihub2RlLmhhc0NsYXNzKGBibG9jay1sYW5ndWFnZS0ke0NPREVCTE9DS19TVEFSVF9TVFJTW2ldfWApKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBhc3luYyBleHBvcnREb2N1bWVudFRvUERGKGVsOiBIVE1MRWxlbWVudCwgZmlsZURPTU1hbmFnZXI6IEZpbGVET01NYW5hZ2VyLCBzb3VyY2VQYXRoOiBzdHJpbmcpIHtcclxuXHJcbiAgICAgICAgLy8gQSB0cnVlIGV4cG9ydCB3aWxsIGJlIHBhc3NlZCBhbiBlbGVtZW50IHdpdGggYWxsIG90aGVyIGl0ZW1zIGluIHRoZSBkb2MgYXMgY2hpbGRyZW4uIFxyXG4gICAgICAgIC8vIFNvIGlmIHRoZXJlIGFyZSBubyBjaGlsZHJlbiB3ZSBjYW4ganVzdCByZXR1cm5cclxuICAgICAgICBsZXQgZG9jQ2hpbGRyZW4gPSBBcnJheS5mcm9tKGVsLmNoaWxkTm9kZXMpO1xyXG4gICAgICAgIGlmKGRvY0NoaWxkcmVuLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBsZXQgY2hpbGRyZW5Ub1JlbW92ZSA9IFtdO1xyXG4gICAgICAgIFxyXG4gICAgICAgIC8vIFRvIGV4cG9ydCBjb2RlYmxvY2tzIHdlIG5lZWQgdG8gZ2V0IHRoZSBJRHMgc28gd2UgY2FuIGdldCB0aGUgZGF0YSBmcm9tIG91ciBtYW5hZ2Vycy5cclxuICAgICAgICAvLyBob3dldmVyIHNpbmNlIHRoZSBJRCBpc250IGJlaW5nIHN0b3JlZCBpbiB0aGUgZWxlbWVudCB5ZXQgdGhpcyBtZWFucyB3ZSBuZWVkIHRvIHJlYWRcclxuICAgICAgICAvLyBhbGwgb2YgdGhlIElEcyBvdXQgb2YgdGhlIGZ1bGwgZG9jdW1lbnQuXHJcbiAgICAgICAgbGV0IGNvZGVibG9ja1N0YXJ0QmxvY2tzID0gW11cclxuICAgICAgICBsZXQgYUZpbGUgPSB0aGlzLmFwcC52YXVsdC5nZXRBYnN0cmFjdEZpbGVCeVBhdGgoc291cmNlUGF0aCk7XHJcbiAgICAgICAgaWYoYUZpbGUgaW5zdGFuY2VvZiBURmlsZSkge1xyXG5cclxuICAgICAgICAgICAgbGV0IGZpbGUgPSBhRmlsZSBhcyBURmlsZVxyXG4gICAgICAgICAgICBsZXQgZmlsZVRleHQgPSBhd2FpdCB0aGlzLmFwcC52YXVsdC5jYWNoZWRSZWFkKGZpbGUpIC8vIElzIGNhY2hlZCByZWFkIE9rIGhlcmU/IEl0IHNob3VsZCBiZS5cclxuXHJcbiAgICAgICAgICAgIC8vIE9uY2Ugd2UgaGF2ZSBvdXIgZGF0YSB3ZSBzZWFyY2ggdGhlIHRleHQgZm9yIGFsbCBjb2RlYmxvY2sgc3RhcnQgdmFsdWVzLlxyXG4gICAgICAgICAgICAvLyBzdG9yaW5nIHRoZW0gaW50byBvdXIgcXVldWUuXHJcbiAgICAgICAgICAgIGxldCBjb2RlQmxvY2tEYXRhID0gbXVsdGlDb2x1bW5QYXJzZXIuZmluZFN0YXJ0Q29kZWJsb2NrKGZpbGVUZXh0KTtcclxuICAgICAgICAgICAgd2hpbGUoY29kZUJsb2NrRGF0YS5mb3VuZCA9PT0gdHJ1ZSkge1xyXG5cclxuICAgICAgICAgICAgICAgIGxldCBjb2RlYmxvY2tUZXh0ID0gZmlsZVRleHQuc2xpY2UoY29kZUJsb2NrRGF0YS5zdGFydFBvc2l0aW9uLCBjb2RlQmxvY2tEYXRhLmVuZFBvc2l0aW9uKTtcclxuICAgICAgICAgICAgICAgIGZpbGVUZXh0ID0gZmlsZVRleHQuc2xpY2UoY29kZUJsb2NrRGF0YS5lbmRQb3NpdGlvbik7XHJcbiAgICAgICAgICAgICAgICBjb2RlYmxvY2tTdGFydEJsb2Nrcy5wdXNoKGNvZGVibG9ja1RleHQpO1xyXG5cclxuICAgICAgICAgICAgICAgIGNvZGVCbG9ja0RhdGEgPSBtdWx0aUNvbHVtblBhcnNlci5maW5kU3RhcnRDb2RlYmxvY2soZmlsZVRleHQpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKGBFcnJvciBnZXR0aW5nIGZpbGUgZnJvbSBzb3VyY2UgcGF0aDogJHtzb3VyY2VQYXRofWApXHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBsZXQgaW5CbG9jayA9IGZhbHNlO1xyXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZG9jQ2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcclxuXHJcbiAgICAgICAgICAgIGxldCBjaGlsZCA9IGRvY0NoaWxkcmVuW2ldO1xyXG4gICAgICAgICAgICBpZiAoY2hpbGQgaW5zdGFuY2VvZiBIVE1MRWxlbWVudCkge1xyXG4gICAgICAgICAgICAgICAgbGV0IGNoaWxkRWwgPSBjaGlsZCBhcyBIVE1MRWxlbWVudDtcclxuICAgICAgICAgICAgICAgIGlmIChpbkJsb2NrID09PSBmYWxzZSkge1xyXG4gICAgICAgICAgICAgICAgICAgIFxyXG4gICAgICAgICAgICAgICAgICAgIGxldCBmb3VuZEJsb2NrRGF0YSA9IGZhbHNlO1xyXG4gICAgICAgICAgICAgICAgICAgIGxldCByZWdpb25LZXkgPSBcIlwiO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICBsZXQgYmxvY2tEYXRhID0gbXVsdGlDb2x1bW5QYXJzZXIuaXNTdGFydFRhZ1dpdGhJRChjaGlsZC50ZXh0Q29udGVudCk7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKGJsb2NrRGF0YS5pc1N0YXJ0VGFnID09PSB0cnVlKSB7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBJZiBhbiBvbGQtc3R5bGUgc3RhcnQgdGFnLlxyXG4gICAgICAgICAgICAgICAgICAgICAgICBmb3VuZEJsb2NrRGF0YSA9IHRydWU7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChibG9ja0RhdGEuaGFzS2V5ID09PSB0cnVlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgZm91bmRLZXkgPSBtdWx0aUNvbHVtblBhcnNlci5nZXRTdGFydFRhZ0tleShjaGlsZC50ZXh0Q29udGVudCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZm91bmRLZXkgIT09IG51bGwpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWdpb25LZXkgPSBmb3VuZEtleTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICBlbHNlIGlmKGJsb2NrRGF0YS5pc1N0YXJ0VGFnID09PSBmYWxzZSAmJiB0aGlzLmlzU3RhcnRDb2RlYmxvY2tJbkV4cG9ydChjaGlsZCkpIHtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIElmIHRoZSBzdGFydCB0YWcgZnJvbSB0aGUgb2xkIHZlcnNpb24gaXMgbnVsbCB3ZSB0aGVuIGNoZWNrIHRvIHNlZSBpZiB0aGUgZWxlbWVudCBpc1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBhIGNvZGVibG9jayBzdGFydC4gSWYgaXQgaXMgd2UgdXNlIHRoZSBuZXh0IGF2YWlsYWJsZSBjb2RlYmxvY2sgZGF0YSB0byByZXRyaWV2ZSBvdXIgSUQuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBjb2RlYmxvY2tUZXh0ID0gY29kZWJsb2NrU3RhcnRCbG9ja3Muc2hpZnQoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYoY29kZWJsb2NrVGV4dCA9PT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKFwiRm91bmQgdW5kZWZpbmVkIGNvZGVibG9jayBkYXRhIHdoZW4gZXhwb3J0aW5nLlwiKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgaWQgPSBwYXJzZVN0YXJ0UmVnaW9uQ29kZUJsb2NrSUQoY29kZWJsb2NrVGV4dCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKGlkICE9PSBcIlwiKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3VuZEJsb2NrRGF0YSA9IHRydWU7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWdpb25LZXkgPSBpZDtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgaWYoZm91bmRCbG9ja0RhdGEgPT09IHRydWUgJiYgcmVnaW9uS2V5ICE9PSBcIlwiKSB7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBpbkJsb2NrID0gdHJ1ZTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSBjaGlsZC5jaGlsZHJlbi5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGQuY2hpbGRyZW5baV0uZGV0YWNoKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGQuaW5uZXJUZXh0ID0gXCJcIjtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkLmNsYXNzTGlzdC5hZGQoTXVsdGlDb2x1bW5MYXlvdXRDU1MuUmVnaW9uUm9vdENvbnRhaW5lckRpdik7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCByZW5kZXJFcnJvclJlZ2lvbiA9IGNoaWxkLmNyZWF0ZURpdih7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbHM6IGAke011bHRpQ29sdW1uTGF5b3V0Q1NTLlJlZ2lvbkVycm9yQ29udGFpbmVyRGl2fSwgJHtNdWx0aUNvbHVtblN0eWxlQ1NTLlJlZ2lvbkVycm9yTWVzc2FnZX1gLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHJlbmRlckNvbHVtblJlZ2lvbiA9IGNoaWxkLmNyZWF0ZURpdih7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbHM6IE11bHRpQ29sdW1uTGF5b3V0Q1NTLlJlZ2lvbkNvbnRlbnRDb250YWluZXJEaXZcclxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XHJcblxyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHJlZ2lvbmFsQ29udGFpbmVyOiBSZWdpb25NYW5hZ2VyQ29udGFpbmVyID0gZmlsZURPTU1hbmFnZXIuZ2V0UmVnaW9uYWxDb250YWluZXIocmVnaW9uS2V5KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJlZ2lvbmFsQ29udGFpbmVyID09PSBudWxsIHx8IHJlZ2lvbmFsQ29udGFpbmVyLmdldFJlZ2lvbigpLm51bWJlck9mQ2hpbGRyZW4gPT09IDApIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIElmIHRoZSBudW1iZXIgb2YgY2hpbGRyZW4gaXMgMCwgd2UgYXJlIHByb2JhYmx5IGluIExpdmVQcmV2aWV3LCB3aGVyZSB0aGUgY29kZWJsb2NrIHN0YXJ0IHJlZ2lvbnMgaGF2ZSBiZWVuIHByb2Nlc3NlZCBieSBuYXRpdmUgb2JzaWRpYW4gbGl2ZSBwcmV2aWV3IGJ1dCBkbyBub3QgaGF2ZSBhbnkgY2hpbGRyZW4gbGlua2VkIHRvIHRoZW0uXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW5kZXJFcnJvclJlZ2lvbi5pbm5lclRleHQgPSBcIkVycm9yIHJlbmRlcmluZyBtdWx0aS1jb2x1bW4gcmVnaW9uLlxcblBsZWFzZSBjbG9zZSBhbmQgcmVvcGVuIHRoZSBmaWxlLCB0aGVuIG1ha2Ugc3VyZSB5b3UgYXJlIGluIHJlYWRpbmcgbW9kZSBiZWZvcmUgZXhwb3J0aW5nLlwiO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHJlZ2lvbmFsTWFuYWdlcjogUmVnaW9uTWFuYWdlciA9IHJlZ2lvbmFsQ29udGFpbmVyLmdldFJlZ2lvbigpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVnaW9uYWxNYW5hZ2VyLmV4cG9ydFJlZ2lvbkVsZW1lbnRzVG9QREYocmVuZGVyQ29sdW1uUmVnaW9uKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGVsc2Uge1xyXG5cclxuICAgICAgICAgICAgICAgICAgICBpZiAobXVsdGlDb2x1bW5QYXJzZXIuY29udGFpbnNFbmRUYWcoY2hpbGQudGV4dENvbnRlbnQpID09PSB0cnVlKSB7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBpbkJsb2NrID0gZmFsc2U7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICBjaGlsZHJlblRvUmVtb3ZlLnB1c2goY2hpbGQpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjaGlsZHJlblRvUmVtb3ZlLmZvckVhY2goY2hpbGQgPT4ge1xyXG4gICAgICAgICAgICBpZihjaGlsZC5wYXJlbnRFbGVtZW50ID09PSBlbCkge1xyXG4gICAgICAgICAgICAgICAgZWwucmVtb3ZlQ2hpbGQoY2hpbGQpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgY2hlY2tFeHBvcnRpbmcoZWxlbWVudDogSFRNTEVsZW1lbnQpOiBib29sZWFuIHtcclxuXHJcbiAgICAgICAgaWYoZWxlbWVudCA9PT0gbnVsbCkge1xyXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZihlbGVtZW50LmNsYXNzTGlzdC5jb250YWlucyhcInByaW50XCIpKSB7XHJcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYoZWxlbWVudC5wYXJlbnROb2RlICE9PSBudWxsKSB7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNoZWNrRXhwb3J0aW5nKGVsZW1lbnQucGFyZW50RWxlbWVudCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICB9XHJcblxyXG4gICAgc2V0dXBNYXJrZG93bkNvZGVibG9ja1Bvc3RQcm9jZXNzb3Ioc3RhcnRTdHI6IHN0cmluZykge1xyXG5cclxuICAgICAgICB0aGlzLnJlZ2lzdGVyTWFya2Rvd25Db2RlQmxvY2tQcm9jZXNzb3Ioc3RhcnRTdHIsIChzb3VyY2UsIGVsLCBjdHgpID0+IHtcclxuXHJcbiAgICAgICAgICAgIGlmKHRoaXMuc2V0dGluZ3MucmVuZGVyT25Nb2JpbGUgPT09IGZhbHNlICYmXHJcbiAgICAgICAgICAgICAgICBQbGF0Zm9ybS5pc01vYmlsZSA9PT0gdHJ1ZSkge1xyXG4gXHJcbiAgICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBjb25zdCBzb3VyY2VQYXRoID0gY3R4LnNvdXJjZVBhdGg7XHJcbiAgICAgICAgXHJcbiAgICAgICAgICAgIC8vIFNldCB1cCBvdXIgQ1NTIHNvIHRoYXQgdGhlIGNvZGVibG9jayBvbmx5IHJlbmRlcnMgdGhpcyBkYXRhIGluIHJlYWRpbmcgbW9kZVxyXG4gICAgICAgICAgICAvLyBzb3VyY2UvbGl2ZSBwcmV2aWV3IG1vZGUgaXMgaGFuZGxlZCBieSB0aGUgQ002IGltcGxlbWVudGF0aW9uLlxyXG4gICAgICAgICAgICBlbC5wYXJlbnRFbGVtZW50Py5hZGRDbGFzcyhcInByZWl2ZXctbWNtLXN0YXJ0LWJsb2NrXCIpO1xyXG4gICAgICAgIFxyXG4gICAgICAgICAgICAvLyBUbyBkZXRlcm1pbmUgd2hhdCBraW5kIG9mIHZpZXcgd2UgYXJlIHJlbmRlcmluZyBpbiB3ZSBuZWVkIGEgbWFya2Rvd24gbGVhZi5cclxuICAgICAgICAgICAgLy8gUmVhbGx5IHRoaXMgc2hvdWxkIG5ldmVyIHJldHVybiBoZXJlIHNpbmNlIHJlbmRlcmluZyBpcyBvbmx5IGRvbmUgaW4gbWFya2Rvd24gbGVhdmVzLlxyXG4gICAgICAgICAgICBsZXQgbWFya2Rvd25MZWF2ZXMgPSBhcHAud29ya3NwYWNlLmdldExlYXZlc09mVHlwZShcIm1hcmtkb3duXCIpO1xyXG4gICAgICAgICAgICBpZihtYXJrZG93bkxlYXZlcy5sZW5ndGggPT09IDApIHtcclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIFxyXG4gICAgICAgICAgICAvLyBDaGVjayB0aGUgdHlwZSBvZiB0aGUgbGVhZlxyXG4gICAgICAgICAgICBsZXQgZm91bmRGaWxlTGVhZiA9IGZhbHNlO1xyXG4gICAgICAgICAgICBmb3IobGV0IGkgPSAwOyBpIDwgbWFya2Rvd25MZWF2ZXMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICBcclxuICAgICAgICAgICAgICAgIGxldCBmaWxlTGVhZiA9IGdldEZpbGVMZWFmKHNvdXJjZVBhdGgpO1xyXG4gICAgICAgICAgICAgICAgaWYoZmlsZUxlYWYgPT09IG51bGwpIHtcclxuICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGZvdW5kRmlsZUxlYWYgPSB0cnVlO1xyXG4gICAgICAgIFxyXG4gICAgICAgICAgICAgICAgaWYoZ2V0TGVhZlNvdXJjZU1vZGUoZmlsZUxlYWYpID09PSBcInNvdXJjZVwiKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgLy8gVGhpcyB3YXMgYWRkZWQgd2hlbiBpbXBsZW1lbnRpbmcgbGl2ZSBwcmV2aWV3LCBidXQgdGhlIHJlYXNvbiBpdCB3YXMgb3JpZ2luYWxseSBhZGRlZCBhcHBlYXJzIHRvIG5vIGxvbmdlciBiZSBhbiBpc3N1ZS5cclxuICAgICAgICAgICAgICAgICAgICAvLyBSZW1vdmluZyB0aGUgcmV0dXJuIGZyb20gaGVyZSB0byBmaXggYnVnIHdoZXJlIG9wZW5pbmcgbXVsdGlwbGUgY29waWVzIG9mIHRoZSBkb2N1bWVudCBjYXVzZXMgcmVnaW9ucyB0byBub3QgcmVuZGVyLlxyXG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZGVidWcoXCJMZWFmIG9mIGZpbGUgaXMgaW4gc291cmNlIG1vZGUuIFNob3VsZCB3ZSBiZSBpZ25vcmluZyBwb3N0IHByb2Nlc3NpbmcgaGVyZT9cIilcclxuICAgICAgICAgICAgICAgICAgICAvLyByZXR1cm47XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICBcclxuICAgICAgICAgICAgaWYodGhpcy5nbG9iYWxNYW5hZ2VyID09PSBudWxsIHx8IHRoaXMuZ2xvYmFsTWFuYWdlciA9PT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhcIkdsb2JhbCBtYW5hZ2VyIGlzIHVuZGVmaW5lZD9cIik7XHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGxldCBmaWxlRE9NTWFuYWdlciA9IHRoaXMuZ2xvYmFsTWFuYWdlci5nZXRGaWxlTWFuYWdlcihzb3VyY2VQYXRoKTtcclxuICAgICAgICAgICAgaWYoZmlsZURPTU1hbmFnZXIgPT09IG51bGwpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBcclxuICAgICAgICAgICAgLy8gU2V0IGZpbGUgdG8gaGF2ZSBzdGFydCB0YWcuXHJcbiAgICAgICAgICAgIGZpbGVET01NYW5hZ2VyLnNldEhhc1N0YXJ0VGFnKCk7XHJcbiAgICAgICAgXHJcbiAgICAgICAgICAgIC8vIEdldCB0aGUgaW5mbyBmb3Igb3VyIGN1cnJlbnQgY29udGV4dCBhbmQgdGhlbiBjaGVja1xyXG4gICAgICAgICAgICAvLyBpZiB0aGUgZW50aXJlIHRleHQgY29udGFpbnMgYSBzdGFydCB0YWcuIElmIHRoZXJlIGlzXHJcbiAgICAgICAgICAgIC8vIG5vIHN0YXJ0IHRhZyBpbiB0aGUgZG9jdW1lbnQgd2UgY2FuIGp1c3QgcmV0dXJuIGFuZFxyXG4gICAgICAgICAgICAvLyBpZ25vcmUgdGhlIHJlc3Qgb2YgdGhlIHBhcnNpbmcuXHJcbiAgICAgICAgICAgIGxldCBpbmZvID0gY3R4LmdldFNlY3Rpb25JbmZvKGVsKTtcclxuICAgICAgICBcclxuICAgICAgICAgICAgLyoqXHJcbiAgICAgICAgICAgICAqIFdlIG5lZWQgdGhlIGNvbnRleHQgaW5mbyB0byBwcm9wZXJseSBwYXJzZSBzbyByZXR1cm5pbmcgaGVyZSBcclxuICAgICAgICAgICAgICogaW5mbyBpcyBudWxsLiBUT0RPOiBTZXQgZXJyb3IgaW4gdmlldyBpZiB0aGlzIG9jY3Vycy5cclxuICAgICAgICAgICAgICovXHJcbiAgICAgICAgICAgIGlmKCFpbmZvKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICBcclxuICAgICAgICAgICAgLyoqIFxyXG4gICAgICAgICAgICAgKiBTZXQgdXAgdGhlIGN1cnJlbnQgZWxlbWVudCB0byBhY3QgYXMgdGhlIHBhcmVudCBmb3IgdGhlIFxyXG4gICAgICAgICAgICAgKiBtdWx0aS1jb2x1bW4gcmVnaW9uLlxyXG4gICAgICAgICAgICAgKi9cclxuICAgICAgICAgICAgZWwuY2xhc3NMaXN0LmFkZChNdWx0aUNvbHVtbkxheW91dENTUy5SZWdpb25Sb290Q29udGFpbmVyRGl2KVxyXG4gICAgICAgICAgICBsZXQgcmVuZGVyRXJyb3JSZWdpb24gPSBlbC5jcmVhdGVEaXYoe1xyXG4gICAgICAgICAgICAgICAgY2xzOiBgJHtNdWx0aUNvbHVtbkxheW91dENTUy5SZWdpb25FcnJvckNvbnRhaW5lckRpdn0gJHtNdWx0aUNvbHVtblN0eWxlQ1NTLlJlZ2lvbkVycm9yTWVzc2FnZX1gLFxyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgbGV0IHJlbmRlckNvbHVtblJlZ2lvbiA9IGVsLmNyZWF0ZURpdih7XHJcbiAgICAgICAgICAgICAgICBjbHM6IE11bHRpQ29sdW1uTGF5b3V0Q1NTLlJlZ2lvbkNvbnRlbnRDb250YWluZXJEaXZcclxuICAgICAgICAgICAgfSlcclxuICAgICAgICBcclxuICAgICAgICAgICAgbGV0IHJlZ2lvbktleSA9IHBhcnNlU3RhcnRSZWdpb25Db2RlQmxvY2tJRChzb3VyY2UpO1xyXG4gICAgICAgIFxyXG4gICAgICAgICAgICBsZXQgY3JlYXRlTmV3UmVnaW9uTWFuYWdlciA9IHRydWU7XHJcbiAgICAgICAgICAgIGlmKGZpbGVET01NYW5hZ2VyLmNoZWNrS2V5RXhpc3RzKHJlZ2lvbktleSkgPT09IHRydWUpIHtcclxuICAgICAgICAgICAgICAgIFxyXG4gICAgICAgICAgICAgICAgY3JlYXRlTmV3UmVnaW9uTWFuYWdlciA9IGZhbHNlO1xyXG4gICAgICAgICAgICAgICAgbGV0IHsgbnVtYmVyT2ZUYWdzLCBrZXlzIH0gPSBtdWx0aUNvbHVtblBhcnNlci5jb3VudFN0YXJ0VGFncyhpbmZvLnRleHQpO1xyXG4gICAgICAgIFxyXG4gICAgICAgICAgICAgICAgbGV0IG51bU1hdGNoZXMgPSAwO1xyXG4gICAgICAgICAgICAgICAgZm9yKGxldCBpID0gMDsgaSA8IG51bWJlck9mVGFnczsgaSsrKSB7XHJcbiAgICAgICAgXHJcbiAgICAgICAgICAgICAgICAgICAgLy8gQmVjYXVzZSB3ZSBjaGVja2VkIGlmIGtleSBleGlzdHMgb25lIG9mIHRoZXNlIGhhcyB0byBtYXRjaC5cclxuICAgICAgICAgICAgICAgICAgICBpZihrZXlzW2ldID09PSByZWdpb25LZXkpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgbnVtTWF0Y2hlcysrO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICBcclxuICAgICAgICAgICAgICAgIC8vIFdlIG9ubHkgd2FudCB0byBkaXNwbGF5IGFuIGVycm9yIGlmIHRoZXJlIGFyZSBtb3JlIHRoYW4gMiBvZiB0aGUgc2FtZSBpZCBhY3Jvc3NcclxuICAgICAgICAgICAgICAgIC8vIHRoZSB3aG9sZSBkb2N1bWVudC4gVGhpcyBwcmV2ZW50cyBlcnJvcyB3aGVuIG9ic2lkaWFuIHJlbG9hZHMgdGhlIHdob2xlIGRvY3VtZW50XHJcbiAgICAgICAgICAgICAgICAvLyBhbmQgdGhlcmUgYXJlIHR3byBvZiB0aGUgc2FtZSBrZXkgaW4gdGhlIG1hcC5cclxuICAgICAgICAgICAgICAgIGlmKG51bU1hdGNoZXMgPj0gMikge1xyXG4gICAgICAgICAgICAgICAgICAgIGlmKHJlZ2lvbktleSA9PT0gXCJcIikge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICByZW5kZXJFcnJvclJlZ2lvbi5pbm5lclRleHQgPSBcIkZvdW5kIG11bHRpcGxlIHJlZ2lvbnMgd2l0aCBlbXB0eSBJRHMuIFBsZWFzZSBzZXQgYSB1bmlxdWUgSUQgYWZ0ZXIgZWFjaCBzdGFydCB0YWcuXFxuRUc6ICc9PT0gbXVsdGktY29sdW1uLXN0YXJ0OiByYW5kb21JRCdcXG5PciB1c2UgJ0ZpeCBNaXNzaW5nIElEcycgaW4gdGhlIGNvbW1hbmQgcGFsZXR0ZSBhbmQgcmVsb2FkIHRoZSBkb2N1bWVudC5cIlxyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgcmVuZGVyRXJyb3JSZWdpb24uaW5uZXJUZXh0ID0gXCJSZWdpb24gSUQgYWxyZWFkeSBleGlzdHMgaW4gZG9jdW1lbnQsIHBsZWFzZSBzZXQgYSB1bmlxdWUgSUQuXFxuRUc6ICc9PT0gbXVsdGktY29sdW1uLXN0YXJ0OiByYW5kb21JRCdcIlxyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgZWwuaWQgPSBgTXVsdGlDb2x1bW5JRDoke3JlZ2lvbktleX1gXHJcbiAgICAgICAgXHJcbiAgICAgICAgICAgIC8vIElmIHNvbWV0aGluZyBjaGFuZ2VzIGluIHRoZSBjb2RlYmxvY2sgd2UgZG9udCBuZWNlc3NhcmlseSB3YW50IHRvIHVwZGF0ZSBvdXJcclxuICAgICAgICAgICAgLy8gb2xkIHJlZmVyZW5jZSB0byB0aGUgcmVnaW9uIG1hbmFnZXIuIFRoaXMgY291bGQgYmUgYSBwb3RlbnRpYWwgYnVnIGFyZWEuXHJcbiAgICAgICAgICAgIGlmKGNyZWF0ZU5ld1JlZ2lvbk1hbmFnZXIgPT09IHRydWUpIHtcclxuICAgICAgICBcclxuICAgICAgICAgICAgICAgIC8vIENyZWF0ZSBhIG5ldyByZWdpb25hbCBtYW5hZ2VyLlxyXG4gICAgICAgICAgICAgICAgbGV0IGVsZW1lbnRNYXJrZG93blJlbmRlcmVyID0gbmV3IE1hcmtkb3duUmVuZGVyQ2hpbGQoZWwpO1xyXG4gICAgICAgICAgICAgICAgZmlsZURPTU1hbmFnZXIuY3JlYXRlUmVnaW9uYWxNYW5hZ2VyKHJlZ2lvbktleSwgZWwsIHJlbmRlckVycm9yUmVnaW9uLCByZW5kZXJDb2x1bW5SZWdpb24pO1xyXG4gICAgICAgIFxyXG4gICAgICAgICAgICAgICAgLy8gU2V0IHVwIHRoZSBvbiB1bmxvYWQgY2FsbGJhY2suIFRoaXMgY2FuIGJlIGNhbGxlZCBpZiB0aGUgdXNlciBjaGFuZ2VzXHJcbiAgICAgICAgICAgICAgICAvLyB0aGUgc3RhcnQvc2V0dGluZ3MgY29kZWJsb2NrIGluIGFueSB3YXkuIFdlIG9ubHkgd2FudCB0byB1bmxvYWRcclxuICAgICAgICAgICAgICAgIC8vIGlmIHRoZSBmaWxlIGlzIGJlaW5nIHJlbW92ZWQgZnJvbSB2aWV3LlxyXG4gICAgICAgICAgICAgICAgZWxlbWVudE1hcmtkb3duUmVuZGVyZXIub251bmxvYWQgPSAoKSA9PiB7XHJcbiAgICAgICAgXHJcbiAgICAgICAgICAgICAgICAgICAgaWYoZmlsZURPTU1hbmFnZXIgJiYgZmlsZVN0aWxsSW5WaWV3KHNvdXJjZVBhdGgpID09PSBmYWxzZSkge1xyXG4gICAgICAgIFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmRlYnVnKFwiRmlsZSBub3QgaW4gYW55IG1hcmtkb3duIGxlYWYuIFJlbW92aW5nIHJlZ2lvbiBmcm9tIGRvbSBtYW5hZ2VyLlwiKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICBmaWxlRE9NTWFuYWdlci5yZW1vdmVSZWdpb24ocmVnaW9uS2V5KTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9O1xyXG4gICAgICAgICAgICAgICAgY3R4LmFkZENoaWxkKGVsZW1lbnRNYXJrZG93blJlbmRlcmVyKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIFxyXG4gICAgICAgICAgICBsZXQgcmVnaW9uYWxNYW5hZ2VyQ29udGFpbmVyID0gZmlsZURPTU1hbmFnZXIuZ2V0UmVnaW9uYWxDb250YWluZXIocmVnaW9uS2V5KTtcclxuICAgICAgICAgICAgaWYocmVnaW9uYWxNYW5hZ2VyQ29udGFpbmVyICE9PSBudWxsKSB7XHJcbiAgICAgICAgXHJcbiAgICAgICAgICAgICAgICBsZXQgcmVnaW9uYWxNYW5hZ2VyID0gcmVnaW9uYWxNYW5hZ2VyQ29udGFpbmVyLnNldFJlZ2lvblNldHRpbmdzKHNvdXJjZSk7XHJcbiAgICAgICAgICAgICAgICByZWdpb25hbE1hbmFnZXIucmVnaW9uUGFyZW50ID0gZWw7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9KVxyXG4gICAgfVxyXG5cclxuICAgIGFzeW5jIGxvYWRTZXR0aW5ncygpIHtcclxuXHJcblx0XHR0aGlzLnNldHRpbmdzID0gT2JqZWN0LmFzc2lnbih7fSwgREVGQVVMVF9TRVRUSU5HUywgYXdhaXQgdGhpcy5sb2FkRGF0YSgpKTtcclxuXHR9XHJcblxyXG5cdGFzeW5jIHNhdmVTZXR0aW5ncygpIHtcclxuXHRcdGF3YWl0IHRoaXMuc2F2ZURhdGEodGhpcy5zZXR0aW5ncyk7XHJcblx0fVxyXG59XHJcblxyXG5cclxuZXhwb3J0IHR5cGUgbmVhcmJ5U2libGluZ3MgPSB7IFxyXG4gICAgc2libGluZ3NBYm92ZTogSFRNTERpdkVsZW1lbnQsXHJcbiAgICBjdXJyZW50T2JqZWN0OiBET01PYmplY3QsIFxyXG59XHJcbmZ1bmN0aW9uIHJlbmRlck1hcmtkb3duRnJvbUxpbmVzKG1kTGluZXM6IHN0cmluZ1tdLCBzb3VyY2VQYXRoOiBzdHJpbmcpOiBIVE1MRGl2RWxlbWVudCB7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBXZSByZS1yZW5kZXIgYWxsIG9mIHRoZSBpdGVtcyBhYm92ZSBvdXIgZWxlbWVudCwgdW50aWwgdGhlIHN0YXJ0IHRhZywgXHJcbiAgICAgKiBzbyB3ZSBjYW4gZGV0ZXJtaW5lIHdoZXJlIHRvIHBsYWNlIHRoZSBuZXcgaXRlbSBpbiB0aGUgbWFuYWdlci5cclxuICAgICAqIFxyXG4gICAgICogVE9ETzogQ2FuIHJlZHVjZSB0aGUgYW1vdW50IG5lZWRpbmcgdG8gYmUgcmVuZGVyZWQgYnkgb25seSByZW5kZXJpbmcgdG9cclxuICAgICAqIHRoZSBzdGFydCB0YWcgb3IgYSBjb2x1bW4tYnJlYWsgd2hpY2hldmVyIGlzIGNsb3Nlci5cclxuICAgICAqL1xyXG4gICAgbGV0IHNpYmxpbmdzID0gY3JlYXRlRGl2KCk7XHJcbiAgICBsZXQgbWFya2Rvd25SZW5kZXJDaGlsZCA9IG5ldyBNYXJrZG93blJlbmRlckNoaWxkKFxyXG4gICAgICAgIHNpYmxpbmdzXHJcbiAgICApO1xyXG4gICAgTWFya2Rvd25SZW5kZXJlci5yZW5kZXJNYXJrZG93bihcclxuICAgICAgICBtZExpbmVzLnJlZHVjZSgocHJldiwgY3VycmVudCkgPT4ge1xyXG4gICAgICAgICAgICByZXR1cm4gcHJldiArIFwiXFxuXCIgICsgY3VycmVudDtcclxuICAgICAgICB9LCBcIlwiKSxcclxuICAgICAgICBzaWJsaW5ncyxcclxuICAgICAgICBzb3VyY2VQYXRoLFxyXG4gICAgICAgIG1hcmtkb3duUmVuZGVyQ2hpbGRcclxuICAgICk7XHJcblxyXG4gICAgcmV0dXJuIHNpYmxpbmdzO1xyXG59XHJcbiJdLCJuYW1lcyI6WyJNYXJrZG93blJlbmRlckNoaWxkIiwiV2lkZ2V0VHlwZSIsIk1hcmtkb3duUmVuZGVyZXIiLCJURmlsZSIsIlN0YXRlRmllbGQiLCJEZWNvcmF0aW9uIiwiUmFuZ2VTZXRCdWlsZGVyIiwic3ludGF4VHJlZSIsImVkaXRvckxpdmVQcmV2aWV3RmllbGQiLCJ0b2tlbkNsYXNzTm9kZVByb3AiLCJFZGl0b3JWaWV3IiwiUGx1Z2luIiwiUGxhdGZvcm0iLCJOb3RpY2UiLCJtdWx0aUNvbHVtblBhcnNlci5maW5kU3RhcnRDb2RlYmxvY2siLCJtdWx0aUNvbHVtblBhcnNlci5pc1N0YXJ0VGFnV2l0aElEIiwibXVsdGlDb2x1bW5QYXJzZXIuY29udGFpbnNTdGFydFRhZyIsIm11bHRpQ29sdW1uUGFyc2VyLmNvbnRhaW5zU3RhcnRDb2RlQmxvY2siLCJtdWx0aUNvbHVtblBhcnNlci5nZXRTdGFydEJsb2NrQWJvdmVMaW5lIiwibXVsdGlDb2x1bW5QYXJzZXIuY291bnRTdGFydFRhZ3MiLCJtdWx0aUNvbHVtblBhcnNlci5nZXRTdGFydEJsb2NrT3JDb2RlYmxvY2tBYm92ZUxpbmUiLCJtdWx0aUNvbHVtblBhcnNlci5nZXRFbmRCbG9ja0JlbG93IiwibXVsdGlDb2x1bW5QYXJzZXIuY29udGFpbnNFbmRUYWciLCJtdWx0aUNvbHVtblBhcnNlci5jb250YWluc0NvbEVuZFRhZyIsIm11bHRpQ29sdW1uUGFyc2VyLmNvbnRhaW5zQ29sU2V0dGluZ3NUYWciLCJtdWx0aUNvbHVtblBhcnNlci5nZXRTdGFydFRhZ0tleSJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7O0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQXVEQTtBQUNPLFNBQVMsU0FBUyxDQUFDLE9BQU8sRUFBRSxVQUFVLEVBQUUsQ0FBQyxFQUFFLFNBQVMsRUFBRTtBQUM3RCxJQUFJLFNBQVMsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLE9BQU8sS0FBSyxZQUFZLENBQUMsR0FBRyxLQUFLLEdBQUcsSUFBSSxDQUFDLENBQUMsVUFBVSxPQUFPLEVBQUUsRUFBRSxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRTtBQUNoSCxJQUFJLE9BQU8sS0FBSyxDQUFDLEtBQUssQ0FBQyxHQUFHLE9BQU8sQ0FBQyxFQUFFLFVBQVUsT0FBTyxFQUFFLE1BQU0sRUFBRTtBQUMvRCxRQUFRLFNBQVMsU0FBUyxDQUFDLEtBQUssRUFBRSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxPQUFPLENBQUMsRUFBRSxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUU7QUFDbkcsUUFBUSxTQUFTLFFBQVEsQ0FBQyxLQUFLLEVBQUUsRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxPQUFPLENBQUMsRUFBRSxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUU7QUFDdEcsUUFBUSxTQUFTLElBQUksQ0FBQyxNQUFNLEVBQUUsRUFBRSxNQUFNLENBQUMsSUFBSSxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEdBQUcsS0FBSyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLFFBQVEsQ0FBQyxDQUFDLEVBQUU7QUFDdEgsUUFBUSxJQUFJLENBQUMsQ0FBQyxTQUFTLEdBQUcsU0FBUyxDQUFDLEtBQUssQ0FBQyxPQUFPLEVBQUUsVUFBVSxJQUFJLEVBQUUsQ0FBQyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7QUFDOUUsS0FBSyxDQUFDLENBQUM7QUFDUDs7QUM3RUE7Ozs7OztBQU1HO0FBRUgsSUFBWSxZQU9YLENBQUE7QUFQRCxDQUFBLFVBQVksWUFBWSxFQUFBO0FBQ3BCLElBQUEsWUFBQSxDQUFBLFlBQUEsQ0FBQSxTQUFBLENBQUEsR0FBQSxDQUFBLENBQUEsR0FBQSxTQUFPLENBQUE7QUFDUCxJQUFBLFlBQUEsQ0FBQSxZQUFBLENBQUEsSUFBQSxDQUFBLEdBQUEsQ0FBQSxDQUFBLEdBQUEsSUFBRSxDQUFBO0FBQ0YsSUFBQSxZQUFBLENBQUEsWUFBQSxDQUFBLE1BQUEsQ0FBQSxHQUFBLENBQUEsQ0FBQSxHQUFBLE1BQUksQ0FBQTtBQUNKLElBQUEsWUFBQSxDQUFBLFlBQUEsQ0FBQSxVQUFBLENBQUEsR0FBQSxDQUFBLENBQUEsR0FBQSxVQUFRLENBQUE7QUFDUixJQUFBLFlBQUEsQ0FBQSxZQUFBLENBQUEsS0FBQSxDQUFBLEdBQUEsQ0FBQSxDQUFBLEdBQUEsS0FBRyxDQUFBO0FBQ0gsSUFBQSxZQUFBLENBQUEsWUFBQSxDQUFBLE9BQUEsQ0FBQSxHQUFBLENBQUEsQ0FBQSxHQUFBLE9BQUssQ0FBQTtBQUNULENBQUMsRUFQVyxZQUFZLEtBQVosWUFBWSxHQU92QixFQUFBLENBQUEsQ0FBQSxDQUFBO0FBRUQsSUFBWSxZQU9YLENBQUE7QUFQRCxDQUFBLFVBQVksWUFBWSxFQUFBO0FBQ3BCLElBQUEsWUFBQSxDQUFBLFlBQUEsQ0FBQSxTQUFBLENBQUEsR0FBQSxDQUFBLENBQUEsR0FBQSxTQUFPLENBQUE7QUFDUCxJQUFBLFlBQUEsQ0FBQSxZQUFBLENBQUEsSUFBQSxDQUFBLEdBQUEsQ0FBQSxDQUFBLEdBQUEsSUFBRSxDQUFBO0FBQ0YsSUFBQSxZQUFBLENBQUEsWUFBQSxDQUFBLE1BQUEsQ0FBQSxHQUFBLENBQUEsQ0FBQSxHQUFBLE1BQUksQ0FBQTtBQUNKLElBQUEsWUFBQSxDQUFBLFlBQUEsQ0FBQSxVQUFBLENBQUEsR0FBQSxDQUFBLENBQUEsR0FBQSxVQUFRLENBQUE7QUFDUixJQUFBLFlBQUEsQ0FBQSxZQUFBLENBQUEsS0FBQSxDQUFBLEdBQUEsQ0FBQSxDQUFBLEdBQUEsS0FBRyxDQUFBO0FBQ0gsSUFBQSxZQUFBLENBQUEsWUFBQSxDQUFBLE9BQUEsQ0FBQSxHQUFBLENBQUEsQ0FBQSxHQUFBLE9BQUssQ0FBQTtBQUNULENBQUMsRUFQVyxZQUFZLEtBQVosWUFBWSxHQU92QixFQUFBLENBQUEsQ0FBQSxDQUFBO0FBRUQsSUFBWSxZQVVYLENBQUE7QUFWRCxDQUFBLFVBQVksWUFBWSxFQUFBO0FBQ3BCLElBQUEsWUFBQSxDQUFBLFlBQUEsQ0FBQSxVQUFBLENBQUEsR0FBQSxDQUFBLENBQUEsR0FBQSxVQUFRLENBQUE7QUFDUixJQUFBLFlBQUEsQ0FBQSxZQUFBLENBQUEsTUFBQSxDQUFBLEdBQUEsQ0FBQSxDQUFBLEdBQUEsTUFBSSxDQUFBO0FBQ0osSUFBQSxZQUFBLENBQUEsWUFBQSxDQUFBLE9BQUEsQ0FBQSxHQUFBLENBQUEsQ0FBQSxHQUFBLE9BQUssQ0FBQTtBQUNMLElBQUEsWUFBQSxDQUFBLFlBQUEsQ0FBQSxRQUFBLENBQUEsR0FBQSxDQUFBLENBQUEsR0FBQSxRQUFNLENBQUE7QUFDTixJQUFBLFlBQUEsQ0FBQSxZQUFBLENBQUEsUUFBQSxDQUFBLEdBQUEsQ0FBQSxDQUFBLEdBQUEsUUFBTSxDQUFBO0FBQ04sSUFBQSxZQUFBLENBQUEsWUFBQSxDQUFBLFFBQUEsQ0FBQSxHQUFBLENBQUEsQ0FBQSxHQUFBLFFBQU0sQ0FBQTtBQUNOLElBQUEsWUFBQSxDQUFBLFlBQUEsQ0FBQSxPQUFBLENBQUEsR0FBQSxDQUFBLENBQUEsR0FBQSxPQUFLLENBQUE7QUFDTCxJQUFBLFlBQUEsQ0FBQSxZQUFBLENBQUEsT0FBQSxDQUFBLEdBQUEsQ0FBQSxDQUFBLEdBQUEsT0FBSyxDQUFBO0FBQ0wsSUFBQSxZQUFBLENBQUEsWUFBQSxDQUFBLE1BQUEsQ0FBQSxHQUFBLENBQUEsQ0FB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
|