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.
1303 lines
194 KiB
1303 lines
194 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');
|
|
|
|
/*! *****************************************************************************
|
|
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 = {}));
|
|
|
|
/*
|
|
* 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",
|
|
"=== *multi-column-start"];
|
|
const START_REGEX_ARR = [];
|
|
for (let i = 0; i < START_REGEX_STRS.length; i++) {
|
|
START_REGEX_ARR.push(new RegExp(START_REGEX_STRS[i]));
|
|
}
|
|
function findStartTag(text) {
|
|
let found = false;
|
|
let startPosition = -1;
|
|
for (let i = 0; i < START_REGEX_ARR.length; i++) {
|
|
if (START_REGEX_ARR[i].test(text)) {
|
|
found = true;
|
|
startPosition = text.search(START_REGEX_STRS[i]);
|
|
break;
|
|
}
|
|
}
|
|
return { found, startPosition };
|
|
}
|
|
function containsStartTag(text) {
|
|
return findStartTag(text).found;
|
|
}
|
|
function isStartTagWithID(text) {
|
|
let startTagData = findStartTag(text);
|
|
if (startTagData.found === true) {
|
|
let key = getStartTagKey(text);
|
|
if (key === null || key === "") {
|
|
return { isStartTag: true, hasKey: false };
|
|
}
|
|
return { isStartTag: true, hasKey: true };
|
|
}
|
|
return { isStartTag: false, hasKey: false };
|
|
}
|
|
const END_REGEX_STRS = ["=== *end-multi-column",
|
|
"=== *multi-column-end"];
|
|
const END_REGEX_ARR = [];
|
|
for (let i = 0; i < END_REGEX_STRS.length; i++) {
|
|
END_REGEX_ARR.push(new RegExp(END_REGEX_STRS[i]));
|
|
}
|
|
function findEndTag(text) {
|
|
let found = false;
|
|
let startPosition = -1;
|
|
for (let i = 0; i < END_REGEX_ARR.length; i++) {
|
|
if (END_REGEX_ARR[i].test(text)) {
|
|
found = true;
|
|
startPosition = text.search(END_REGEX_STRS[i]);
|
|
break;
|
|
}
|
|
}
|
|
return { found, startPosition };
|
|
}
|
|
function containsEndTag(text) {
|
|
return findEndTag(text).found;
|
|
}
|
|
const COL_REGEX_STRS = ["=== *column-end *===",
|
|
"=== *end-column *===",
|
|
"=== *column-break *===",
|
|
"=== *break-column *==="];
|
|
const COL_REGEX_ARR = [];
|
|
for (let i = 0; i < COL_REGEX_STRS.length; i++) {
|
|
COL_REGEX_ARR.push(new RegExp(COL_REGEX_STRS[i]));
|
|
}
|
|
function containsColEndTag(text) {
|
|
let found = false;
|
|
for (let i = 0; i < COL_REGEX_ARR.length; i++) {
|
|
if (COL_REGEX_ARR[i].test(text)) {
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
return found;
|
|
}
|
|
const COL_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 parseColumnSettings(settingsStr) {
|
|
// Set the minimum number of columnds to 2.
|
|
let numberOfColumns = 2;
|
|
let columnLayout = ColumnLayout.standard;
|
|
let borderDrawn = true;
|
|
let shadowDrawn = true;
|
|
let settingsLines = settingsStr.split("\n");
|
|
for (let i = 0; i < settingsLines.length; i++) {
|
|
if (settingsLines[i].toLowerCase().replace(/\s/g, "").contains("numberofcolumns:")) {
|
|
let userDefNumberOfCols = parseInt(settingsLines[i].split(":")[1]);
|
|
if (Number.isNaN(userDefNumberOfCols) === false) {
|
|
if (userDefNumberOfCols === 3) {
|
|
numberOfColumns = 3;
|
|
}
|
|
else if (userDefNumberOfCols === 2) {
|
|
numberOfColumns = 2;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
for (let i = 0; i < settingsLines.length; i++) {
|
|
if (settingsLines[i].toLowerCase().replace(/\s/g, "").contains("largestcolumn:")) {
|
|
let setting = settingsLines[i].split(":")[1].trimStart().trimEnd().toLowerCase();
|
|
let userDefLayout = ColumnLayout[setting];
|
|
if (userDefLayout !== undefined) {
|
|
columnLayout = userDefLayout;
|
|
}
|
|
}
|
|
}
|
|
for (let i = 0; i < settingsLines.length; i++) {
|
|
if (settingsLines[i].toLowerCase().replace(/\s/g, "").contains("border:")) {
|
|
let setting = settingsLines[i].split(":")[1].trimStart().trimEnd().toLowerCase();
|
|
let isBorderDrawn = BorderOption[setting];
|
|
if (isBorderDrawn !== undefined) {
|
|
switch (isBorderDrawn) {
|
|
case (BorderOption.disabled):
|
|
case (BorderOption.off):
|
|
case (BorderOption.false):
|
|
borderDrawn = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for (let i = 0; i < settingsLines.length; i++) {
|
|
if (settingsLines[i].toLowerCase().replace(/\s/g, "").contains("shadow:")) {
|
|
let setting = settingsLines[i].split(":")[1].trimStart().trimEnd().toLowerCase();
|
|
let isShadowDrawn = ShadowOption[setting];
|
|
if (isShadowDrawn !== undefined) {
|
|
switch (isShadowDrawn) {
|
|
case (ShadowOption.disabled):
|
|
case (ShadowOption.off):
|
|
case (ShadowOption.false):
|
|
shadowDrawn = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
let settings = { numberOfColumns, columnLayout, drawBorder: borderDrawn, drawShadow: shadowDrawn };
|
|
return settings;
|
|
}
|
|
function countStartTags(text) {
|
|
let keys = [];
|
|
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);
|
|
}
|
|
return { numberOfTags: keys.length, keys };
|
|
}
|
|
/**
|
|
* 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);
|
|
}
|
|
}
|
|
return { startBlockKey, linesAboveArray };
|
|
}
|
|
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;
|
|
}
|
|
|
|
/*
|
|
* 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;
|
|
}
|
|
|
|
var ElementRenderType;
|
|
(function (ElementRenderType) {
|
|
ElementRenderType[ElementRenderType["undefined"] = 0] = "undefined";
|
|
ElementRenderType[ElementRenderType["normalRender"] = 1] = "normalRender";
|
|
ElementRenderType[ElementRenderType["specialRender"] = 2] = "specialRender";
|
|
})(ElementRenderType || (ElementRenderType = {}));
|
|
function getElementRenderType(element) {
|
|
/**
|
|
* 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) {
|
|
return ElementRenderType.specialRender;
|
|
}
|
|
if (hasAdmonition(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)) {
|
|
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")) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
function hasList(element) {
|
|
if (element.innerHTML.startsWith("<ul") ||
|
|
element.innerHTML.startsWith("<ol")) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
function hasDiceRoller(element) {
|
|
return element.getElementsByClassName("dice-roller").length !== 0;
|
|
}
|
|
function hasAdmonition(element) {
|
|
return element.getElementsByClassName("admonition").length !== 0;
|
|
}
|
|
|
|
/*
|
|
* Filename: multi-column-markdown/src/domObject.ts
|
|
* Created Date: Tuesday, February 1st 2022, 12:04:00 pm
|
|
* Author: Cameron Robinson
|
|
*
|
|
* Copyright (c) 2022 Cameron Robinson
|
|
*/
|
|
var DOMObjectTag;
|
|
(function (DOMObjectTag) {
|
|
DOMObjectTag[DOMObjectTag["none"] = 0] = "none";
|
|
DOMObjectTag[DOMObjectTag["startRegion"] = 1] = "startRegion";
|
|
DOMObjectTag[DOMObjectTag["regionSettings"] = 2] = "regionSettings";
|
|
DOMObjectTag[DOMObjectTag["columnBreak"] = 3] = "columnBreak";
|
|
DOMObjectTag[DOMObjectTag["endRegion"] = 4] = "endRegion";
|
|
})(DOMObjectTag || (DOMObjectTag = {}));
|
|
class DOMObject {
|
|
constructor(element, randomID = getUID(), tag = DOMObjectTag.none) {
|
|
this.elementType = ElementRenderType.undefined;
|
|
this.elementContainer = null;
|
|
this.nodeKey = element.innerText.trim();
|
|
this.element = element;
|
|
this.UID = randomID;
|
|
this.tag = tag;
|
|
this.usingOriginalElement = false;
|
|
}
|
|
setMainDOMElement(domElement) {
|
|
this.element = domElement;
|
|
this.usingOriginalElement = true;
|
|
}
|
|
}
|
|
class DOMRegionSettingsObject extends DOMObject {
|
|
constructor(baseDOMObject, regionSettings) {
|
|
super(baseDOMObject.element, baseDOMObject.UID, DOMObjectTag.regionSettings);
|
|
this.regionSettings = regionSettings;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* 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"] = "multiColumnContainer";
|
|
MultiColumnLayoutCSS["RegionErrorContainerDiv"] = "multiColumnErrorContainer";
|
|
MultiColumnLayoutCSS["RegionContentContainerDiv"] = "RenderColRegion";
|
|
MultiColumnLayoutCSS["RegionColumnContainerDiv"] = "multiColumnParent";
|
|
MultiColumnLayoutCSS["RegionColumnContent"] = "columnContent";
|
|
MultiColumnLayoutCSS["ColumnDualElementContainer"] = "MultiColumn_ElementContainer";
|
|
MultiColumnLayoutCSS["OriginalElementType"] = "MultiColumn_OriginalElement";
|
|
MultiColumnLayoutCSS["ClonedElementType"] = "MultiColumn_ClonedElement";
|
|
})(MultiColumnLayoutCSS || (MultiColumnLayoutCSS = {}));
|
|
var MultiColumnStyleCSS;
|
|
(function (MultiColumnStyleCSS) {
|
|
MultiColumnStyleCSS["RegionErrorMessage"] = "multiColumnErrorMessage";
|
|
MultiColumnStyleCSS["RegionSettings"] = "multiColumnSettings";
|
|
MultiColumnStyleCSS["RegionContent"] = "multiColumnContent";
|
|
MultiColumnStyleCSS["RegionEndTag"] = "multiColumnRegionEndTag";
|
|
MultiColumnStyleCSS["ColumnEndTag"] = "multiColumnBreak";
|
|
MultiColumnStyleCSS["RegionShadow"] = "multiColumnParentShadow";
|
|
MultiColumnStyleCSS["ColumnShadow"] = "columnShadow";
|
|
MultiColumnStyleCSS["ColumnBorder"] = "columnBorder";
|
|
})(MultiColumnStyleCSS || (MultiColumnStyleCSS = {}));
|
|
|
|
/*
|
|
* 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
|
|
*/
|
|
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 regionManager = regionMap.get(regionKey);
|
|
if (regionManager) {
|
|
regionManager.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 regonalManager = createRegionalDomManager(this, regionKey, rootElement, renderRegionElement);
|
|
regionMap.set(regionKey, regonalManager);
|
|
return regonalManager;
|
|
}
|
|
function getRegionalManager(regionKey) {
|
|
let regonalManager = null;
|
|
if (regionMap.has(regionKey) === true) {
|
|
regonalManager = regionMap.get(regionKey);
|
|
}
|
|
return regonalManager;
|
|
}
|
|
function getAllRegionalManagers() {
|
|
return Array.from(regionMap.values());
|
|
}
|
|
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,
|
|
getRegionalManager: getRegionalManager,
|
|
getAllRegionalManagers: getAllRegionalManagers,
|
|
removeRegion: removeRegion,
|
|
setHasStartTag: setHasStartTag,
|
|
getHasStartTag: getHasStartTag,
|
|
getNumberOfRegions: getNumberOfRegions,
|
|
checkKeyExists: checkKeyExists
|
|
};
|
|
}
|
|
function createRegionalDomManager(fileManager, regionKey, rootElement, renderRegionElement) {
|
|
/**
|
|
* We use a list and a map to help keep track of the objects. Requires
|
|
* more memory but makes processing things a little cleaner and presumably
|
|
* faster.
|
|
*
|
|
* Use the map to look up object by key and the list is used to track objects
|
|
* in the order they are in the document.
|
|
*/
|
|
let domList = [];
|
|
let domObjectMap = new Map();
|
|
let regionParent = renderRegionElement;
|
|
let regionSettings = [];
|
|
function addObject(siblingsAbove, siblingsBelow, obj) {
|
|
let prevObj = siblingsAbove.children[siblingsAbove.children.length - 1];
|
|
let nextObj = siblingsBelow.children[0];
|
|
let addAtIndex = siblingsAbove.children.length;
|
|
if (prevObj !== undefined) {
|
|
for (let i = domList.length - 1; i >= 0; i--) {
|
|
if (domList[i].nodeKey === prevObj.innerText) {
|
|
addAtIndex = i + 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
let nextElIndex = addAtIndex;
|
|
if (nextObj !== undefined) {
|
|
for (let i = addAtIndex; i < domList.length; i++) {
|
|
if (domList[i].nodeKey === nextObj.innerText.trim()) {
|
|
nextElIndex = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
// console.log(" Prev: ", siblingsAbove.children[siblingsAbove.children.length - 1], "Adding: ", obj.element, " Next: ", siblingsBelow.children[0], "Overwriting:", domList.slice(addAtIndex, nextElIndex));
|
|
domList.splice(addAtIndex, nextElIndex - addAtIndex, obj);
|
|
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 = domList.slice(0);
|
|
// console.log(x);
|
|
return addAtIndex;
|
|
}
|
|
function 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 = domObjectMap.get(objectUID);
|
|
domObjectMap.delete(objectUID);
|
|
if (obj === undefined) {
|
|
return;
|
|
}
|
|
if (domList.contains(obj)) {
|
|
domList.remove(obj);
|
|
}
|
|
// If the object is a settings object we need to remove from the
|
|
// settings list.
|
|
if (obj.tag === DOMObjectTag.regionSettings) {
|
|
let settingsObj = obj;
|
|
if (regionSettings.contains(settingsObj)) {
|
|
regionSettings.remove(settingsObj);
|
|
}
|
|
}
|
|
if (domList.length === 0) {
|
|
fileManager.removeRegion(regionKey);
|
|
}
|
|
// x = domList.slice(0);
|
|
// console.log(x);
|
|
}
|
|
function updateElementTag(objectUID, newTag) {
|
|
let obj = domObjectMap.get(objectUID);
|
|
let index = domList.indexOf(obj);
|
|
if (index !== -1) {
|
|
domList[index].tag = newTag;
|
|
}
|
|
}
|
|
function setElementToSettingsBlock(objectUID, settingsText) {
|
|
let obj = domObjectMap.get(objectUID);
|
|
let index = domList.indexOf(obj);
|
|
if (index !== -1) {
|
|
let settings = parseColumnSettings(settingsText);
|
|
let regionSettingsObj = new DOMRegionSettingsObject(domList[index], settings);
|
|
domObjectMap.set(regionSettingsObj.UID, regionSettingsObj);
|
|
domList[index] = regionSettingsObj;
|
|
regionSettings.push(regionSettingsObj);
|
|
}
|
|
}
|
|
/**
|
|
* 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.
|
|
*/
|
|
function getRegionRenderData() {
|
|
// Set defaults before attempting to get settings.
|
|
let settings = { numberOfColumns: 2, columnLayout: ColumnLayout.standard, drawBorder: true, drawShadow: true };
|
|
if (regionSettings.length > 0) {
|
|
/**
|
|
* Since we append settings onto the end of the array we want the last
|
|
* item in the array as that would be the most recent settings we parsed.
|
|
*/
|
|
settings = regionSettings[regionSettings.length - 1].regionSettings;
|
|
}
|
|
return {
|
|
parentRenderElement: regionParent,
|
|
parentRenderSettings: settings,
|
|
domObjects: 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.
|
|
*/
|
|
function displayOriginalElements() {
|
|
for (let i = 0; i < domList.length; i++) {
|
|
if (domList[i].element) {
|
|
domList[i].element.removeClasses([MultiColumnStyleCSS.RegionEndTag,
|
|
MultiColumnStyleCSS.ColumnEndTag,
|
|
MultiColumnStyleCSS.RegionSettings,
|
|
MultiColumnStyleCSS.RegionContent]);
|
|
if (domList[i].element.parentElement) {
|
|
domList[i].element.parentElement.removeChild(domList[i].element);
|
|
}
|
|
}
|
|
}
|
|
for (let i = 0; i < regionSettings.length; i++) {
|
|
if (regionSettings[i].element) {
|
|
regionSettings[i].element.removeClasses([MultiColumnStyleCSS.RegionEndTag,
|
|
MultiColumnStyleCSS.ColumnEndTag,
|
|
MultiColumnStyleCSS.RegionSettings,
|
|
MultiColumnStyleCSS.RegionContent]);
|
|
if (regionSettings[i].element.parentElement) {
|
|
regionSettings[i].element.parentElement.removeChild(regionSettings[i].element);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
function getRootRegionElement() {
|
|
return rootElement;
|
|
}
|
|
return { addObject: addObject,
|
|
removeObject: removeObject,
|
|
updateElementTag: updateElementTag,
|
|
setElementToSettingsBlock: setElementToSettingsBlock,
|
|
getRegionRenderData: getRegionRenderData,
|
|
displayOriginalElements: displayOriginalElements,
|
|
getRootRegionElement: getRootRegionElement
|
|
};
|
|
}
|
|
|
|
/*
|
|
* File: multi-column-markdown/src/main.ts
|
|
* Created Date: Tuesday, October 5th 2021, 1:09 pm
|
|
* Author: Cameron Robinson
|
|
*
|
|
* Copyright (c) 2022 Cameron Robinson
|
|
*/
|
|
class MultiColumnMarkdown extends obsidian.Plugin {
|
|
constructor() {
|
|
// settings: SplitColumnMarkdownSettings;
|
|
super(...arguments);
|
|
this.globalManager = new GlobalDOMManager();
|
|
}
|
|
onload() {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
console.log("Loading multi-column markdown");
|
|
this.setupMarkdownPostProcessor();
|
|
//TODO: Set up this as a modal to set settings automatically
|
|
this.addCommand({
|
|
id: `insert-multi-column-region`,
|
|
name: `Insert Multi-Column Region`,
|
|
editorCallback: (editor, view) => {
|
|
try {
|
|
editor.getDoc().replaceSelection(`
|
|
=== multi-column-start: ID_${getUID(4)}
|
|
\`\`\`column-settings
|
|
Number of Columns: 2
|
|
Largest Column: standard
|
|
\`\`\`
|
|
|
|
=== end-column ===
|
|
|
|
=== multi-column-end
|
|
|
|
${editor.getDoc().getSelection()}`);
|
|
}
|
|
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 lines = editor.getRange({ line: 0, ch: 0 }, { line: editor.getDoc().lineCount(), ch: 0 }).split("\n");
|
|
/**
|
|
* 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) {
|
|
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} 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();
|
|
}, 2000));
|
|
});
|
|
}
|
|
UpdateOpenFilePreviews() {
|
|
let fileManagers = this.globalManager.getAllFileManagers();
|
|
fileManagers.forEach(element => {
|
|
let regionalManagers = element.getAllRegionalManagers();
|
|
regionalManagers.forEach(regionManager => {
|
|
let parentElementData = regionManager.getRegionRenderData();
|
|
this.updateRenderedMarkdown(parentElementData.domObjects);
|
|
});
|
|
});
|
|
}
|
|
setupMarkdownPostProcessor() {
|
|
this.registerMarkdownPostProcessor((el, ctx) => __awaiter(this, void 0, void 0, function* () {
|
|
// 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;
|
|
}
|
|
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;
|
|
}
|
|
/**
|
|
* 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)) {
|
|
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 docLines = info.text.split("\n");
|
|
let linesAboveArray = docLines.slice(0, info.lineStart);
|
|
let linesOfElement = docLines.slice(info.lineStart, info.lineEnd + 1);
|
|
let linesBelowArray = docLines.slice(info.lineEnd + 1);
|
|
/**
|
|
* 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.
|
|
*/
|
|
let elementTextSpaced = linesOfElement.reduce((prev, curr) => {
|
|
return prev + "\n" + curr;
|
|
});
|
|
if (containsStartTag(el.textContent)) {
|
|
/**
|
|
* 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);
|
|
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;
|
|
}
|
|
/**
|
|
* 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 = getStartBlockAboveLine(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 regionalManager = fileDOMManager.getRegionalManager(startBockAbove.startBlockKey);
|
|
if (regionalManager === null) {
|
|
return;
|
|
}
|
|
/**
|
|
* 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);
|
|
el.id = currentObject.UID;
|
|
/**
|
|
* 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 (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;
|
|
}
|
|
this.renderColumnMarkdown(regionRenderData.parentRenderElement, regionRenderData.domObjects, regionRenderData.parentRenderSettings);
|
|
}
|
|
};
|
|
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) {
|
|
el.addClass(MultiColumnStyleCSS.RegionEndTag);
|
|
regionalManager.updateElementTag(currentObject.UID, DOMObjectTag.endRegion);
|
|
}
|
|
else if (containsColEndTag(elementTextSpaced) === true) {
|
|
el.addClass(MultiColumnStyleCSS.ColumnEndTag);
|
|
regionalManager.updateElementTag(currentObject.UID, DOMObjectTag.columnBreak);
|
|
}
|
|
else if (containsColSettingsTag(elementTextSpaced) === true) {
|
|
el.addClass(MultiColumnStyleCSS.RegionSettings);
|
|
regionalManager.setElementToSettingsBlock(currentObject.UID, elementTextSpaced);
|
|
}
|
|
else {
|
|
el.addClass(MultiColumnStyleCSS.RegionContent);
|
|
}
|
|
/**
|
|
* Use our regional manager to get everything needed to render the region.
|
|
*/
|
|
let parentElementData = regionalManager.getRegionRenderData();
|
|
this.renderColumnMarkdown(parentElementData.parentRenderElement, parentElementData.domObjects, parentElementData.parentRenderSettings);
|
|
return;
|
|
}));
|
|
}
|
|
/**
|
|
* 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 (settings.drawShadow === true) {
|
|
multiColumnParent.addClass(MultiColumnStyleCSS.RegionShadow);
|
|
}
|
|
/**
|
|
* Pass our parent div and settings to parser to create the required
|
|
* column divs as children of the parent.
|
|
*/
|
|
let columnContentDivs = getColumnContentDivs(settings, multiColumnParent);
|
|
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);
|
|
let columnIndex = 0;
|
|
for (let i = 0; i < regionElements.length; i++) {
|
|
if (regionElements[i].tag !== DOMObjectTag.startRegion ||
|
|
regionElements[i].tag !== DOMObjectTag.regionSettings ||
|
|
regionElements[i].tag !== DOMObjectTag.endRegion ||
|
|
regionElements[i].tag !== DOMObjectTag.columnBreak) {
|
|
// We store the elements in a wrapper container until we determine
|
|
let element = createDiv({
|
|
cls: MultiColumnLayoutCSS.ColumnDualElementContainer,
|
|
});
|
|
regionElements[i].elementContainer = element;
|
|
// Otherwise we just make a copy of the original element to display.
|
|
element.appendChild(regionElements[i].element.cloneNode(true));
|
|
if (element !== null) {
|
|
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++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
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.
|
|
*/
|
|
// Remove the old elements before we set up the dual rendered elements.
|
|
let containerElement = domElement.elementContainer;
|
|
let renderElement = domElement.element;
|
|
for (let i = containerElement.children.length - 1; i >= 0; i--) {
|
|
containerElement.children[i].detach();
|
|
}
|
|
containerElement.appendChild(renderElement);
|
|
renderElement.addClass(MultiColumnLayoutCSS.OriginalElementType);
|
|
let clonedNode = renderElement.cloneNode(true);
|
|
clonedNode.addClass(MultiColumnLayoutCSS.ClonedElementType);
|
|
clonedNode.removeClasses([MultiColumnStyleCSS.RegionContent, MultiColumnLayoutCSS.OriginalElementType]);
|
|
containerElement.appendChild(clonedNode);
|
|
}
|
|
updateRenderedMarkdown(regionElements) {
|
|
/**
|
|
* Go through every node of the region looking for the "specialRender" type
|
|
* which are the elements that may need to be rendered using the original
|
|
* element rather than a copy.
|
|
*/
|
|
for (let i = 0; i < regionElements.length; i++) {
|
|
/**
|
|
* Here we check every item again to see if they need to be updated.
|
|
* This could be made slightly more efficient if we can truly determine
|
|
* wether an item is a normal render item, however it seems like it
|
|
* may take a bit of extra time in order for the classes we check for
|
|
* to be added to the elements.
|
|
*/
|
|
let elementType = regionElements[i].elementType;
|
|
// If the element is not currently a special render element we check again
|
|
// as the original element may have been updated.
|
|
if (elementType !== ElementRenderType.specialRender) {
|
|
// If the new result returns as a special renderer we update so
|
|
// this wont run again for this item.
|
|
elementType = getElementRenderType(regionElements[i].element);
|
|
}
|
|
if (elementType === ElementRenderType.specialRender) {
|
|
regionElements[i].elementType = elementType;
|
|
this.setUpDualRender(regionElements[i]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/**
|
|
* 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.
|
|
*/
|
|
function getColumnContentDivs(settings, multiColumnParent) {
|
|
let columnContentDivs = [];
|
|
if (settings.numberOfColumns === 2) {
|
|
switch (settings.columnLayout) {
|
|
case (ColumnLayout.standard):
|
|
case (ColumnLayout.middle):
|
|
case (ColumnLayout.center):
|
|
case (ColumnLayout.third):
|
|
columnContentDivs.push(multiColumnParent.createDiv({
|
|
cls: `columnContent twoEqualColumns_Left`
|
|
}));
|
|
columnContentDivs.push(multiColumnParent.createDiv({
|
|
cls: `columnContent twoEqualColumns_Right`
|
|
}));
|
|
break;
|
|
case (ColumnLayout.left):
|
|
case (ColumnLayout.first):
|
|
columnContentDivs.push(multiColumnParent.createDiv({
|
|
cls: `columnContent twoColumnsHeavyLeft_Left`
|
|
}));
|
|
columnContentDivs.push(multiColumnParent.createDiv({
|
|
cls: `columnContent twoColumnsHeavyLeft_Right`
|
|
}));
|
|
break;
|
|
case (ColumnLayout.right):
|
|
case (ColumnLayout.second):
|
|
case (ColumnLayout.last):
|
|
columnContentDivs.push(multiColumnParent.createDiv({
|
|
cls: `columnContent twoColumnsHeavyRight_Left`
|
|
}));
|
|
columnContentDivs.push(multiColumnParent.createDiv({
|
|
cls: `columnContent twoColumnsHeavyRight_Right`
|
|
}));
|
|
break;
|
|
}
|
|
}
|
|
else if (settings.numberOfColumns === 3) {
|
|
switch (settings.columnLayout) {
|
|
case (ColumnLayout.standard):
|
|
columnContentDivs.push(multiColumnParent.createDiv({
|
|
cls: `columnContent threeEqualColumns_Left`
|
|
}));
|
|
columnContentDivs.push(multiColumnParent.createDiv({
|
|
cls: `columnContent threeEqualColumns_Middle`
|
|
}));
|
|
columnContentDivs.push(multiColumnParent.createDiv({
|
|
cls: `columnContent threeEqualColumns_Right`
|
|
}));
|
|
break;
|
|
case (ColumnLayout.left):
|
|
case (ColumnLayout.first):
|
|
columnContentDivs.push(multiColumnParent.createDiv({
|
|
cls: `columnContent threColumnsHeavyLeft_Left`
|
|
}));
|
|
columnContentDivs.push(multiColumnParent.createDiv({
|
|
cls: `columnContent threColumnsHeavyLeft_Middle`
|
|
}));
|
|
columnContentDivs.push(multiColumnParent.createDiv({
|
|
cls: `columnContent threColumnsHeavyLeft_Right`
|
|
}));
|
|
break;
|
|
case (ColumnLayout.middle):
|
|
case (ColumnLayout.center):
|
|
case (ColumnLayout.second):
|
|
columnContentDivs.push(multiColumnParent.createDiv({
|
|
cls: `columnContent threColumnsHeavyMiddle_Left`
|
|
}));
|
|
columnContentDivs.push(multiColumnParent.createDiv({
|
|
cls: `columnContent threColumnsHeavyMiddle_Middle`
|
|
}));
|
|
columnContentDivs.push(multiColumnParent.createDiv({
|
|
cls: `columnContent threColumnsHeavyMiddle_Right`
|
|
}));
|
|
break;
|
|
case (ColumnLayout.right):
|
|
case (ColumnLayout.third):
|
|
case (ColumnLayout.last):
|
|
columnContentDivs.push(multiColumnParent.createDiv({
|
|
cls: `columnContent threColumnsHeavyRight_Left`
|
|
}));
|
|
columnContentDivs.push(multiColumnParent.createDiv({
|
|
cls: `columnContent threColumnsHeavyRight_Middle`
|
|
}));
|
|
columnContentDivs.push(multiColumnParent.createDiv({
|
|
cls: `columnContent threColumnsHeavyRight_Right`
|
|
}));
|
|
break;
|
|
}
|
|
}
|
|
return columnContentDivs;
|
|
}
|
|
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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFpbi5qcyIsInNvdXJjZXMiOlsibm9kZV9tb2R1bGVzL3RzbGliL3RzbGliLmVzNi5qcyIsInNyYy9yZWdpb25TZXR0aW5ncy50cyIsInNyYy91dGlsaXRpZXMvdGV4dFBhcnNlci50cyIsInNyYy91dGlsaXRpZXMvdXRpbHMudHMiLCJzcmMvdXRpbGl0aWVzL2VsZW1lbnRSZW5kZXJUeXBlUGFyc2VyLnRzIiwic3JjL2RvbV9tYW5hZ2VyL2RvbU9iamVjdC50cyIsInNyYy91dGlsaXRpZXMvY3NzRGVmaW5pdGlvbnMudHMiLCJzcmMvZG9tX21hbmFnZXIvZG9tTWFuYWdlci50cyIsInNyYy9tYWluLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qISAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxyXG5Db3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi5cclxuXHJcblBlcm1pc3Npb24gdG8gdXNlLCBjb3B5LCBtb2RpZnksIGFuZC9vciBkaXN0cmlidXRlIHRoaXMgc29mdHdhcmUgZm9yIGFueVxyXG5wdXJwb3NlIHdpdGggb3Igd2l0aG91dCBmZWUgaXMgaGVyZWJ5IGdyYW50ZWQuXHJcblxyXG5USEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiIEFORCBUSEUgQVVUSE9SIERJU0NMQUlNUyBBTEwgV0FSUkFOVElFUyBXSVRIXHJcblJFR0FSRCBUTyBUSElTIFNPRlRXQVJFIElOQ0xVRElORyBBTEwgSU1QTElFRCBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWVxyXG5BTkQgRklUTkVTUy4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIEFVVEhPUiBCRSBMSUFCTEUgRk9SIEFOWSBTUEVDSUFMLCBESVJFQ1QsXHJcbklORElSRUNULCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVMgT1IgQU5ZIERBTUFHRVMgV0hBVFNPRVZFUiBSRVNVTFRJTkcgRlJPTVxyXG5MT1NTIE9GIFVTRSwgREFUQSBPUiBQUk9GSVRTLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgTkVHTElHRU5DRSBPUlxyXG5PVEhFUiBUT1JUSU9VUyBBQ1RJT04sIEFSSVNJTkcgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgVVNFIE9SXHJcblBFUkZPUk1BTkNFIE9GIFRISVMgU09GVFdBUkUuXHJcbioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqICovXHJcbi8qIGdsb2JhbCBSZWZsZWN0LCBQcm9taXNlICovXHJcblxyXG52YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uKGQsIGIpIHtcclxuICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcclxuICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XHJcbiAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKSBkW3BdID0gYltwXTsgfTtcclxuICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xyXG59O1xyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fZXh0ZW5kcyhkLCBiKSB7XHJcbiAgICBpZiAodHlwZW9mIGIgIT09IFwiZnVuY3Rpb25cIiAmJiBiICE9PSBudWxsKVxyXG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDbGFzcyBleHRlbmRzIHZhbHVlIFwiICsgU3RyaW5nKGIpICsgXCIgaXMgbm90IGEgY29uc3RydWN0b3Igb3IgbnVsbFwiKTtcclxuICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XHJcbiAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cclxuICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcclxufVxyXG5cclxuZXhwb3J0IHZhciBfX2Fzc2lnbiA9IGZ1bmN0aW9uKCkge1xyXG4gICAgX19hc3NpZ24gPSBPYmplY3QuYXNzaWduIHx8IGZ1bmN0aW9uIF9fYXNzaWduKHQpIHtcclxuICAgICAgICBmb3IgKHZhciBzLCBpID0gMSwgbiA9IGFyZ3VtZW50cy5sZW5ndGg7IGkgPCBuOyBpKyspIHtcclxuICAgICAgICAgICAgcyA9IGFyZ3VtZW50c1tpXTtcclxuICAgICAgICAgICAgZm9yICh2YXIgcCBpbiBzKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHMsIHApKSB0W3BdID0gc1twXTtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHQ7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gX19hc3NpZ24uYXBwbHkodGhpcywgYXJndW1lbnRzKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fcmVzdChzLCBlKSB7XHJcbiAgICB2YXIgdCA9IHt9O1xyXG4gICAgZm9yICh2YXIgcCBpbiBzKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHMsIHApICYmIGUuaW5kZXhPZihwKSA8IDApXHJcbiAgICAgICAgdFtwXSA9IHNbcF07XHJcbiAgICBpZiAocyAhPSBudWxsICYmIHR5cGVvZiBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzID09PSBcImZ1bmN0aW9uXCIpXHJcbiAgICAgICAgZm9yICh2YXIgaSA9IDAsIHAgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKHMpOyBpIDwgcC5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICBpZiAoZS5pbmRleE9mKHBbaV0pIDwgMCAmJiBPYmplY3QucHJvdG90eXBlLnByb3BlcnR5SXNFbnVtZXJhYmxlLmNhbGwocywgcFtpXSkpXHJcbiAgICAgICAgICAgICAgICB0W3BbaV1dID0gc1twW2ldXTtcclxuICAgICAgICB9XHJcbiAgICByZXR1cm4gdDtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcclxuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XHJcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xyXG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA6IGMgPiAzID8gZCh0YXJnZXQsIGtleSwgcikgOiBkKHRhcmdldCwga2V5KSkgfHwgcjtcclxuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3BhcmFtKHBhcmFtSW5kZXgsIGRlY29yYXRvcikge1xyXG4gICAgcmV0dXJuIGZ1bmN0aW9uICh0YXJnZXQsIGtleSkgeyBkZWNvcmF0b3IodGFyZ2V0LCBrZXksIHBhcmFtSW5kZXgpOyB9XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX21ldGFkYXRhKG1ldGFkYXRhS2V5LCBtZXRhZGF0YVZhbHVlKSB7XHJcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QubWV0YWRhdGEgPT09IFwiZnVuY3Rpb25cIikgcmV0dXJuIFJlZmxlY3QubWV0YWRhdGEobWV0YWRhdGFLZXksIG1ldGFkYXRhVmFsdWUpO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19hd2FpdGVyKHRoaXNBcmcsIF9hcmd1bWVudHMsIFAsIGdlbmVyYXRvcikge1xyXG4gICAgZnVuY3Rpb24gYWRvcHQodmFsdWUpIHsgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgUCA/IHZhbHVlIDogbmV3IFAoZnVuY3Rpb24gKHJlc29sdmUpIHsgcmVzb2x2ZSh2YWx1ZSk7IH0pOyB9XHJcbiAgICByZXR1cm4gbmV3IChQIHx8IChQID0gUHJvbWlzZSkpKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcclxuICAgICAgICBmdW5jdGlvbiBmdWxmaWxsZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3IubmV4dCh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9XHJcbiAgICAgICAgZnVuY3Rpb24gcmVqZWN0ZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3JbXCJ0aHJvd1wiXSh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9XHJcbiAgICAgICAgZnVuY3Rpb24gc3RlcChyZXN1bHQpIHsgcmVzdWx0LmRvbmUgPyByZXNvbHZlKHJlc3VsdC52YWx1ZSkgOiBhZG9wdChyZXN1bHQudmFsdWUpLnRoZW4oZnVsZmlsbGVkLCByZWplY3RlZCk7IH1cclxuICAgICAgICBzdGVwKChnZW5lcmF0b3IgPSBnZW5lcmF0b3IuYXBwbHkodGhpc0FyZywgX2FyZ3VtZW50cyB8fCBbXSkpLm5leHQoKSk7XHJcbiAgICB9KTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fZ2VuZXJhdG9yKHRoaXNBcmcsIGJvZHkpIHtcclxuICAgIHZhciBfID0geyBsYWJlbDogMCwgc2VudDogZnVuY3Rpb24oKSB7IGlmICh0WzBdICYgMSkgdGhyb3cgdFsxXTsgcmV0dXJuIHRbMV07IH0sIHRyeXM6IFtdLCBvcHM6IFtdIH0sIGYsIHksIHQsIGc7XHJcbiAgICByZXR1cm4gZyA9IHsgbmV4dDogdmVyYigwKSwgXCJ0aHJvd1wiOiB2ZXJiKDEpLCBcInJldHVyblwiOiB2ZXJiKDIpIH0sIHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiAoZ1tTeW1ib2wuaXRlcmF0b3JdID0gZnVuY3Rpb24oKSB7IHJldHVybiB0aGlzOyB9KSwgZztcclxuICAgIGZ1bmN0aW9uIHZlcmIobikgeyByZXR1cm4gZnVuY3Rpb24gKHYpIHsgcmV0dXJuIHN0ZXAoW24sIHZdKTsgfTsgfVxyXG4gICAgZnVuY3Rpb24gc3RlcChvcCkge1xyXG4gICAgICAgIGlmIChmKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiR2VuZXJhdG9yIGlzIGFscmVhZHkgZXhlY3V0aW5nLlwiKTtcclxuICAgICAgICB3aGlsZSAoXykgdHJ5IHtcclxuICAgICAgICAgICAgaWYgKGYgPSAxLCB5ICYmICh0ID0gb3BbMF0gJiAyID8geVtcInJldHVyblwiXSA6IG9wWzBdID8geVtcInRocm93XCJdIHx8ICgodCA9IHlbXCJyZXR1cm5cIl0pICYmIHQuY2FsbCh5KSwgMCkgOiB5Lm5leHQpICYmICEodCA9IHQuY2FsbCh5LCBvcFsxXSkpLmRvbmUpIHJldHVybiB0O1xyXG4gICAgICAgICAgICBpZiAoeSA9IDAsIHQpIG9wID0gW29wWzBdICYgMiwgdC52YWx1ZV07XHJcbiAgICAgICAgICAgIHN3aXRjaCAob3BbMF0pIHtcclxuICAgICAgICAgICAgICAgIGNhc2UgMDogY2FzZSAxOiB0ID0gb3A7IGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgY2FzZSA0OiBfLmxhYmVsKys7IHJldHVybiB7IHZhbHVlOiBvcFsxXSwgZG9uZTogZmFsc2UgfTtcclxuICAgICAgICAgICAgICAgIGNhc2UgNTogXy5sYWJlbCsrOyB5ID0gb3BbMV07IG9wID0gWzBdOyBjb250aW51ZTtcclxuICAgICAgICAgICAgICAgIGNhc2UgNzogb3AgPSBfLm9wcy5wb3AoKTsgXy50cnlzLnBvcCgpOyBjb250aW51ZTtcclxuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEodCA9IF8udHJ5cywgdCA9IHQubGVuZ3RoID4gMCAmJiB0W3QubGVuZ3RoIC0gMV0pICYmIChvcFswXSA9PT0gNiB8fCBvcFswXSA9PT0gMikpIHsgXyA9IDA7IGNvbnRpbnVlOyB9XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wWzBdID09PSAzICYmICghdCB8fCAob3BbMV0gPiB0WzBdICYmIG9wWzFdIDwgdFszXSkpKSB7IF8ubGFiZWwgPSBvcFsxXTsgYnJlYWs7IH1cclxuICAgICAgICAgICAgICAgICAgICBpZiAob3BbMF0gPT09IDYgJiYgXy5sYWJlbCA8IHRbMV0pIHsgXy5sYWJlbCA9IHRbMV07IHQgPSBvcDsgYnJlYWs7IH1cclxuICAgICAgICAgICAgICAgICAgICBpZiAodCAmJiBfLmxhYmVsIDwgdFsyXSkgeyBfLmxhYmVsID0gdFsyXTsgXy5vcHMucHVzaChvcCk7IGJyZWFrOyB9XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRbMl0pIF8ub3BzLnBvcCgpO1xyXG4gICAgICAgICAgICAgICAgICAgIF8udHJ5cy5wb3AoKTsgY29udGludWU7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgb3AgPSBib2R5LmNhbGwodGhpc0FyZywgXyk7XHJcbiAgICAgICAgfSBjYXRjaCAoZSkgeyBvcCA9IFs2LCBlXTsgeSA9IDA7IH0gZmluYWxseSB7IGYgPSB0ID0gMDsgfVxyXG4gICAgICAgIGlmIChvcFswXSAmIDUpIHRocm93IG9wWzFdOyByZXR1cm4geyB2YWx1ZTogb3BbMF0gPyBvcFsxXSA6IHZvaWQgMCwgZG9uZTogdHJ1ZSB9O1xyXG4gICAgfVxyXG59XHJcblxyXG5leHBvcnQgdmFyIF9fY3JlYXRlQmluZGluZyA9IE9iamVjdC5jcmVhdGUgPyAoZnVuY3Rpb24obywgbSwgaywgazIpIHtcclxuICAgIGlmIChrMiA9PT0gdW5kZWZpbmVkKSBrMiA9IGs7XHJcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkobywgazIsIHsgZW51bWVyYWJsZTogdHJ1ZSwgZ2V0OiBmdW5jdGlvbigpIHsgcmV0dXJuIG1ba107IH0gfSk7XHJcbn0pIDogKGZ1bmN0aW9uKG8sIG0sIGssIGsyKSB7XHJcbiAgICBpZiAoazIgPT09IHVuZGVmaW5lZCkgazIgPSBrO1xyXG4gICAgb1trMl0gPSBtW2tdO1xyXG59KTtcclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2V4cG9ydFN0YXIobSwgbykge1xyXG4gICAgZm9yICh2YXIgcCBpbiBtKSBpZiAocCAhPT0gXCJkZWZhdWx0XCIgJiYgIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChvLCBwKSkgX19jcmVhdGVCaW5kaW5nKG8sIG0sIHApO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX192YWx1ZXMobykge1xyXG4gICAgdmFyIHMgPSB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgU3ltYm9sLml0ZXJhdG9yLCBtID0gcyAmJiBvW3NdLCBpID0gMDtcclxuICAgIGlmIChtKSByZXR1cm4gbS5jYWxsKG8pO1xyXG4gICAgaWYgKG8gJiYgdHlwZW9mIG8ubGVuZ3RoID09PSBcIm51bWJlclwiKSByZXR1cm4ge1xyXG4gICAgICAgIG5leHQ6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgaWYgKG8gJiYgaSA+PSBvLmxlbmd0aCkgbyA9IHZvaWQgMDtcclxuICAgICAgICAgICAgcmV0dXJuIHsgdmFsdWU6IG8gJiYgb1tpKytdLCBkb25lOiAhbyB9O1xyXG4gICAgICAgIH1cclxuICAgIH07XHJcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKHMgPyBcIk9iamVjdCBpcyBub3QgaXRlcmFibGUuXCIgOiBcIlN5bWJvbC5pdGVyYXRvciBpcyBub3QgZGVmaW5lZC5cIik7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3JlYWQobywgbikge1xyXG4gICAgdmFyIG0gPSB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgb1tTeW1ib2wuaXRlcmF0b3JdO1xyXG4gICAgaWYgKCFtKSByZXR1cm4gbztcclxuICAgIHZhciBpID0gbS5jYWxsKG8pLCByLCBhciA9IFtdLCBlO1xyXG4gICAgdHJ5IHtcclxuICAgICAgICB3aGlsZSAoKG4gPT09IHZvaWQgMCB8fCBuLS0gPiAwKSAmJiAhKHIgPSBpLm5leHQoKSkuZG9uZSkgYXIucHVzaChyLnZhbHVlKTtcclxuICAgIH1cclxuICAgIGNhdGNoIChlcnJvcikgeyBlID0geyBlcnJvcjogZXJyb3IgfTsgfVxyXG4gICAgZmluYWxseSB7XHJcbiAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgaWYgKHIgJiYgIXIuZG9uZSAmJiAobSA9IGlbXCJyZXR1cm5cIl0pKSBtLmNhbGwoaSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGZpbmFsbHkgeyBpZiAoZSkgdGhyb3cgZS5lcnJvcjsgfVxyXG4gICAgfVxyXG4gICAgcmV0dXJuIGFyO1xyXG59XHJcblxyXG4vKiogQGRlcHJlY2F0ZWQgKi9cclxuZXhwb3J0IGZ1bmN0aW9uIF9fc3ByZWFkKCkge1xyXG4gICAgZm9yICh2YXIgYXIgPSBbXSwgaSA9IDA7IGkgPCBhcmd1bWVudHMubGVuZ3RoOyBpKyspXHJcbiAgICAgICAgYXIgPSBhci5jb25jYXQoX19yZWFkKGFyZ3VtZW50c1tpXSkpO1xyXG4gICAgcmV0dXJuIGFyO1xyXG59XHJcblxyXG4vKiogQGRlcHJlY2F0ZWQgKi9cclxuZXhwb3J0IGZ1bmN0aW9uIF9fc3ByZWFkQXJyYXlzKCkge1xyXG4gICAgZm9yICh2YXIgcyA9IDAsIGkgPSAwLCBpbCA9IGFyZ3VtZW50cy5sZW5ndGg7IGkgPCBpbDsgaSsrKSBzICs9IGFyZ3VtZW50c1tpXS5sZW5ndGg7XHJcbiAgICBmb3IgKHZhciByID0gQXJyYXkocyksIGsgPSAwLCBpID0gMDsgaSA8IGlsOyBpKyspXHJcbiAgICAgICAgZm9yICh2YXIgYSA9IGFyZ3VtZW50c1tpXSwgaiA9IDAsIGpsID0gYS5sZW5ndGg7IGogPCBqbDsgaisrLCBrKyspXHJcbiAgICAgICAgICAgIHJba10gPSBhW2pdO1xyXG4gICAgcmV0dXJuIHI7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3NwcmVhZEFycmF5KHRvLCBmcm9tLCBwYWNrKSB7XHJcbiAgICBpZiAocGFjayB8fCBhcmd1bWVudHMubGVuZ3RoID09PSAyKSBmb3IgKHZhciBpID0gMCwgbCA9IGZyb20ubGVuZ3RoLCBhcjsgaSA8IGw7IGkrKykge1xyXG4gICAgICAgIGlmIChhciB8fCAhKGkgaW4gZnJvbSkpIHtcclxuICAgICAgICAgICAgaWYgKCFhcikgYXIgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChmcm9tLCAwLCBpKTtcclxuICAgICAgICAgICAgYXJbaV0gPSBmcm9tW2ldO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuICAgIHJldHVybiB0by5jb25jYXQoYXIgfHwgQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoZnJvbSkpO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19hd2FpdCh2KSB7XHJcbiAgICByZXR1cm4gdGhpcyBpbnN0YW5jZW9mIF9fYXdhaXQgPyAodGhpcy52ID0gdiwgdGhpcykgOiBuZXcgX19hd2FpdCh2KTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fYXN5bmNHZW5lcmF0b3IodGhpc0FyZywgX2FyZ3VtZW50cywgZ2VuZXJhdG9yKSB7XHJcbiAgICBpZiAoIVN5bWJvbC5hc3luY0l0ZXJhdG9yKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiU3ltYm9sLmFzeW5jSXRlcmF0b3IgaXMgbm90IGRlZmluZWQuXCIpO1xyXG4gICAgdmFyIGcgPSBnZW5lcmF0b3IuYXBwbHkodGhpc0FyZywgX2FyZ3VtZW50cyB8fCBbXSksIGksIHEgPSBbXTtcclxuICAgIHJldHVybiBpID0ge30sIHZlcmIoXCJuZXh0XCIpLCB2ZXJiKFwidGhyb3dcIiksIHZlcmIoXCJyZXR1cm5cIiksIGlbU3ltYm9sLmFzeW5jSXRlcmF0b3JdID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpczsgfSwgaTtcclxuICAgIGZ1bmN0aW9uIHZlcmIobikgeyBpZiAoZ1tuXSkgaVtuXSA9IGZ1bmN0aW9uICh2KSB7IHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiAoYSwgYikgeyBxLnB1c2goW24sIHYsIGEsIGJdKSA+IDEgfHwgcmVzdW1lKG4sIHYpOyB9KTsgfTsgfVxyXG4gICAgZnVuY3Rpb24gcmVzdW1lKG4sIHYpIHsgdHJ5IHsgc3RlcChnW25dKHYpKTsgfSBjYXRjaCAoZSkgeyBzZXR0bGUocVswXVszXSwgZSk7IH0gfVxyXG4gICAgZnVuY3Rpb24gc3RlcChyKSB7IHIudmFsdWUgaW5zdGFuY2VvZiBfX2F3YWl0ID8gUHJvbWlzZS5yZXNvbHZlKHIudmFsdWUudikudGhlbihmdWxmaWxsLCByZWplY3QpIDogc2V0dGxlKHFbMF1bMl0sIHIpOyB9XHJcbiAgICBmdW5jdGlvbiBmdWxmaWxsKHZhbHVlKSB7IHJlc3VtZShcIm5leHRcIiwgdmFsdWUpOyB9XHJcbiAgICBmdW5jdGlvbiByZWplY3QodmFsdWUpIHsgcmVzdW1lKFwidGhyb3dcIiwgdmFsdWUpOyB9XHJcbiAgICBmdW5jdGlvbiBzZXR0bGUoZiwgdikgeyBpZiAoZih2KSwgcS5zaGlmdCgpLCBxLmxlbmd0aCkgcmVzdW1lKHFbMF1bMF0sIHFbMF1bMV0pOyB9XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2FzeW5jRGVsZWdhdG9yKG8pIHtcclxuICAgIHZhciBpLCBwO1xyXG4gICAgcmV0dXJuIGkgPSB7fSwgdmVyYihcIm5leHRcIiksIHZlcmIoXCJ0aHJvd1wiLCBmdW5jdGlvbiAoZSkgeyB0aHJvdyBlOyB9KSwgdmVyYihcInJldHVyblwiKSwgaVtTeW1ib2wuaXRlcmF0b3JdID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpczsgfSwgaTtcclxuICAgIGZ1bmN0aW9uIHZlcmIobiwgZikgeyBpW25dID0gb1tuXSA/IGZ1bmN0aW9uICh2KSB7IHJldHVybiAocCA9ICFwKSA/IHsgdmFsdWU6IF9fYXdhaXQob1tuXSh2KSksIGRvbmU6IG4gPT09IFwicmV0dXJuXCIgfSA6IGYgPyBmKHYpIDogdjsgfSA6IGY7IH1cclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fYXN5bmNWYWx1ZXMobykge1xyXG4gICAgaWYgKCFTeW1ib2wuYXN5bmNJdGVyYXRvcikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlN5bWJvbC5hc3luY0l0ZXJhdG9yIGlzIG5vdCBkZWZpbmVkLlwiKTtcclxuICAgIHZhciBtID0gb1tTeW1ib2wuYXN5bmNJdGVyYXRvcl0sIGk7XHJcbiAgICByZXR1cm4gbSA/IG0uY2FsbChvKSA6IChvID0gdHlwZW9mIF9fdmFsdWVzID09PSBcImZ1bmN0aW9uXCIgPyBfX3ZhbHVlcyhvKSA6IG9bU3ltYm9sLml0ZXJhdG9yXSgpLCBpID0ge30sIHZlcmIoXCJuZXh0XCIpLCB2ZXJiKFwidGhyb3dcIiksIHZlcmIoXCJyZXR1cm5cIiksIGlbU3ltYm9sLmFzeW5jSXRlcmF0b3JdID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpczsgfSwgaSk7XHJcbiAgICBmdW5jdGlvbiB2ZXJiKG4pIHsgaVtuXSA9IG9bbl0gJiYgZnVuY3Rpb24gKHYpIHsgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHsgdiA9IG9bbl0odiksIHNldHRsZShyZXNvbHZlLCByZWplY3QsIHYuZG9uZSwgdi52YWx1ZSk7IH0pOyB9OyB9XHJcbiAgICBmdW5jdGlvbiBzZXR0bGUocmVzb2x2ZSwgcmVqZWN0LCBkLCB2KSB7IFByb21pc2UucmVzb2x2ZSh2KS50aGVuKGZ1bmN0aW9uKHYpIHsgcmVzb2x2ZSh7IHZhbHVlOiB2LCBkb25lOiBkIH0pOyB9LCByZWplY3QpOyB9XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX21ha2VUZW1wbGF0ZU9iamVjdChjb29rZWQsIHJhdykge1xyXG4gICAgaWYgKE9iamVjdC5kZWZpbmVQcm9wZXJ0eSkgeyBPYmplY3QuZGVmaW5lUHJvcGVydHkoY29va2VkLCBcInJhd1wiLCB7IHZhbHVlOiByYXcgfSk7IH0gZWxzZSB7IGNvb2tlZC5yYXcgPSByYXc7IH1cclxuICAgIHJldHVybiBjb29rZWQ7XHJcbn07XHJcblxyXG52YXIgX19zZXRNb2R1bGVEZWZhdWx0ID0gT2JqZWN0LmNyZWF0ZSA/IChmdW5jdGlvbihvLCB2KSB7XHJcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkobywgXCJkZWZhdWx0XCIsIHsgZW51bWVyYWJsZTogdHJ1ZSwgdmFsdWU6IHYgfSk7XHJcbn0pIDogZnVuY3Rpb24obywgdikge1xyXG4gICAgb1tcImRlZmF1bHRcIl0gPSB2O1xyXG59O1xyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9faW1wb3J0U3Rhcihtb2QpIHtcclxuICAgIGlmIChtb2QgJiYgbW9kLl9fZXNNb2R1bGUpIHJldHVybiBtb2Q7XHJcbiAgICB2YXIgcmVzdWx0ID0ge307XHJcbiAgICBpZiAobW9kICE9IG51bGwpIGZvciAodmFyIGsgaW4gbW9kKSBpZiAoayAhPT0gXCJkZWZhdWx0XCIgJiYgT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG1vZCwgaykpIF9fY3JlYXRlQmluZGluZyhyZXN1bHQsIG1vZCwgayk7XHJcbiAgICBfX3NldE1vZHVsZURlZmF1bHQocmVzdWx0LCBtb2QpO1xyXG4gICAgcmV0dXJuIHJlc3VsdDtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9faW1wb3J0RGVmYXVsdChtb2QpIHtcclxuICAgIHJldHVybiAobW9kICYmIG1vZC5fX2VzTW9kdWxlKSA/IG1vZCA6IHsgZGVmYXVsdDogbW9kIH07XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHJlY2VpdmVyLCBzdGF0ZSwga2luZCwgZikge1xyXG4gICAgaWYgKGtpbmQgPT09IFwiYVwiICYmICFmKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiUHJpdmF0ZSBhY2Nlc3NvciB3YXMgZGVmaW5lZCB3aXRob3V0IGEgZ2V0dGVyXCIpO1xyXG4gICAgaWYgKHR5cGVvZiBzdGF0ZSA9PT0gXCJmdW5jdGlvblwiID8gcmVjZWl2ZXIgIT09IHN0YXRlIHx8ICFmIDogIXN0YXRlLmhhcyhyZWNlaXZlcikpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3QgcmVhZCBwcml2YXRlIG1lbWJlciBmcm9tIGFuIG9iamVjdCB3aG9zZSBjbGFzcyBkaWQgbm90IGRlY2xhcmUgaXRcIik7XHJcbiAgICByZXR1cm4ga2luZCA9PT0gXCJtXCIgPyBmIDoga2luZCA9PT0gXCJhXCIgPyBmLmNhbGwocmVjZWl2ZXIpIDogZiA/IGYudmFsdWUgOiBzdGF0ZS5nZXQocmVjZWl2ZXIpO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19jbGFzc1ByaXZhdGVGaWVsZFNldChyZWNlaXZlciwgc3RhdGUsIHZhbHVlLCBraW5kLCBmKSB7XHJcbiAgICBpZiAoa2luZCA9PT0gXCJtXCIpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJQcml2YXRlIG1ldGhvZCBpcyBub3Qgd3JpdGFibGVcIik7XHJcbiAgICBpZiAoa2luZCA9PT0gXCJhXCIgJiYgIWYpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJQcml2YXRlIGFjY2Vzc29yIHdhcyBkZWZpbmVkIHdpdGhvdXQgYSBzZXR0ZXJcIik7XHJcbiAgICBpZiAodHlwZW9mIHN0YXRlID09PSBcImZ1bmN0aW9uXCIgPyByZWNlaXZlciAhPT0gc3RhdGUgfHwgIWYgOiAhc3RhdGUuaGFzKHJlY2VpdmVyKSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCB3cml0ZSBwcml2YXRlIG1lbWJlciB0byBhbiBvYmplY3Qgd2hvc2UgY2xhc3MgZGlkIG5vdCBkZWNsYXJlIGl0XCIpO1xyXG4gICAgcmV0dXJuIChraW5kID09PSBcImFcIiA/IGYuY2FsbChyZWNlaXZlciwgdmFsdWUpIDogZiA/IGYudmFsdWUgPSB2YWx1ZSA6IHN0YXRlLnNldChyZWNlaXZlciwgdmFsdWUpKSwgdmFsdWU7XHJcbn1cclxuIiwiLypcbiAqIEZpbGVuYW1lOiBtdWx0aS1jb2x1bW4tbWFya2Rvd24vc3JjL3JlZ2lvblNldHRpbmdzLnRzXG4gKiBDcmVhdGVkIERhdGU6IFR1ZXNkYXksIEZlYnJ1YXJ5IDFzdCAyMDIyLCAxMjoyMzo1MyBwbVxuICogQXV0aG9yOiBDYW1lcm9uIFJvYmluc29uXG4gKiBcbiAqIENvcHlyaWdodCAoYykgMjAyMiBDYW1lcm9uIFJvYmluc29uXG4gKi9cblxuZXhwb3J0IGVudW0gQm9yZGVyT3B0aW9uIHtcbiAgICBlbmFibGVkLFxuICAgIG9uLFxuICAgIHRydWUsXG4gICAgZGlzYWJsZWQsXG4gICAgb2ZmLFxuICAgIGZhbHNlXG59XG5cbmV4cG9ydCBlbnVtIFNoYWRvd09wdGlvbiB7XG4gICAgZW5hYmxlZCxcbiAgICBvbixcbiAgICB0cnVlLFxuICAgIGRpc2FibGVkLFxuICAgIG9mZixcbiAgICBmYWxzZVxufVxuXG5leHBvcnQgZW51bSBDb2x1bW5MYXlvdXQgeyBcbiAgICBzdGFuZGFyZCxcbiAgICBsZWZ0LFxuICAgIGZpcnN0LFxuICAgIGNlbnRlcixcbiAgICBtaWRkbGUsXG4gICAgc2Vjb25kLFxuICAgIHJpZ2h0LFxuICAgIHRoaXJkLFxuICAgIGxhc3Rcbn07XG5cbmV4cG9ydCB0eXBlIE11bHRpQ29sdW1uU2V0dGluZ3MgPSB7XG4gICAgbnVtYmVyT2ZDb2x1bW5zOiBudW1iZXIsXG4gICAgY29sdW1uTGF5b3V0OiBDb2x1bW5MYXlvdXQsXG4gICAgZHJhd0JvcmRlcjogYm9vbGVhbixcbiAgICBkcmF3U2hhZG93OiBib29sZWFuXG59IiwiLypcbiAqIEZpbGU6IG11bHRpLWNvbHVtbi1tYXJrZG93bi9zcmMvTXVsdGlDb2x1bW5QYXJzZXIudHNcbiAqIENyZWF0ZWQgRGF0ZTogU2F0dXJkYXksIEphbnVhcnkgMjJuZCAyMDIyLCA2OjAyOjQ2IHBtXG4gKiBBdXRob3I6IENhbWVyb24gUm9iaW5zb25cbiAqIFxuICogQ29weXJpZ2h0IChjKSAyMDIyIENhbWVyb24gUm9iaW5zb25cbiAqL1xuXG5pbXBvcnQgeyBNdWx0aUNvbHVtblNldHRpbmdzLCBDb2x1bW5MYXlvdXQsIEJvcmRlck9wdGlvbiwgU2hhZG93T3B0aW9uIH0gZnJvbSBcIi4uL3JlZ2lvblNldHRpbmdzXCI7XG5cbmNvbnN0IFNUQVJUX1JFR0VYX1NUUlMgPSBbXCI9PT0gKnN0YXJ0LW11bHRpLWNvbHVtblwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICBcIj09PSAqbXVsdGktY29sdW1uLXN0YXJ0XCJdXG5jb25zdCBTVEFSVF9SRUdFWF9BUlI6IFJlZ0V4cFtdID0gW107XG5mb3IobGV0IGkgPSAwOyBpIDwgU1RBUlRfUkVHRVhfU1RSUy5sZW5ndGg7IGkrKykge1xuICAgIFNUQVJUX1JFR0VYX0FSUi5wdXNoKG5ldyBSZWdFeHAoU1RBUlRfUkVHRVhfU1RSU1tpXSkpO1xufVxuZnVuY3Rpb24gZmluZFN0YXJ0VGFnKHRleHQ6IHN0cmluZyk6IHsgZm91bmQ6IGJvb2xlYW4sIHN0YXJ0UG9zaXRpb246IG51bWJlciB9IHtcblxuICAgIGxldCBmb3VuZCA9IGZhbHNlO1xuICAgIGxldCBzdGFydFBvc2l0aW9uID0gLTE7XG4gICAgZm9yKGxldCBpID0gMDsgaTwgU1RBUlRfUkVHRVhfQVJSLmxlbmd0aDsgaSsrKSB7XG5cbiAgICAgICAgaWYoU1RBUlRfUkVHRVhfQVJSW2ldLnRlc3QodGV4dCkpIHtcbiAgICAgICAgICAgIGZvdW5kID0gdHJ1ZTtcbiAgICAgICAgICAgIHN0YXJ0UG9zaXRpb24gPSB0ZXh0LnNlYXJjaChTVEFSVF9SRUdFWF9TVFJTW2ldKVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4geyBmb3VuZCwgc3RhcnRQb3NpdGlvbiB9O1xufVxuZXhwb3J0IGZ1bmN0aW9uIGNvbnRhaW5zU3RhcnRUYWcodGV4dDogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIGZpbmRTdGFydFRhZyh0ZXh0KS5mb3VuZFxufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNTdGFydFRhZ1dpdGhJRCh0ZXh0OiBzdHJpbmcpOiB7aXNTdGFydFRhZzogYm9vbGVhbiwgaGFzS2V5OiBib29sZWFufSB7XG5cbiAgICBsZXQgc3RhcnRUYWdEYXRhID0gZmluZFN0YXJ0VGFnKHRleHQpO1xuICAgIGlmKHN0YXJ0VGFnRGF0YS5mb3VuZCA9PT0gdHJ1ZSkge1xuXG4gICAgICAgIGxldCBrZXkgPSBnZXRTdGFydFRhZ0tleSh0ZXh0KVxuICAgICAgICBpZihrZXkgPT09IG51bGwgfHwga2V5ID09PSBcIlwiKSB7XG4gICAgICAgICAgICByZXR1cm4ge2lzU3RhcnRUYWc6IHRydWUsIGhhc0tleTogZmFsc2V9O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7aXNTdGFydFRhZzogdHJ1ZSwgaGFzS2V5OiB0cnVlfTtcbiAgICB9XG5cbiAgICByZXR1cm4ge2lzU3RhcnRUYWc6IGZhbHNlLCBoYXNLZXk6IGZhbHNlfTtcbn1cblxuY29uc3QgRU5EX1JFR0VYX1NUUlMgPSBbXCI9PT0gKmVuZC1tdWx0aS1jb2x1bW5cIixcbiAgICAgICAgICAgICAgICAgICAgICAgIFwiPT09ICptdWx0aS1jb2x1bW4tZW5kXCJdXG5jb25zdCBFTkRfUkVHRVhfQVJSOiBSZWdFeHBbXSA9IFtdO1xuZm9yKGxldCBpID0gMDsgaSA8IEVORF9SRUdFWF9TVFJTLmxlbmd0aDsgaSsrKSB7XG4gICAgRU5EX1JFR0VYX0FSUi5wdXNoKG5ldyBSZWdFeHAoRU5EX1JFR0VYX1NUUlNbaV0pKTtcbn1cbmZ1bmN0aW9uIGZpbmRFbmRUYWcodGV4dDogc3RyaW5nKTogeyBmb3VuZDogYm9vbGVhbiwgc3RhcnRQb3NpdGlvbjogbnVtYmVyIH0ge1xuXG4gICAgbGV0IGZvdW5kID0gZmFsc2U7XG4gICAgbGV0IHN0YXJ0UG9zaXRpb24gPSAtMTtcbiAgICBmb3IobGV0IGkgPSAwOyBpPCBFTkRfUkVHRVhfQVJSLmxlbmd0aDsgaSsrKSB7XG5cbiAgICAgICAgaWYoRU5EX1JFR0VYX0FSUltpXS50ZXN0KHRleHQpKSB7XG4gICAgICAgICAgICBmb3VuZCA9IHRydWU7XG4gICAgICAgICAgICBzdGFydFBvc2l0aW9uID0gdGV4dC5zZWFyY2goRU5EX1JFR0VYX1NUUlNbaV0pXG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB7IGZvdW5kLCBzdGFydFBvc2l0aW9uIH07XG59XG5leHBvcnQgZnVuY3Rpb24gY29udGFpbnNFbmRUYWcodGV4dDogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIGZpbmRFbmRUYWcodGV4dCkuZm91bmRcbn1cblxuY29uc3QgQ09MX1JFR0VYX1NUUlM6IHN0cmluZ1tdID0gW1wiPT09ICpjb2x1bW4tZW5kICo9PT1cIixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIj09PSAqZW5kLWNvbHVtbiAqPT09XCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCI9PT0gKmNvbHVtbi1icmVhayAqPT09XCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCI9PT0gKmJyZWFrLWNvbHVtbiAqPT09XCJdO1xuY29uc3QgQ09MX1JFR0VYX0FSUjogUmVnRXhwW10gPSBbXTtcbmZvcihsZXQgaSA9IDA7IGkgPCBDT0xfUkVHRVhfU1RSUy5sZW5ndGg7IGkrKykge1xuICAgIENPTF9SRUdFWF9BUlIucHVzaChuZXcgUmVnRXhwKENPTF9SRUdFWF9TVFJTW2ldKSk7XG59XG5leHBvcnQgZnVuY3Rpb24gY29udGFpbnNDb2xFbmRUYWcodGV4dDogc3RyaW5nKTogYm9vbGVhbiB7XG5cbiAgICBsZXQgZm91bmQgPSBmYWxzZTtcbiAgICBmb3IobGV0IGkgPSAwOyBpPCBDT0xfUkVHRVhfQVJSLmxlbmd0aDsgaSsrKSB7XG5cbiAgICAgICAgaWYoQ09MX1JFR0VYX0FSUltpXS50ZXN0KHRleHQpKSB7XG4gICAgICAgICAgICBmb3VuZCA9IHRydWU7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBmb3VuZDtcbn1cblxuY29uc3QgQ09MX1NFVFRJTkdTX1JFR0VYX1NUUlMgPSBbXCJgYGBzZXR0aW5nc1wiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJgYGBjb2x1bW4tc2V0dGluZ3NcIixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiYGBgbXVsdGktY29sdW1uLXNldHRpbmdzXCJdO1xuY29uc3QgQ09MX1NFVFRJTkdTX1JFR0VYX0FSUjogUmVnRXhwW10gPSBbXTtcbmZvcihsZXQgaSA9IDA7IGkgPCBDT0xfU0VUVElOR1NfUkVHRVhfU1RSUy5sZW5ndGg7IGkrKykge1xuICAgIENPTF9TRVRUSU5HU19SRUdFWF9BUlIucHVzaChuZXcgUmVnRXhwKENPTF9TRVRUSU5HU19SRUdFWF9TVFJTW2ldKSk7XG59XG5leHBvcnQgZnVuY3Rpb24gY29udGFpbnNDb2xTZXR0aW5nc1RhZyh0ZXh0OiBzdHJpbmcpOiBib29sZWFuIHtcblxuICAgIGxldCBmb3VuZCA9IGZhbHNlO1xuICAgIGZvcihsZXQgaSA9IDA7IGk8IENPTF9TRVRUSU5HU19SRUdFWF9BUlIubGVuZ3RoOyBpKyspIHtcblxuICAgICAgICBpZihDT0xfU0VUVElOR1NfUkVHRVhfQVJSW2ldLnRlc3QodGV4dCkpIHtcbiAgICAgICAgICAgIGZvdW5kID0gdHJ1ZTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGZvdW5kO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VDb2x1bW5TZXR0aW5ncyhzZXR0aW5nc1N0cjogc3RyaW5nKTogTXVsdGlDb2x1bW5TZXR0aW5ncyB7XG5cbiAgICAvLyBTZXQgdGhlIG1pbmltdW0gbnVtYmVyIG9mIGNvbHVtbmRzIHRvIDIuXG4gICAgbGV0IG51bWJlck9mQ29sdW1ucyA9IDI7XG4gICAgbGV0IGNvbHVtbkxheW91dDogQ29sdW1uTGF5b3V0ID0gQ29sdW1uTGF5b3V0LnN0YW5kYXJkXG4gICAgbGV0IGJvcmRlckRyYXduOiBib29sZWFuID0gdHJ1ZTtcbiAgICBsZXQgc2hhZG93RHJhd246IGJvb2xlYW4gPSB0cnVlO1xuXG4gICAgbGV0IHNldHRpbmdzTGluZXMgPSBzZXR0aW5nc1N0ci5zcGxpdChcIlxcblwiKTtcblxuICAgIGZvcihsZXQgaSA9IDA7IGkgPCBzZXR0aW5nc0xpbmVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGlmKHNldHRpbmdzTGluZXNbaV0udG9Mb3dlckNhc2UoKS5yZXBsYWNlKC9cXHMvZywgXCJcIikuY29udGFpbnMoXCJudW1iZXJvZmNvbHVtbnM6XCIpKSB7XG4gICAgICAgICAgICBsZXQgdXNlckRlZk51bWJlck9mQ29scyA9IHBhcnNlSW50KHNldHRpbmdzTGluZXNbaV0uc3BsaXQoXCI6XCIpWzFdKVxuXG4gICAgICAgICAgICBpZihOdW1iZXIuaXNOYU4odXNlckRlZk51bWJlck9mQ29scykgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgICAgaWYodXNlckRlZk51bWJlck9mQ29scyA9PT0gMykge1xuICAgICAgICAgICAgICAgICAgICBudW1iZXJPZkNvbHVtbnMgPSAzXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYodXNlckRlZk51bWJlck9mQ29scyA9PT0gMikge1xuICAgICAgICAgICAgICAgICAgICBudW1iZXJPZkNvbHVtbnMgPSAyO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmb3IobGV0IGkgPSAwOyBpIDwgc2V0dGluZ3NMaW5lcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZihzZXR0aW5nc0xpbmVzW2ldLnRvTG93ZXJDYXNlKCkucmVwbGFjZSgvXFxzL2csIFwiXCIpLmNvbnRhaW5zKFwibGFyZ2VzdGNvbHVtbjpcIikpIHtcblxuICAgICAgICAgICAgbGV0IHNldHRpbmcgPSBzZXR0aW5nc0xpbmVzW2ldLnNwbGl0KFwiOlwiKVsxXS50cmltU3RhcnQoKS50cmltRW5kKCkudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgICAgIGxldCB1c2VyRGVmTGF5b3V0OiBDb2x1bW5MYXlvdXQgPSAoPGFueT5Db2x1bW5MYXlvdXQpW3NldHRpbmddXG5cbiAgICAgICAgICAgIGlmKHVzZXJEZWZMYXlvdXQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIGNvbHVtbkxheW91dCA9IHVzZXJEZWZMYXlvdXQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmb3IobGV0IGkgPSAwOyBpIDwgc2V0dGluZ3NMaW5lcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZihzZXR0aW5nc0xpbmVzW2ldLnRvTG93ZXJDYXNlKCkucmVwbGFjZSgvXFxzL2csIFwiXCIpLmNvbnRhaW5zKFwiYm9yZGVyOlwiKSkge1xuXG4gICAgICAgICAgICBsZXQgc2V0dGluZyA9IHNldHRpbmdzTGluZXNbaV0uc3BsaXQoXCI6XCIpWzFdLnRyaW1TdGFydCgpLnRyaW1FbmQoKS50b0xvd2VyQ2FzZSgpO1xuICAgICAgICAgICAgbGV0IGlzQm9yZGVyRHJhd246IEJvcmRlck9wdGlvbiA9ICg8YW55PkJvcmRlck9wdGlvbilbc2V0dGluZ11cblxuICAgICAgICAgICAgaWYoaXNCb3JkZXJEcmF3biAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgc3dpdGNoKGlzQm9yZGVyRHJhd24pe1xuICAgICAgICAgICAgICAgICAgICBjYXNlKEJvcmRlck9wdGlvbi5kaXNhYmxlZCk6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UoQm9yZGVyT3B0aW9uLm9mZik6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UoQm9yZGVyT3B0aW9uLmZhbHNlKTpcbiAgICAgICAgICAgICAgICAgICAgICAgIGJvcmRlckRyYXduID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmb3IobGV0IGkgPSAwOyBpIDwgc2V0dGluZ3NMaW5lcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZihzZXR0aW5nc0xpbmVzW2ldLnRvTG93ZXJDYXNlKCkucmVwbGFjZSgvXFxzL2csIFwiXCIpLmNvbnRhaW5zKFwic2hhZG93OlwiKSkge1xuXG4gICAgICAgICAgICBsZXQgc2V0dGluZyA9IHNldHRpbmdzTGluZXNbaV0uc3BsaXQoXCI6XCIpWzFdLnRyaW1TdGFydCgpLnRyaW1FbmQoKS50b0xvd2VyQ2FzZSgpO1xuICAgICAgICAgICAgbGV0IGlzU2hhZG93RHJhd246IFNoYWRvd09wdGlvbiA9ICg8YW55PlNoYWRvd09wdGlvbilbc2V0dGluZ11cblxuICAgICAgICAgICAgaWYoaXNTaGFkb3dEcmF3biAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgc3dpdGNoKGlzU2hhZG93RHJhd24pe1xuICAgICAgICAgICAgICAgICAgICBjYXNlKFNoYWRvd09wdGlvbi5kaXNhYmxlZCk6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UoU2hhZG93T3B0aW9uLm9mZik6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UoU2hhZG93T3B0aW9uLmZhbHNlKTpcbiAgICAgICAgICAgICAgICAgICAgICAgIHNoYWRvd0RyYXduID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBsZXQgc2V0dGluZ3MgPSB7IG51bWJlck9mQ29sdW1ucywgY29sdW1uTGF5b3V0LCBkcmF3Qm9yZGVyOiBib3JkZXJEcmF3biwgZHJhd1NoYWRvdzogc2hhZG93RHJhd24gfVxuXG4gICAgcmV0dXJuIHNldHRpbmdzO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY291bnRTdGFydFRhZ3ModGV4dDogc3RyaW5nKTogeyBudW1iZXJPZlRhZ3M6IG51bWJlciwga2V5czogc3RyaW5nW10gfSB7XG5cbiAgICBsZXQga2V5czogc3RyaW5nW10gPSBbXTtcbiAgICBsZXQgc3RhcnRUYWdEYXRhID0gZmluZFN0YXJ0VGFnKHRleHQpO1xuICAgIHdoaWxlKHN0YXJ0VGFnRGF0YS5mb3VuZCkge1xuICAgICAgICBcbiAgICAgICAgLy8gU2xpY2Ugb2ZmIGV2ZXJ5dGhpbmcgYmVmb3JlIHRoZSB0YWdcbiAgICAgICAgdGV4dCA9IHRleHQuc2xpY2Uoc3RhcnRUYWdEYXRhLnN0YXJ0UG9zaXRpb24pO1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBHZXQganVzdCB0aGUgc3RhcnQgdGFnIGxpbmUgYW5kIHRoZW4gc2V0IHRleHQgdG8gZXZlcnl0aGluZyBqdXN0XG4gICAgICAgICAqIGFmdGVyIHRoZSBzdGFydCB0YWcuXG4gICAgICAgICAqL1xuICAgICAgICBsZXQgdGFnID0gdGV4dC5zcGxpdChcIlxcblwiKVswXTtcbiAgICAgICAgdGV4dCA9IHRleHQuc2xpY2UoMSk7IC8vIFRoaXMgbW92ZXMgdGhlIHRleHQgMSBjaGFyYWN0ZXIgc28gd2UgZG9udCBtYXRjaCB0aGUgc2FtZSB0YWcuXG5cbiAgICAgICAgLy8gUGFyc2Ugb3V0IHRoZSBrZXkgYW5kIGFwcGVuZCB0byB0aGUgbGlzdC5cbiAgICAgICAgbGV0IGtleSA9IGdldFN0YXJ0VGFnS2V5KHRhZyk7XG4gICAgICAgIGlmKGtleSA9PT0gbnVsbCkge1xuICAgICAgICAgICAga2V5ID0gXCJcIlxuICAgICAgICB9XG4gICAgICAgIGtleXMucHVzaChrZXkpO1xuXG4gICAgICAgIC8vIFNlYXJjaCBhZ2FpbiBmb3IgYW5vdGhlciB0YWcgYmVmb3JlIGxvb3BpbmcuXG4gICAgICAgIHN0YXJ0VGFnRGF0YSA9IGZpbmRTdGFydFRhZyh0ZXh0KTtcbiAgICB9XG5cbiAgICByZXR1cm4geyBudW1iZXJPZlRhZ3M6IGtleXMubGVuZ3RoLCBrZXlzIH07XG59XG5cbi8qKlxuICogVGhpcyBmdW5jdGlvbiB3aWxsIGZpbHRlciBhIHNldCBvZiBzdHJpbmdzLCByZXR1cm5pbmcgYWxsIGl0ZW1zIHN0YXJ0aW5nXG4gKiBmcm9tIHRoZSBjbG9zZXN0IG9wZW4gc3RhcnQgdGFnIHRocm91Z2ggdGhlIGxhc3QgaXRlbSBpbiB0aGUgc2V0LiBcbiAqIFxuICogVGhlIGZ1bmN0aW9uIGZpbHRlcnMgb3V0IGFsbCBlbmQgdGFncyB0byBtYWtlIHN1cmUgdGhhdCB0aGUgc3RhcnQgdGFnIHdlIFxuICogZmluZCBpcyB0aGUgcHJvcGVyIHN0YXJ0IHRhZyBmb3IgdGhlIGxpc3Qgc2VudC4gXG4gKiBAcGFyYW0gbGluZXNBYm92ZUFycmF5IFxuICogQHJldHVybnMgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRTdGFydEJsb2NrQWJvdmVMaW5lKGxpbmVzQWJvdmVBcnJheTogc3RyaW5nW10pOiB7IHN0YXJ0QmxvY2tLZXk6IHN0cmluZywgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmVzQWJvdmVBcnJheTogc3RyaW5nW10gfSB8IG51bGwge1xuXG4gICAgLy8gUmVkdWNlIHRoZSBhcnJheSBkb3duIGludG8gYSBzaW5nbGUgc3RyaW5nIHNvIHRoYXQgd2UgY2FuXG4gICAgLy8gZWFzaWx5IFJlZ0V4IG92ZXIgdGhlIHN0cmluZyBhbmQgZmluZCB0aGUgaW5kaWNpZXMgd2UncmUgbG9va2luZyBmb3IuXG4gICAgbGV0IGxpbmVzQWJvdmVTdHIgPSBsaW5lc0Fib3ZlQXJyYXkucmVkdWNlKChwcmV2LCBjdXJyZW50KSA9PiB7XG4gICAgICAgIHJldHVybiBwcmV2ICsgXCJcXG5cIiAgKyBjdXJyZW50O1xuICAgIH0sIFwiXCIpO1xuXG4gICAgLypcbiAgICAgICAgKiBGaXJzdCB0aGluZyB3ZSBuZWVkIHRvIGRvIGlzIGNoZWNrIGlmIHRoZXJlIGFyZSBhbnkgZW5kIHRhZ3MgaW4gdGhlXG4gICAgICAgICogc2V0IG9mIHN0cmluZ3MgKHdoaWNoIGxvZ2ljYWxseSB3b3VsZCBjbG9zZSBzdGFydCB0YWdzIGFuZCB0aGVyZWZvcmVcbiAgICAgICAgKiB0aGUgc3RhcnQgdGFnIGl0IGNsb3NlcyBpcyBub3Qgd2hhdCB3ZSB3YW50KS4gSWYgdGhlcmUgYXJlIHdlIHdhbnQgdG8gXG4gICAgICAgICogc2xvd2x5IG5hcnJvdyBkb3duIG91ciBzZXQgb2Ygc3RyaW5ncyB1bnRpbCB0aGUgbGFzdCBlbmQgdGFnIGlzIFxuICAgICAgICAqIHJlbW92ZWQuIFRoaXMgbWFrZXMgaXQgZWFzaWVyIHRvIGZpbmQgdGhlIGNsb3Nlc3Qgb3BlbiBzdGFydCB0YWcgXG4gICAgICAgICogaW4gdGhlIGRhdGEuXG4gICAgICAgICovXG4gICAgbGV0IGVuZFRhZ1NlcmFjaERhdGEgPSBmaW5kRW5kVGFnKGxpbmVzQWJvdmVTdHIpO1xuICAgIHdoaWxlKGVuZFRhZ1NlcmFjaERhdGEuZm91bmQgPT09IHRydWUpIHtcblxuICAgICAgICAvLyBHZXQgdGhlIGluZGV4IG9mIHdoZXJlIHRoZSBmaXJzdCByZWdleCBtYXRjaCBpbiB0aGVcbiAgICAgICAgLy8gc3RyaW5nIGlzLiB0aGVuIHdlIHNsaWNlIGZyb20gMCB0byBpbmRleCBvZmYgb2YgdGhlIHN0cmluZ1xuICAgICAgICAvLyBzcGxpdCBpdCBieSBuZXdsaW5lLCBjdXQgb2ZmIHRoZSBmaXJzdCBsaW5lICh3aGljaCBhY3R1YWxseVxuICAgICAgICAvLyBjb250YWlucyB0aGUgcmVnZXgpIHRoZW4gcmVkdWNlIGJhY2sgZG93biB0byBhIHNpbmdsZSBzdHJpbmcuXG4gICAgICAgIC8vXG4gICAgICAgIC8vIFRPRE86IFRoaXMgY291bGQgYmUgc2ltcGxpZmllZCBpZiB3ZSBqdXN0IHNsaWNlIHRoZSB0ZXh0IGFmdGVyXG4gICAgICAgIC8vIHRoZSBlbmQgdGFnIGluc3RlYWQgb2YgdGhlIGJlZ2luaW5nLlxuICAgICAgICBsZXQgaW5kZXhPZlJlZ2V4ID0gZW5kVGFnU2VyYWNoRGF0YS5zdGFydFBvc2l0aW9uO1xuICAgICAgICBsaW5lc0Fib3ZlQXJyYXkgPSBsaW5lc0Fib3ZlU3RyLnNsaWNlKGluZGV4T2ZSZWdleCkuc3BsaXQoXCJcXG5cIikuc3BsaWNlKDEpXG4gICAgICAgIGxpbmVzQWJvdmVTdHIgPSBsaW5lc0Fib3ZlQXJyYXkucmVkdWNlKChwcmV2LCBjdXJyZW50KSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gcHJldiArIFwiXFxuXCIgICsgY3VycmVudDtcbiAgICAgICAgfSwgXCJcIik7XG4gICAgICAgIGVuZFRhZ1NlcmFjaERhdGEgPSBmaW5kRW5kVGFnKGxpbmVzQWJvdmVTdHIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE5vdyB3ZSBoYXZlIHRoZSBzZXQgb2YgbGluZXMgYWZ0ZXIgYWxsIG90aGVyIGVuZCB0YWdzLiBXZSBub3dcbiAgICAgKiBuZWVkIHRvIGNoZWNrIGlmIHRoZXJlIGlzIHN0aWxsIGEgc3RhcnQgdGFnIGxlZnQgaW4gdGhlIGRhdGEuIElmIFxuICAgICAqIHRoZXJlIGlzIG5vIHN0YXJ0IHRhZyB0aGVuIHdlIHdhbnQgdG8gcmV0dXJuIGFuIGVtcHR5IGFycmF5IGFuZCBlbXB0eSBcbiAgICAgKiBrZXkuXG4gICAgICovIFxuICAgIGxldCBzdGFydEJsb2NrS2V5ID0gXCJcIjtcbiAgICBsZXQgc3RhcnRUYWdTZWFyY2hEYXRhID0gZmluZFN0YXJ0VGFnKGxpbmVzQWJvdmVTdHIpO1xuICAgIGlmKHN0YXJ0VGFnU2VhcmNoRGF0YS5mb3VuZCA9PT0gZmFsc2UpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIGVsc2Uge1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBOb3cgd2Uga25vdyB0aGVyZSBpcyBhdCBsZWFzdCAxIHN0YXJ0IGtleSBsZWZ0LCBob3dldmVyIHRoZXJlXG4gICAgICAgICAqIG1heSBiZSBtdWx0aXBsZSBzdGFydCBrZXlzIGlmIHRoZSB1c2VyIGlzIG5vdCBjbG9zaW5nIHRoZWlyXG4gICAgICAgICAqIGJsb2Nrcy4gV2UgY3VycmVudGx5IGRvbnQgYWxsb3cgcmVjdXNpdmUgc3BsaXR0aW5nIHNvIHdlIFxuICAgICAgICAgKiB3YW50IHRvIGdldCB0aGUgbGFzdCBrZXkgaW4gb3VyIHJlbWFpbmluZyBzZXQuIFNhbWUgaWRlYSBhc1xuICAgICAgICAgKiBhYm92ZS5cbiAgICAgICAgICovXG4gICAgICAgIHdoaWxlKHN0YXJ0VGFnU2VhcmNoRGF0YS5mb3VuZCA9PT0gdHJ1ZSkge1xuXG4gICAgICAgICAgICAvLyBHZXQgdGhlIGluZGV4IG9mIHdoZXJlIHRoZSBmaXJzdCByZWdleCBtYXRjaCBpbiB0aGVcbiAgICAgICAgICAgIC8vIHN0cmluZyBpcy4gdGhlbiB3ZSBzbGljZSBmcm9tIDAgdG8gaW5kZXggb2ZmIG9mIHRoZSBzdHJpbmdcbiAgICAgICAgICAgIC8vIHNwbGl0IGl0IGJ5IG5ld2xpbmUsIGN1dCBvZmYgdGhlIGZpcnN0IGxpbmUgKHdoaWNoIGFjdHVhbGx5XG4gICAgICAgICAgICAvLyBjb250YWlucyB0aGUgcmVnZXgpIHRoZW4gcmVkdWNlIGJhY2sgZG93biB0byBhIHNpbmdsZSBzdHJpbmcuXG4gICAgICAgICAgICAvL1xuICAgICAgICAgICAgLy8gVE9ETzogVGhpcyBjb3VsZCBiZSBzaW1wbGlmaWVkIGlmIHdlIGp1c3Qgc2xpY2UgdGhlIHRleHQgYWZ0ZXJcbiAgICAgICAgICAgIC8vIHRoZSBlbmQgdGFnIGluc3RlYWQgb2YgdGhlIGJlZ2luaW5nLlxuICAgICAgICAgICAgbGV0IHN0YXJ0SW5kZXggPSBzdGFydFRhZ1NlYXJjaERhdGEuc3RhcnRQb3NpdGlvbjtcblxuICAgICAgICAgICAgbGluZXNBYm92ZUFycmF5ID0gbGluZXNBYm92ZVN0ci5zbGljZShzdGFydEluZGV4KS5zcGxpdChcIlxcblwiKVxuICAgICAgICAgICAgXG4gICAgICAgICAgICBsZXQgc3RhcnRUYWcgPSBsaW5lc0Fib3ZlQXJyYXlbMF07XG4gICAgICAgICAgICBsZXQga2V5ID0gZ2V0U3RhcnRUYWdLZXkoc3RhcnRUYWcpO1xuICAgICAgICAgICAgaWYoa2V5ICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgc3RhcnRCbG9ja0tleSA9IGtleTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbGluZXNBYm92ZUFycmF5ID0gbGluZXNBYm92ZUFycmF5LnNwbGljZSgxKVxuICAgICAgICAgICAgbGluZXNBYm92ZVN0ciA9IGxpbmVzQWJvdmVBcnJheS5yZWR1Y2UoKHByZXYsIGN1cnJlbnQpID0+IHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcHJldiArIFwiXFxuXCIgICsgY3VycmVudDtcbiAgICAgICAgICAgIH0sIFwiXCIpO1xuXG4gICAgICAgICAgICBzdGFydFRhZ1NlYXJjaERhdGEgPSBmaW5kU3RhcnRUYWcobGluZXNBYm92ZVN0cik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4geyBzdGFydEJsb2NrS2V5LCBsaW5lc0Fib3ZlQXJyYXkgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldEVuZEJsb2NrQmVsb3cobGluZXNCZWxvdzogc3RyaW5nW10pOiBzdHJpbmdbXSB7XG5cbiAgICAvLyBSZWR1Y2UgdGhlIGFycmF5IGRvd24gaW50byBhIHNpbmdsZSBzdHJpbmcgc28gdGhhdCB3ZSBjYW5cbiAgICAvLyBlYXNpbHkgUmVnRXggb3ZlciB0aGUgc3RyaW5nIGFuZCBmaW5kIHRoZSBpbmRpY2llcyB3ZSdyZSBsb29raW5nIGZvci5cbiAgICBsZXQgbGluZXNCZWxvd1N0ciA9IGxpbmVzQmVsb3cucmVkdWNlKChwcmV2LCBjdXJyZW50KSA9PiB7XG4gICAgICAgIHJldHVybiBwcmV2ICsgXCJcXG5cIiAgKyBjdXJyZW50O1xuICAgIH0sIFwiXCIpO1xuICAgIGxldCBlbmRUYWdTZXJhY2hEYXRhID0gZmluZEVuZFRhZyhsaW5lc0JlbG93U3RyKTtcbiAgICBsZXQgc3RhcnRUYWdTZWFyY2hEYXRhID0gZmluZFN0YXJ0VGFnKGxpbmVzQmVsb3dTdHIpO1xuXG4gICAgbGV0IHNsaWNlRW5kSW5kZXggPSAtMTsgLy8gSWYgbmVpdGhlciBzdGFydCBvciBlbmQgZm91bmQgd2UgcmV0dXJuIHRoZSBlbnRpcmUgYXJyYXkuXG4gICAgaWYoZW5kVGFnU2VyYWNoRGF0YS5mb3VuZCA9PT0gdHJ1ZSAmJiBzdGFydFRhZ1NlYXJjaERhdGEuZm91bmQgPT09IGZhbHNlKSB7XG5cbiAgICAgICAgc2xpY2VFbmRJbmRleCA9IGVuZFRhZ1NlcmFjaERhdGEuc3RhcnRQb3NpdGlvbjtcbiAgICB9XG4gICAgZWxzZSBpZihlbmRUYWdTZXJhY2hEYXRhLmZvdW5kID09PSBmYWxzZSAmJiBzdGFydFRhZ1NlYXJjaERhdGEuZm91bmQgPT09IHRydWUpIHtcblxuICAgICAgICBzbGljZUVuZEluZGV4ID0gc3RhcnRUYWdTZWFyY2hEYXRhLnN0YXJ0UG9zaXRpb247XG4gICAgfVxuICAgIGVsc2UgaWYoZW5kVGFnU2VyYWNoRGF0YS5mb3VuZCA9PT0gdHJ1ZSAmJiBzdGFydFRhZ1NlYXJjaERhdGEuZm91bmQgPT09IHRydWUpIHtcblxuICAgICAgICBzbGljZUVuZEluZGV4ID0gZW5kVGFnU2VyYWNoRGF0YS5zdGFydFBvc2l0aW9uO1xuICAgICAgICBpZihzdGFydFRhZ1NlYXJjaERhdGEuc3RhcnRQb3NpdGlvbiA8IGVuZFRhZ1NlcmFjaERhdGEuc3RhcnRQb3NpdGlvbikge1xuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIElmIHdlIGZvdW5kIGEgc3RhcnQgdGFnIGJlZm9yZSBhbiBlbmQgdGFnIHdlIHdhbnQgdG8gdXNlIHRoZSBzdGFydCB0YWdcbiAgICAgICAgICAgICAqIG91ciBjdXJyZW50IGJsb2NrIGlzIG5vdCBwcm9wZXJseSBlbmRlZCBhbmQgd2UgdXNlIHRoZSBuZXh0IHN0YXJ0IHRhZyBcbiAgICAgICAgICAgICAqIGFzIG91ciBsaW1pdFxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBzbGljZUVuZEluZGV4ID0gc3RhcnRUYWdTZWFyY2hEYXRhLnN0YXJ0UG9zaXRpb247XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gbGluZXNCZWxvdy5zbGljZSgwLCBzbGljZUVuZEluZGV4KTtcbn1cblxuZnVuY3Rpb24gZ2V0U3RhcnRUYWdLZXkoc3RhcnRUYWc6IHN0cmluZyk6IHN0cmluZyB8IG51bGwge1xuXG4gICAgbGV0IGtleVNwbGl0ID0gc3RhcnRUYWcuc3BsaXQoXCI6XCIpO1xuICAgIGlmKGtleVNwbGl0Lmxlbmd0aCA+IDEpe1xuICAgICAgICByZXR1cm4ga2V5U3BsaXRbMV0ucmVwbGFjZShcIiBcIiwgXCJcIilcbiAgICB9XG5cbiAgICByZXR1cm4gbnVsbDtcbn1cbiIsIi8qXG4gKiBGaWxlbmFtZTogbXVsdGktY29sdW1uLW1hcmtkb3duL3NyYy91dGlsaXRpZXMvdXRpbHMudHNcbiAqIENyZWF0ZWQgRGF0ZTogVHVlc2RheSwgSmFudWFyeSAzMHRoIDIwMjIsIDQ6MDI6MTkgcG1cbiAqIEF1dGhvcjogQ2FtZXJvbiBSb2JpbnNvblxuICogXG4gKiBDb3B5cmlnaHQgKGMpIDIwMjIgQ2FtZXJvbiBSb2JpbnNvblxuICovXG5cblxuZXhwb3J0IGZ1bmN0aW9uIGdldFVJRChsZW5ndGg6IG51bWJlciA9IDEwKTogc3RyaW5nIHtcblxuICAgIGlmKGxlbmd0aCA+IDEwKSB7XG4gICAgICAgIGxlbmd0aCA9IDEwO1xuICAgIH1cbiAgICBsZXQgVUlEID0gTWF0aC5yYW5kb20oKS50b1N0cmluZygzNikuc3Vic3RyaW5nKDIpO1xuICAgIFVJRCA9IFVJRC5zbGljZSgwLCBsZW5ndGgpO1xuICAgIFxuICAgIHJldHVybiBVSUQ7XG59IiwiZXhwb3J0IGVudW0gRWxlbWVudFJlbmRlclR5cGUge1xuICAgIHVuZGVmaW5lZCxcbiAgICBub3JtYWxSZW5kZXIsXG4gICAgc3BlY2lhbFJlbmRlclxufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0RWxlbWVudFJlbmRlclR5cGUoZWxlbWVudDogSFRNTEVsZW1lbnQpOiBFbGVtZW50UmVuZGVyVHlwZSB7XG5cbiAgICAvKipcbiAgICAgKiBMb29rIGZvciBzcGVjaWZpYyBraW5kcyBvZiBlbGVtZW50cyBieSB0aGVpciBDU1MgY2xhc3MgbmFtZXMgaGVyZS4gVGhlc2UgXG4gICAgICogYXJlIGdvaW5nIHRvIGJlIGJyaXR0bGUgbGlua3MgYXMgdGhleSByZWx5IG9uIG90aGVyIHBsdWdpbiBkZWZpbml0aW9ucyBidXRcbiAgICAgKiBhcyB0aGlzIGlzIG9ubHkgYWRkaW5nIGluIGV4dHJhIGNvbXBhdGFiaWxpdHkgdG8gdGhlIHBsdWdpbnMgZGVmaW5lZCBoZXJlIFxuICAgICAqIGl0IHNob3VsZCBiZSBvay5cbiAgICAgKiBcbiAgICAgKiBUaGVzZSBtYXkgYmUgY2xhc3NlcyBvbiBvbmUgb2YgdGhlIHNpbXBsZSBlbGVtZW50cyAoc3VjaCBhcyBhIHBhcmFncmFwaClcbiAgICAgKiB0aGF0IHdlIHNlYXJjaCBmb3IgYmVsb3cgc28gbmVlZCB0byBsb29rIGZvciB0aGVzZSBmaXJzdC5cbiAgICAgKi9cbiAgICBpZihoYXNEaWNlUm9sbGVyKGVsZW1lbnQpID09PSB0cnVlKSB7XG5cbiAgICAgICAgcmV0dXJuIEVsZW1lbnRSZW5kZXJUeXBlLnNwZWNpYWxSZW5kZXJcbiAgICB9XG5cbiAgICBpZihoYXNBZG1vbml0aW9uKGVsZW1lbnQpID09PSB0cnVlKSB7XG4gICAgICAgIFxuICAgICAgICByZXR1cm4gRWxlbWVudFJlbmRlclR5cGUubm9ybWFsUmVuZGVyXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSWYgd2UgZGlkbnQgZmluZCBhIHNwZWNpYWwgZWxlbWVudCB3ZSB3YW50IHRvIGNoZWNrIGZvciBzaW1wbGUgZWxlbWVudHNcbiAgICAgKiBzdWNoIGFzIHBhcmFncmFwaHMgb3IgbGlzdHMuIEluIHRoZSBjdXJyZW50IGltcGxlbWVudGF0aW9uIHdlIG9ubHkgc2V0IHVwXG4gICAgICogdGhlIHNwZWNpYWwgY2FzZSBmb3IgXCJzcGVjaWFsUmVuZGVyXCIgZWxlbWVudHMgc28gdGhpcyAqc2hvdWxkKiBiZSBzYXZpbmdcbiAgICAgKiBzb21lIHJlbmRlcmluZyB0aW1lIGJ5IHNldHRpbmcgdGhlc2UgdGFncyBwcm9wZXJseS5cbiAgICAgKi9cbiAgICBpZihoYXNQYXJhZ3JhcGgoZWxlbWVudCkgfHwgXG4gICAgICAgaGFzSGVhZGVyKGVsZW1lbnQpICAgIHx8XG4gICAgICAgaGFzTGlzdChlbGVtZW50KSkge1xuXG4gICAgICAgIHJldHVybiBFbGVtZW50UmVuZGVyVHlwZS5ub3JtYWxSZW5kZXI7XG4gICAgfVxuXG4gICAgLy8gSWYgc3RpbGwgbm90aGluZyBmb3VuZCB3ZSByZXR1cm4gb3RoZXIgYXMgdGhlIGRlZmF1bHQgcmVzcG9uc2UgaWYgbm90aGluZyBlbHNlIGZvdW5kLlxuICAgIHJldHVybiBFbGVtZW50UmVuZGVyVHlwZS5zcGVjaWFsUmVuZGVyO1xufVxuXG5mdW5jdGlvbiBoYXNQYXJhZ3JhcGgoZWxlbWVudDogSFRNTEVsZW1lbnQpOiBib29sZWFuIHtcbiAgICByZXR1cm4gZWxlbWVudC5pbm5lckhUTUwuc3RhcnRzV2l0aChcIjxwXCIpO1xufVxuXG5mdW5jdGlvbiBoYXNIZWFkZXIoZWxlbWVudDogSFRNTEVsZW1lbnQpOiBib29sZWFuIHtcblxuICAgIGlmKGVsZW1lbnQuaW5uZXJIVE1MLnN0YXJ0c1dpdGgoXCI8aDFcIikgfHwgXG4gICAgICAgZWxlbWVudC5pbm5lckhUTUwuc3RhcnRzV2l0aChcIjxoMlwiKSB8fCBcbiAgICAgICBlbGVtZW50LmlubmVySFRNTC5zdGFydHNXaXRoKFwiPGgzXCIpIHx8IFxuICAgICAgIGVsZW1lbnQuaW5uZXJIVE1MLnN0YXJ0c1dpdGgoXCI8aDRcIikgfHxcbiAgICAgICBlbGVtZW50LmlubmVySFRNTC5zdGFydHNXaXRoKFwiPGg1XCIpKSB7XG5cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBoYXNMaXN0KGVsZW1lbnQ6IEhUTUxFbGVtZW50KTogYm9vbGVhbiB7XG4gICAgXG4gICAgaWYoZWxlbWVudC5pbm5lckhUTUwuc3RhcnRzV2l0aChcIjx1bFwiKSB8fCBcbiAgICAgICBlbGVtZW50LmlubmVySFRNTC5zdGFydHNXaXRoKFwiPG9sXCIpKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gaGFzRGljZVJvbGxlcihlbGVtZW50OiBIVE1MRWxlbWVudCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBlbGVtZW50LmdldEVsZW1lbnRzQnlDbGFzc05hbWUoXCJkaWNlLXJvbGxlclwiKS5sZW5ndGggIT09IDA7XG59XG5cbmZ1bmN0aW9uIGhhc0FkbW9uaXRpb24oZWxlbWVudDogSFRNTEVsZW1lbnQpOiBib29sZWFuIHtcbiAgICByZXR1cm4gZWxlbWVudC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKFwiYWRtb25pdGlvblwiKS5sZW5ndGggIT09IDA7XG59IiwiLypcbiAqIEZpbGVuYW1lOiBtdWx0aS1jb2x1bW4tbWFya2Rvd24vc3JjL2RvbU9iamVjdC50c1xuICogQ3JlYXRlZCBEYXRlOiBUdWVzZGF5LCBGZWJydWFyeSAxc3QgMjAyMiwgMTI6MDQ6MDAgcG1cbiAqIEF1dGhvcjogQ2FtZXJvbiBSb2JpbnNvblxuICogXG4gKiBDb3B5cmlnaHQgKGMpIDIwMjIgQ2FtZXJvbiBSb2JpbnNvblxuICovXG5cbmltcG9ydCB7IGdldFVJRCB9IGZyb20gXCIuLi91dGlsaXRpZXMvdXRpbHNcIjtcbmltcG9ydCB7IEVsZW1lbnRSZW5kZXJUeXBlIH0gZnJvbSBcIi4uL3V0aWxpdGllcy9lbGVtZW50UmVuZGVyVHlwZVBhcnNlclwiO1xuaW1wb3J0IHsgTXVsdGlDb2x1bW5TZXR0aW5ncyB9IGZyb20gXCIuLi9yZWdpb25TZXR0aW5nc1wiO1xuXG5leHBvcnQgZW51bSBET01PYmplY3RUYWcge1xuICAgIG5vbmUsXG4gICAgc3RhcnRSZWdpb24sXG4gICAgcmVnaW9uU2V0dGluZ3MsXG4gICAgY29sdW1uQnJlYWssXG4gICAgZW5kUmVnaW9uXG59XG5cbmV4cG9ydCBjbGFzcyBET01PYmplY3Qge1xuICAgIG5vZGVLZXk6IHN0cmluZztcbiAgICBlbGVtZW50OiBIVE1MRWxlbWVudDtcbiAgICBVSUQ6IHN0cmluZztcbiAgICB0YWc6IERPTU9iamVjdFRhZztcbiAgICB1c2luZ09yaWdpbmFsRWxlbWVudDogYm9vbGVhblxuICAgIGVsZW1lbnRUeXBlOiBFbGVtZW50UmVuZGVyVHlwZSA9IEVsZW1lbnRSZW5kZXJUeXBlLnVuZGVmaW5lZDtcbiAgICBlbGVtZW50Q29udGFpbmVyOiBIVE1MRGl2RWxlbWVudCA9IG51bGw7XG5cbiAgICBjb25zdHJ1Y3RvcihlbGVtZW50OiBIVE1MRWxlbWVudCwgXG4gICAgICAgICAgICAgICAgcmFuZG9tSUQ6c3RyaW5nID0gZ2V0VUlEKCksIFxuICAgICAgICAgICAgICAgIHRhZzogRE9NT2JqZWN0VGFnID0gRE9NT2JqZWN0VGFnLm5vbmUgKSB7XG4gICAgICAgIHRoaXMubm9kZUtleSA9IGVsZW1lbnQuaW5uZXJUZXh0LnRyaW0oKTtcbiAgICAgICAgdGhpcy5lbGVtZW50ID0gZWxlbWVudDtcbiAgICAgICAgdGhpcy5VSUQgPSByYW5kb21JRDtcbiAgICAgICAgdGhpcy50YWcgPSB0YWc7XG4gICAgICAgIHRoaXMudXNpbmdPcmlnaW5hbEVsZW1lbnQgPSBmYWxzZVxuICAgIH1cblxuICAgIHNldE1haW5ET01FbGVtZW50KGRvbUVsZW1lbnQ6IEhUTUxFbGVtZW50KSB7XG4gICAgICAgIHRoaXMuZWxlbWVudCA9IGRvbUVsZW1lbnQ7XG4gICAgICAgIHRoaXMudXNpbmdPcmlnaW5hbEVsZW1lbnQgPSB0cnVlXG4gICAgfVxufVxuXG5leHBvcnQgY2xhc3MgRE9NU3RhcnRSZWdpb25PYmplY3QgZXh0ZW5kcyBET01PYmplY3Qge1xuXG4gICAgcmVnaW9uRWxlbWVudDogSFRNTEVsZW1lbnQ7XG5cbiAgICBjb25zdHJ1Y3RvcihiYXNlRE9NT2JqZWN0OiBET01PYmplY3QsIHJlZ2lvbkVsZW1lbnQ6IEhUTUxFbGVtZW50KSB7XG5cbiAgICAgICAgc3VwZXIoYmFzZURPTU9iamVjdC5lbGVtZW50LCBiYXNlRE9NT2JqZWN0LlVJRCwgRE9NT2JqZWN0VGFnLnN0YXJ0UmVnaW9uKTtcbiAgICAgICAgdGhpcy5yZWdpb25FbGVtZW50ID0gcmVnaW9uRWxlbWVudDtcbiAgICB9XG59XG5cbmV4cG9ydCBjbGFzcyBET01SZWdpb25TZXR0aW5nc09iamVjdCBleHRlbmRzIERPTU9iamVjdCB7XG5cbiAgICByZWdpb25TZXR0aW5nczogTXVsdGlDb2x1bW5TZXR0aW5ncztcblxuICAgIGNvbnN0cnVjdG9yKGJhc2VET01PYmplY3Q6IERPTU9iamVjdCwgcmVnaW9uU2V0dGluZ3M6IE11bHRpQ29sdW1uU2V0dGluZ3MpIHtcbiAgICAgICAgc3VwZXIoYmFzZURPTU9iamVjdC5lbGVtZW50LCBiYXNlRE9NT2JqZWN0LlVJRCwgRE9NT2JqZWN0VGFnLnJlZ2lvblNldHRpbmdzKTtcblxuICAgICAgICB0aGlzLnJlZ2lvblNldHRpbmdzID0gcmVnaW9uU2V0dGluZ3M7XG4gICAgfVxufSIsIi8qXG4gKiBGaWxlOiBtdWx0aS1jb2x1bW4tbWFya2Rvd24vc3JjL3V0aWxpdGllcy9jc3NEZWZpbml0aW9ucy50c1xuICogQ3JlYXRlZCBEYXRlOiBXZWRuZXNkYXksIEZlYnJ1YXJ5IDE2dGggMjAyMiwgMTE6MDk6MDYgYW1cbiAqIEF1dGhvcjogQ2FtZXJvbiBSb2JpbnNvblxuICogXG4gKiBDb3B5cmlnaHQgKGMpIDIwMjIgQ2FtZXJvbiBSb2JpbnNvblxuICovXG5cbmV4cG9ydCBlbnVtIE11bHRpQ29sdW1uTGF5b3V0Q1NTIHtcblxuICAgIFJlZ2lvblJvb3RDb250YWluZXJEaXYgPSBcIm11bHRpQ29sdW1uQ29udGFpbmVyXCIsXG4gICAgUmVnaW9uRXJyb3JDb250YWluZXJEaXYgPSBcIm11bHRpQ29sdW1uRXJyb3JDb250YWluZXJcIixcbiAgICBSZWdpb25Db250ZW50Q29udGFpbmVyRGl2ID0gXCJSZW5kZXJDb2xSZWdpb25cIixcbiAgICBSZWdpb25Db2x1bW5Db250YWluZXJEaXYgPSBcIm11bHRpQ29sdW1uUGFyZW50XCIsXG4gICAgUmVnaW9uQ29sdW1uQ29udGVudCA9IFwiY29sdW1uQ29udGVudFwiLFxuICAgIENvbHVtbkR1YWxFbGVtZW50Q29udGFpbmVyID0gXCJNdWx0aUNvbHVtbl9FbGVtZW50Q29udGFpbmVyXCIsXG4gICAgT3JpZ2luYWxFbGVtZW50VHlwZSA9IFwiTXVsdGlDb2x1bW5fT3JpZ2luYWxFbGVtZW50XCIsXG4gICAgQ2xvbmVkRWxlbWVudFR5cGUgPSBcIk11bHRpQ29sdW1uX0Nsb25lZEVsZW1lbnRcIlxufVxuXG5leHBvcnQgZW51bSBNdWx0aUNvbHVtblN0eWxlQ1NTIHtcblxuICAgIFJlZ2lvbkVycm9yTWVzc2FnZSA9IFwibXVsdGlDb2x1bW5FcnJvck1lc3NhZ2VcIixcbiAgICBSZWdpb25TZXR0aW5ncyA9IFwibXVsdGlDb2x1bW5TZXR0aW5nc1wiLFxuICAgIFJlZ2lvbkNvbnRlbnQgPSBcIm11bHRpQ29sdW1uQ29udGVudFwiLFxuICAgIFJlZ2lvbkVuZFRhZyA9IFwibXVsdGlDb2x1bW5SZWdpb25FbmRUYWdcIixcbiAgICBDb2x1bW5FbmRUYWcgPSBcIm11bHRpQ29sdW1uQnJlYWtcIixcbiAgICBSZWdpb25TaGFkb3cgPSBcIm11bHRpQ29sdW1uUGFyZW50U2hhZG93XCIsXG4gICAgQ29sdW1uU2hhZG93ID0gXCJjb2x1bW5TaGFkb3dcIixcbiAgICBDb2x1bW5Cb3JkZXIgPSBcImNvbHVtbkJvcmRlclwiLFxufSIsIi8qXG4gKiBGaWxlOiBtdWx0aS1jb2x1bW4tbWFya2Rvd24vc3JjL2RvbU1hbmFnZXIudHNcbiAqIENyZWF0ZWQgRGF0ZTogU2F0dXJkYXksIEphbnVhcnkgMzB0aCAyMDIyLCAzOjE2OjMyIHBtXG4gKiBBdXRob3I6IENhbWVyb24gUm9iaW5zb25cbiAqIFxuICogQ29weXJpZ2h0IChjKSAyMDIyIENhbWVyb24gUm9iaW5zb25cbiAqL1xuXG5pbXBvcnQgeyBwYXJzZUNvbHVtblNldHRpbmdzIH0gZnJvbSAnLi4vdXRpbGl0aWVzL3RleHRQYXJzZXInO1xuaW1wb3J0IHsgRE9NT2JqZWN0LCBET01SZWdpb25TZXR0aW5nc09iamVjdCwgRE9NT2JqZWN0VGFnIH0gZnJvbSAnLi9kb21PYmplY3QnO1xuaW1wb3J0IHsgTXVsdGlDb2x1bW5TZXR0aW5ncywgQ29sdW1uTGF5b3V0IH0gZnJvbSBcIi4uL3JlZ2lvblNldHRpbmdzXCI7XG5pbXBvcnQgeyBNdWx0aUNvbHVtbkxheW91dENTUywgTXVsdGlDb2x1bW5TdHlsZUNTUyB9IGZyb20gJy4uL3V0aWxpdGllcy9jc3NEZWZpbml0aW9ucyc7XG5cbmV4cG9ydCBjbGFzcyBHbG9iYWxET01NYW5hZ2VyIHtcbiAgICBtYW5hZ2VyczogTWFwPHN0cmluZywgRmlsZURPTU1hbmFnZXI+O1xuXG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHRoaXMubWFuYWdlcnMgPSBuZXcgTWFwKCk7XG4gICAgfVxuXG4gICAgcHVibGljIHJlbW92ZUZpbGVNYW5hZ2VyQ2FsbGJhY2soa2V5OiBzdHJpbmcpIHtcbiAgICAgICAgaWYodGhpcy5tYW5hZ2Vycy5oYXMoa2V5KSA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgdGhpcy5tYW5hZ2Vycy5kZWxldGUoa2V5KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyBnZXRGaWxlTWFuYWdlcihrZXk6IHN0cmluZykge1xuXG4gICAgICAgIGxldCBmaWxlTWFuYWdlciA9IG51bGw7XG4gICAgICAgIGlmKHRoaXMubWFuYWdlcnMuaGFzKGtleSkgPT09IHRydWUpIHtcbiAgICAgICAgICAgIGZpbGVNYW5hZ2VyID0gdGhpcy5tYW5hZ2Vycy5nZXQoa2V5KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGZpbGVNYW5hZ2VyID0gY3JlYXRlRmlsZURPTU1hbmFnZXIodGhpcywga2V5KTtcbiAgICAgICAgICAgIHRoaXMubWFuYWdlcnMuc2V0KGtleSwgZmlsZU1hbmFnZXIpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGZpbGVNYW5hZ2VyO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXRBbGxGaWxlTWFuYWdlcnMoKSB7XG4gICAgICAgIHJldHVybiBBcnJheS5mcm9tKHRoaXMubWFuYWdlcnMudmFsdWVzKCkpO1xuICAgIH1cbn1cblxuZXhwb3J0IHR5cGUgRmlsZURPTU1hbmFnZXIgPSB7XG4gICAgcmVnaW9uTWFwOiBNYXA8c3RyaW5nLCBSZWdpb25ET01NYW5hZ2VyPixcbiAgICBoYXNTdGFydFRhZzogYm9vbGVhbixcbiAgICBjcmVhdGVSZWdpb25hbE1hbmFnZXI6IChyZWdpb25LZXk6IHN0cmluZywgcm9vdEVsZW1lbnQ6IEhUTUxFbGVtZW50LCBlcnJvckVsZW1lbnQ6IEhUTUxFbGVtZW50LCByZW5kZXJSZWdpb25FbGVtZW50OiBIVE1MRWxlbWVudCkgPT4gUmVnaW9uRE9NTWFuYWdlclxuICAgIGdldFJlZ2lvbmFsTWFuYWdlcjogKHJlZ2lvbktleTogc3RyaW5nKSA9PiBSZWdpb25ET01NYW5hZ2VyIHwgbnVsbCxcbiAgICBnZXRBbGxSZWdpb25hbE1hbmFnZXJzOiAoKSA9PiBSZWdpb25ET01NYW5hZ2VyW10sXG4gICAgcmVtb3ZlUmVnaW9uOiAocmVnaW9uS2V5OiBzdHJpbmcpID0+IHZvaWQsXG4gICAgc2V0SGFzU3RhcnRUYWc6ICgpID0+IHZvaWQsXG4gICAgZ2V0SGFzU3RhcnRUYWc6ICgpID0+IGJvb2xlYW4sXG4gICAgZ2V0TnVtYmVyT2ZSZWdpb25zOiAoKSA9PiBudW1iZXIsXG4gICAgY2hlY2tLZXlFeGlzdHM6IChjaGVja0tleTogc3RyaW5nKSA9PiBib29sZWFuXG59XG5mdW5jdGlvbiBjcmVhdGVGaWxlRE9NTWFuYWdlcihwYXJlbnRNYW5hZ2VyOiBHbG9iYWxET01NYW5hZ2VyLCBmaWxlS2V5OiBzdHJpbmcpOiBGaWxlRE9NTWFuYWdlciB7XG4gICAgXG4gICAgbGV0IHJlZ2lvbk1hcDogTWFwPHN0cmluZywgUmVnaW9uRE9NTWFuYWdlcj4gPSBuZXcgTWFwKCk7XG4gICAgbGV0IGhhc1N0YXJ0VGFnOiBib29sZWFuID0gZmFsc2U7XG5cbiAgICBmdW5jdGlvbiByZW1vdmVSZWdpb24ocmVnaW9uS2V5OiBzdHJpbmcpOiB2b2lkIHtcblxuICAgICAgICBsZXQgcmVnaW9uTWFuYWdlciA9IHJlZ2lvbk1hcC5nZXQocmVnaW9uS2V5KTtcbiAgICAgICAgaWYocmVnaW9uTWFuYWdlcikge1xuICAgICAgICAgICAgcmVnaW9uTWFuYWdlci5kaXNwbGF5T3JpZ2luYWxFbGVtZW50cygpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmVnaW9uTWFwLmRlbGV0ZShyZWdpb25LZXkpO1xuICAgICAgICBcbiAgICAgICAgaWYocmVnaW9uTWFwLnNpemUgPT09IDApIHtcbiAgICAgICAgICAgIHBhcmVudE1hbmFnZXIucmVtb3ZlRmlsZU1hbmFnZXJDYWxsYmFjayhmaWxlS2V5KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNyZWF0ZVJlZ2lvbmFsTWFuYWdlcihyZWdpb25LZXk6IHN0cmluZywgcm9vdEVsZW1lbnQ6IEhUTUxFbGVtZW50LCBlcnJvckVsZW1lbnQ6IEhUTUxFbGVtZW50LCByZW5kZXJSZWdpb25FbGVtZW50OiBIVE1MRWxlbWVudCkge1xuXG4gICAgICAgIC8vVE9ETzogVXNlIHRoZSBlcnJvciBlbGVtZW50IHdoZW5ldmVyIHRoZXJlIGlzIGFuIGVycm9yLlxuXG4gICAgICAgIGxldCByZWdvbmFsTWFuYWdlciA9IGNyZWF0ZVJlZ2lvbmFsRG9tTWFuYWdlcih0aGlzLCByZWdpb25LZXksIHJvb3RFbGVtZW50LCByZW5kZXJSZWdpb25FbGVtZW50KTtcbiAgICAgICAgcmVnaW9uTWFwLnNldChyZWdpb25LZXksIHJlZ29uYWxNYW5hZ2VyKTtcbiAgICAgICAgcmV0dXJuIHJlZ29uYWxNYW5hZ2VyO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldFJlZ2lvbmFsTWFuYWdlcihyZWdpb25LZXk6IHN0cmluZyk6IFJlZ2lvbkRPTU1hbmFnZXIgfCBudWxsIHtcblxuICAgICAgICBsZXQgcmVnb25hbE1hbmFnZXIgPSBudWxsO1xuICAgICAgICBpZihyZWdpb25NYXAuaGFzKHJlZ2lvbktleSkgPT09IHRydWUpIHtcbiAgICAgICAgICAgIHJlZ29uYWxNYW5hZ2VyID0gcmVnaW9uTWFwLmdldChyZWdpb25LZXkpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJlZ29uYWxNYW5hZ2VyO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldEFsbFJlZ2lvbmFsTWFuYWdlcnMoKTogUmVnaW9uRE9NTWFuYWdlcltdIHtcblxuICAgICAgICByZXR1cm4gQXJyYXkuZnJvbShyZWdpb25NYXAudmFsdWVzKCkpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHNldEhhc1N0YXJ0VGFnKCkge1xuICAgICAgICBoYXNTdGFydFRhZyA9IHRydWU7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0SGFzU3RhcnRUYWcoKSB7XG4gICAgICAgIHJldHVybiBoYXNTdGFydFRhZztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBnZXROdW1iZXJPZlJlZ2lvbnMoKSB7XG4gICAgICAgIHJldHVybiByZWdpb25NYXAuc2l6ZVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNoZWNrS2V5RXhpc3RzKGNoZWNrS2V5OiBzdHJpbmcpIHtcbiAgICAgICAgcmV0dXJuIHJlZ2lvbk1hcC5oYXMoY2hlY2tLZXkpO1xuICAgIH1cblxuICAgIHJldHVybiB7IHJlZ2lvbk1hcDogcmVnaW9uTWFwLCBcbiAgICAgICAgaGFzU3RhcnRUYWc6IGhhc1N0YXJ0VGFnLCAgXG4gICAgICAgIGNyZWF0ZVJlZ2lvbmFsTWFuYWdlcjogY3JlYXRlUmVnaW9uYWxNYW5hZ2VyLCBcbiAgICAgICAgZ2V0UmVnaW9uYWxNYW5hZ2VyOiBnZXRSZWdpb25hbE1hbmFnZXIsXG4gICAgICAgIGdldEFsbFJlZ2lvbmFsTWFuYWdlcnM6IGdldEFsbFJlZ2lvbmFsTWFuYWdlcnMsXG4gICAgICAgIHJlbW92ZVJlZ2lvbjogcmVtb3ZlUmVnaW9uLCBcbiAgICAgICAgc2V0SGFzU3RhcnRUYWc6IHNldEhhc1N0YXJ0VGFnLCBcbiAgICAgICAgZ2V0SGFzU3RhcnRUYWc6IGdldEhhc1N0YXJ0VGFnLFxuICAgICAgICBnZXROdW1iZXJPZlJlZ2lvbnM6IGdldE51bWJlck9mUmVnaW9ucyxcbiAgICAgICAgY2hlY2tLZXlFeGlzdHM6IGNoZWNrS2V5RXhpc3RzXG4gICAgfVxufVxuXG5leHBvcnQgdHlwZSBNdWx0aUNvbHVtblJlbmRlckRhdGEgPSB7IFxuICAgIHBhcmVudFJlbmRlckVsZW1lbnQ6IEhUTUxFbGVtZW50LCBcbiAgICBwYXJlbnRSZW5kZXJTZXR0aW5nczogTXVsdGlDb2x1bW5TZXR0aW5ncyxcbiAgICBkb21PYmplY3RzOiBET01PYmplY3RbXVxufVxuXG5leHBvcnQgdHlwZSBSZWdpb25ET01NYW5hZ2VyID0ge1xuXG4gICAgYWRkT2JqZWN0OiAoc2libGluZ3NBYm92ZTogSFRNTERpdkVsZW1lbnQsIHNpYmxpbmdzQmVsb3c6IEhUTUxEaXZFbGVtZW50LCBvYmo6IERPTU9iamVjdCkgPT4gbnVtYmVyLFxuICAgIHJlbW92ZU9iamVjdDogKG9iamVjdEtleTogc3RyaW5nKSA9PiB2b2lkLFxuICAgIHVwZGF0ZUVsZW1lbnRUYWc6IChvYmplY3RVSUQ6IHN0cmluZywgbmV3VGFnOiBET01PYmplY3RUYWcpID0+IHZvaWQsXG4gICAgc2V0RWxlbWVudFRvU2V0dGluZ3NCbG9jazogKG9iamVjdFVJRDogc3RyaW5nLCBzZXR0aW5nc1RleHQ6IHN0cmluZykgPT4gdm9pZCxcbiAgICBnZXRSZWdpb25SZW5kZXJEYXRhOiAoKSA9PiBNdWx0aUNvbHVtblJlbmRlckRhdGEsXG4gICAgZGlzcGxheU9yaWdpbmFsRWxlbWVudHM6ICgpID0+IHZvaWQsXG4gICAgZ2V0Um9vdFJlZ2lvbkVsZW1lbnQ6ICgpID0+IEhUTUxFbGVtZW50XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZVJlZ2lvbmFsRG9tTWFuYWdlcihmaWxlTWFuYWdlcjogRmlsZURPTU1hbmFnZXIsIHJlZ2lvbktleTogc3RyaW5nLCByb290RWxlbWVudDogSFRNTEVsZW1lbnQsIHJlbmRlclJlZ2lvbkVsZW1lbnQ6IEhUTUxFbGVtZW50KTogUmVnaW9uRE9NTWFuYWdlciB7XG5cbiAgICAvKipcbiAgICAgKiBXZSB1c2UgYSBsaXN0IGFuZCBhIG1hcCB0byBoZWxwIGtlZXAgdHJhY2sgb2YgdGhlIG9iamVjdHMuIFJlcXVpcmVzXG4gICAgICogbW9yZSBtZW1vcnkgYnV0IG1ha2VzIHByb2Nlc3NpbmcgdGhpbmdzIGEgbGl0dGxlIGNsZWFuZXIgYW5kIHByZXN1bWFibHlcbiAgICAgKiBmYXN0ZXIuXG4gICAgICogXG4gICAgICogVXNlIHRoZSBtYXAgdG8gbG9vayB1cCBvYmplY3QgYnkga2V5IGFuZCB0aGUgbGlzdCBpcyB1c2VkIHRvIHRyYWNrIG9iamVjdHNcbiAgICAgKiBpbiB0aGUgb3JkZXIgdGhleSBhcmUgaW4gdGhlIGRvY3VtZW50LlxuICAgICAqL1xuICAgIGxldCBkb21MaXN0OiBET01PYmplY3RbXSA9IFtdXG4gICAgbGV0IGRvbU9iamVjdE1hcDogTWFwPHN0cmluZywgRE9NT2JqZWN0PiA9IG5ldyBNYXAoKTtcbiAgICBsZXQgcmVnaW9uUGFyZW50OiBIVE1MRWxlbWVudCA9IHJlbmRlclJlZ2lvbkVsZW1lbnQ7XG4gICAgbGV0IHJlZ2lvblNldHRpbmdzOiBET01SZWdpb25TZXR0aW5nc09iamVjdFtdID0gW107XG5cbiAgICBmdW5jdGlvbiBhZGRPYmplY3Qoc2libGluZ3NBYm92ZTogSFRNTERpdkVsZW1lbnQsIHNpYmxpbmdzQmVsb3c6IEhUTUxEaXZFbGVtZW50LCBvYmo6IERPTU9iamVjdCk6IG51bWJlciB7XG5cbiAgICAgICAgbGV0IHByZXZPYmogPSBzaWJsaW5nc0Fib3ZlLmNoaWxkcmVuW3NpYmxpbmdzQWJvdmUuY2hpbGRyZW4ubGVuZ3RoIC0gMV0gYXMgSFRNTEVsZW1lbnQ7XG4gICAgICAgIGxldCBuZXh0T2JqID0gc2libGluZ3NCZWxvdy5jaGlsZHJlblswXSBhcyBIVE1MRWxlbWVudDtcblxuICAgICAgICBsZXQgYWRkQXRJbmRleCA9IHNpYmxpbmdzQWJvdmUuY2hpbGRyZW4ubGVuZ3RoO1xuXG4gICAgICAgIGxldCBwcmV2T2JqVGV4dCA9IFwiXCJcbiAgICAgICAgaWYocHJldk9iaiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBcbiAgICAgICAgICAgIHByZXZPYmpUZXh0ID0gcHJldk9iai5pbm5lclRleHQ7XG5cbiAgICAgICAgICAgIGZvcihsZXQgaSA9IGRvbUxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICAgICAgICBpZihkb21MaXN0W2ldLm5vZGVLZXkgPT09IHByZXZPYmouaW5uZXJUZXh0KSB7XG4gICAgICAgICAgICAgICAgICAgIGFkZEF0SW5kZXggPSBpICsgMTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgbGV0IG5leHRFbEluZGV4ID0gYWRkQXRJbmRleDtcbiAgICAgICAgbGV0IG5leHRPYmpUZXh0ID0gXCJcIlxuICAgICAgICBpZihuZXh0T2JqICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgbGV0IGZvdW5kTmV4dCA9IGZhbHNlO1xuICAgICAgICAgICAgbmV4dE9ialRleHQgPSBuZXh0T2JqLmlubmVyVGV4dDtcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgZm9yKGxldCBpID0gYWRkQXRJbmRleDsgaSA8IGRvbUxpc3QubGVuZ3RoOyBpKyspIHtcblxuICAgICAgICAgICAgICAgIGlmKGRvbUxpc3RbaV0ubm9kZUtleSA9PT0gbmV4dE9iai5pbm5lclRleHQudHJpbSgpKSB7XG4gICAgXG4gICAgICAgICAgICAgICAgICAgIG5leHRFbEluZGV4ID0gaTtcbiAgICAgICAgICAgICAgICAgICAgZm91bmROZXh0ID0gdHJ1ZVxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBjb25zb2xlLmxvZyhcIiBQcmV2OiBcIiwgc2libGluZ3NBYm92ZS5jaGlsZHJlbltzaWJsaW5nc0Fib3ZlLmNoaWxkcmVuLmxlbmd0aCAtIDFdLCBcIkFkZGluZzogXCIsIG9iai5lbGVtZW50LCBcIiBOZXh0OiBcIiwgc2libGluZ3NCZWxvdy5jaGlsZHJlblswXSwgXCJPdmVyd3JpdGluZzpcIiwgZG9tTGlzdC5zbGljZShhZGRBdEluZGV4LCBuZXh0RWxJbmRleCkpO1xuXG4gICAgICAgIGRvbUxpc3Quc3BsaWNlKGFkZEF0SW5kZXgsIG5leHRFbEluZGV4IC0gYWRkQXRJbmRleCwgb2JqKTtcbiAgICAgICAgZG9tT2JqZWN0TWFwLnNldChvYmouVUlELCBvYmopO1xuXG4gICAgICAgIC8vIC8qKlxuICAgICAgICAvLyAgKiBNYWtlIGEgY29weSBvZiB0aGUgbGlzdCB0byBsb2csIG9ubHkgYmVjYXVzZVxuICAgICAgICAvLyAgKiBjb25zb2xlIGxvZyB1cGRhdGVzIGl0cyByZWZlcmVuY2VzIHdpdGggdXBkYXRlcyBpbiBtZW1vcnkuXG4gICAgICAgIC8vICAqL1xuICAgICAgICAvLyBsZXQgeCA9IGRvbUxpc3Quc2xpY2UoMCk7XG4gICAgICAgIC8vIGNvbnNvbGUubG9nKHgpO1xuXG4gICAgICAgIHJldHVybiBhZGRBdEluZGV4O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHJlbW92ZU9iamVjdChvYmplY3RVSUQ6IHN0cmluZyk6IHZvaWQge1xuXG4gICAgICAgIC8vIC8qKlxuICAgICAgICAvLyAgKiBNYWtlIGEgY29weSBvZiB0aGUgbGlzdCB0byBsb2dcbiAgICAgICAgLy8gICovXG4gICAgICAgIC8vIGxldCB4ID0gZG9tTGlzdC5zbGljZSgwKTtcbiAgICAgICAgLy8gY29uc29sZS5sb2coeCk7XG5cbiAgICAgICAgLy8gR2V0IHRoZSBvYmplY3QgYnkga2V5LCByZW1vdmUgaXQgZnJvbSB0aGUgbWFwIGFuZCB0aGVuXG4gICAgICAgIC8vIGZyb20gdGhlIGxpc3QuXG4gICAgICAgIGxldCBvYmogPSBkb21PYmplY3RNYXAuZ2V0KG9iamVjdFVJRCk7XG4gICAgICAgIGRvbU9iamVjdE1hcC5kZWxldGUob2JqZWN0VUlEKTtcbiAgICAgICAgXG4gICAgICAgIGlmKG9iaiA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZihkb21MaXN0LmNvbnRhaW5zKG9iaikpIHtcbiAgICAgICAgICAgIGRvbUxpc3QucmVtb3ZlKG9iaik7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBJZiB0aGUgb2JqZWN0IGlzIGEgc2V0dGluZ3Mgb2JqZWN0IHdlIG5lZWQgdG8gcmVtb3ZlIGZyb20gdGhlIFxuICAgICAgICAvLyBzZXR0aW5ncyBsaXN0LlxuICAgICAgICBpZihvYmoudGFnID09PSBET01PYmplY3RUYWcucmVnaW9uU2V0dGluZ3MpIHtcbiAgICAgICAgICAgIGxldCBzZXR0aW5nc09iaiA9IG9iaiBhcyBET01SZWdpb25TZXR0aW5nc09iamVjdDtcbiAgICAgICAgICAgIGlmKHJlZ2lvblNldHRpbmdzLmNvbnRhaW5zKHNldHRpbmdzT2JqKSkge1xuICAgICAgICAgICAgICAgIHJlZ2lvblNldHRpbmdzLnJlbW92ZShzZXR0aW5nc09iaik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZihkb21MaXN0Lmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgZmlsZU1hbmFnZXIucmVtb3ZlUmVnaW9uKHJlZ2lvbktleSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyB4ID0gZG9tTGlzdC5zbGljZSgwKTtcbiAgICAgICAgLy8gY29uc29sZS5sb2coeCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gdXBkYXRlRWxlbWVudFRhZyhvYmplY3RVSUQ6IHN0cmluZywgbmV3VGFnOiBET01PYmplY3RUYWcpOiB2b2lkIHtcblxuICAgICAgICBsZXQgb2JqID0gZG9tT2JqZWN0TWFwLmdldChvYmplY3RVSUQpO1xuICAgICAgICBsZXQgaW5kZXggPSBkb21MaXN0LmluZGV4T2Yob2JqKTtcbiAgICAgICAgaWYoaW5kZXggIT09IC0xKSB7XG4gICAgICAgICAgICBkb21MaXN0W2luZGV4XS50YWcgPSBuZXdUYWc7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBzZXRFbGVtZW50VG9TZXR0aW5nc0Jsb2NrKG9iamVjdFVJRDogc3RyaW5nLCBzZXR0aW5nc1RleHQ6IHN0cmluZyk6IHZvaWQge1xuICAgICAgICBcblxuICAgICAgICBsZXQgb2JqID0gZG9tT2JqZWN0TWFwLmdldChvYmplY3RVSUQpO1xuICAgICAgICBsZXQgaW5kZXggPSBkb21MaXN0LmluZGV4T2Yob2JqKTtcbiAgICAgICAgaWYoaW5kZXggIT09IC0xKSB7XG4gICAgICAgICAgICBsZXQgc2V0dGluZ3M6IE11bHRpQ29sdW1uU2V0dGluZ3MgPSBwYXJzZUNvbHVtblNldHRpbmdzKHNldHRpbmdzVGV4dCk7XG4gICAgICAgICAgICBsZXQgcmVnaW9uU2V0dGluZ3NPYmo6IERPTVJlZ2lvblNldHRpbmdzT2JqZWN0ID0gbmV3IERPTVJlZ2lvblNldHRpbmdzT2JqZWN0KGRvbUxpc3RbaW5kZXhdLCBzZXR0aW5ncyk7XG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGRvbU9iamVjdE1hcC5zZXQocmVnaW9uU2V0dGluZ3NPYmouVUlELCByZWdpb25TZXR0aW5nc09iaik7XG4gICAgICAgICAgICBkb21MaXN0W2luZGV4XSA9IHJlZ2lvblNldHRpbmdzT2JqO1xuXG4gICAgICAgICAgICByZWdpb25TZXR0aW5ncy5wdXNoKHJlZ2lvblNldHRpbmdzT2JqKVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBvYmplY3QgY29udGFpbmluZyBhbGwgbmVjZXNzYXJ5IGluZm9ybWF0aW9uIGZvciB0aGUgcmVnaW9uXG4gICAgICogdG8gYmUgcmVuZGVyZWQgdG8gdGhlIHByZXZpZXcgcGFuZS5cbiAgICAgKiBcbiAgICAgKiBAcmV0dXJucyBhIE11bHRpQ29sdW1uUmVuZGVyRGF0YSBvYmplY3Qgd2l0aCB0aGUgcm9vdCBET00gZWxlbWVudCwgc2V0dGluZ3Mgb2JqZWN0LCBhbmQgXG4gICAgICogYWxsIGNoaWxkIG9iamVjdHMgaW4gdGhlIG9yZGVyIHRoZXkgc2hvdWxkIGJlIHJlbmRlcmVkLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldFJlZ2lvblJlbmRlckRhdGEoKTogTXVsdGlDb2x1bW5SZW5kZXJEYXRhIHtcblxuICAgICAgICAvLyBTZXQgZGVmYXVsdHMgYmVmb3JlIGF0dGVtcHRpbmcgdG8gZ2V0IHNldHRpbmdzLlxuICAgICAgICBsZXQgc2V0dGluZ3M6IE11bHRpQ29sdW1uU2V0dGluZ3MgPSB7bnVtYmVyT2ZDb2x1bW5zOiAyLCBjb2x1bW5MYXlvdXQ6IENvbHVtbkxheW91dC5zdGFuZGFyZCwgZHJhd0JvcmRlcjogdHJ1ZSwgZHJhd1NoYWRvdzogdHJ1ZX07XG4gICAgICAgIGlmKHJlZ2lvblNldHRpbmdzLmxlbmd0aCA+IDApIHtcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBTaW5jZSB3ZSBhcHBlbmQgc2V0dGluZ3Mgb250byB0aGUgZW5kIG9mIHRoZSBhcnJheSB3ZSB3YW50IHRoZSBsYXN0XG4gICAgICAgICAgICAgKiBpdGVtIGluIHRoZSBhcnJheSBhcyB0aGF0IHdvdWxkIGJlIHRoZSBtb3N0IHJlY2VudCBzZXR0aW5ncyB3ZSBwYXJzZWQuXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIHNldHRpbmdzID0gcmVnaW9uU2V0dGluZ3NbcmVnaW9uU2V0dGluZ3MubGVuZ3RoIC0gMV0ucmVnaW9uU2V0dGluZ3M7XG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgIHJldHVybiB7IFxuICAgICAgICAgICAgcGFyZW50UmVuZGVyRWxlbWVudDogcmVnaW9uUGFyZW50LCBcbiAgICAgICAgICAgIHBhcmVudFJlbmRlclNldHRpbmdzOiBzZXR0aW5ncyxcbiAgICAgICAgICAgIGRvbU9iamVjdHM6IGRvbUxpc3RcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIGZ1Y3Rpb24gaXMgY2FsbGVkIHdoZW4gYSBzdGFydCB0YWcgaXMgcmVtb3ZlZCBmcm9tIHZpZXcgbWVhbmluZ1xuICAgICAqIG91ciBwYXJlbnQgZWxlbWVudCBzdG9yaW5nIHRoZSBtdWx0aS1jb2x1bW4gcmVnaW9uIGlzIHJlbW92ZWQuIEl0IFxuICAgICAqIHJlbW92ZXMgdGhlIENTUyBjbGFzcyBmcm9tIGFsbCBvZiB0aGUgZWxlbWVudHMgc28gdGhleSB3aWxsIGJlXG4gICAgICogcmUtcmVuZGVyZWQgaW4gdGhlIHByZXZpZXcgd2luZG93LlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGRpc3BsYXlPcmlnaW5hbEVsZW1lbnRzKCkge1xuXG4gICAgICAgIFxuICAgICAgICBmb3IobGV0IGkgPSAwOyBpIDwgZG9tTGlzdC5sZW5ndGg7IGkrKykge1xuXG4gICAgICAgICAgICBpZihkb21MaXN0W2ldLmVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICBkb21MaXN0W2ldLmVsZW1lbnQucmVtb3ZlQ2xhc3NlcyhbTXVsdGlDb2x1bW5TdHlsZUNTUy5SZWdpb25FbmRUYWcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE11bHRpQ29sdW1uU3R5bGVDU1MuQ29sdW1uRW5kVGFnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBNdWx0aUNvbHVtblN0eWxlQ1NTLlJlZ2lvblNldHRpbmdzLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBNdWx0aUNvbHVtblN0eWxlQ1NTLlJlZ2lvbkNvbnRlbnRdKTtcbiAgICAgICAgICAgICAgICBpZihkb21MaXN0W2ldLmVsZW1lbnQucGFyZW50RWxlbWVudCkge1xuICAgICAgICAgICAgICAgICAgICBkb21MaXN0W2ldLmVsZW1lbnQucGFyZW50RWxlbWVudC5yZW1vdmVDaGlsZChkb21MaXN0W2ldLmVsZW1lbnQpXG4gICAgICAgICAgICAgICAgfSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZm9yKGxldCBpID0gMDsgaSA8IHJlZ2lvblNldHRpbmdzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBpZihyZWdpb25TZXR0aW5nc1tpXS5lbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgcmVnaW9uU2V0dGluZ3NbaV0uZWxlbWVudC5yZW1vdmVDbGFzc2VzKFtNdWx0aUNvbHVtblN0eWxlQ1NTLlJlZ2lvbkVuZFRhZyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE11bHRpQ29sdW1uU3R5bGVDU1MuQ29sdW1uRW5kVGFnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTXVsdGlDb2x1bW5TdHlsZUNTUy5SZWdpb25TZXR0aW5ncyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE11bHRpQ29sdW1uU3R5bGVDU1MuUmVnaW9uQ29udGVudF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gICAgICAgICAgICAgICAgaWYocmVnaW9uU2V0dGluZ3NbaV0uZWxlbWVudC5wYXJlbnRFbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIHJlZ2lvblNldHRpbmdzW2ldLmVsZW1lbnQucGFyZW50RWxlbWVudC5yZW1vdmVDaGlsZChyZWdpb25TZXR0aW5nc1tpXS5lbGVtZW50KVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldFJvb3RSZWdpb25FbGVtZW50KCk6IEhUTUxFbGVtZW50IHtcbiAgICAgICAgcmV0dXJuIHJvb3RFbGVtZW50O1xuICAgIH1cblxuICAgIHJldHVybiB7IGFkZE9iamVjdDogYWRkT2JqZWN0LCBcbiAgICAgICAgICAgICByZW1vdmVPYmplY3Q6IHJlbW92ZU9iamVjdCwgXG4gICAgICAgICAgICAgdXBkYXRlRWxlbWVudFRhZzogdXBkYXRlRWxlbWVudFRhZywgXG4gICAgICAgICAgICAgc2V0RWxlbWVudFRvU2V0dGluZ3NCbG9jazogc2V0RWxlbWVudFRvU2V0dGluZ3NCbG9jayxcbiAgICAgICAgICAgICBnZXRSZWdpb25SZW5kZXJEYXRhOiBnZXRSZWdpb25SZW5kZXJEYXRhLFxuICAgICAgICAgICAgIGRpc3BsYXlPcmlnaW5hbEVsZW1lbnRzOiBkaXNwbGF5T3JpZ2luYWxFbGVtZW50cyxcbiAgICAgICAgICAgICBnZXRSb290UmVnaW9uRWxlbWVudDogZ2V0Um9vdFJlZ2lvbkVsZW1lbnRcbiAgICB9XG59XG4iLCIvKlxyXG4gKiBGaWxlOiBtdWx0aS1jb2x1bW4tbWFya2Rvd24vc3JjL21haW4udHNcclxuICogQ3JlYXRlZCBEYXRlOiBUdWVzZGF5LCBPY3RvYmVyIDV0aCAyMDIxLCAxOjA5IHBtXHJcbiAqIEF1dGhvcjogQ2FtZXJvbiBSb2JpbnNvblxyXG4gKiBcclxuICogQ29weXJpZ2h0IChjKSAyMDIyIENhbWVyb24gUm9iaW5zb25cclxuICovXHJcblxyXG5pbXBvcnQgeyBOb3RpY2UsIFBsdWdpbiwgIE1hcmtkb3duUmVuZGVyQ2hpbGQsIE1hcmtkb3duUmVuZGVyZXIgfSBmcm9tICdvYnNpZGlhbic7XHJcbmltcG9ydCAqIGFzIG11bHRpQ29sdW1uUGFyc2VyIGZyb20gJy4vdXRpbGl0aWVzL3RleHRQYXJzZXInO1xyXG5pbXBvcnQgeyBSZWdpb25ET01NYW5hZ2VyLCBNdWx0aUNvbHVtblJlbmRlckRhdGEsIEdsb2JhbERPTU1hbmFnZXIgfSBmcm9tICcuL2RvbV9tYW5hZ2VyL2RvbU1hbmFnZXInO1xyXG5pbXBvcnQgeyBET01PYmplY3QsIERPTU9iamVjdFRhZyB9IGZyb20gJy4vZG9tX21hbmFnZXIvZG9tT2JqZWN0JztcclxuaW1wb3J0IHsgTXVsdGlDb2x1bW5TZXR0aW5ncywgQ29sdW1uTGF5b3V0IH0gZnJvbSBcIi4vcmVnaW9uU2V0dGluZ3NcIjtcclxuXHJcbmltcG9ydCB7IGdldFVJRCB9IGZyb20gJy4vdXRpbGl0aWVzL3V0aWxzJztcclxuaW1wb3J0IHsgTXVsdGlDb2x1bW5MYXlvdXRDU1MsIE11bHRpQ29sdW1uU3R5bGVDU1MgfSBmcm9tICcuL3V0aWxpdGllcy9jc3NEZWZpbml0aW9ucyc7XHJcbmltcG9ydCB7IEVsZW1lbnRSZW5kZXJUeXBlLCBnZXRFbGVtZW50UmVuZGVyVHlwZSB9IGZyb20gJy4vdXRpbGl0aWVzL2VsZW1lbnRSZW5kZXJUeXBlUGFyc2VyJztcclxuXHJcbmV4cG9ydCBkZWZhdWx0IGNsYXNzIE11bHRpQ29sdW1uTWFya2Rvd24gZXh0ZW5kcyBQbHVnaW4ge1xyXG5cdC8vIHNldHRpbmdzOiBTcGxpdENvbHVtbk1hcmtkb3duU2V0dGluZ3M7XHJcblxyXG4gICAgZ2xvYmFsTWFuYWdlcjogR2xvYmFsRE9NTWFuYWdlciA9IG5ldyBHbG9iYWxET01NYW5hZ2VyKCk7XHJcbiAgICBcclxuXHRhc3luYyBvbmxvYWQoKSB7XHJcblxyXG4gICAgICAgIGNvbnNvbGUubG9nKFwiTG9hZGluZyBtdWx0aS1jb2x1bW4gbWFya2Rvd25cIik7XHJcblxyXG4gICAgICAgIHRoaXMuc2V0dXBNYXJrZG93blBvc3RQcm9jZXNzb3IoKTtcclxuXHJcbiAgICAgICAgLy9UT0RPOiBTZXQgdXAgdGhpcyBhcyBhIG1vZGFsIHRvIHNldCBzZXR0aW5ncyBhdXRvbWF0aWNhbGx5XHJcbiAgICAgICAgdGhpcy5hZGRDb21tYW5kKHsgICAgICAgICAgICBcclxuICAgICAgICAgICAgaWQ6IGBpbnNlcnQtbXVsdGktY29sdW1uLXJlZ2lvbmAsXHJcbiAgICAgICAgICAgIG5hbWU6IGBJbnNlcnQgTXVsdGktQ29sdW1uIFJlZ2lvbmAsXHJcbiAgICAgICAgICAgIGVkaXRvckNhbGxiYWNrOiAoZWRpdG9yLCB2aWV3KSA9PiB7XHJcblxyXG4gICAgICAgICAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgICAgICAgICBlZGl0b3IuZ2V0RG9jKCkucmVwbGFjZVNlbGVjdGlvbihcclxuYFxyXG49PT0gbXVsdGktY29sdW1uLXN0YXJ0OiBJRF8ke2dldFVJRCg0KX1cclxuXFxgXFxgXFxgY29sdW1uLXNldHRpbmdzXHJcbk51bWJlciBvZiBDb2x1bW5zOiAyXHJcbkxhcmdlc3QgQ29sdW1uOiBzdGFuZGFyZFxyXG5cXGBcXGBcXGBcclxuXHJcbj09PSBlbmQtY29sdW1uID09PVxyXG5cclxuPT09IG11bHRpLWNvbHVtbi1lbmRcclxuXHJcbiR7ZWRpdG9yLmdldERvYygpLmdldFNlbGVjdGlvbigpfWBcclxuICAgICAgICAgICAgICAgICAgICApO1xyXG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xyXG4gICAgICAgICAgICAgICAgICAgIG5ldyBOb3RpY2UoXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIFwiRW5jb3VudGVyZWQgYW4gZXJyb3IgaW5zZXJ0aW5nIGEgbXVsdGktY29sdW1uIHJlZ2lvbi4gUGxlYXNlIHRyeSBhZ2FpbiBsYXRlci5cIlxyXG4gICAgICAgICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgdGhpcy5hZGRDb21tYW5kKHsgICAgICAgICAgICBcclxuICAgICAgICAgICAgaWQ6IGBhZGQtSURzLVRvLW11bHRpLWNvbHVtbi1yZWdpb25gLFxyXG4gICAgICAgICAgICBuYW1lOiBgRml4IE1pc3NpbmcgSURzIGZvciBNdWx0aS1Db2x1bW4gUmVnaW9uc2AsXHJcbiAgICAgICAgICAgIGVkaXRvckNhbGxiYWNrOiAoZWRpdG9yLCB2aWV3KSA9PiB7XHJcblxyXG4gICAgICAgICAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgICAgICAgICAvKipcclxuICAgICAgICAgICAgICAgICAgICAgKiBOb3Qgc3VyZSBpZiB0aGVyZSBpcyBhbiBlYXNpZXIgd2F5IHRvIGRvIHRoaXMuXHJcbiAgICAgICAgICAgICAgICAgICAgICogXHJcbiAgICAgICAgICAgICAgICAgICAgICogR2V0IGFsbCBvZiB0aGUgbGluZXMgb2YgdGhlIGRvY3VtZW50IHNwbGl0IGJ5IG5ld2xpbmVzLlxyXG4gICAgICAgICAgICAgICAgICAgICAqL1xyXG4gICAgICAgICAgICAgICAgICAgIGxldCBsaW5lcyA9IGVkaXRvci5nZXRSYW5nZSh7IGxpbmU6IDAsIGNoOiAwIH0sIHsgbGluZTogZWRpdG9yLmdldERvYygpLmxpbmVDb3VudCgpLCBjaDogMH0pLnNwbGl0KFwiXFxuXCIpO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAvKipcclxuICAgICAgICAgICAgICAgICAgICAgKiBMb29wIHRocm91Z2ggYWxsIG9mIHRoZSBsaW5lcyBjaGVja2luZyBpZiB0aGUgbGluZSBpcyBhIFxyXG4gICAgICAgICAgICAgICAgICAgICAqIHN0YXJ0IHRhZyBhbmQgaWYgc28gaXMgaXQgbWlzc2luZyBhbiBJRC5cclxuICAgICAgICAgICAgICAgICAgICAgKi9cclxuICAgICAgICAgICAgICAgICAgICBsZXQgbGluZXNXaXRob3V0SURzID0gW11cclxuICAgICAgICAgICAgICAgICAgICBsZXQgdGV4dFdpdGhvdXRJRHMgPSBbXVxyXG4gICAgICAgICAgICAgICAgICAgIGZvcihsZXQgaSA9IDA7IGkgPCBsaW5lcy5sZW5ndGg7IGkrKykge1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGRhdGEgPSBtdWx0aUNvbHVtblBhcnNlci5pc1N0YXJ0VGFnV2l0aElEKGxpbmVzW2ldKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYoZGF0YS5pc1N0YXJ0VGFnID09PSB0cnVlICYmIGRhdGEuaGFzS2V5ID09PSBmYWxzZSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGluZXNXaXRob3V0SURzLnB1c2goaSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXh0V2l0aG91dElEcy5wdXNoKGxpbmVzW2ldKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgfSAgICAgICAgICAgICAgICAgICAgXHJcblxyXG4gICAgICAgICAgICAgICAgICAgIGlmKGxpbmVzV2l0aG91dElEcy5sZW5ndGggPT09IDApIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgbmV3IE5vdGljZSAoXCJGb3VuZCAwIG1pc3NpbmcgSURzIGluIHRoZSBjdXJyZW50IGRvY3VtZW50LlwiKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgLyoqXHJcbiAgICAgICAgICAgICAgICAgICAgICogTm93IGxvb3AgdGhyb3VnaCBlYWNoIGxpbmUgdGhhdCBpcyBtaXNzaW5nIGFuIElEIGFuZFxyXG4gICAgICAgICAgICAgICAgICAgICAqIGdlbmVyYXRlIGEgcmFuZG9tIElEIGFuZCByZXBsYWNlIHRoZSBvcmlnaW5hbCB0ZXh0LlxyXG4gICAgICAgICAgICAgICAgICAgICAqL1xyXG4gICAgICAgICAgICAgICAgICAgIGZvcihsZXQgaSA9IDA7IGkgPCBsaW5lc1dpdGhvdXRJRHMubGVuZ3RoOyBpKyspIHtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBvcmlnaW5hbFRleHQgPSB0ZXh0V2l0aG91dElEc1tpXVxyXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgdGV4dCA9IG9yaWdpbmFsVGV4dDtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGV4dCA9IHRleHQudHJpbUVuZCgpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZih0ZXh0LmNoYXJBdCh0ZXh0Lmxlbmd0aCAtIDEpID09PSBcIjpcIikge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGV4dCA9IHRleHQuc2xpY2UoMCwgdGV4dC5sZW5ndGgtMSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgdGV4dCA9IGAke3RleHR9OiBJRF8ke2dldFVJRCg0KX1gO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgZWRpdG9yLnJlcGxhY2VSYW5nZSh0ZXh0LCB7IGxpbmU6IGxpbmVzV2l0aG91dElEc1tpXSwgY2g6IDAgfSwgXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeyBsaW5lOiBsaW5lc1dpdGhvdXRJRHNbaV0sIGNoOiBvcmlnaW5hbFRleHQubGVuZ3RofSk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIG5ldyBOb3RpY2UgKGBSZXBsYWNlZCAke2xpbmVzV2l0aG91dElEcy5sZW5ndGh9IG1pc3NpbmcgSUQocykgaW4gdGhlIGN1cnJlbnQgZG9jdW1lbnQuYCk7XHJcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgbmV3IE5vdGljZShcclxuICAgICAgICAgICAgICAgICAgICAgICAgXCJFbmNvdW50ZXJlZCBhbiBlcnJvciBhZGRpZ24gSURzIHRvIG11bHRpLWNvbHVtbiByZWdpb25zLiBQbGVhc2UgdHJ5IGFnYWluIGxhdGVyLlwiXHJcbiAgICAgICAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0pO1xyXG5cclxuICAgICAgICB0aGlzLnJlZ2lzdGVySW50ZXJ2YWwod2luZG93LnNldEludGVydmFsKCgpID0+IHtcclxuICAgICAgICAgICAgXHJcbiAgICAgICAgICAgIHRoaXMuVXBkYXRlT3BlbkZpbGVQcmV2aWV3cygpO1xyXG4gICAgICAgIH0sIDIwMDApKTtcclxuICAgIH1cclxuXHJcbiAgICBVcGRhdGVPcGVuRmlsZVByZXZpZXdzKCkge1xyXG5cclxuICAgICAgICBsZXQgZmlsZU1hbmFnZXJzID0gdGhpcy5nbG9iYWxNYW5hZ2VyLmdldEFsbEZpbGVNYW5hZ2VycygpO1xyXG4gICAgICAgIGZpbGVNYW5hZ2Vycy5mb3JFYWNoKGVsZW1lbnQgPT4ge1xyXG4gICAgICAgICAgICBcclxuICAgICAgICAgICAgbGV0IHJlZ2lvbmFsTWFuYWdlcnMgPSBlbGVtZW50LmdldEFsbFJlZ2lvbmFsTWFuYWdlcnMoKTtcclxuICAgICAgICAgICAgcmVnaW9uYWxNYW5hZ2Vycy5mb3JFYWNoKHJlZ2lvbk1hbmFnZXIgPT4ge1xyXG4gICAgICAgICAgICAgICAgXHJcbiAgICAgICAgICAgICAgICBsZXQgcGFyZW50RWxlbWVudERhdGE6IE11bHRpQ29sdW1uUmVuZGVyRGF0YSA9IHJlZ2lvbk1hbmFnZXIuZ2V0UmVnaW9uUmVuZGVyRGF0YSgpO1xyXG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGVSZW5kZXJlZE1hcmtkb3duKHBhcmVudEVsZW1lbnREYXRhLmRvbU9iamVjdHMpOyAgICAgICAgICAgICAgICBcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgc2V0dXBNYXJrZG93blBvc3RQcm9jZXNzb3IoKSB7XHJcblxyXG4gICAgICAgIHRoaXMucmVnaXN0ZXJNYXJrZG93blBvc3RQcm9jZXNzb3IoYXN5bmMgKGVsLCBjdHgpID0+IHtcclxuXHJcbiAgICAgICAgICAgIC8vIEdldCB0aGUgaW5mbyBmb3Igb3VyIGN1cnJlbnQgY29udGV4dCBhbmQgdGhlbiBjaGVja1xyXG4gICAgICAgICAgICAvLyBpZiB0aGUgZW50aXJlIHRleHQgY29udGFpbnMgYSBzdGFydCB0YWcuIElmIHRoZXJlIGlzXHJcbiAgICAgICAgICAgIC8vIG5vIHN0YXJ0IHRhZyBpbiB0aGUgZG9jdW1lbnQgd2UgY2FuIGp1c3QgcmV0dXJuIGFuZFxyXG4gICAgICAgICAgICAvLyBpZ25vcmUgdGhlIHJlc3Qgb2YgdGhlIHBhcnNpbmcuXHJcbiAgICAgICAgICAgIGxldCBpbmZvID0gY3R4LmdldFNlY3Rpb25JbmZvKGVsKTtcclxuXHJcbiAgICAgICAgICAgIC8qKlxyXG4gICAgICAgICAgICAgKiBXZSBuZWVkIHRoZSBjb250ZXh0IGluZm8gdG8gcHJvcGVybHkgcGFyc2Ugc28gcmV0dXJuaW5nIGhlcmUgXHJcbiAgICAgICAgICAgICAqIGluZm8gaXMgbnVsbC4gVE9ETzogU2V0IGVycm9yIGluIHZpZXcgaWYgdGhpcyBvY2N1cnMuXHJcbiAgICAgICAgICAgICAqL1xyXG4gICAgICAgICAgICBpZighaW5mbykge1xyXG5cclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgY29uc3Qgc291cmNlUGF0aCA9IGN0eC5zb3VyY2VQYXRoO1xyXG5cclxuICAgICAgICAgICAgbGV0IGZpbGVET01NYW5hZ2VyID0gdGhpcy5nbG9iYWxNYW5hZ2VyLmdldEZpbGVNYW5hZ2VyKHNvdXJjZVBhdGgpO1xyXG4gICAgICAgICAgICBpZihmaWxlRE9NTWFuYWdlciA9PT0gbnVsbCkge1xyXG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coXCJGb3VuZCBudWxsIERPTSBtYW5hZ2VyLiBDb3VsZCBub3QgcHJvY2VzcyBtdWx0aS1jb2x1bW4gbWFya2Rvd24uXCIpXHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIC8qKlxyXG4gICAgICAgICAgICAgKiBJZiB3ZSBlbmNvdW50ZXIgYSBzdGFydCB0YWcgb24gdGhlIGRvY3VtZW50IHdlIHNldCB0aGUgZmxhZyB0byBzdGFydFxyXG4gICAgICAgICAgICAgKiBwYXJzaW5nIHRoZSByZXN0IG9mIHRoZSBkb2N1bWVudC5cclxuICAgICAgICAgICAgICovXHJcbiAgICAgICAgICAgIGlmKG11bHRpQ29sdW1uUGFyc2VyLmNvbnRhaW5zU3RhcnRUYWcoZWwudGV4dENvbnRlbnQpKSB7XHJcbiAgICAgICAgICAgICAgICBmaWxlRE9NTWFuYWdlci5zZXRIYXNTdGFydFRhZygpO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAvKiogXHJcbiAgICAgICAgICAgICAqIElmIHRoZSBkb2N1bWVudCBkb2VzIG5vdCBjb250YWluIGFueSBzdGFydCB0YWdzIHdlIGlnbm9yZSB0aGVcclxuICAgICAgICAgICAgICogcmVzdCBvZiB0aGUgcGFyc2luZy4gVGhpcyBpcyBvbmx5IHNldCB0byB0cnVlIG9uY2UgdGhlIGZpcnN0XHJcbiAgICAgICAgICAgICAqIHN0YXJ0IHRhZyBlbGVtZW50IGlzIHBhcnNlZCBhYm92ZS5cclxuICAgICAgICAgICAgICovXHJcbiAgICAgICAgICAgIGlmKGZpbGVET01NYW5hZ2VyLmdldEhhc1N0YXJ0VGFnKCkgPT09IGZhbHNlKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIC8qKlxyXG4gICAgICAgICAgICAgKiBUYWtlIHRoZSBpbmZvIHByb3ZpZGVkIGFuZCBnZW5lcmF0ZSB0aGUgcmVxdWlyZWQgdmFyaWFibGVzIGZyb20gXHJcbiAgICAgICAgICAgICAqIHRoZSBsaW5lIHN0YXJ0IGFuZCBlbmQgdmFsdWVzLlxyXG4gICAgICAgICAgICAgKi9cclxuICAgICAgICAgICAgbGV0IGRvY0xpbmVzID0gaW5mby50ZXh0LnNwbGl0KFwiXFxuXCIpO1xyXG4gICAgICAgICAgICBsZXQgbGluZXNBYm92ZUFycmF5ID0gZG9jTGluZXMuc2xpY2UoMCwgaW5mby5saW5lU3RhcnQpXHJcbiAgICAgICAgICAgIGxldCBsaW5lc09mRWxlbWVudCA9IGRvY0xpbmVzLnNsaWNlKGluZm8ubGluZVN0YXJ0LCBpbmZvLmxpbmVFbmQgKyAxKTtcclxuICAgICAgICAgICAgbGV0IGxpbmVzQmVsb3dBcnJheSA9IGRvY0xpbmVzLnNsaWNlKGluZm8ubGluZUVuZCArIDEpXHJcblxyXG4gICAgICAgICAgICAvKipcclxuICAgICAgICAgICAgICogSWYgdGhlIGN1cnJlbnQgbGluZSBpcyBhIHN0YXJ0IHRhZyB3ZSB3YW50IHRvIHNldCB1cCB0aGVcclxuICAgICAgICAgICAgICogcmVnaW9uIG1hbmFnZXIuIFRoZSByZWdpb25hbCBtYW5hZ2VyIHRha2VzIGNhcmVcclxuICAgICAgICAgICAgICogb2YgYWxsIGl0ZW1zIGJldHdlZW4gaXQncyBzdGFydCBhbmQgZW5kIHRhZ3Mgd2hpbGUgdGhlXHJcbiAgICAgICAgICAgICAqIGZpbGUgbWFuYWdlciB3ZSBnb3QgYWJvdmUgYWJvdmUgdGFrZXMgY2FyZSBvZiBhbGwgcmVnaW9uYWwgXHJcbiAgICAgICAgICAgICAqIG1hbmFnZXJzIGluIGVhY2ggZmlsZS5cclxuICAgICAgICAgICAgICovXHJcbiAgICAgICAgICAgIGxldCBlbGVtZW50VGV4dFNwYWNlZCA9IGxpbmVzT2ZFbGVtZW50LnJlZHVjZSgocHJldiwgY3VycikgPT4ge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHByZXYgKyBcIlxcblwiICsgY3VycjtcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIGlmKG11bHRpQ29sdW1uUGFyc2VyLmNvbnRhaW5zU3RhcnRUYWcoZWwudGV4dENvbnRlbnQpKSB7XHJcblxyXG4gICAgICAgICAgICAgICAgLyoqIFxyXG4gICAgICAgICAgICAgICAgICogU2V0IHVwIHRoZSBjdXJyZW50IGVsZW1lbnQgdG8gYWN0IGFzIHRoZSBwYXJlbnQgZm9yIHRoZSBcclxuICAgICAgICAgICAgICAgICAqIG11bHRpLWNvbHVtbiByZWdpb24uXHJcbiAgICAgICAgICAgICAgICAgKi9cclxuICAgICAgICAgICAgICAgIGVsLmNoaWxkcmVuWzBdLmRldGFjaCgpO1xyXG4gICAgICAgICAgICAgICAgZWwuY2xhc3NMaXN0LmFkZChNdWx0aUNvbHVtbkxheW91dENTUy5SZWdpb25Sb290Q29udGFpbmVyRGl2KVxyXG4gICAgICAgICAgICAgICAgbGV0IHJlbmRlckVycm9yUmVnaW9uID0gZWwuY3JlYXRlRGl2KHtcclxuICAgICAgICAgICAgICAgICAgICBjbHM6IGAke011bHRpQ29sdW1uTGF5b3V0Q1NTLlJlZ2lvbkVycm9yQ29udGFpbmVyRGl2fSwgJHtNdWx0aUNvbHVtblN0eWxlQ1NTLlJlZ2lvbkVycm9yTWVzc2FnZX1gLFxyXG4gICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICBsZXQgcmVuZGVyQ29sdW1uUmVnaW9uID0gZWwuY3JlYXRlRGl2KHtcclxuICAgICAgICAgICAgICAgICAgICBjbHM6IE11bHRpQ29sdW1uTGF5b3V0Q1NTLlJlZ2lvbkNvbnRlbnRDb250YWluZXJEaXZcclxuICAgICAgICAgICAgICAgIH0pXHJcblxyXG4gICAgICAgICAgICAgICAgbGV0IHN0YXJ0QmxvY2tEYXRhID0gbXVsdGlDb2x1bW5QYXJzZXIuZ2V0U3RhcnRCbG9ja0Fib3ZlTGluZShsaW5lc09mRWxlbWVudClcclxuICAgICAgICAgICAgICAgIGxldCByZWdpb25LZXkgPSBzdGFydEJsb2NrRGF0YS5zdGFydEJsb2NrS2V5O1xyXG4gICAgICAgICAgICAgICAgaWYoZmlsZURPTU1hbmFnZXIuY2hlY2tLZXlFeGlzdHMocmVnaW9uS2V5KSA9PT0gdHJ1ZSkge1xyXG5cclxuICAgICAgICAgICAgICAgICAgICBsZXQgeyBudW1iZXJPZlRhZ3MsIGtleXMgfSA9IG11bHRpQ29sdW1uUGFyc2VyLmNvdW50U3RhcnRUYWdzKGluZm8udGV4dCk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIGxldCBudW1NYXRjaGVzID0gMDtcclxuICAgICAgICAgICAgICAgICAgICBmb3IobGV0IGkgPSAwOyBpIDwgbnVtYmVyT2ZUYWdzOyBpKyspIHtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEJlY2F1c2Ugd2UgY2hlY2tlZCBpZiBrZXkgZXhpc3RzIG9uZSBvZiB0aGVzZSBoYXMgdG8gbWF0Y2guXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKGtleXNbaV0gPT09IHJlZ2lvbktleSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbnVtTWF0Y2hlcysrO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICAvLyBXZSBvbmx5IHdhbnQgdG8gZGlzcGxheSBhbiBlcnJvciBpZiB0aGVyZSBhcmUgbW9yZSB0aGFuIDIgb2YgdGhlIHNhbWUgaWQgYWNyb3NzXHJcbiAgICAgICAgICAgICAgICAgICAgLy8gdGhlIHdob2xlIGRvY3VtZW50LiBUaGlzIHByZXZlbnRzIGVycm9zIHdoZW4gb2JzaWRpYW4gcmVsb2FkcyB0aGUgd2hvbGUgZG9jdW1lbnRcclxuICAgICAgICAgICAgICAgICAgICAvLyBhbmQgdGhlcmUgYXJlIHR3byBvZiB0aGUgc2FtZSBrZXkgaW4gdGhlIG1hcC5cclxuICAgICAgICAgICAgICAgICAgICBpZihudW1NYXRjaGVzID49IDIpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYocmVnaW9uS2V5ID09PSBcIlwiKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW5kZXJFcnJvclJlZ2lvbi5pbm5lclRleHQgPSBcIkZvdW5kIG11bHRpcGxlIHJlZ2lvbnMgd2l0aCBlbXB0eSBJRHMuIFBsZWFzZSBzZXQgYSB1bmlxdWUgSUQgYWZ0ZXIgZWFjaCBzdGFydCB0YWcuXFxuRUc6ICc9PT0gbXVsdGktY29sdW1uLXN0YXJ0OiByYW5kb21JRCdcXG5PciB1c2UgJ0ZpeCBNaXNzaW5nIElEcycgaW4gdGhlIGNvbW1hbmQgcGFsZXR0ZSBhbmQgcmVsb2FkIHRoZSBkb2N1bWVudC5cIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVuZGVyRXJyb3JSZWdpb24uaW5uZXJUZXh0ID0gXCJSZWdpb24gSUQgYWxyZWFkeSBleGlzdHMgaW4gZG9jdW1lbnQsIHBsZWFzZSBzZXQgYSB1bmlxdWUgSUQuXFxuRUc6ICc9PT0gbXVsdGktY29sdW1uLXN0YXJ0OiByYW5kb21JRCdcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBlbC5pZCA9IGBNdWx0aUNvbHVtbklEOiR7cmVnaW9uS2V5fWBcclxuXHJcbiAgICAgICAgICAgICAgICBsZXQgZWxlbWVudE1hcmtkb3duUmVuZGVyZXIgPSBuZXcgTWFya2Rvd25SZW5kZXJDaGlsZChlbCk7XHJcbiAgICAgICAgICAgICAgICBmaWxlRE9NTWFuYWdlci5jcmVhdGVSZWdpb25hbE1hbmFnZXIocmVnaW9uS2V5LCBlbCwgcmVuZGVyRXJyb3JSZWdpb24sIHJlbmRlckNvbHVtblJlZ2lvbik7XHJcbiAgICAgICAgICAgICAgICBlbGVtZW50TWFya2Rvd25SZW5kZXJlci5vbnVubG9hZCA9ICgpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICBpZihmaWxlRE9NTWFuYWdlcikge1xyXG4gICAgXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGZpbGVET01NYW5hZ2VyLnJlbW92ZVJlZ2lvbihzdGFydEJsb2NrRGF0YS5zdGFydEJsb2NrS2V5KTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9O1xyXG4gICAgICAgICAgICAgICAgY3R4LmFkZENoaWxkKGVsZW1lbnRNYXJrZG93blJlbmRlcmVyKTtcclxuXHJcbiAgICAgICAgICAgICAgICAvKipcclxuICAgICAgICAgICAgICAgICAqIE5vdyB3ZSBoYXZlIGNyZWF0ZWQgb3VyIHJlZ2lvbmFsIG1hbmFnZXIgYW5kIGRlZmluZWQgd2hhdCBlbGVtZW50cyBcclxuICAgICAgICAgICAgICAgICAqIG5lZWQgdG8gYmUgcmVuZGVyZWQgaW50by4gU28gd2UgY2FuIHJldHVybiB3aXRob3V0IGFueSBtb3JlIHByb2Nlc3NpbmcuXHJcbiAgICAgICAgICAgICAgICAgKi9cclxuICAgICAgICAgICAgICAgIHJldHVyblxyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAvKipcclxuICAgICAgICAgICAgICogQ2hlY2sgaWYgYW55IG9mIHRoZSBsaW5lcyBhYm92ZSB1cyBjb250YWluIGEgc3RhcnQgYmxvY2ssIGFuZCBpZlxyXG4gICAgICAgICAgICAgKiBzbyBnZXQgdGhlIGxpbmVzIGZyb20gb3VyIGN1cnJlbnQgZWxlbWVudCB0byB0aGUgc3RhcnQgYmxvY2suXHJcbiAgICAgICAgICAgICAqL1xyXG4gICAgICAgICAgICBsZXQgc3RhcnRCb2NrQWJvdmUgPSBtdWx0aUNvbHVtblBhcnNlci5nZXRTdGFydEJsb2NrQWJvdmVMaW5lKGxpbmVzQWJvdmVBcnJheSk7XHJcbiAgICAgICAgICAgIGlmKHN0YXJ0Qm9ja0Fib3ZlID09PSBudWxsKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgLyoqXHJcbiAgICAgICAgICAgICAqIFdlIG5vdyBrbm93IHdlJ3JlIHdpdGhpbiBhIG11bHRpLWNvbHVtbiByZWdpb24sIHNvIHdlIHVwZGF0ZSBvdXJcclxuICAgICAgICAgICAgICogbGlzdCBvZiBsaW5lcyBhYm92ZSB0byBqdXN0IGJlIHRoZSBpdGVtcyB3aXRoaW4gdGhpcyByZWdpb24uXHJcbiAgICAgICAgICAgICAqL1xyXG4gICAgICAgICAgICBsaW5lc0Fib3ZlQXJyYXkgPSBzdGFydEJvY2tBYm92ZS5saW5lc0Fib3ZlQXJyYXk7XHJcblxyXG4gICAgICAgICAgICAvKipcclxuICAgICAgICAgICAgICogV2UgdXNlIHRoZSBzdGFydCBibG9jaydzIGtleSB0byBnZXQgb3VyIHJlZ2lvbmFsIG1hbmFnZXIuIElmIHRoaXNcclxuICAgICAgICAgICAgICogbG9va3VwIGZhaWxzIHdlIGNhbiBub3QgY29udGludWUgcHJvY2Vzc2luZyB0aGlzIGVsZW1lbnQuXHJcbiAgICAgICAgICAgICAqL1xyXG4gICAgICAgICAgICBsZXQgcmVnaW9uYWxNYW5hZ2VyOiBSZWdpb25ET01NYW5hZ2VyID0gZmlsZURPTU1hbmFnZXIuZ2V0UmVnaW9uYWxNYW5hZ2VyKHN0YXJ0Qm9ja0Fib3ZlLnN0YXJ0QmxvY2tLZXkpO1xyXG4gICAgICAgICAgICBpZihyZWdpb25hbE1hbmFnZXIgPT09IG51bGwpIHtcclxuICAgICAgICAgICAgICAgIHJldHVyblxyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAvKipcclxuICAgICAgICAgICAgICogVG8gbWFrZSBzdXJlIHdlJ3JlIHBsYWNpbmcgdGhlIGl0ZW0gaW4gdGhlIHJpZ2h0IGxvY2F0aW9uIChhbmQgXHJcbiAgICAgICAgICAgICAqIG92ZXJ3cml0ZSBlbGVtZW50cyB0aGF0IGFyZSBub3cgZ29uZSkgd2Ugbm93IHdhbnQgYWxsIG9mIHRoZVxyXG4gICAgICAgICAgICAgKiBsaW5lcyBhZnRlciB0aGlzIGVsZW1lbnQgdXAgdG8gdGhlIGVuZCB0YWcuXHJcbiAgICAgICAgICAgICAqL1xyXG4gICAgICAgICAgICBsaW5lc0JlbG93QXJyYXkgPSAgbXVsdGlDb2x1bW5QYXJzZXIuZ2V0RW5kQmxvY2tCZWxvdyhsaW5lc0JlbG93QXJyYXkpO1xyXG5cclxuICAgICAgICAgICAgLyoqXHJcbiAgICAgICAgICAgICAqIE5vdyB3ZSB0YWtlIHRoZSBsaW5lcyBhYm92ZSBvdXIgY3VycmVudCBlbGVtZW50IHVwIHVudGlsIHRoZVxyXG4gICAgICAgICAgICAgKiBzdGFydCByZWdpb24gdGFnIGFuZCByZW5kZXIgdGhhdCBpbnRvIGFuIEhUTUwgZWxlbWVudC4gV2Ugd2lsbCBcclxuICAgICAgICAgICAgICogdXNlIHRoZXNlIGVsZW1lbnRzIHRvIGRldGVybWluZSB3aGVyZSB0byBwbGFjZSBvdXIgY3VycmVudCBlbGVtZW50LlxyXG4gICAgICAgICAgICAgKi9cclxuICAgICAgICAgICAgbGV0IHNpYmxpbmdzQWJvdmU6IEhUTUxEaXZFbGVtZW50ID0gcmVuZGVyTWFya2Rvd25Gcm9tTGluZXMobGluZXNBYm92ZUFycmF5LCBzb3VyY2VQYXRoKTtcclxuXHJcbiAgICAgICAgICAgIGxldCBzaWJsaW5nc0JlbG93OiBIVE1MRGl2RWxlbWVudCA9IHJlbmRlck1hcmtkb3duRnJvbUxpbmVzKGxpbmVzQmVsb3dBcnJheSwgc291cmNlUGF0aCk7XHJcblxyXG4gICAgICAgICAgICAvKipcclxuICAgICAgICAgICAgICogU2V0IHVwIG91ciBkb20gb2JqZWN0IHRvIGJlIGFkZGVkIHRvIHRoZSBtYW5hZ2VyLlxyXG4gICAgICAgICAgICAgKi9cclxuICAgICAgICAgICAgbGV0IGN1cnJlbnRPYmplY3Q6IERPTU9iamVjdCA9IG5ldyBET01PYmplY3QoZWwpXHJcbiAgICAgICAgICAgIGVsLmlkID0gY3VycmVudE9iamVjdC5VSUQ7XHJcblxyXG4gICAgICAgICAgICAvKipcclxuICAgICAgICAgICAgICogTm93IHdlIGFkZCB0aGUgb2JqZWN0IHRvIHRoZSBtYW5hZ2VyIGFuZCB0aGVuIHNldHVwIHRoZVxyXG4gICAgICAgICAgICAgKiBjYWxsYmFjayBmb3Igd2hlbiB0aGUgb2JqZWN0IGlzIHJlbW92ZWQgZnJvbSB2aWV3IHRoYXQgd2lsbCByZW1vdmUgXHJcbiAgICAgICAgICAgICAqIHRoZSBpdGVtIGZyb20gdGhlIG1hbmFnZXIuXHJcbiAgICAgICAgICAgICAqL1xyXG4gICAgICAgICAgICByZWdpb25hbE1hbmFnZXIuYWRkT2JqZWN0KHNpYmxpbmdzQWJvdmUsIHNpYmxpbmdzQmVsb3csIGN1cnJlbnRPYmplY3QpO1xyXG5cclxuICAgICAgICAgICAgbGV0IGVsZW1lbnRNYXJrZG93blJlbmRlcmVyID0gbmV3IE1hcmtkb3duUmVuZGVyQ2hpbGQoZWwpO1xyXG4gICAgICAgICAgICBlbGVtZW50TWFya2Rvd25SZW5kZXJlci5vbnVubG9hZCA9ICgpID0+IHtcclxuICAgICAgICAgICAgICAgIGlmKHJlZ2lvbmFsTWFuYWdlcikge1xyXG4gICAgICAgICAgICAgICAgICAgIFxyXG4gICAgICAgICAgICAgICAgICAgIC8vIFdlIGNhbiBhdHRlbXB0IHRvIHVwZGF0ZSB0aGUgdmlldyBoZXJlIGFmdGVyIHRoZSBpdGVtIGlzIHJlbW92ZWRcclxuICAgICAgICAgICAgICAgICAgICAvLyBidXQgbmVlZCB0byBnZXQgdGhlIGl0ZW0ncyBwYXJlbnQgZWxlbWVudCBiZWZvcmUgcmVtb3Zpbmcgb2JqZWN0IGZyb20gbWFuYWdlci5cclxuICAgICAgICAgICAgICAgICAgICBsZXQgcmVnaW9uUmVuZGVyRGF0YTogTXVsdGlDb2x1bW5SZW5kZXJEYXRhID0gcmVnaW9uYWxNYW5hZ2VyLmdldFJlZ2lvblJlbmRlckRhdGEoKTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgcmVnaW9uYWxNYW5hZ2VyLnJlbW92ZU9iamVjdChjdXJyZW50T2JqZWN0LlVJRCk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIC8qKlxyXG4gICAgICAgICAgICAgICAgICAgICAqIE5lZWQgdG8gY2hlY2sgaGVyZSBpZiBlbGVtZW50IGlzIG51bGwgYXMgdGhpcyBjbG9zdXJlIHdpbGwgYmUgY2FsbGVkXHJcbiAgICAgICAgICAgICAgICAgICAgICogcmVwZWF0ZWRseSBvbiBmaWxlIGNoYW5nZS5cclxuICAgICAgICAgICAgICAgICAgICAgKi9cclxuICAgICAgICAgICAgICAgICAgICBpZihyZWdpb25SZW5kZXJEYXRhLnBhcmVudFJlbmRlckVsZW1lbnQgPT09IG51bGwpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbmRlckNvbHVtbk1hcmtkb3duKHJlZ2lvblJlbmRlckRhdGEucGFyZW50UmVuZGVyRWxlbWVudCwgcmVnaW9uUmVuZGVyRGF0YS5kb21PYmplY3RzLCByZWdpb25SZW5kZXJEYXRhLnBhcmVudFJlbmRlclNldHRpbmdzKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfTtcclxuICAgICAgICAgICAgY3R4LmFkZENoaWxkKGVsZW1lbnRNYXJrZG93blJlbmRlcmVyKTtcclxuXHJcbiAgICAgICAgICAgIC8qKlxyXG4gICAgICAgICAgICAgKiBOb3cgd2UgY2hlY2sgaWYgb3VyIGN1cnJlbnQgZWxlbWVudCBpcyBhIHNwZWNpYWwgZmxhZyBzbyB3ZSBjYW5cclxuICAgICAgICAgICAgICogcHJvcGVybHkgc2V0IHRoZSBlbGVtZW50IHRhZyB3aXRoaW4gdGhlIHJlZ2lvbmFsIG1hbmFnZXIuXHJcbiAgICAgICAgICAgICAqL1xyXG4gICAgICAgICAgICBpZihtdWx0aUNvbHVtblBhcnNlci5jb250YWluc0VuZFRhZyhlbC50ZXh0Q29udGVudCkgPT09IHRydWUpIHtcclxuXHJcbiAgICAgICAgICAgICAgICBlbC5hZGRDbGFzcyhNdWx0aUNvbHVtblN0eWxlQ1NTLlJlZ2lvbkVuZFRhZylcclxuICAgICAgICAgICAgICAgIHJlZ2lvbmFsTWFuYWdlci51cGRhdGVFbGVtZW50VGFnKGN1cnJlbnRPYmplY3QuVUlELCBET01PYmplY3RUYWcuZW5kUmVnaW9uKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBlbHNlIGlmKG11bHRpQ29sdW1uUGFyc2VyLmNvbnRhaW5zQ29sRW5kVGFnKGVsZW1lbnRUZXh0U3BhY2VkKSA9PT0gdHJ1ZSkge1xyXG5cclxuICAgICAgICAgICAgICAgIGVsLmFkZENsYXNzKE11bHRpQ29sdW1uU3R5bGVDU1MuQ29sdW1uRW5kVGFnKVxyXG4gICAgICAgICAgICAgICAgcmVnaW9uYWxNYW5hZ2VyLnVwZGF0ZUVsZW1lbnRUYWcoY3VycmVudE9iamVjdC5VSUQsIERPTU9iamVjdFRhZy5jb2x1bW5CcmVhayk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgZWxzZSBpZihtdWx0aUNvbHVtblBhcnNlci5jb250YWluc0NvbFNldHRpbmdzVGFnKGVsZW1lbnRUZXh0U3BhY2VkKSA9PT0gdHJ1ZSkge1xyXG5cclxuICAgICAgICAgICAgICAgIGVsLmFkZENsYXNzKE11bHRpQ29sdW1uU3R5bGVDU1MuUmVnaW9uU2V0dGluZ3MpXHJcbiAgICAgICAgICAgICAgICByZWdpb25hbE1hbmFnZXIuc2V0RWxlbWVudFRvU2V0dGluZ3NCbG9jayhjdXJyZW50T2JqZWN0LlVJRCwgZWxlbWVudFRleHRTcGFjZWQpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgZWwuYWRkQ2xhc3MoTXVsdGlDb2x1bW5TdHlsZUNTUy5SZWdpb25Db250ZW50KVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIFxyXG4gICAgICAgICAgICAvKipcclxuICAgICAgICAgICAgICogVXNlIG91ciByZWdpb25hbCBtYW5hZ2VyIHRvIGdldCBldmVyeXRoaW5nIG5lZWRlZCB0byByZW5kZXIgdGhlIHJlZ2lvbi5cclxuICAgICAgICAgICAgICovXHJcbiAgICAgICAgICAgIGxldCBwYXJlbnRFbGVtZW50RGF0YTogTXVsdGlDb2x1bW5SZW5kZXJEYXRhID0gcmVnaW9uYWxNYW5hZ2VyLmdldFJlZ2lvblJlbmRlckRhdGEoKTtcclxuICAgICAgICAgICAgdGhpcy5yZW5kZXJDb2x1bW5NYXJrZG93bihwYXJlbnRFbGVtZW50RGF0YS5wYXJlbnRSZW5kZXJFbGVtZW50LCBwYXJlbnRFbGVtZW50RGF0YS5kb21PYmplY3RzLCBwYXJlbnRFbGVtZW50RGF0YS5wYXJlbnRSZW5kZXJTZXR0aW5ncyk7XHJcblxyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBUaGlzIGZ1bmN0aW9uIHRha2VzIGluIHRoZSBkYXRhIGZvciB0aGUgbXVsdGktY29sdW1uIHJlZ2lvbiBhbmQgc2V0cyB1cCB0aGUgXHJcbiAgICAgKiB1c2VyIGRlZmluZWQgbnVtYmVyIG9mIGNoaWxkcmVuIHdpdGggdGhlIHByb3BlciBjc3MgY2xhc3NlcyB0byBiZSByZW5kZXJlZCBwcm9wZXJseS5cclxuICAgICAqIFxyXG4gICAgICogQHBhcmFtIHBhcmVudEVsZW1lbnQgVGhlIGVsZW1lbnQgdGhhdCB0aGUgbXVsdGktY29sdW1uIHJlZ2lvbiB3aWxsIGJlIHJlbmRlcmVkIHVuZGVyLlxyXG4gICAgICogQHBhcmFtIHJlZ2lvbkVsZW1lbnRzIFRoZSBsaXN0IG9mIERPTSBvYmplY3RzIHRoYXQgd2lsbCBiZSBjb3BwaWVkIHVuZGVyIHRoZSBwYXJlbnQgb2JqZWN0XHJcbiAgICAgKiBAcGFyYW0gc2V0dGluZ3MgVGhlIHNldHRpbmdzIHRoZSB1c2VyIGhhcyBkZWZpbmVkIGZvciB0aGUgcmVnaW9uLlxyXG4gICAgICovXHJcbiAgICByZW5kZXJDb2x1bW5NYXJrZG93bihwYXJlbnRFbGVtZW50OiBIVE1MRWxlbWVudCwgcmVnaW9uRWxlbWVudHM6IERPTU9iamVjdFtdLCBzZXR0aW5nczogTXVsdGlDb2x1bW5TZXR0aW5ncykge1xyXG5cclxuICAgICAgICBsZXQgbXVsdGlDb2x1bW5QYXJlbnQgPSBjcmVhdGVEaXYoe1xyXG4gICAgICAgICAgICBjbHM6IE11bHRpQ29sdW1uTGF5b3V0Q1NTLlJlZ2lvbkNvbHVtbkNvbnRhaW5lckRpdixcclxuICAgICAgICB9KTtcclxuICAgICAgICBpZihzZXR0aW5ncy5kcmF3U2hhZG93ID09PSB0cnVlKSB7XHJcbiAgICAgICAgICAgIG11bHRpQ29sdW1uUGFyZW50LmFkZENsYXNzKE11bHRpQ29sdW1uU3R5bGVDU1MuUmVnaW9uU2hhZG93KTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8qKlxyXG4gICAgICAgICAqIFBhc3Mgb3VyIHBhcmVudCBkaXYgYW5kIHNldHRpbmdzIHRvIHBhcnNlciB0byBjcmVhdGUgdGhlIHJlcXVpcmVkXHJcbiAgICAgICAgICogY29sdW1uIGRpdnMgYXMgY2hpbGRyZW4gb2YgdGhlIHBhcmVudC5cclxuICAgICAgICAgKi9cclxuICAgICAgICBsZXQgY29sdW1uQ29udGVudERpdnMgPSBnZXRDb2x1bW5Db250ZW50RGl2cyhzZXR0aW5ncywgbXVsdGlDb2x1bW5QYXJlbnQpO1xyXG4gICAgICAgIGZvcihsZXQgaSA9IDA7IGkgPCBjb2x1bW5Db250ZW50RGl2cy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICBpZihzZXR0aW5ncy5kcmF3Qm9yZGVyID09PSB0cnVlKSB7XHJcbiAgICAgICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2c1tpXS5hZGRDbGFzcyhNdWx0aUNvbHVtblN0eWxlQ1NTLkNvbHVtbkJvcmRlcik7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGlmKHNldHRpbmdzLmRyYXdTaGFkb3cgPT09IHRydWUpIHtcclxuICAgICAgICAgICAgICAgIGNvbHVtbkNvbnRlbnREaXZzW2ldLmFkZENsYXNzKE11bHRpQ29sdW1uU3R5bGVDU1MuQ29sdW1uU2hhZG93KTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gQ3JlYXRlIG1hcmtkb3duIHJlbmRlcmVyIHRvIHBhcnNlIHRoZSBwYXNzZWQgbWFya2Rvd25cclxuICAgICAgICAvLyBiZXR3ZWVuIHRoZSB0YWdzLlxyXG4gICAgICAgIGxldCBtYXJrZG93blJlbmRlckNoaWxkID0gbmV3IE1hcmtkb3duUmVuZGVyQ2hpbGQoXHJcbiAgICAgICAgICAgIG11bHRpQ29sdW1uUGFyZW50XHJcbiAgICAgICAgKTtcclxuXHJcbiAgICAgICAgLy8gUmVtb3ZlIGV2ZXJ5IG90aGVyIGNoaWxkIGZyb20gdGhlIHBhcmVudCBzbyBcclxuICAgICAgICAvLyB3ZSBkb250IGVuZCB1cCB3aXRoIG11bHRpcGxlIHNldHMgb2YgZGF0YS4gVGhpcyBzaG91bGRcclxuICAgICAgICAvLyByZWFsbHkgb25seSBuZWVkIHRvIGxvb3Agb25jZSBmb3IgaSA9IDAgYnV0IGxvb3AganVzdFxyXG4gICAgICAgIC8vIGluIGNhc2UuXHJcbiAgICAgICAgZm9yKGxldCBpID0gcGFyZW50RWxlbWVudC5jaGlsZHJlbi5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xyXG4gICAgICAgICAgICBwYXJlbnRFbGVtZW50LmNoaWxkcmVuW2ldLmRldGFjaCgpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBwYXJlbnRFbGVtZW50LmFwcGVuZENoaWxkKG1hcmtkb3duUmVuZGVyQ2hpbGQuY29udGFpbmVyRWwpO1xyXG5cclxuICAgICAgICBsZXQgY29sdW1uSW5kZXggPSAwO1xyXG4gICAgICAgIGZvcihsZXQgaSA9IDA7IGkgPCByZWdpb25FbGVtZW50cy5sZW5ndGg7IGkrKykge1xyXG5cclxuICAgICAgICAgICAgaWYgKHJlZ2lvbkVsZW1lbnRzW2ldLnRhZyAhPT0gRE9NT2JqZWN0VGFnLnN0YXJ0UmVnaW9uICAgIHx8XHJcbiAgICAgICAgICAgICAgICByZWdpb25FbGVtZW50c1tpXS50YWcgIT09IERPTU9iamVjdFRhZy5yZWdpb25TZXR0aW5ncyB8fFxyXG4gICAgICAgICAgICAgICAgcmVnaW9uRWxlbWVudHNbaV0udGFnICE9PSBET01PYmplY3RUYWcuZW5kUmVnaW9uICAgICAgfHxcclxuICAgICAgICAgICAgICAgIHJlZ2lvbkVsZW1lbnRzW2ldLnRhZyAhPT0gRE9NT2JqZWN0VGFnLmNvbHVtbkJyZWFrICkge1xyXG5cclxuICAgICAgICAgICAgICAgIC8vIFdlIHN0b3JlIHRoZSBlbGVtZW50cyBpbiBhIHdyYXBwZXIgY29udGFpbmVyIHVudGlsIHdlIGRldGVybWluZVxyXG4gICAgICAgICAgICAgICAgbGV0IGVsZW1lbnQgPSBjcmVhdGVEaXYoe1xyXG4gICAgICAgICAgICAgICAgICAgIGNsczogTXVsdGlDb2x1bW5MYXlvdXRDU1MuQ29sdW1uRHVhbEVsZW1lbnRDb250YWluZXIsXHJcbiAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICAgIHJlZ2lvbkVsZW1lbnRzW2ldLmVsZW1lbnRDb250YWluZXIgPSBlbGVtZW50O1xyXG4gICAgICAgICAgICAgICAgLy8gT3RoZXJ3aXNlIHdlIGp1c3QgbWFrZSBhIGNvcHkgb2YgdGhlIG9yaWdpbmFsIGVsZW1lbnQgdG8gZGlzcGxheS5cclxuICAgICAgICAgICAgICAgIGVsZW1lbnQuYXBwZW5kQ2hpbGQocmVnaW9uRWxlbWVudHNbaV0uZWxlbWVudC5jbG9uZU5vZGUodHJ1ZSkgYXMgSFRNTERpdkVsZW1lbnQpO1xyXG5cclxuICAgICAgICAgICAgICAgIGlmKGVsZW1lbnQgIT09IG51bGwpIHtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgY29sdW1uQ29udGVudERpdnNbY29sdW1uSW5kZXhdLmFwcGVuZENoaWxkKGVsZW1lbnQpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIC8qKlxyXG4gICAgICAgICAgICAgICAgICogSWYgdGhlIHRhZyBpcyBhIGNvbHVtbiBicmVhayB3ZSB1cGRhdGUgdGhlIGNvbHVtbiBpbmRleCBhZnRlclxyXG4gICAgICAgICAgICAgICAgICogYXBwZW5kaW5nIHRoZSBpdGVtIHRvIHRoZSBjb2x1bW4gZGl2LiBUaGlzIGtlZXBzIHRoZSBtYWluIERPTVxyXG4gICAgICAgICAgICAgICAgICogY2xlYW5lciBieSByZW1vdmluZyBvdGhlciBpdGVtcyBhbmQgcGxhY2luZyB0aGVtIGFsbCB3aXRoaW5cclxuICAgICAgICAgICAgICAgICAqIGEgcmVnaW9uIGNvbnRhaW5lci5cclxuICAgICAgICAgICAgICAgICAqL1xyXG4gICAgICAgICAgICAgICAgaWYocmVnaW9uRWxlbWVudHNbaV0udGFnID09PSBET01PYmplY3RUYWcuY29sdW1uQnJlYWsgJiYgXHJcbiAgICAgICAgICAgICAgICAgICAoY29sdW1uSW5kZXggKyAxKSA8IHNldHRpbmdzLm51bWJlck9mQ29sdW1ucykge1xyXG4gICAgIFxyXG4gICAgICAgICAgICAgICAgICAgICBjb2x1bW5JbmRleCsrO1xyXG4gICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBzZXRVcER1YWxSZW5kZXIoZG9tRWxlbWVudDogRE9NT2JqZWN0KSB7XHJcblxyXG4gICAgICAgIC8qKlxyXG4gICAgICAgICAqIElmIG91ciBlbGVtZW50IGlzIG9mIFwic3BlY2lhbFJlbmRlclwiIHR5cGUgaXQgKm1heSogbmVlZCB0byBiZSByZW5kZXJlZFxyXG4gICAgICAgICAqIHVzaW5nIHRoZSBvcmlnaW5hbCBlbGVtZW50IHJhdGhlciB0aGFuIGEgY29weS4gRm9yIGV4YW1wbGUsIGFuIGVsZW1lbnRcclxuICAgICAgICAgKiBtYXkgaGF2ZSBhbiBvbkNsaWNrIGV2ZW50IHRoYXQgd291bGQgbm90IGdldCBjb3BwaWVkIHRvIHRoZSBjbG9uZS5cclxuICAgICAgICAgKiBcclxuICAgICAgICAgKiBJZiB3ZSBqdXN0IG1vdmVkIHRoZXNlIGVsZW1lbnRzIGludG8gdGhlIHJlZ2lvbiBpdCB3b3VsZCBnZXQgXHJcbiAgICAgICAgICogbW92ZWQgYmFjayBvdXQgaW50byB0aGUgb3JpZ2luYWwgbG9jYXRpb24gaW4gdGhlIERPTSBieSBvYnNpZGlhblxyXG4gICAgICAgICAqIHdoZW4gc2Nyb2xsaW5nIG9yIHdoZW4gdGhlIGZpbGUgaXMgdXBkYXRlZC4gT24gdGhlIG5leHQgcmVmcmVzaCBpdFxyXG4gICAgICAgICAqIHdvdWxkIGJlIG1vdmVkIGJhY2sgYnV0IHRoYXQgY2FuIGxlYWQgdG8gYSByZWdpb24ganVtcGluZ1xyXG4gICAgICAgICAqIGFyb3VuZCBhcyB0aGUgaXRlbSBpcyBtb3ZlZCBpbiBhbmQgb3V0LiBcclxuICAgICAgICAgKiBcclxuICAgICAgICAgKiBIZXJlIHdlIHNldCB1cCB0aGUgZGl2IHRvIGNvbnRhaW4gdGhlIGVsZW1lbnQgYW5kIGNyZWF0ZVxyXG4gICAgICAgICAqIGEgdmlzdWFsIG9ubHkgY2xvbmUgb2YgaXQuIFRoZSBjbG9uZSB3aWxsIG9ubHkgYmUgdmlzaWJsZVxyXG4gICAgICAgICAqIHdoZW4gdGhlIG9yaWdpbmFsIGlzIG5vdCBpbiB0aGUgbXVsdGktY29sdW1uIHJlZ2lvbiBzbyBpdFxyXG4gICAgICAgICAqIHNhdmVzIHVzIGZyb20gdGhlIHZpc3VhbCBub2lzZSBvZiB0aGUgcmVnaW9uIGp1bXBpbmcgYXJvdW5kLlxyXG4gICAgICAgICAqL1xyXG5cclxuICAgICAgICAvLyBSZW1vdmUgdGhlIG9sZCBlbGVtZW50cyBiZWZvcmUgd2Ugc2V0IHVwIHRoZSBkdWFsIHJlbmRlcmVkIGVsZW1lbnRzLlxyXG4gICAgICAgIGxldCBjb250YWluZXJFbGVtZW50OiBIVE1MRGl2RWxlbWVudCA9IGRvbUVsZW1lbnQuZWxlbWVudENvbnRhaW5lclxyXG4gICAgICAgIGxldCByZW5kZXJFbGVtZW50OiBIVE1MRGl2RWxlbWVudCA9IGRvbUVsZW1lbnQuZWxlbWVudCBhcyBIVE1MRGl2RWxlbWVudFxyXG4gICAgICAgIGZvcihsZXQgaSA9IGNvbnRhaW5lckVsZW1lbnQuY2hpbGRyZW4ubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcclxuICAgICAgICAgICAgY29udGFpbmVyRWxlbWVudC5jaGlsZHJlbltpXS5kZXRhY2goKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnRhaW5lckVsZW1lbnQuYXBwZW5kQ2hpbGQocmVuZGVyRWxlbWVudCkgICAgICAgICAgICAgICAgICAgIFxyXG4gICAgICAgIHJlbmRlckVsZW1lbnQuYWRkQ2xhc3MoTXVsdGlDb2x1bW5MYXlvdXRDU1MuT3JpZ2luYWxFbGVtZW50VHlwZSlcclxuXHJcbiAgICAgICAgbGV0IGNsb25lZE5vZGUgPSByZW5kZXJFbGVtZW50LmNsb25lTm9kZSh0cnVlKSBhcyBIVE1MRGl2RWxlbWVudDtcclxuICAgICAgICBjbG9uZWROb2RlLmFkZENsYXNzKE11bHRpQ29sdW1uTGF5b3V0Q1NTLkNsb25lZEVsZW1lbnRUeXBlKVxyXG4gICAgICAgIGNsb25lZE5vZGUucmVtb3ZlQ2xhc3NlcyhbTXVsdGlDb2x1bW5TdHlsZUNTUy5SZWdpb25Db250ZW50LCBNdWx0aUNvbHVtbkxheW91dENTUy5PcmlnaW5hbEVsZW1lbnRUeXBlXSlcclxuICAgICAgICBjb250YWluZXJFbGVtZW50LmFwcGVuZENoaWxkKGNsb25lZE5vZGUpO1xyXG4gICAgfVxyXG5cclxuICAgIHVwZGF0ZVJlbmRlcmVkTWFya2Rvd24ocmVnaW9uRWxlbWVudHM6IERPTU9iamVjdFtdKSB7XHJcblxyXG4gICAgICAgIC8qKlxyXG4gICAgICAgICAqIEdvIHRocm91Z2ggZXZlcnkgbm9kZSBvZiB0aGUgcmVnaW9uIGxvb2tpbmcgZm9yIHRoZSBcInNwZWNpYWxSZW5kZXJcIiB0eXBlXHJcbiAgICAgICAgICogd2hpY2ggYXJlIHRoZSBlbGVtZW50cyB0aGF0IG1heSBuZWVkIHRvIGJlIHJlbmRlcmVkIHVzaW5nIHRoZSBvcmlnaW5hbFxyXG4gICAgICAgICAqIGVsZW1lbnQgcmF0aGVyIHRoYW4gYSBjb3B5LlxyXG4gICAgICAgICAqL1xyXG4gICAgICAgIGZvcihsZXQgaSA9IDA7IGkgPCByZWdpb25FbGVtZW50cy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICBcclxuXHJcbiAgICAgICAgICAgIC8qKlxyXG4gICAgICAgICAgICAgKiBIZXJlIHdlIGNoZWNrIGV2ZXJ5IGl0ZW0gYWdhaW4gdG8gc2VlIGlmIHRoZXkgbmVlZCB0byBiZSB1cGRhdGVkLlxyXG4gICAgICAgICAgICAgKiBUaGlzIGNvdWxkIGJlIG1hZGUgc2xpZ2h0bHkgbW9yZSBlZmZpY2llbnQgaWYgd2UgY2FuIHRydWx5IGRldGVybWluZVxyXG4gICAgICAgICAgICAgKiB3ZXRoZXIgYW4gaXRlbSBpcyBhIG5vcm1hbCByZW5kZXIgaXRlbSwgaG93ZXZlciBpdCBzZWVtcyBsaWtlIGl0XHJcbiAgICAgICAgICAgICAqIG1heSB0YWtlIGEgYml0IG9mIGV4dHJhIHRpbWUgaW4gb3JkZXIgZm9yIHRoZSBjbGFzc2VzIHdlIGNoZWNrIGZvclxyXG4gICAgICAgICAgICAgKiB0byBiZSBhZGRlZCB0byB0aGUgZWxlbWVudHMuXHJcbiAgICAgICAgICAgICAqL1xyXG4gICAgICAgICAgICBsZXQgZWxlbWVudFR5cGUgPSByZWdpb25FbGVtZW50c1tpXS5lbGVtZW50VHlwZTtcclxuXHJcbiAgICAgICAgICAgIC8vIElmIHRoZSBlbGVtZW50IGlzIG5vdCBjdXJyZW50bHkgYSBzcGVjaWFsIHJlbmRlciBlbGVtZW50IHdlIGNoZWNrIGFnYWluXHJcbiAgICAgICAgICAgIC8vIGFzIHRoZSBvcmlnaW5hbCBlbGVtZW50IG1heSBoYXZlIGJlZW4gdXBkYXRlZC5cclxuICAgICAgICAgICAgaWYoZWxlbWVudFR5cGUgIT09IEVsZW1lbnRSZW5kZXJUeXBlLnNwZWNpYWxSZW5kZXIpIHtcclxuICAgICAgICAgICAgICAgIFxyXG4gICAgICAgICAgICAgICAgLy8gSWYgdGhlIG5ldyByZXN1bHQgcmV0dXJucyBhcyBhIHNwZWNpYWwgcmVuZGVyZXIgd2UgdXBkYXRlIHNvXHJcbiAgICAgICAgICAgICAgICAvLyB0aGlzIHdvbnQgcnVuIGFnYWluIGZvciB0aGlzIGl0ZW0uXHJcbiAgICAgICAgICAgICAgICBlbGVtZW50VHlwZSA9IGdldEVsZW1lbnRSZW5kZXJUeXBlKHJlZ2lvbkVsZW1lbnRzW2ldLmVsZW1lbnQpO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBpZihlbGVtZW50VHlwZSA9PT0gRWxlbWVudFJlbmRlclR5cGUuc3BlY2lhbFJlbmRlcikge1xyXG4gICAgICAgICAgICAgICAgICAgIFxyXG4gICAgICAgICAgICAgICAgcmVnaW9uRWxlbWVudHNbaV0uZWxlbWVudFR5cGUgPSBlbGVtZW50VHlwZTtcclxuXHJcbiAgICAgICAgICAgICAgICB0aGlzLnNldFVwRHVhbFJlbmRlcihyZWdpb25FbGVtZW50c1tpXSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICB9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBTZXRzIHVwIHRoZSBDU1MgY2xhc3NlcyBhbmQgdGhlIG51bWJlciBvZiBjb2x1bW5zIGJhc2VkIG9uIHRoZSBwYXNzZWQgc2V0dGluZ3MuXHJcbiAqIEBwYXJhbSBzZXR0aW5ncyBUaGUgdXNlciBkZWZpbmVkIHNldHRpbmdzIHRoYXQgZGV0ZXJtaW5lIHdoYXQgQ1NTIGlzIHNldCBoZXJlLlxyXG4gKiBAcGFyYW0gbXVsdGlDb2x1bW5QYXJlbnQgVGhlIHBhcmVudCBvYmplY3QgdGhhdCB0aGUgY29sdW1uIGRpdnMgd2lsbCBiZSBjcmVhdGVkIHVuZGVyLlxyXG4gKiBAcmV0dXJucyBUaGUgbGlzdCBvZiBjb2x1bW4gZGl2cyBjcmVhdGVkIHVuZGVyIHRoZSBwYXNzZWQgcGFyZW50IGVsZW1lbnQuXHJcbiAqL1xyXG5mdW5jdGlvbiBnZXRDb2x1bW5Db250ZW50RGl2cyhzZXR0aW5nczogTXVsdGlDb2x1bW5TZXR0aW5ncywgbXVsdGlDb2x1bW5QYXJlbnQ6IEhUTUxEaXZFbGVtZW50KTogSFRNTERpdkVsZW1lbnRbXSB7XHJcblxyXG4gICAgbGV0IGNvbHVtbkNvbnRlbnREaXZzOiBIVE1MRGl2RWxlbWVudFtdID0gW11cclxuICAgIGlmKHNldHRpbmdzLm51bWJlck9mQ29sdW1ucyA9PT0gMikge1xyXG5cclxuICAgICAgICBzd2l0Y2goc2V0dGluZ3MuY29sdW1uTGF5b3V0KSB7XHJcbiAgICAgICAgICAgIGNhc2UoQ29sdW1uTGF5b3V0LnN0YW5kYXJkKTpcclxuICAgICAgICAgICAgY2FzZShDb2x1bW5MYXlvdXQubWlkZGxlKTpcclxuICAgICAgICAgICAgY2FzZShDb2x1bW5MYXlvdXQuY2VudGVyKTpcclxuICAgICAgICAgICAgY2FzZShDb2x1bW5MYXlvdXQudGhpcmQpOlxyXG4gICAgICAgICAgICAgICAgY29sdW1uQ29udGVudERpdnMucHVzaChtdWx0aUNvbHVtblBhcmVudC5jcmVhdGVEaXYoe1xyXG4gICAgICAgICAgICAgICAgICAgIGNsczogYGNvbHVtbkNvbnRlbnQgdHdvRXF1YWxDb2x1bW5zX0xlZnRgXHJcbiAgICAgICAgICAgICAgICB9KSk7XHJcbiAgICAgICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2cy5wdXNoKG11bHRpQ29sdW1uUGFyZW50LmNyZWF0ZURpdih7XHJcbiAgICAgICAgICAgICAgICAgICAgY2xzOiBgY29sdW1uQ29udGVudCB0d29FcXVhbENvbHVtbnNfUmlnaHRgXHJcbiAgICAgICAgICAgICAgICB9KSk7XHJcbiAgICAgICAgICAgICAgICBicmVhaztcclxuXHJcbiAgICAgICAgICAgIGNhc2UoQ29sdW1uTGF5b3V0LmxlZnQpOlxyXG4gICAgICAgICAgICBjYXNlKENvbHVtbkxheW91dC5maXJzdCk6XHJcbiAgICAgICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2cy5wdXNoKG11bHRpQ29sdW1uUGFyZW50LmNyZWF0ZURpdih7XHJcbiAgICAgICAgICAgICAgICAgICAgY2xzOiBgY29sdW1uQ29udGVudCB0d29Db2x1bW5zSGVhdnlMZWZ0X0xlZnRgXHJcbiAgICAgICAgICAgICAgICB9KSk7XHJcbiAgICAgICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2cy5wdXNoKG11bHRpQ29sdW1uUGFyZW50LmNyZWF0ZURpdih7XHJcbiAgICAgICAgICAgICAgICAgICAgY2xzOiBgY29sdW1uQ29udGVudCB0d29Db2x1bW5zSGVhdnlMZWZ0X1JpZ2h0YFxyXG4gICAgICAgICAgICAgICAgfSkpO1xyXG4gICAgICAgICAgICAgICAgYnJlYWs7XHJcblxyXG4gICAgICAgICAgICBjYXNlKENvbHVtbkxheW91dC5yaWdodCk6XHJcbiAgICAgICAgICAgIGNhc2UoQ29sdW1uTGF5b3V0LnNlY29uZCk6XHJcbiAgICAgICAgICAgIGNhc2UoQ29sdW1uTGF5b3V0Lmxhc3QpOlxyXG4gICAgICAgICAgICAgICAgY29sdW1uQ29udGVudERpdnMucHVzaChtdWx0aUNvbHVtblBhcmVudC5jcmVhdGVEaXYoe1xyXG4gICAgICAgICAgICAgICAgICAgIGNsczogYGNvbHVtbkNvbnRlbnQgdHdvQ29sdW1uc0hlYXZ5UmlnaHRfTGVmdGBcclxuICAgICAgICAgICAgICAgIH0pKTtcclxuICAgICAgICAgICAgICAgIGNvbHVtbkNvbnRlbnREaXZzLnB1c2gobXVsdGlDb2x1bW5QYXJlbnQuY3JlYXRlRGl2KHtcclxuICAgICAgICAgICAgICAgICAgICBjbHM6IGBjb2x1bW5Db250ZW50IHR3b0NvbHVtbnNIZWF2eVJpZ2h0X1JpZ2h0YFxyXG4gICAgICAgICAgICAgICAgfSkpO1xyXG4gICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG4gICAgZWxzZSBpZihzZXR0aW5ncy5udW1iZXJPZkNvbHVtbnMgPT09IDMpIHtcclxuXHJcbiAgICAgICAgc3dpdGNoKHNldHRpbmdzLmNvbHVtbkxheW91dCkge1xyXG4gICAgICAgICAgICBjYXNlKENvbHVtbkxheW91dC5zdGFuZGFyZCk6XHJcbiAgICAgICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2cy5wdXNoKG11bHRpQ29sdW1uUGFyZW50LmNyZWF0ZURpdih7XHJcbiAgICAgICAgICAgICAgICAgICAgY2xzOiBgY29sdW1uQ29udGVudCB0aHJlZUVxdWFsQ29sdW1uc19MZWZ0YFxyXG4gICAgICAgICAgICAgICAgfSkpO1xyXG4gICAgICAgICAgICAgICAgY29sdW1uQ29udGVudERpdnMucHVzaChtdWx0aUNvbHVtblBhcmVudC5jcmVhdGVEaXYoe1xyXG4gICAgICAgICAgICAgICAgICAgIGNsczogYGNvbHVtbkNvbnRlbnQgdGhyZWVFcXVhbENvbHVtbnNfTWlkZGxlYFxyXG4gICAgICAgICAgICAgICAgfSkpO1xyXG4gICAgICAgICAgICAgICAgY29sdW1uQ29udGVudERpdnMucHVzaChtdWx0aUNvbHVtblBhcmVudC5jcmVhdGVEaXYoe1xyXG4gICAgICAgICAgICAgICAgICAgIGNsczogYGNvbHVtbkNvbnRlbnQgdGhyZWVFcXVhbENvbHVtbnNfUmlnaHRgXHJcbiAgICAgICAgICAgICAgICB9KSk7XHJcbiAgICAgICAgICAgICAgICBicmVhaztcclxuXHJcbiAgICAgICAgICAgIGNhc2UoQ29sdW1uTGF5b3V0LmxlZnQpOlxyXG4gICAgICAgICAgICBjYXNlKENvbHVtbkxheW91dC5maXJzdCk6XHJcbiAgICAgICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2cy5wdXNoKG11bHRpQ29sdW1uUGFyZW50LmNyZWF0ZURpdih7XHJcbiAgICAgICAgICAgICAgICAgICAgY2xzOiBgY29sdW1uQ29udGVudCB0aHJlQ29sdW1uc0hlYXZ5TGVmdF9MZWZ0YFxyXG4gICAgICAgICAgICAgICAgfSkpO1xyXG4gICAgICAgICAgICAgICAgY29sdW1uQ29udGVudERpdnMucHVzaChtdWx0aUNvbHVtblBhcmVudC5jcmVhdGVEaXYoe1xyXG4gICAgICAgICAgICAgICAgICAgIGNsczogYGNvbHVtbkNvbnRlbnQgdGhyZUNvbHVtbnNIZWF2eUxlZnRfTWlkZGxlYFxyXG4gICAgICAgICAgICAgICAgfSkpO1xyXG4gICAgICAgICAgICAgICAgY29sdW1uQ29udGVudERpdnMucHVzaChtdWx0aUNvbHVtblBhcmVudC5jcmVhdGVEaXYoe1xyXG4gICAgICAgICAgICAgICAgICAgIGNsczogYGNvbHVtbkNvbnRlbnQgdGhyZUNvbHVtbnNIZWF2eUxlZnRfUmlnaHRgXHJcbiAgICAgICAgICAgICAgICB9KSk7XHJcbiAgICAgICAgICAgICAgICBicmVhaztcclxuXHJcbiAgICAgICAgICAgIGNhc2UoQ29sdW1uTGF5b3V0Lm1pZGRsZSk6XHJcbiAgICAgICAgICAgIGNhc2UoQ29sdW1uTGF5b3V0LmNlbnRlcik6XHJcbiAgICAgICAgICAgIGNhc2UoQ29sdW1uTGF5b3V0LnNlY29uZCk6XHJcbiAgICAgICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2cy5wdXNoKG11bHRpQ29sdW1uUGFyZW50LmNyZWF0ZURpdih7XHJcbiAgICAgICAgICAgICAgICAgICAgY2xzOiBgY29sdW1uQ29udGVudCB0aHJlQ29sdW1uc0hlYXZ5TWlkZGxlX0xlZnRgXHJcbiAgICAgICAgICAgICAgICB9KSk7XHJcbiAgICAgICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2cy5wdXNoKG11bHRpQ29sdW1uUGFyZW50LmNyZWF0ZURpdih7XHJcbiAgICAgICAgICAgICAgICAgICAgY2xzOiBgY29sdW1uQ29udGVudCB0aHJlQ29sdW1uc0hlYXZ5TWlkZGxlX01pZGRsZWBcclxuICAgICAgICAgICAgICAgIH0pKTtcclxuICAgICAgICAgICAgICAgIGNvbHVtbkNvbnRlbnREaXZzLnB1c2gobXVsdGlDb2x1bW5QYXJlbnQuY3JlYXRlRGl2KHtcclxuICAgICAgICAgICAgICAgICAgICBjbHM6IGBjb2x1bW5Db250ZW50IHRocmVDb2x1bW5zSGVhdnlNaWRkbGVfUmlnaHRgXHJcbiAgICAgICAgICAgICAgICB9KSk7XHJcbiAgICAgICAgICAgICAgICBicmVhaztcclxuXHJcbiAgICAgICAgICAgIGNhc2UoQ29sdW1uTGF5b3V0LnJpZ2h0KTpcclxuICAgICAgICAgICAgY2FzZShDb2x1bW5MYXlvdXQudGhpcmQpOlxyXG4gICAgICAgICAgICBjYXNlKENvbHVtbkxheW91dC5sYXN0KTpcclxuICAgICAgICAgICAgICAgIGNvbHVtbkNvbnRlbnREaXZzLnB1c2gobXVsdGlDb2x1bW5QYXJlbnQuY3JlYXRlRGl2KHtcclxuICAgICAgICAgICAgICAgICAgICBjbHM6IGBjb2x1bW5Db250ZW50IHRocmVDb2x1bW5zSGVhdnlSaWdodF9MZWZ0YFxyXG4gICAgICAgICAgICAgICAgfSkpO1xyXG4gICAgICAgICAgICAgICAgY29sdW1uQ29udGVudERpdnMucHVzaChtdWx0aUNvbHVtblBhcmVudC5jcmVhdGVEaXYoe1xyXG4gICAgICAgICAgICAgICAgICAgIGNsczogYGNvbHVtbkNvbnRlbnQgdGhyZUNvbHVtbnNIZWF2eVJpZ2h0X01pZGRsZWBcclxuICAgICAgICAgICAgICAgIH0pKTtcclxuICAgICAgICAgICAgICAgIGNvbHVtbkNvbnRlbnREaXZzLnB1c2gobXVsdGlDb2x1bW5QYXJlbnQuY3JlYXRlRGl2KHtcclxuICAgICAgICAgICAgICAgICAgICBjbHM6IGBjb2x1bW5Db250ZW50IHRocmVDb2x1bW5zSGVhdnlSaWdodF9SaWdodGBcclxuICAgICAgICAgICAgICAgIH0pKTtcclxuICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gY29sdW1uQ29udGVudERpdnM7XHJcbn1cclxuXHJcblxyXG5leHBvcnQgdHlwZSBuZWFyYnlTaWJsaW5ncyA9IHsgXHJcbiAgICBzaWJsaW5nc0Fib3ZlOiBIVE1MRGl2RWxlbWVudCxcclxuICAgIGN1cnJlbnRPYmplY3Q6IERPTU9iamVjdCwgXHJcbn1cclxuZnVuY3Rpb24gcmVuZGVyTWFya2Rvd25Gcm9tTGluZXMobWRMaW5lczogc3RyaW5nW10sIHNvdXJjZVBhdGg6IHN0cmluZyk6IEhUTUxEaXZFbGVtZW50IHtcclxuXHJcbiAgICAvKipcclxuICAgICAqIFdlIHJlLXJlbmRlciBhbGwgb2YgdGhlIGl0ZW1zIGFib3ZlIG91ciBlbGVtZW50LCB1bnRpbCB0aGUgc3RhcnQgdGFnLCBcclxuICAgICAqIHNvIHdlIGNhbiBkZXRlcm1pbmUgd2hlcmUgdG8gcGxhY2UgdGhlIG5ldyBpdGVtIGluIHRoZSBtYW5hZ2VyLlxyXG4gICAgICogXHJcbiAgICAgKiBUT0RPOiBDYW4gcmVkdWNlIHRoZSBhbW91bnQgbmVlZGluZyB0byBiZSByZW5kZXJlZCBieSBvbmx5IHJlbmRlcmluZyB0b1xyXG4gICAgICogdGhlIHN0YXJ0IHRhZyBvciBhIGNvbHVtbi1icmVhayB3aGljaGV2ZXIgaXMgY2xvc2VyLlxyXG4gICAgICovXHJcbiAgICBsZXQgc2libGluZ3MgPSBjcmVhdGVEaXYoKTtcclxuICAgIGxldCBtYXJrZG93blJlbmRlckNoaWxkID0gbmV3IE1hcmtkb3duUmVuZGVyQ2hpbGQoXHJcbiAgICAgICAgc2libGluZ3NcclxuICAgICk7XHJcbiAgICBNYXJrZG93blJlbmRlcmVyLnJlbmRlck1hcmtkb3duKFxyXG4gICAgICAgIG1kTGluZXMucmVkdWNlKChwcmV2LCBjdXJyZW50KSA9PiB7XHJcbiAgICAgICAgICAgIHJldHVybiBwcmV2ICsgXCJcXG5cIiAgKyBjdXJyZW50O1xyXG4gICAgICAgIH0sIFwiXCIpLFxyXG4gICAgICAgIHNpYmxpbmdzLFxyXG4gICAgICAgIHNvdXJjZVBhdGgsXHJcbiAgICAgICAgbWFya2Rvd25SZW5kZXJDaGlsZFxyXG4gICAgKTtcclxuXHJcbiAgICByZXR1cm4gc2libGluZ3M7XHJcbn0iXSwibmFtZXMiOlsiUGx1Z2luIiwiTm90aWNlIiwibXVsdGlDb2x1bW5QYXJzZXIuaXNTdGFydFRhZ1dpdGhJRCIsIm11bHRpQ29sdW1uUGFyc2VyLmNvbnRhaW5zU3RhcnRUYWciLCJtdWx0aUNvbHVtblBhcnNlci5nZXRTdGFydEJsb2NrQWJvdmVMaW5lIiwibXVsdGlDb2x1bW5QYXJzZXIuY291bnRTdGFydFRhZ3MiLCJNYXJrZG93blJlbmRlckNoaWxkIiwibXVsdGlDb2x1bW5QYXJzZXIuZ2V0RW5kQmxvY2tCZWxvdyIsIm11bHRpQ29sdW1uUGFyc2VyLmNvbnRhaW5zRW5kVGFnIiwibXVsdGlDb2x1bW5QYXJzZXIuY29udGFpbnNDb2xFbmRUYWciLCJtdWx0aUNvbHVtblBhcnNlci5jb250YWluc0NvbFNldHRpbmdzVGFnIiwiTWFya2Rvd25SZW5kZXJlciJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7O0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQXVEQTtBQUNPLFNBQVMsU0FBUyxDQUFDLE9BQU8sRUFBRSxVQUFVLEVBQUUsQ0FBQyxFQUFFLFNBQVMsRUFBRTtBQUM3RCxJQUFJLFNBQVMsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLE9BQU8sS0FBSyxZQUFZLENBQUMsR0FBRyxLQUFLLEdBQUcsSUFBSSxDQUFDLENBQUMsVUFBVSxPQUFPLEVBQUUsRUFBRSxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRTtBQUNoSCxJQUFJLE9BQU8sS0FBSyxDQUFDLEtBQUssQ0FBQyxHQUFHLE9BQU8sQ0FBQyxFQUFFLFVBQVUsT0FBTyxFQUFFLE1BQU0sRUFBRTtBQUMvRCxRQUFRLFNBQVMsU0FBUyxDQUFDLEtBQUssRUFBRSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxPQUFPLENBQUMsRUFBRSxFQUFFLE1BQU0sQ0FBQyxD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
|