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.
1044 lines
155 KiB
1044 lines
155 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 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;
|
|
}
|
|
|
|
/*
|
|
* 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(nodeKey, element, randomID = getUID(), tag = DOMObjectTag.none) {
|
|
this.nodeKey = nodeKey;
|
|
this.element = element;
|
|
this.UID = randomID;
|
|
this.tag = tag;
|
|
}
|
|
}
|
|
class DOMRegionSettingsObject extends DOMObject {
|
|
constructor(baseDOMObject, regionSettings) {
|
|
super(baseDOMObject.nodeKey, baseDOMObject.element, baseDOMObject.UID, DOMObjectTag.regionSettings);
|
|
this.regionSettings = regionSettings;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* 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;
|
|
}
|
|
}
|
|
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, errorElement, regionElement) {
|
|
//TODO: Use the error element whenever there is an error.
|
|
let regonalManager = createRegionalDomManager(this, regionKey, regionElement);
|
|
regionMap.set(regionKey, regonalManager);
|
|
return regonalManager;
|
|
}
|
|
function getRegionalManager(regionKey) {
|
|
let regonalManager = null;
|
|
if (regionMap.has(regionKey) === true) {
|
|
regonalManager = regionMap.get(regionKey);
|
|
}
|
|
return regonalManager;
|
|
}
|
|
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,
|
|
removeRegion: removeRegion,
|
|
setHasStartTag: setHasStartTag,
|
|
getHasStartTag: getHasStartTag,
|
|
getNumberOfRegions: getNumberOfRegions,
|
|
checkKeyExists: checkKeyExists
|
|
};
|
|
}
|
|
function createRegionalDomManager(fileManager, regionKey, startRegionElement) {
|
|
/**
|
|
* 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 = startRegionElement;
|
|
let regionSettings = [];
|
|
function addObject(siblingsAbove, obj) {
|
|
let addAtIndex = siblingsAbove.children.length;
|
|
// console.log("Attempting to add:", obj, `at index: ${addAtIndex}`);
|
|
domList.splice(addAtIndex, 0, 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 (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++) {
|
|
domList[i].element.removeClass("multiColumnDataHidden");
|
|
}
|
|
for (let i = 0; i < regionSettings.length; i++) {
|
|
regionSettings[i].element.removeClass("multiColumnDataHidden");
|
|
}
|
|
}
|
|
return { addObject: addObject,
|
|
removeObject: removeObject,
|
|
updateElementTag: updateElementTag,
|
|
setElementToSettingsBlock: setElementToSettingsBlock,
|
|
getRegionRenderData: getRegionRenderData,
|
|
displayOriginalElements: displayOriginalElements
|
|
};
|
|
}
|
|
|
|
/*
|
|
* 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.");
|
|
}
|
|
}
|
|
});
|
|
});
|
|
}
|
|
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 linesOfElement = info.text.split("\n").splice(info.lineStart, (info.lineEnd + 1 - info.lineStart));
|
|
let elementTextSpaced = linesOfElement.reduce((prev, curr) => {
|
|
return prev + "\n" + curr;
|
|
});
|
|
let elementText = linesOfElement.reduce((prev, curr) => {
|
|
// TODO: This can probably be removed as it is only used to identify DOMObjects.
|
|
return prev + curr;
|
|
});
|
|
/**
|
|
* If the current line is a start tag we want to set up the
|
|
* region manager. The regional manager takes care
|
|
* of all items between it's start and end tags while the
|
|
* file manager we got above above takes care of all regional
|
|
* managers in each file.
|
|
*/
|
|
if (containsStartTag(el.textContent)) {
|
|
/**
|
|
* Set up the current element to act as the parent for the
|
|
* multi-column region.
|
|
*/
|
|
el.id = `TwoColumnContainer-${getUID()}`;
|
|
el.children[0].detach();
|
|
el.classList.add("multiColumnContainer");
|
|
let renderErrorRegion = el.createDiv({
|
|
cls: `multiColumnErrorMessage`,
|
|
});
|
|
let renderColumnRegion = el.createDiv({
|
|
cls: `RenderColRegion`
|
|
});
|
|
let startBlockData = getStartBlockAboveLine(linesOfElement);
|
|
let regionKey = startBlockData.startBlockKey;
|
|
if (fileDOMManager.checkKeyExists(regionKey) === true) {
|
|
let { numberOfTags, keys } = countStartTags(info.text);
|
|
let index = 0;
|
|
for (; index < numberOfTags; index++) {
|
|
// Because we checked if key exists one of these has to match.
|
|
if (keys[index] === regionKey) {
|
|
break;
|
|
}
|
|
}
|
|
if (keys[index] === "") {
|
|
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;
|
|
}
|
|
let elementMarkdownRenderer = new obsidian.MarkdownRenderChild(el);
|
|
fileDOMManager.createRegionalManager(regionKey, 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;
|
|
}
|
|
/**
|
|
* Get a list of all of the lines above our current element.
|
|
* We will use this to determine if the element is within a block so
|
|
* we can otherwise ignore the element and keep compute time down.
|
|
*/
|
|
let linesAboveArray = info.text.split("\n").slice(0, info.lineStart);
|
|
linesAboveArray.reduce((prev, curr) => {
|
|
return prev + "\n" + curr;
|
|
}, "");
|
|
/**
|
|
* A line above us contains a start tag now see if we're within that
|
|
* block.
|
|
*/
|
|
let startBockAbove = getStartBlockAboveLine(linesAboveArray);
|
|
if (startBockAbove == null) {
|
|
return;
|
|
}
|
|
/**
|
|
* Here we now know we're within a regional block.
|
|
*/
|
|
// Now we only want to work with the lines within the current region.
|
|
linesAboveArray = startBockAbove.linesAboveArray;
|
|
let regionalManager = fileDOMManager.getRegionalManager(startBockAbove.startBlockKey);
|
|
/**
|
|
* If we can not get the start block and this region's dom manager
|
|
* we can not continue something has gone wrong.
|
|
*/
|
|
if (regionalManager === null) {
|
|
return;
|
|
}
|
|
/**
|
|
* 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 this element to determine where to place our current element.
|
|
*/
|
|
let siblingsAbove = findSiblingsAboveEl(linesAboveArray, sourcePath);
|
|
/**
|
|
* Set up our dom object to be added to the manager.
|
|
*/
|
|
let currentObject = new DOMObject(elementText, el);
|
|
/**
|
|
* 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, 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) {
|
|
regionalManager.updateElementTag(currentObject.UID, DOMObjectTag.endRegion);
|
|
}
|
|
else if (containsColEndTag(elementTextSpaced) === true) {
|
|
regionalManager.updateElementTag(currentObject.UID, DOMObjectTag.columnBreak);
|
|
}
|
|
else if (containsColSettingsTag(elementTextSpaced) === true) {
|
|
regionalManager.setElementToSettingsBlock(currentObject.UID, elementTextSpaced);
|
|
}
|
|
/**
|
|
* Use our regional manager to get everything needed to render the region.
|
|
*/
|
|
let parentElementData = regionalManager.getRegionRenderData();
|
|
/**
|
|
* We want to hide all of the original elements that are now going to be
|
|
* rendered within our mutli-column region
|
|
*/
|
|
el.addClass("multiColumnDataHidden");
|
|
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: `multiColumnParent rowC`,
|
|
});
|
|
if (settings.drawShadow === true) {
|
|
multiColumnParent.addClass("multiColumnParentShadow");
|
|
}
|
|
/**
|
|
* 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("columnBorder");
|
|
}
|
|
if (settings.drawShadow === true) {
|
|
columnContentDivs[i].addClass("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++) {
|
|
// We want to skip column break tags but only if we have columns
|
|
// left to enter data for.
|
|
if (regionElements[i].tag === DOMObjectTag.columnBreak &&
|
|
(columnIndex + 1) < settings.numberOfColumns) {
|
|
columnIndex++;
|
|
}
|
|
else if (regionElements[i].tag !== DOMObjectTag.startRegion &&
|
|
regionElements[i].tag !== DOMObjectTag.endRegion &&
|
|
regionElements[i].tag !== DOMObjectTag.regionSettings) {
|
|
/**
|
|
* Make a deep copy of the element so we can remove the hidden class before
|
|
* appending to our column div.
|
|
*/
|
|
let clonedElement = regionElements[i].element.cloneNode(true);
|
|
clonedElement.removeClass("multiColumnDataHidden");
|
|
clonedElement.style.display = "block";
|
|
columnContentDivs[columnIndex].appendChild(clonedElement);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/**
|
|
* Sets up the CSS classes and the number of columns based on the passed settings.
|
|
* @param settings The user defined settings that determine what CSS is set here.
|
|
* @param multiColumnParent The parent object that the column divs will be created under.
|
|
* @returns The list of column divs created under the passed parent element.
|
|
*/
|
|
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 findSiblingsAboveEl(linesAbove, 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 siblingsAbove = createDiv();
|
|
let markdownRenderChild = new obsidian.MarkdownRenderChild(siblingsAbove);
|
|
obsidian.MarkdownRenderer.renderMarkdown(linesAbove.reduce((prev, current) => {
|
|
return prev + "\n" + current;
|
|
}, ""), siblingsAbove, sourcePath, markdownRenderChild);
|
|
return siblingsAbove;
|
|
}
|
|
|
|
module.exports = MultiColumnMarkdown;
|
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFpbi5qcyIsInNvdXJjZXMiOlsibm9kZV9tb2R1bGVzL3RzbGliL3RzbGliLmVzNi5qcyIsInNyYy9yZWdpb25TZXR0aW5ncy50cyIsInNyYy91dGlsaXRpZXMvdGV4dFBhcnNlci50cyIsInNyYy91dGlsaXRpZXMvdXRpbHMudHMiLCJzcmMvZG9tX21hbmFnZXIvZG9tT2JqZWN0LnRzIiwic3JjL2RvbV9tYW5hZ2VyL2RvbU1hbmFnZXIudHMiLCJzcmMvbWFpbi50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKiEgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcclxuQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uXHJcblxyXG5QZXJtaXNzaW9uIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBhbmQvb3IgZGlzdHJpYnV0ZSB0aGlzIHNvZnR3YXJlIGZvciBhbnlcclxucHVycG9zZSB3aXRoIG9yIHdpdGhvdXQgZmVlIGlzIGhlcmVieSBncmFudGVkLlxyXG5cclxuVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiBBTkQgVEhFIEFVVEhPUiBESVNDTEFJTVMgQUxMIFdBUlJBTlRJRVMgV0lUSFxyXG5SRUdBUkQgVE8gVEhJUyBTT0ZUV0FSRSBJTkNMVURJTkcgQUxMIElNUExJRUQgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFlcclxuQU5EIEZJVE5FU1MuIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1IgQkUgTElBQkxFIEZPUiBBTlkgU1BFQ0lBTCwgRElSRUNULFxyXG5JTkRJUkVDVCwgT1IgQ09OU0VRVUVOVElBTCBEQU1BR0VTIE9SIEFOWSBEQU1BR0VTIFdIQVRTT0VWRVIgUkVTVUxUSU5HIEZST01cclxuTE9TUyBPRiBVU0UsIERBVEEgT1IgUFJPRklUUywgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIE5FR0xJR0VOQ0UgT1JcclxuT1RIRVIgVE9SVElPVVMgQUNUSU9OLCBBUklTSU5HIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFVTRSBPUlxyXG5QRVJGT1JNQU5DRSBPRiBUSElTIFNPRlRXQVJFLlxyXG4qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiAqL1xyXG4vKiBnbG9iYWwgUmVmbGVjdCwgUHJvbWlzZSAqL1xyXG5cclxudmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbihkLCBiKSB7XHJcbiAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XHJcbiAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxyXG4gICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChiLCBwKSkgZFtwXSA9IGJbcF07IH07XHJcbiAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcclxufTtcclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2V4dGVuZHMoZCwgYikge1xyXG4gICAgaWYgKHR5cGVvZiBiICE9PSBcImZ1bmN0aW9uXCIgJiYgYiAhPT0gbnVsbClcclxuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2xhc3MgZXh0ZW5kcyB2YWx1ZSBcIiArIFN0cmluZyhiKSArIFwiIGlzIG5vdCBhIGNvbnN0cnVjdG9yIG9yIG51bGxcIik7XHJcbiAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xyXG4gICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XHJcbiAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XHJcbn1cclxuXHJcbmV4cG9ydCB2YXIgX19hc3NpZ24gPSBmdW5jdGlvbigpIHtcclxuICAgIF9fYXNzaWduID0gT2JqZWN0LmFzc2lnbiB8fCBmdW5jdGlvbiBfX2Fzc2lnbih0KSB7XHJcbiAgICAgICAgZm9yICh2YXIgcywgaSA9IDEsIG4gPSBhcmd1bWVudHMubGVuZ3RoOyBpIDwgbjsgaSsrKSB7XHJcbiAgICAgICAgICAgIHMgPSBhcmd1bWVudHNbaV07XHJcbiAgICAgICAgICAgIGZvciAodmFyIHAgaW4gcykgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzLCBwKSkgdFtwXSA9IHNbcF07XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiB0O1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIF9fYXNzaWduLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3Jlc3QocywgZSkge1xyXG4gICAgdmFyIHQgPSB7fTtcclxuICAgIGZvciAodmFyIHAgaW4gcykgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzLCBwKSAmJiBlLmluZGV4T2YocCkgPCAwKVxyXG4gICAgICAgIHRbcF0gPSBzW3BdO1xyXG4gICAgaWYgKHMgIT0gbnVsbCAmJiB0eXBlb2YgT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyA9PT0gXCJmdW5jdGlvblwiKVxyXG4gICAgICAgIGZvciAodmFyIGkgPSAwLCBwID0gT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhzKTsgaSA8IHAubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgICAgaWYgKGUuaW5kZXhPZihwW2ldKSA8IDAgJiYgT2JqZWN0LnByb3RvdHlwZS5wcm9wZXJ0eUlzRW51bWVyYWJsZS5jYWxsKHMsIHBbaV0pKVxyXG4gICAgICAgICAgICAgICAgdFtwW2ldXSA9IHNbcFtpXV07XHJcbiAgICAgICAgfVxyXG4gICAgcmV0dXJuIHQ7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2RlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XHJcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xyXG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcclxuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XHJcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19wYXJhbShwYXJhbUluZGV4LCBkZWNvcmF0b3IpIHtcclxuICAgIHJldHVybiBmdW5jdGlvbiAodGFyZ2V0LCBrZXkpIHsgZGVjb3JhdG9yKHRhcmdldCwga2V5LCBwYXJhbUluZGV4KTsgfVxyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19tZXRhZGF0YShtZXRhZGF0YUtleSwgbWV0YWRhdGFWYWx1ZSkge1xyXG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0Lm1ldGFkYXRhID09PSBcImZ1bmN0aW9uXCIpIHJldHVybiBSZWZsZWN0Lm1ldGFkYXRhKG1ldGFkYXRhS2V5LCBtZXRhZGF0YVZhbHVlKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fYXdhaXRlcih0aGlzQXJnLCBfYXJndW1lbnRzLCBQLCBnZW5lcmF0b3IpIHtcclxuICAgIGZ1bmN0aW9uIGFkb3B0KHZhbHVlKSB7IHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFAgPyB2YWx1ZSA6IG5ldyBQKGZ1bmN0aW9uIChyZXNvbHZlKSB7IHJlc29sdmUodmFsdWUpOyB9KTsgfVxyXG4gICAgcmV0dXJuIG5ldyAoUCB8fCAoUCA9IFByb21pc2UpKShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XHJcbiAgICAgICAgZnVuY3Rpb24gZnVsZmlsbGVkKHZhbHVlKSB7IHRyeSB7IHN0ZXAoZ2VuZXJhdG9yLm5leHQodmFsdWUpKTsgfSBjYXRjaCAoZSkgeyByZWplY3QoZSk7IH0gfVxyXG4gICAgICAgIGZ1bmN0aW9uIHJlamVjdGVkKHZhbHVlKSB7IHRyeSB7IHN0ZXAoZ2VuZXJhdG9yW1widGhyb3dcIl0odmFsdWUpKTsgfSBjYXRjaCAoZSkgeyByZWplY3QoZSk7IH0gfVxyXG4gICAgICAgIGZ1bmN0aW9uIHN0ZXAocmVzdWx0KSB7IHJlc3VsdC5kb25lID8gcmVzb2x2ZShyZXN1bHQudmFsdWUpIDogYWRvcHQocmVzdWx0LnZhbHVlKS50aGVuKGZ1bGZpbGxlZCwgcmVqZWN0ZWQpOyB9XHJcbiAgICAgICAgc3RlcCgoZ2VuZXJhdG9yID0gZ2VuZXJhdG9yLmFwcGx5KHRoaXNBcmcsIF9hcmd1bWVudHMgfHwgW10pKS5uZXh0KCkpO1xyXG4gICAgfSk7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2dlbmVyYXRvcih0aGlzQXJnLCBib2R5KSB7XHJcbiAgICB2YXIgXyA9IHsgbGFiZWw6IDAsIHNlbnQ6IGZ1bmN0aW9uKCkgeyBpZiAodFswXSAmIDEpIHRocm93IHRbMV07IHJldHVybiB0WzFdOyB9LCB0cnlzOiBbXSwgb3BzOiBbXSB9LCBmLCB5LCB0LCBnO1xyXG4gICAgcmV0dXJuIGcgPSB7IG5leHQ6IHZlcmIoMCksIFwidGhyb3dcIjogdmVyYigxKSwgXCJyZXR1cm5cIjogdmVyYigyKSB9LCB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgKGdbU3ltYm9sLml0ZXJhdG9yXSA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gdGhpczsgfSksIGc7XHJcbiAgICBmdW5jdGlvbiB2ZXJiKG4pIHsgcmV0dXJuIGZ1bmN0aW9uICh2KSB7IHJldHVybiBzdGVwKFtuLCB2XSk7IH07IH1cclxuICAgIGZ1bmN0aW9uIHN0ZXAob3ApIHtcclxuICAgICAgICBpZiAoZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkdlbmVyYXRvciBpcyBhbHJlYWR5IGV4ZWN1dGluZy5cIik7XHJcbiAgICAgICAgd2hpbGUgKF8pIHRyeSB7XHJcbiAgICAgICAgICAgIGlmIChmID0gMSwgeSAmJiAodCA9IG9wWzBdICYgMiA/IHlbXCJyZXR1cm5cIl0gOiBvcFswXSA/IHlbXCJ0aHJvd1wiXSB8fCAoKHQgPSB5W1wicmV0dXJuXCJdKSAmJiB0LmNhbGwoeSksIDApIDogeS5uZXh0KSAmJiAhKHQgPSB0LmNhbGwoeSwgb3BbMV0pKS5kb25lKSByZXR1cm4gdDtcclxuICAgICAgICAgICAgaWYgKHkgPSAwLCB0KSBvcCA9IFtvcFswXSAmIDIsIHQudmFsdWVdO1xyXG4gICAgICAgICAgICBzd2l0Y2ggKG9wWzBdKSB7XHJcbiAgICAgICAgICAgICAgICBjYXNlIDA6IGNhc2UgMTogdCA9IG9wOyBicmVhaztcclxuICAgICAgICAgICAgICAgIGNhc2UgNDogXy5sYWJlbCsrOyByZXR1cm4geyB2YWx1ZTogb3BbMV0sIGRvbmU6IGZhbHNlIH07XHJcbiAgICAgICAgICAgICAgICBjYXNlIDU6IF8ubGFiZWwrKzsgeSA9IG9wWzFdOyBvcCA9IFswXTsgY29udGludWU7XHJcbiAgICAgICAgICAgICAgICBjYXNlIDc6IG9wID0gXy5vcHMucG9wKCk7IF8udHJ5cy5wb3AoKTsgY29udGludWU7XHJcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxyXG4gICAgICAgICAgICAgICAgICAgIGlmICghKHQgPSBfLnRyeXMsIHQgPSB0Lmxlbmd0aCA+IDAgJiYgdFt0Lmxlbmd0aCAtIDFdKSAmJiAob3BbMF0gPT09IDYgfHwgb3BbMF0gPT09IDIpKSB7IF8gPSAwOyBjb250aW51ZTsgfVxyXG4gICAgICAgICAgICAgICAgICAgIGlmIChvcFswXSA9PT0gMyAmJiAoIXQgfHwgKG9wWzFdID4gdFswXSAmJiBvcFsxXSA8IHRbM10pKSkgeyBfLmxhYmVsID0gb3BbMV07IGJyZWFrOyB9XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wWzBdID09PSA2ICYmIF8ubGFiZWwgPCB0WzFdKSB7IF8ubGFiZWwgPSB0WzFdOyB0ID0gb3A7IGJyZWFrOyB9XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHQgJiYgXy5sYWJlbCA8IHRbMl0pIHsgXy5sYWJlbCA9IHRbMl07IF8ub3BzLnB1c2gob3ApOyBicmVhazsgfVxyXG4gICAgICAgICAgICAgICAgICAgIGlmICh0WzJdKSBfLm9wcy5wb3AoKTtcclxuICAgICAgICAgICAgICAgICAgICBfLnRyeXMucG9wKCk7IGNvbnRpbnVlO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIG9wID0gYm9keS5jYWxsKHRoaXNBcmcsIF8pO1xyXG4gICAgICAgIH0gY2F0Y2ggKGUpIHsgb3AgPSBbNiwgZV07IHkgPSAwOyB9IGZpbmFsbHkgeyBmID0gdCA9IDA7IH1cclxuICAgICAgICBpZiAob3BbMF0gJiA1KSB0aHJvdyBvcFsxXTsgcmV0dXJuIHsgdmFsdWU6IG9wWzBdID8gb3BbMV0gOiB2b2lkIDAsIGRvbmU6IHRydWUgfTtcclxuICAgIH1cclxufVxyXG5cclxuZXhwb3J0IHZhciBfX2NyZWF0ZUJpbmRpbmcgPSBPYmplY3QuY3JlYXRlID8gKGZ1bmN0aW9uKG8sIG0sIGssIGsyKSB7XHJcbiAgICBpZiAoazIgPT09IHVuZGVmaW5lZCkgazIgPSBrO1xyXG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG8sIGsyLCB7IGVudW1lcmFibGU6IHRydWUsIGdldDogZnVuY3Rpb24oKSB7IHJldHVybiBtW2tdOyB9IH0pO1xyXG59KSA6IChmdW5jdGlvbihvLCBtLCBrLCBrMikge1xyXG4gICAgaWYgKGsyID09PSB1bmRlZmluZWQpIGsyID0gaztcclxuICAgIG9bazJdID0gbVtrXTtcclxufSk7XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19leHBvcnRTdGFyKG0sIG8pIHtcclxuICAgIGZvciAodmFyIHAgaW4gbSkgaWYgKHAgIT09IFwiZGVmYXVsdFwiICYmICFPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwobywgcCkpIF9fY3JlYXRlQmluZGluZyhvLCBtLCBwKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fdmFsdWVzKG8pIHtcclxuICAgIHZhciBzID0gdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIFN5bWJvbC5pdGVyYXRvciwgbSA9IHMgJiYgb1tzXSwgaSA9IDA7XHJcbiAgICBpZiAobSkgcmV0dXJuIG0uY2FsbChvKTtcclxuICAgIGlmIChvICYmIHR5cGVvZiBvLmxlbmd0aCA9PT0gXCJudW1iZXJcIikgcmV0dXJuIHtcclxuICAgICAgICBuZXh0OiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIGlmIChvICYmIGkgPj0gby5sZW5ndGgpIG8gPSB2b2lkIDA7XHJcbiAgICAgICAgICAgIHJldHVybiB7IHZhbHVlOiBvICYmIG9baSsrXSwgZG9uZTogIW8gfTtcclxuICAgICAgICB9XHJcbiAgICB9O1xyXG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihzID8gXCJPYmplY3QgaXMgbm90IGl0ZXJhYmxlLlwiIDogXCJTeW1ib2wuaXRlcmF0b3IgaXMgbm90IGRlZmluZWQuXCIpO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19yZWFkKG8sIG4pIHtcclxuICAgIHZhciBtID0gdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIG9bU3ltYm9sLml0ZXJhdG9yXTtcclxuICAgIGlmICghbSkgcmV0dXJuIG87XHJcbiAgICB2YXIgaSA9IG0uY2FsbChvKSwgciwgYXIgPSBbXSwgZTtcclxuICAgIHRyeSB7XHJcbiAgICAgICAgd2hpbGUgKChuID09PSB2b2lkIDAgfHwgbi0tID4gMCkgJiYgIShyID0gaS5uZXh0KCkpLmRvbmUpIGFyLnB1c2goci52YWx1ZSk7XHJcbiAgICB9XHJcbiAgICBjYXRjaCAoZXJyb3IpIHsgZSA9IHsgZXJyb3I6IGVycm9yIH07IH1cclxuICAgIGZpbmFsbHkge1xyXG4gICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgIGlmIChyICYmICFyLmRvbmUgJiYgKG0gPSBpW1wicmV0dXJuXCJdKSkgbS5jYWxsKGkpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBmaW5hbGx5IHsgaWYgKGUpIHRocm93IGUuZXJyb3I7IH1cclxuICAgIH1cclxuICAgIHJldHVybiBhcjtcclxufVxyXG5cclxuLyoqIEBkZXByZWNhdGVkICovXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3NwcmVhZCgpIHtcclxuICAgIGZvciAodmFyIGFyID0gW10sIGkgPSAwOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKVxyXG4gICAgICAgIGFyID0gYXIuY29uY2F0KF9fcmVhZChhcmd1bWVudHNbaV0pKTtcclxuICAgIHJldHVybiBhcjtcclxufVxyXG5cclxuLyoqIEBkZXByZWNhdGVkICovXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3NwcmVhZEFycmF5cygpIHtcclxuICAgIGZvciAodmFyIHMgPSAwLCBpID0gMCwgaWwgPSBhcmd1bWVudHMubGVuZ3RoOyBpIDwgaWw7IGkrKykgcyArPSBhcmd1bWVudHNbaV0ubGVuZ3RoO1xyXG4gICAgZm9yICh2YXIgciA9IEFycmF5KHMpLCBrID0gMCwgaSA9IDA7IGkgPCBpbDsgaSsrKVxyXG4gICAgICAgIGZvciAodmFyIGEgPSBhcmd1bWVudHNbaV0sIGogPSAwLCBqbCA9IGEubGVuZ3RoOyBqIDwgamw7IGorKywgaysrKVxyXG4gICAgICAgICAgICByW2tdID0gYVtqXTtcclxuICAgIHJldHVybiByO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19zcHJlYWRBcnJheSh0bywgZnJvbSwgcGFjaykge1xyXG4gICAgaWYgKHBhY2sgfHwgYXJndW1lbnRzLmxlbmd0aCA9PT0gMikgZm9yICh2YXIgaSA9IDAsIGwgPSBmcm9tLmxlbmd0aCwgYXI7IGkgPCBsOyBpKyspIHtcclxuICAgICAgICBpZiAoYXIgfHwgIShpIGluIGZyb20pKSB7XHJcbiAgICAgICAgICAgIGlmICghYXIpIGFyID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoZnJvbSwgMCwgaSk7XHJcbiAgICAgICAgICAgIGFyW2ldID0gZnJvbVtpXTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcbiAgICByZXR1cm4gdG8uY29uY2F0KGFyIHx8IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGZyb20pKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fYXdhaXQodikge1xyXG4gICAgcmV0dXJuIHRoaXMgaW5zdGFuY2VvZiBfX2F3YWl0ID8gKHRoaXMudiA9IHYsIHRoaXMpIDogbmV3IF9fYXdhaXQodik7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2FzeW5jR2VuZXJhdG9yKHRoaXNBcmcsIF9hcmd1bWVudHMsIGdlbmVyYXRvcikge1xyXG4gICAgaWYgKCFTeW1ib2wuYXN5bmNJdGVyYXRvcikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlN5bWJvbC5hc3luY0l0ZXJhdG9yIGlzIG5vdCBkZWZpbmVkLlwiKTtcclxuICAgIHZhciBnID0gZ2VuZXJhdG9yLmFwcGx5KHRoaXNBcmcsIF9hcmd1bWVudHMgfHwgW10pLCBpLCBxID0gW107XHJcbiAgICByZXR1cm4gaSA9IHt9LCB2ZXJiKFwibmV4dFwiKSwgdmVyYihcInRocm93XCIpLCB2ZXJiKFwicmV0dXJuXCIpLCBpW1N5bWJvbC5hc3luY0l0ZXJhdG9yXSA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXM7IH0sIGk7XHJcbiAgICBmdW5jdGlvbiB2ZXJiKG4pIHsgaWYgKGdbbl0pIGlbbl0gPSBmdW5jdGlvbiAodikgeyByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKGEsIGIpIHsgcS5wdXNoKFtuLCB2LCBhLCBiXSkgPiAxIHx8IHJlc3VtZShuLCB2KTsgfSk7IH07IH1cclxuICAgIGZ1bmN0aW9uIHJlc3VtZShuLCB2KSB7IHRyeSB7IHN0ZXAoZ1tuXSh2KSk7IH0gY2F0Y2ggKGUpIHsgc2V0dGxlKHFbMF1bM10sIGUpOyB9IH1cclxuICAgIGZ1bmN0aW9uIHN0ZXAocikgeyByLnZhbHVlIGluc3RhbmNlb2YgX19hd2FpdCA/IFByb21pc2UucmVzb2x2ZShyLnZhbHVlLnYpLnRoZW4oZnVsZmlsbCwgcmVqZWN0KSA6IHNldHRsZShxWzBdWzJdLCByKTsgfVxyXG4gICAgZnVuY3Rpb24gZnVsZmlsbCh2YWx1ZSkgeyByZXN1bWUoXCJuZXh0XCIsIHZhbHVlKTsgfVxyXG4gICAgZnVuY3Rpb24gcmVqZWN0KHZhbHVlKSB7IHJlc3VtZShcInRocm93XCIsIHZhbHVlKTsgfVxyXG4gICAgZnVuY3Rpb24gc2V0dGxlKGYsIHYpIHsgaWYgKGYodiksIHEuc2hpZnQoKSwgcS5sZW5ndGgpIHJlc3VtZShxWzBdWzBdLCBxWzBdWzFdKTsgfVxyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19hc3luY0RlbGVnYXRvcihvKSB7XHJcbiAgICB2YXIgaSwgcDtcclxuICAgIHJldHVybiBpID0ge30sIHZlcmIoXCJuZXh0XCIpLCB2ZXJiKFwidGhyb3dcIiwgZnVuY3Rpb24gKGUpIHsgdGhyb3cgZTsgfSksIHZlcmIoXCJyZXR1cm5cIiksIGlbU3ltYm9sLml0ZXJhdG9yXSA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXM7IH0sIGk7XHJcbiAgICBmdW5jdGlvbiB2ZXJiKG4sIGYpIHsgaVtuXSA9IG9bbl0gPyBmdW5jdGlvbiAodikgeyByZXR1cm4gKHAgPSAhcCkgPyB7IHZhbHVlOiBfX2F3YWl0KG9bbl0odikpLCBkb25lOiBuID09PSBcInJldHVyblwiIH0gOiBmID8gZih2KSA6IHY7IH0gOiBmOyB9XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2FzeW5jVmFsdWVzKG8pIHtcclxuICAgIGlmICghU3ltYm9sLmFzeW5jSXRlcmF0b3IpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJTeW1ib2wuYXN5bmNJdGVyYXRvciBpcyBub3QgZGVmaW5lZC5cIik7XHJcbiAgICB2YXIgbSA9IG9bU3ltYm9sLmFzeW5jSXRlcmF0b3JdLCBpO1xyXG4gICAgcmV0dXJuIG0gPyBtLmNhbGwobykgOiAobyA9IHR5cGVvZiBfX3ZhbHVlcyA9PT0gXCJmdW5jdGlvblwiID8gX192YWx1ZXMobykgOiBvW1N5bWJvbC5pdGVyYXRvcl0oKSwgaSA9IHt9LCB2ZXJiKFwibmV4dFwiKSwgdmVyYihcInRocm93XCIpLCB2ZXJiKFwicmV0dXJuXCIpLCBpW1N5bWJvbC5hc3luY0l0ZXJhdG9yXSA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXM7IH0sIGkpO1xyXG4gICAgZnVuY3Rpb24gdmVyYihuKSB7IGlbbl0gPSBvW25dICYmIGZ1bmN0aW9uICh2KSB7IHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7IHYgPSBvW25dKHYpLCBzZXR0bGUocmVzb2x2ZSwgcmVqZWN0LCB2LmRvbmUsIHYudmFsdWUpOyB9KTsgfTsgfVxyXG4gICAgZnVuY3Rpb24gc2V0dGxlKHJlc29sdmUsIHJlamVjdCwgZCwgdikgeyBQcm9taXNlLnJlc29sdmUodikudGhlbihmdW5jdGlvbih2KSB7IHJlc29sdmUoeyB2YWx1ZTogdiwgZG9uZTogZCB9KTsgfSwgcmVqZWN0KTsgfVxyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19tYWtlVGVtcGxhdGVPYmplY3QoY29va2VkLCByYXcpIHtcclxuICAgIGlmIChPYmplY3QuZGVmaW5lUHJvcGVydHkpIHsgT2JqZWN0LmRlZmluZVByb3BlcnR5KGNvb2tlZCwgXCJyYXdcIiwgeyB2YWx1ZTogcmF3IH0pOyB9IGVsc2UgeyBjb29rZWQucmF3ID0gcmF3OyB9XHJcbiAgICByZXR1cm4gY29va2VkO1xyXG59O1xyXG5cclxudmFyIF9fc2V0TW9kdWxlRGVmYXVsdCA9IE9iamVjdC5jcmVhdGUgPyAoZnVuY3Rpb24obywgdikge1xyXG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG8sIFwiZGVmYXVsdFwiLCB7IGVudW1lcmFibGU6IHRydWUsIHZhbHVlOiB2IH0pO1xyXG59KSA6IGZ1bmN0aW9uKG8sIHYpIHtcclxuICAgIG9bXCJkZWZhdWx0XCJdID0gdjtcclxufTtcclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2ltcG9ydFN0YXIobW9kKSB7XHJcbiAgICBpZiAobW9kICYmIG1vZC5fX2VzTW9kdWxlKSByZXR1cm4gbW9kO1xyXG4gICAgdmFyIHJlc3VsdCA9IHt9O1xyXG4gICAgaWYgKG1vZCAhPSBudWxsKSBmb3IgKHZhciBrIGluIG1vZCkgaWYgKGsgIT09IFwiZGVmYXVsdFwiICYmIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChtb2QsIGspKSBfX2NyZWF0ZUJpbmRpbmcocmVzdWx0LCBtb2QsIGspO1xyXG4gICAgX19zZXRNb2R1bGVEZWZhdWx0KHJlc3VsdCwgbW9kKTtcclxuICAgIHJldHVybiByZXN1bHQ7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2ltcG9ydERlZmF1bHQobW9kKSB7XHJcbiAgICByZXR1cm4gKG1vZCAmJiBtb2QuX19lc01vZHVsZSkgPyBtb2QgOiB7IGRlZmF1bHQ6IG1vZCB9O1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19jbGFzc1ByaXZhdGVGaWVsZEdldChyZWNlaXZlciwgc3RhdGUsIGtpbmQsIGYpIHtcclxuICAgIGlmIChraW5kID09PSBcImFcIiAmJiAhZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlByaXZhdGUgYWNjZXNzb3Igd2FzIGRlZmluZWQgd2l0aG91dCBhIGdldHRlclwiKTtcclxuICAgIGlmICh0eXBlb2Ygc3RhdGUgPT09IFwiZnVuY3Rpb25cIiA/IHJlY2VpdmVyICE9PSBzdGF0ZSB8fCAhZiA6ICFzdGF0ZS5oYXMocmVjZWl2ZXIpKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IHJlYWQgcHJpdmF0ZSBtZW1iZXIgZnJvbSBhbiBvYmplY3Qgd2hvc2UgY2xhc3MgZGlkIG5vdCBkZWNsYXJlIGl0XCIpO1xyXG4gICAgcmV0dXJuIGtpbmQgPT09IFwibVwiID8gZiA6IGtpbmQgPT09IFwiYVwiID8gZi5jYWxsKHJlY2VpdmVyKSA6IGYgPyBmLnZhbHVlIDogc3RhdGUuZ2V0KHJlY2VpdmVyKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fY2xhc3NQcml2YXRlRmllbGRTZXQocmVjZWl2ZXIsIHN0YXRlLCB2YWx1ZSwga2luZCwgZikge1xyXG4gICAgaWYgKGtpbmQgPT09IFwibVwiKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiUHJpdmF0ZSBtZXRob2QgaXMgbm90IHdyaXRhYmxlXCIpO1xyXG4gICAgaWYgKGtpbmQgPT09IFwiYVwiICYmICFmKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiUHJpdmF0ZSBhY2Nlc3NvciB3YXMgZGVmaW5lZCB3aXRob3V0IGEgc2V0dGVyXCIpO1xyXG4gICAgaWYgKHR5cGVvZiBzdGF0ZSA9PT0gXCJmdW5jdGlvblwiID8gcmVjZWl2ZXIgIT09IHN0YXRlIHx8ICFmIDogIXN0YXRlLmhhcyhyZWNlaXZlcikpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3Qgd3JpdGUgcHJpdmF0ZSBtZW1iZXIgdG8gYW4gb2JqZWN0IHdob3NlIGNsYXNzIGRpZCBub3QgZGVjbGFyZSBpdFwiKTtcclxuICAgIHJldHVybiAoa2luZCA9PT0gXCJhXCIgPyBmLmNhbGwocmVjZWl2ZXIsIHZhbHVlKSA6IGYgPyBmLnZhbHVlID0gdmFsdWUgOiBzdGF0ZS5zZXQocmVjZWl2ZXIsIHZhbHVlKSksIHZhbHVlO1xyXG59XHJcbiIsIi8qXG4gKiBGaWxlbmFtZTogbXVsdGktY29sdW1uLW1hcmtkb3duL3NyYy9yZWdpb25TZXR0aW5ncy50c1xuICogQ3JlYXRlZCBEYXRlOiBUdWVzZGF5LCBGZWJydWFyeSAxc3QgMjAyMiwgMTI6MjM6NTMgcG1cbiAqIEF1dGhvcjogQ2FtZXJvbiBSb2JpbnNvblxuICogXG4gKiBDb3B5cmlnaHQgKGMpIDIwMjIgQ2FtZXJvbiBSb2JpbnNvblxuICovXG5cbmV4cG9ydCBlbnVtIEJvcmRlck9wdGlvbiB7XG4gICAgZW5hYmxlZCxcbiAgICBvbixcbiAgICB0cnVlLFxuICAgIGRpc2FibGVkLFxuICAgIG9mZixcbiAgICBmYWxzZVxufVxuXG5leHBvcnQgZW51bSBTaGFkb3dPcHRpb24ge1xuICAgIGVuYWJsZWQsXG4gICAgb24sXG4gICAgdHJ1ZSxcbiAgICBkaXNhYmxlZCxcbiAgICBvZmYsXG4gICAgZmFsc2Vcbn1cblxuZXhwb3J0IGVudW0gQ29sdW1uTGF5b3V0IHsgXG4gICAgc3RhbmRhcmQsXG4gICAgbGVmdCxcbiAgICBmaXJzdCxcbiAgICBjZW50ZXIsXG4gICAgbWlkZGxlLFxuICAgIHNlY29uZCxcbiAgICByaWdodCxcbiAgICB0aGlyZCxcbiAgICBsYXN0XG59O1xuXG5leHBvcnQgdHlwZSBNdWx0aUNvbHVtblNldHRpbmdzID0ge1xuICAgIG51bWJlck9mQ29sdW1uczogbnVtYmVyLFxuICAgIGNvbHVtbkxheW91dDogQ29sdW1uTGF5b3V0LFxuICAgIGRyYXdCb3JkZXI6IGJvb2xlYW4sXG4gICAgZHJhd1NoYWRvdzogYm9vbGVhblxufSIsIi8qXG4gKiBGaWxlOiBtdWx0aS1jb2x1bW4tbWFya2Rvd24vc3JjL011bHRpQ29sdW1uUGFyc2VyLnRzXG4gKiBDcmVhdGVkIERhdGU6IFNhdHVyZGF5LCBKYW51YXJ5IDIybmQgMjAyMiwgNjowMjo0NiBwbVxuICogQXV0aG9yOiBDYW1lcm9uIFJvYmluc29uXG4gKiBcbiAqIENvcHlyaWdodCAoYykgMjAyMiBDYW1lcm9uIFJvYmluc29uXG4gKi9cblxuaW1wb3J0IHsgTXVsdGlDb2x1bW5TZXR0aW5ncywgQ29sdW1uTGF5b3V0LCBCb3JkZXJPcHRpb24sIFNoYWRvd09wdGlvbiB9IGZyb20gXCIuLi9yZWdpb25TZXR0aW5nc1wiO1xuXG5jb25zdCBTVEFSVF9SRUdFWF9TVFJTID0gW1wiPT09ICpzdGFydC1tdWx0aS1jb2x1bW5cIixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgXCI9PT0gKm11bHRpLWNvbHVtbi1zdGFydFwiXVxuY29uc3QgU1RBUlRfUkVHRVhfQVJSOiBSZWdFeHBbXSA9IFtdO1xuZm9yKGxldCBpID0gMDsgaSA8IFNUQVJUX1JFR0VYX1NUUlMubGVuZ3RoOyBpKyspIHtcbiAgICBTVEFSVF9SRUdFWF9BUlIucHVzaChuZXcgUmVnRXhwKFNUQVJUX1JFR0VYX1NUUlNbaV0pKTtcbn1cbmZ1bmN0aW9uIGZpbmRTdGFydFRhZyh0ZXh0OiBzdHJpbmcpOiB7IGZvdW5kOiBib29sZWFuLCBzdGFydFBvc2l0aW9uOiBudW1iZXIgfSB7XG5cbiAgICBsZXQgZm91bmQgPSBmYWxzZTtcbiAgICBsZXQgc3RhcnRQb3NpdGlvbiA9IC0xO1xuICAgIGZvcihsZXQgaSA9IDA7IGk8IFNUQVJUX1JFR0VYX0FSUi5sZW5ndGg7IGkrKykge1xuXG4gICAgICAgIGlmKFNUQVJUX1JFR0VYX0FSUltpXS50ZXN0KHRleHQpKSB7XG4gICAgICAgICAgICBmb3VuZCA9IHRydWU7XG4gICAgICAgICAgICBzdGFydFBvc2l0aW9uID0gdGV4dC5zZWFyY2goU1RBUlRfUkVHRVhfU1RSU1tpXSlcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHsgZm91bmQsIHN0YXJ0UG9zaXRpb24gfTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBjb250YWluc1N0YXJ0VGFnKHRleHQ6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBmaW5kU3RhcnRUYWcodGV4dCkuZm91bmRcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzU3RhcnRUYWdXaXRoSUQodGV4dDogc3RyaW5nKToge2lzU3RhcnRUYWc6IGJvb2xlYW4sIGhhc0tleTogYm9vbGVhbn0ge1xuXG4gICAgbGV0IHN0YXJ0VGFnRGF0YSA9IGZpbmRTdGFydFRhZyh0ZXh0KTtcbiAgICBpZihzdGFydFRhZ0RhdGEuZm91bmQgPT09IHRydWUpIHtcblxuICAgICAgICBsZXQga2V5ID0gZ2V0U3RhcnRUYWdLZXkodGV4dClcbiAgICAgICAgaWYoa2V5ID09PSBudWxsIHx8IGtleSA9PT0gXCJcIikge1xuICAgICAgICAgICAgcmV0dXJuIHtpc1N0YXJ0VGFnOiB0cnVlLCBoYXNLZXk6IGZhbHNlfTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4ge2lzU3RhcnRUYWc6IHRydWUsIGhhc0tleTogdHJ1ZX07XG4gICAgfVxuXG4gICAgcmV0dXJuIHtpc1N0YXJ0VGFnOiBmYWxzZSwgaGFzS2V5OiBmYWxzZX07XG59XG5cbmNvbnN0IEVORF9SRUdFWF9TVFJTID0gW1wiPT09ICplbmQtbXVsdGktY29sdW1uXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICBcIj09PSAqbXVsdGktY29sdW1uLWVuZFwiXVxuY29uc3QgRU5EX1JFR0VYX0FSUjogUmVnRXhwW10gPSBbXTtcbmZvcihsZXQgaSA9IDA7IGkgPCBFTkRfUkVHRVhfU1RSUy5sZW5ndGg7IGkrKykge1xuICAgIEVORF9SRUdFWF9BUlIucHVzaChuZXcgUmVnRXhwKEVORF9SRUdFWF9TVFJTW2ldKSk7XG59XG5mdW5jdGlvbiBmaW5kRW5kVGFnKHRleHQ6IHN0cmluZyk6IHsgZm91bmQ6IGJvb2xlYW4sIHN0YXJ0UG9zaXRpb246IG51bWJlciB9IHtcblxuICAgIGxldCBmb3VuZCA9IGZhbHNlO1xuICAgIGxldCBzdGFydFBvc2l0aW9uID0gLTE7XG4gICAgZm9yKGxldCBpID0gMDsgaTwgRU5EX1JFR0VYX0FSUi5sZW5ndGg7IGkrKykge1xuXG4gICAgICAgIGlmKEVORF9SRUdFWF9BUlJbaV0udGVzdCh0ZXh0KSkge1xuICAgICAgICAgICAgZm91bmQgPSB0cnVlO1xuICAgICAgICAgICAgc3RhcnRQb3NpdGlvbiA9IHRleHQuc2VhcmNoKEVORF9SRUdFWF9TVFJTW2ldKVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4geyBmb3VuZCwgc3RhcnRQb3NpdGlvbiB9O1xufVxuZXhwb3J0IGZ1bmN0aW9uIGNvbnRhaW5zRW5kVGFnKHRleHQ6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBmaW5kRW5kVGFnKHRleHQpLmZvdW5kXG59XG5cbmNvbnN0IENPTF9SRUdFWF9TVFJTOiBzdHJpbmdbXSA9IFtcIj09PSAqY29sdW1uLWVuZCAqPT09XCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCI9PT0gKmVuZC1jb2x1bW4gKj09PVwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiPT09ICpjb2x1bW4tYnJlYWsgKj09PVwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiPT09ICpicmVhay1jb2x1bW4gKj09PVwiXTtcbmNvbnN0IENPTF9SRUdFWF9BUlI6IFJlZ0V4cFtdID0gW107XG5mb3IobGV0IGkgPSAwOyBpIDwgQ09MX1JFR0VYX1NUUlMubGVuZ3RoOyBpKyspIHtcbiAgICBDT0xfUkVHRVhfQVJSLnB1c2gobmV3IFJlZ0V4cChDT0xfUkVHRVhfU1RSU1tpXSkpO1xufVxuZXhwb3J0IGZ1bmN0aW9uIGNvbnRhaW5zQ29sRW5kVGFnKHRleHQ6IHN0cmluZyk6IGJvb2xlYW4ge1xuXG4gICAgbGV0IGZvdW5kID0gZmFsc2U7XG4gICAgZm9yKGxldCBpID0gMDsgaTwgQ09MX1JFR0VYX0FSUi5sZW5ndGg7IGkrKykge1xuXG4gICAgICAgIGlmKENPTF9SRUdFWF9BUlJbaV0udGVzdCh0ZXh0KSkge1xuICAgICAgICAgICAgZm91bmQgPSB0cnVlO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gZm91bmQ7XG59XG5cbmNvbnN0IENPTF9TRVRUSU5HU19SRUdFWF9TVFJTID0gW1wiYGBgc2V0dGluZ3NcIixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiYGBgY29sdW1uLXNldHRpbmdzXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImBgYG11bHRpLWNvbHVtbi1zZXR0aW5nc1wiXTtcbmNvbnN0IENPTF9TRVRUSU5HU19SRUdFWF9BUlI6IFJlZ0V4cFtdID0gW107XG5mb3IobGV0IGkgPSAwOyBpIDwgQ09MX1NFVFRJTkdTX1JFR0VYX1NUUlMubGVuZ3RoOyBpKyspIHtcbiAgICBDT0xfU0VUVElOR1NfUkVHRVhfQVJSLnB1c2gobmV3IFJlZ0V4cChDT0xfU0VUVElOR1NfUkVHRVhfU1RSU1tpXSkpO1xufVxuZXhwb3J0IGZ1bmN0aW9uIGNvbnRhaW5zQ29sU2V0dGluZ3NUYWcodGV4dDogc3RyaW5nKTogYm9vbGVhbiB7XG5cbiAgICBsZXQgZm91bmQgPSBmYWxzZTtcbiAgICBmb3IobGV0IGkgPSAwOyBpPCBDT0xfU0VUVElOR1NfUkVHRVhfQVJSLmxlbmd0aDsgaSsrKSB7XG5cbiAgICAgICAgaWYoQ09MX1NFVFRJTkdTX1JFR0VYX0FSUltpXS50ZXN0KHRleHQpKSB7XG4gICAgICAgICAgICBmb3VuZCA9IHRydWU7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBmb3VuZDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlQ29sdW1uU2V0dGluZ3Moc2V0dGluZ3NTdHI6IHN0cmluZyk6IE11bHRpQ29sdW1uU2V0dGluZ3Mge1xuXG4gICAgLy8gU2V0IHRoZSBtaW5pbXVtIG51bWJlciBvZiBjb2x1bW5kcyB0byAyLlxuICAgIGxldCBudW1iZXJPZkNvbHVtbnMgPSAyO1xuICAgIGxldCBjb2x1bW5MYXlvdXQ6IENvbHVtbkxheW91dCA9IENvbHVtbkxheW91dC5zdGFuZGFyZFxuICAgIGxldCBib3JkZXJEcmF3bjogYm9vbGVhbiA9IHRydWU7XG4gICAgbGV0IHNoYWRvd0RyYXduOiBib29sZWFuID0gdHJ1ZTtcblxuICAgIGxldCBzZXR0aW5nc0xpbmVzID0gc2V0dGluZ3NTdHIuc3BsaXQoXCJcXG5cIik7XG5cbiAgICBmb3IobGV0IGkgPSAwOyBpIDwgc2V0dGluZ3NMaW5lcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZihzZXR0aW5nc0xpbmVzW2ldLnRvTG93ZXJDYXNlKCkucmVwbGFjZSgvXFxzL2csIFwiXCIpLmNvbnRhaW5zKFwibnVtYmVyb2Zjb2x1bW5zOlwiKSkge1xuICAgICAgICAgICAgbGV0IHVzZXJEZWZOdW1iZXJPZkNvbHMgPSBwYXJzZUludChzZXR0aW5nc0xpbmVzW2ldLnNwbGl0KFwiOlwiKVsxXSlcblxuICAgICAgICAgICAgaWYoTnVtYmVyLmlzTmFOKHVzZXJEZWZOdW1iZXJPZkNvbHMpID09PSBmYWxzZSkge1xuICAgICAgICAgICAgICAgIGlmKHVzZXJEZWZOdW1iZXJPZkNvbHMgPT09IDMpIHtcbiAgICAgICAgICAgICAgICAgICAgbnVtYmVyT2ZDb2x1bW5zID0gM1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmKHVzZXJEZWZOdW1iZXJPZkNvbHMgPT09IDIpIHtcbiAgICAgICAgICAgICAgICAgICAgbnVtYmVyT2ZDb2x1bW5zID0gMjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZm9yKGxldCBpID0gMDsgaSA8IHNldHRpbmdzTGluZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYoc2V0dGluZ3NMaW5lc1tpXS50b0xvd2VyQ2FzZSgpLnJlcGxhY2UoL1xccy9nLCBcIlwiKS5jb250YWlucyhcImxhcmdlc3Rjb2x1bW46XCIpKSB7XG5cbiAgICAgICAgICAgIGxldCBzZXR0aW5nID0gc2V0dGluZ3NMaW5lc1tpXS5zcGxpdChcIjpcIilbMV0udHJpbVN0YXJ0KCkudHJpbUVuZCgpLnRvTG93ZXJDYXNlKCk7XG4gICAgICAgICAgICBsZXQgdXNlckRlZkxheW91dDogQ29sdW1uTGF5b3V0ID0gKDxhbnk+Q29sdW1uTGF5b3V0KVtzZXR0aW5nXVxuXG4gICAgICAgICAgICBpZih1c2VyRGVmTGF5b3V0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBjb2x1bW5MYXlvdXQgPSB1c2VyRGVmTGF5b3V0O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgZm9yKGxldCBpID0gMDsgaSA8IHNldHRpbmdzTGluZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYoc2V0dGluZ3NMaW5lc1tpXS50b0xvd2VyQ2FzZSgpLnJlcGxhY2UoL1xccy9nLCBcIlwiKS5jb250YWlucyhcImJvcmRlcjpcIikpIHtcblxuICAgICAgICAgICAgbGV0IHNldHRpbmcgPSBzZXR0aW5nc0xpbmVzW2ldLnNwbGl0KFwiOlwiKVsxXS50cmltU3RhcnQoKS50cmltRW5kKCkudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgICAgIGxldCBpc0JvcmRlckRyYXduOiBCb3JkZXJPcHRpb24gPSAoPGFueT5Cb3JkZXJPcHRpb24pW3NldHRpbmddXG5cbiAgICAgICAgICAgIGlmKGlzQm9yZGVyRHJhd24gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIHN3aXRjaChpc0JvcmRlckRyYXduKXtcbiAgICAgICAgICAgICAgICAgICAgY2FzZShCb3JkZXJPcHRpb24uZGlzYWJsZWQpOlxuICAgICAgICAgICAgICAgICAgICBjYXNlKEJvcmRlck9wdGlvbi5vZmYpOlxuICAgICAgICAgICAgICAgICAgICBjYXNlKEJvcmRlck9wdGlvbi5mYWxzZSk6XG4gICAgICAgICAgICAgICAgICAgICAgICBib3JkZXJEcmF3biA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgZm9yKGxldCBpID0gMDsgaSA8IHNldHRpbmdzTGluZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYoc2V0dGluZ3NMaW5lc1tpXS50b0xvd2VyQ2FzZSgpLnJlcGxhY2UoL1xccy9nLCBcIlwiKS5jb250YWlucyhcInNoYWRvdzpcIikpIHtcblxuICAgICAgICAgICAgbGV0IHNldHRpbmcgPSBzZXR0aW5nc0xpbmVzW2ldLnNwbGl0KFwiOlwiKVsxXS50cmltU3RhcnQoKS50cmltRW5kKCkudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgICAgIGxldCBpc1NoYWRvd0RyYXduOiBTaGFkb3dPcHRpb24gPSAoPGFueT5TaGFkb3dPcHRpb24pW3NldHRpbmddXG5cbiAgICAgICAgICAgIGlmKGlzU2hhZG93RHJhd24gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIHN3aXRjaChpc1NoYWRvd0RyYXduKXtcbiAgICAgICAgICAgICAgICAgICAgY2FzZShTaGFkb3dPcHRpb24uZGlzYWJsZWQpOlxuICAgICAgICAgICAgICAgICAgICBjYXNlKFNoYWRvd09wdGlvbi5vZmYpOlxuICAgICAgICAgICAgICAgICAgICBjYXNlKFNoYWRvd09wdGlvbi5mYWxzZSk6XG4gICAgICAgICAgICAgICAgICAgICAgICBzaGFkb3dEcmF3biA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgbGV0IHNldHRpbmdzID0geyBudW1iZXJPZkNvbHVtbnMsIGNvbHVtbkxheW91dCwgZHJhd0JvcmRlcjogYm9yZGVyRHJhd24sIGRyYXdTaGFkb3c6IHNoYWRvd0RyYXduIH1cblxuICAgIHJldHVybiBzZXR0aW5ncztcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNvdW50U3RhcnRUYWdzKHRleHQ6IHN0cmluZyk6IHsgbnVtYmVyT2ZUYWdzOiBudW1iZXIsIGtleXM6IHN0cmluZ1tdIH0ge1xuXG4gICAgbGV0IGtleXM6IHN0cmluZ1tdID0gW107XG4gICAgbGV0IHN0YXJ0VGFnRGF0YSA9IGZpbmRTdGFydFRhZyh0ZXh0KTtcbiAgICB3aGlsZShzdGFydFRhZ0RhdGEuZm91bmQpIHtcbiAgICAgICAgXG4gICAgICAgIC8vIFNsaWNlIG9mZiBldmVyeXRoaW5nIGJlZm9yZSB0aGUgdGFnXG4gICAgICAgIHRleHQgPSB0ZXh0LnNsaWNlKHN0YXJ0VGFnRGF0YS5zdGFydFBvc2l0aW9uKTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogR2V0IGp1c3QgdGhlIHN0YXJ0IHRhZyBsaW5lIGFuZCB0aGVuIHNldCB0ZXh0IHRvIGV2ZXJ5dGhpbmcganVzdFxuICAgICAgICAgKiBhZnRlciB0aGUgc3RhcnQgdGFnLlxuICAgICAgICAgKi9cbiAgICAgICAgbGV0IHRhZyA9IHRleHQuc3BsaXQoXCJcXG5cIilbMF07XG4gICAgICAgIHRleHQgPSB0ZXh0LnNsaWNlKDEpOyAvLyBUaGlzIG1vdmVzIHRoZSB0ZXh0IDEgY2hhcmFjdGVyIHNvIHdlIGRvbnQgbWF0Y2ggdGhlIHNhbWUgdGFnLlxuXG4gICAgICAgIC8vIFBhcnNlIG91dCB0aGUga2V5IGFuZCBhcHBlbmQgdG8gdGhlIGxpc3QuXG4gICAgICAgIGxldCBrZXkgPSBnZXRTdGFydFRhZ0tleSh0YWcpO1xuICAgICAgICBpZihrZXkgPT09IG51bGwpIHtcbiAgICAgICAgICAgIGtleSA9IFwiXCJcbiAgICAgICAgfVxuICAgICAgICBrZXlzLnB1c2goa2V5KTtcblxuICAgICAgICAvLyBTZWFyY2ggYWdhaW4gZm9yIGFub3RoZXIgdGFnIGJlZm9yZSBsb29waW5nLlxuICAgICAgICBzdGFydFRhZ0RhdGEgPSBmaW5kU3RhcnRUYWcodGV4dCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHsgbnVtYmVyT2ZUYWdzOiBrZXlzLmxlbmd0aCwga2V5cyB9O1xufVxuXG4vKipcbiAqIFRoaXMgZnVuY3Rpb24gd2lsbCBmaWx0ZXIgYSBzZXQgb2Ygc3RyaW5ncywgcmV0dXJuaW5nIGFsbCBpdGVtcyBzdGFydGluZ1xuICogZnJvbSB0aGUgY2xvc2VzdCBvcGVuIHN0YXJ0IHRhZyB0aHJvdWdoIHRoZSBsYXN0IGl0ZW0gaW4gdGhlIHNldC4gXG4gKiBcbiAqIFRoZSBmdW5jdGlvbiBmaWx0ZXJzIG91dCBhbGwgZW5kIHRhZ3MgdG8gbWFrZSBzdXJlIHRoYXQgdGhlIHN0YXJ0IHRhZyB3ZSBcbiAqIGZpbmQgaXMgdGhlIHByb3BlciBzdGFydCB0YWcgZm9yIHRoZSBsaXN0IHNlbnQuIFxuICogQHBhcmFtIGxpbmVzQWJvdmVBcnJheSBcbiAqIEByZXR1cm5zIFxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0U3RhcnRCbG9ja0Fib3ZlTGluZShsaW5lc0Fib3ZlQXJyYXk6IHN0cmluZ1tdKTogeyBzdGFydEJsb2NrS2V5OiBzdHJpbmcsIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5lc0Fib3ZlQXJyYXk6IHN0cmluZ1tdIH0gfCBudWxsIHtcblxuICAgIC8vIFJlZHVjZSB0aGUgYXJyYXkgZG93biBpbnRvIGEgc2luZ2xlIHN0cmluZyBzbyB0aGF0IHdlIGNhblxuICAgIC8vIGVhc2lseSBSZWdFeCBvdmVyIHRoZSBzdHJpbmcgYW5kIGZpbmQgdGhlIGluZGljaWVzIHdlJ3JlIGxvb2tpbmcgZm9yLlxuICAgIGxldCBsaW5lc0Fib3ZlU3RyID0gbGluZXNBYm92ZUFycmF5LnJlZHVjZSgocHJldiwgY3VycmVudCkgPT4ge1xuICAgICAgICByZXR1cm4gcHJldiArIFwiXFxuXCIgICsgY3VycmVudDtcbiAgICB9LCBcIlwiKTtcblxuICAgIC8qXG4gICAgICAgICogRmlyc3QgdGhpbmcgd2UgbmVlZCB0byBkbyBpcyBjaGVjayBpZiB0aGVyZSBhcmUgYW55IGVuZCB0YWdzIGluIHRoZVxuICAgICAgICAqIHNldCBvZiBzdHJpbmdzICh3aGljaCBsb2dpY2FsbHkgd291bGQgY2xvc2Ugc3RhcnQgdGFncyBhbmQgdGhlcmVmb3JlXG4gICAgICAgICogdGhlIHN0YXJ0IHRhZyBpdCBjbG9zZXMgaXMgbm90IHdoYXQgd2Ugd2FudCkuIElmIHRoZXJlIGFyZSB3ZSB3YW50IHRvIFxuICAgICAgICAqIHNsb3dseSBuYXJyb3cgZG93biBvdXIgc2V0IG9mIHN0cmluZ3MgdW50aWwgdGhlIGxhc3QgZW5kIHRhZyBpcyBcbiAgICAgICAgKiByZW1vdmVkLiBUaGlzIG1ha2VzIGl0IGVhc2llciB0byBmaW5kIHRoZSBjbG9zZXN0IG9wZW4gc3RhcnQgdGFnIFxuICAgICAgICAqIGluIHRoZSBkYXRhLlxuICAgICAgICAqL1xuICAgIGxldCBlbmRUYWdTZXJhY2hEYXRhID0gZmluZEVuZFRhZyhsaW5lc0Fib3ZlU3RyKTtcbiAgICB3aGlsZShlbmRUYWdTZXJhY2hEYXRhLmZvdW5kID09PSB0cnVlKSB7XG5cbiAgICAgICAgLy8gR2V0IHRoZSBpbmRleCBvZiB3aGVyZSB0aGUgZmlyc3QgcmVnZXggbWF0Y2ggaW4gdGhlXG4gICAgICAgIC8vIHN0cmluZyBpcy4gdGhlbiB3ZSBzbGljZSBmcm9tIDAgdG8gaW5kZXggb2ZmIG9mIHRoZSBzdHJpbmdcbiAgICAgICAgLy8gc3BsaXQgaXQgYnkgbmV3bGluZSwgY3V0IG9mZiB0aGUgZmlyc3QgbGluZSAod2hpY2ggYWN0dWFsbHlcbiAgICAgICAgLy8gY29udGFpbnMgdGhlIHJlZ2V4KSB0aGVuIHJlZHVjZSBiYWNrIGRvd24gdG8gYSBzaW5nbGUgc3RyaW5nLlxuICAgICAgICAvL1xuICAgICAgICAvLyBUT0RPOiBUaGlzIGNvdWxkIGJlIHNpbXBsaWZpZWQgaWYgd2UganVzdCBzbGljZSB0aGUgdGV4dCBhZnRlclxuICAgICAgICAvLyB0aGUgZW5kIHRhZyBpbnN0ZWFkIG9mIHRoZSBiZWdpbmluZy5cbiAgICAgICAgbGV0IGluZGV4T2ZSZWdleCA9IGVuZFRhZ1NlcmFjaERhdGEuc3RhcnRQb3NpdGlvbjtcbiAgICAgICAgbGluZXNBYm92ZUFycmF5ID0gbGluZXNBYm92ZVN0ci5zbGljZShpbmRleE9mUmVnZXgpLnNwbGl0KFwiXFxuXCIpLnNwbGljZSgxKVxuICAgICAgICBsaW5lc0Fib3ZlU3RyID0gbGluZXNBYm92ZUFycmF5LnJlZHVjZSgocHJldiwgY3VycmVudCkgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIHByZXYgKyBcIlxcblwiICArIGN1cnJlbnQ7XG4gICAgICAgIH0sIFwiXCIpO1xuICAgICAgICBlbmRUYWdTZXJhY2hEYXRhID0gZmluZEVuZFRhZyhsaW5lc0Fib3ZlU3RyKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBOb3cgd2UgaGF2ZSB0aGUgc2V0IG9mIGxpbmVzIGFmdGVyIGFsbCBvdGhlciBlbmQgdGFncy4gV2Ugbm93XG4gICAgICogbmVlZCB0byBjaGVjayBpZiB0aGVyZSBpcyBzdGlsbCBhIHN0YXJ0IHRhZyBsZWZ0IGluIHRoZSBkYXRhLiBJZiBcbiAgICAgKiB0aGVyZSBpcyBubyBzdGFydCB0YWcgdGhlbiB3ZSB3YW50IHRvIHJldHVybiBhbiBlbXB0eSBhcnJheSBhbmQgZW1wdHkgXG4gICAgICoga2V5LlxuICAgICAqLyBcbiAgICBsZXQgc3RhcnRCbG9ja0tleSA9IFwiXCI7XG4gICAgbGV0IHN0YXJ0VGFnU2VhcmNoRGF0YSA9IGZpbmRTdGFydFRhZyhsaW5lc0Fib3ZlU3RyKTtcbiAgICBpZihzdGFydFRhZ1NlYXJjaERhdGEuZm91bmQgPT09IGZhbHNlKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICBlbHNlIHtcblxuICAgICAgICAvKipcbiAgICAgICAgICogTm93IHdlIGtub3cgdGhlcmUgaXMgYXQgbGVhc3QgMSBzdGFydCBrZXkgbGVmdCwgaG93ZXZlciB0aGVyZVxuICAgICAgICAgKiBtYXkgYmUgbXVsdGlwbGUgc3RhcnQga2V5cyBpZiB0aGUgdXNlciBpcyBub3QgY2xvc2luZyB0aGVpclxuICAgICAgICAgKiBibG9ja3MuIFdlIGN1cnJlbnRseSBkb250IGFsbG93IHJlY3VzaXZlIHNwbGl0dGluZyBzbyB3ZSBcbiAgICAgICAgICogd2FudCB0byBnZXQgdGhlIGxhc3Qga2V5IGluIG91ciByZW1haW5pbmcgc2V0LiBTYW1lIGlkZWEgYXNcbiAgICAgICAgICogYWJvdmUuXG4gICAgICAgICAqL1xuICAgICAgICB3aGlsZShzdGFydFRhZ1NlYXJjaERhdGEuZm91bmQgPT09IHRydWUpIHtcblxuICAgICAgICAgICAgLy8gR2V0IHRoZSBpbmRleCBvZiB3aGVyZSB0aGUgZmlyc3QgcmVnZXggbWF0Y2ggaW4gdGhlXG4gICAgICAgICAgICAvLyBzdHJpbmcgaXMuIHRoZW4gd2Ugc2xpY2UgZnJvbSAwIHRvIGluZGV4IG9mZiBvZiB0aGUgc3RyaW5nXG4gICAgICAgICAgICAvLyBzcGxpdCBpdCBieSBuZXdsaW5lLCBjdXQgb2ZmIHRoZSBmaXJzdCBsaW5lICh3aGljaCBhY3R1YWxseVxuICAgICAgICAgICAgLy8gY29udGFpbnMgdGhlIHJlZ2V4KSB0aGVuIHJlZHVjZSBiYWNrIGRvd24gdG8gYSBzaW5nbGUgc3RyaW5nLlxuICAgICAgICAgICAgLy9cbiAgICAgICAgICAgIC8vIFRPRE86IFRoaXMgY291bGQgYmUgc2ltcGxpZmllZCBpZiB3ZSBqdXN0IHNsaWNlIHRoZSB0ZXh0IGFmdGVyXG4gICAgICAgICAgICAvLyB0aGUgZW5kIHRhZyBpbnN0ZWFkIG9mIHRoZSBiZWdpbmluZy5cbiAgICAgICAgICAgIGxldCBzdGFydEluZGV4ID0gc3RhcnRUYWdTZWFyY2hEYXRhLnN0YXJ0UG9zaXRpb247XG5cbiAgICAgICAgICAgIGxpbmVzQWJvdmVBcnJheSA9IGxpbmVzQWJvdmVTdHIuc2xpY2Uoc3RhcnRJbmRleCkuc3BsaXQoXCJcXG5cIilcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgbGV0IHN0YXJ0VGFnID0gbGluZXNBYm92ZUFycmF5WzBdO1xuICAgICAgICAgICAgbGV0IGtleSA9IGdldFN0YXJ0VGFnS2V5KHN0YXJ0VGFnKTtcbiAgICAgICAgICAgIGlmKGtleSAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHN0YXJ0QmxvY2tLZXkgPSBrZXk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGxpbmVzQWJvdmVBcnJheSA9IGxpbmVzQWJvdmVBcnJheS5zcGxpY2UoMSlcbiAgICAgICAgICAgIGxpbmVzQWJvdmVTdHIgPSBsaW5lc0Fib3ZlQXJyYXkucmVkdWNlKChwcmV2LCBjdXJyZW50KSA9PiB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHByZXYgKyBcIlxcblwiICArIGN1cnJlbnQ7XG4gICAgICAgICAgICB9LCBcIlwiKTtcblxuICAgICAgICAgICAgc3RhcnRUYWdTZWFyY2hEYXRhID0gZmluZFN0YXJ0VGFnKGxpbmVzQWJvdmVTdHIpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHsgc3RhcnRCbG9ja0tleSwgbGluZXNBYm92ZUFycmF5IH07XG59XG5cbmZ1bmN0aW9uIGdldFN0YXJ0VGFnS2V5KHN0YXJ0VGFnOiBzdHJpbmcpOiBzdHJpbmcgfCBudWxsIHtcblxuICAgIGxldCBrZXlTcGxpdCA9IHN0YXJ0VGFnLnNwbGl0KFwiOlwiKTtcbiAgICBpZihrZXlTcGxpdC5sZW5ndGggPiAxKXtcbiAgICAgICAgcmV0dXJuIGtleVNwbGl0WzFdLnJlcGxhY2UoXCIgXCIsIFwiXCIpXG4gICAgfVxuXG4gICAgcmV0dXJuIG51bGw7XG59XG4iLCIvKlxuICogRmlsZW5hbWU6IG11bHRpLWNvbHVtbi1tYXJrZG93bi9zcmMvdXRpbGl0aWVzL3V0aWxzLnRzXG4gKiBDcmVhdGVkIERhdGU6IFR1ZXNkYXksIEphbnVhcnkgMzB0aCAyMDIyLCA0OjAyOjE5IHBtXG4gKiBBdXRob3I6IENhbWVyb24gUm9iaW5zb25cbiAqIFxuICogQ29weXJpZ2h0IChjKSAyMDIyIENhbWVyb24gUm9iaW5zb25cbiAqL1xuXG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRVSUQobGVuZ3RoOiBudW1iZXIgPSAxMCk6IHN0cmluZyB7XG5cbiAgICBpZihsZW5ndGggPiAxMCkge1xuICAgICAgICBsZW5ndGggPSAxMDtcbiAgICB9XG4gICAgbGV0IFVJRCA9IE1hdGgucmFuZG9tKCkudG9TdHJpbmcoMzYpLnN1YnN0cmluZygyKTtcbiAgICBVSUQgPSBVSUQuc2xpY2UoMCwgbGVuZ3RoKTtcbiAgICBcbiAgICByZXR1cm4gVUlEO1xufSIsIi8qXG4gKiBGaWxlbmFtZTogbXVsdGktY29sdW1uLW1hcmtkb3duL3NyYy9kb21PYmplY3QudHNcbiAqIENyZWF0ZWQgRGF0ZTogVHVlc2RheSwgRmVicnVhcnkgMXN0IDIwMjIsIDEyOjA0OjAwIHBtXG4gKiBBdXRob3I6IENhbWVyb24gUm9iaW5zb25cbiAqIFxuICogQ29weXJpZ2h0IChjKSAyMDIyIENhbWVyb24gUm9iaW5zb25cbiAqL1xuXG5pbXBvcnQgeyBnZXRVSUQgfSBmcm9tIFwiLi4vdXRpbGl0aWVzL3V0aWxzXCI7XG5pbXBvcnQgeyBNdWx0aUNvbHVtblNldHRpbmdzIH0gZnJvbSBcIi4uL3JlZ2lvblNldHRpbmdzXCI7XG5cbmV4cG9ydCBlbnVtIERPTU9iamVjdFRhZyB7XG4gICAgbm9uZSxcbiAgICBzdGFydFJlZ2lvbixcbiAgICByZWdpb25TZXR0aW5ncyxcbiAgICBjb2x1bW5CcmVhayxcbiAgICBlbmRSZWdpb25cbn1cblxuZXhwb3J0IGNsYXNzIERPTU9iamVjdCB7XG4gICAgbm9kZUtleTogc3RyaW5nO1xuICAgIGVsZW1lbnQ6IEhUTUxFbGVtZW50O1xuICAgIFVJRDogc3RyaW5nO1xuICAgIHRhZzogRE9NT2JqZWN0VGFnO1xuXG4gICAgY29uc3RydWN0b3Iobm9kZUtleTogc3RyaW5nLCBlbGVtZW50OiBIVE1MRWxlbWVudCwgXG4gICAgICAgICAgICAgICAgcmFuZG9tSUQ6c3RyaW5nID0gZ2V0VUlEKCksIFxuICAgICAgICAgICAgICAgIHRhZzogRE9NT2JqZWN0VGFnID0gRE9NT2JqZWN0VGFnLm5vbmUgKSB7XG4gICAgICAgIHRoaXMubm9kZUtleSA9IG5vZGVLZXk7XG4gICAgICAgIHRoaXMuZWxlbWVudCA9IGVsZW1lbnQ7XG4gICAgICAgIHRoaXMuVUlEID0gcmFuZG9tSUQ7XG4gICAgICAgIHRoaXMudGFnID0gdGFnO1xuICAgIH1cbn1cblxuZXhwb3J0IGNsYXNzIERPTVN0YXJ0UmVnaW9uT2JqZWN0IGV4dGVuZHMgRE9NT2JqZWN0IHtcblxuICAgIHJlZ2lvbkVsZW1lbnQ6IEhUTUxFbGVtZW50O1xuXG4gICAgY29uc3RydWN0b3IoYmFzZURPTU9iamVjdDogRE9NT2JqZWN0LCByZWdpb25FbGVtZW50OiBIVE1MRWxlbWVudCkge1xuXG4gICAgICAgIHN1cGVyKGJhc2VET01PYmplY3Qubm9kZUtleSwgYmFzZURPTU9iamVjdC5lbGVtZW50LCBiYXNlRE9NT2JqZWN0LlVJRCwgRE9NT2JqZWN0VGFnLnN0YXJ0UmVnaW9uKTtcbiAgICAgICAgdGhpcy5yZWdpb25FbGVtZW50ID0gcmVnaW9uRWxlbWVudDtcbiAgICB9XG59XG5cbmV4cG9ydCBjbGFzcyBET01SZWdpb25TZXR0aW5nc09iamVjdCBleHRlbmRzIERPTU9iamVjdCB7XG5cbiAgICByZWdpb25TZXR0aW5nczogTXVsdGlDb2x1bW5TZXR0aW5ncztcblxuICAgIGNvbnN0cnVjdG9yKGJhc2VET01PYmplY3Q6IERPTU9iamVjdCwgcmVnaW9uU2V0dGluZ3M6IE11bHRpQ29sdW1uU2V0dGluZ3MpIHtcbiAgICAgICAgc3VwZXIoYmFzZURPTU9iamVjdC5ub2RlS2V5LCBiYXNlRE9NT2JqZWN0LmVsZW1lbnQsIGJhc2VET01PYmplY3QuVUlELCBET01PYmplY3RUYWcucmVnaW9uU2V0dGluZ3MpO1xuXG4gICAgICAgIHRoaXMucmVnaW9uU2V0dGluZ3MgPSByZWdpb25TZXR0aW5ncztcbiAgICB9XG59IiwiLypcbiAqIEZpbGU6IG11bHRpLWNvbHVtbi1tYXJrZG93bi9zcmMvZG9tTWFuYWdlci50c1xuICogQ3JlYXRlZCBEYXRlOiBTYXR1cmRheSwgSmFudWFyeSAzMHRoIDIwMjIsIDM6MTY6MzIgcG1cbiAqIEF1dGhvcjogQ2FtZXJvbiBSb2JpbnNvblxuICogXG4gKiBDb3B5cmlnaHQgKGMpIDIwMjIgQ2FtZXJvbiBSb2JpbnNvblxuICovXG5cbmltcG9ydCB7IHBhcnNlQ29sdW1uU2V0dGluZ3MgfSBmcm9tICcuLi91dGlsaXRpZXMvdGV4dFBhcnNlcic7XG5pbXBvcnQgeyBET01PYmplY3QsIERPTVN0YXJ0UmVnaW9uT2JqZWN0LCBET01SZWdpb25TZXR0aW5nc09iamVjdCwgRE9NT2JqZWN0VGFnIH0gZnJvbSAnLi9kb21PYmplY3QnO1xuaW1wb3J0IHsgTXVsdGlDb2x1bW5TZXR0aW5ncywgQ29sdW1uTGF5b3V0IH0gZnJvbSBcIi4uL3JlZ2lvblNldHRpbmdzXCI7XG5cbmV4cG9ydCBjbGFzcyBHbG9iYWxET01NYW5hZ2VyIHtcbiAgICBtYW5hZ2VyczogTWFwPHN0cmluZywgRmlsZURPTU1hbmFnZXI+O1xuXG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHRoaXMubWFuYWdlcnMgPSBuZXcgTWFwKCk7XG4gICAgfVxuXG4gICAgcHVibGljIHJlbW92ZUZpbGVNYW5hZ2VyQ2FsbGJhY2soa2V5OiBzdHJpbmcpIHtcbiAgICAgICAgaWYodGhpcy5tYW5hZ2Vycy5oYXMoa2V5KSA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgdGhpcy5tYW5hZ2Vycy5kZWxldGUoa2V5KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyBnZXRGaWxlTWFuYWdlcihrZXk6IHN0cmluZykge1xuXG4gICAgICAgIGxldCBmaWxlTWFuYWdlciA9IG51bGw7XG4gICAgICAgIGlmKHRoaXMubWFuYWdlcnMuaGFzKGtleSkgPT09IHRydWUpIHtcbiAgICAgICAgICAgIGZpbGVNYW5hZ2VyID0gdGhpcy5tYW5hZ2Vycy5nZXQoa2V5KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGZpbGVNYW5hZ2VyID0gY3JlYXRlRmlsZURPTU1hbmFnZXIodGhpcywga2V5KTtcbiAgICAgICAgICAgIHRoaXMubWFuYWdlcnMuc2V0KGtleSwgZmlsZU1hbmFnZXIpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGZpbGVNYW5hZ2VyO1xuICAgIH1cbn1cblxuZXhwb3J0IHR5cGUgRmlsZURPTU1hbmFnZXIgPSB7XG4gICAgcmVnaW9uTWFwOiBNYXA8c3RyaW5nLCBSZWdpb25ET01NYW5hZ2VyPixcbiAgICBoYXNTdGFydFRhZzogYm9vbGVhbixcbiAgICBjcmVhdGVSZWdpb25hbE1hbmFnZXI6IChyZWdpb25LZXk6IHN0cmluZywgZXJyb3JFbGVtZW50OiBIVE1MRWxlbWVudCwgcmVnaW9uRWxlbWVudDogSFRNTEVsZW1lbnQpID0+IFJlZ2lvbkRPTU1hbmFnZXJcbiAgICBnZXRSZWdpb25hbE1hbmFnZXI6IChyZWdpb25LZXk6IHN0cmluZykgPT4gUmVnaW9uRE9NTWFuYWdlciB8IG51bGwsXG4gICAgcmVtb3ZlUmVnaW9uOiAocmVnaW9uS2V5OiBzdHJpbmcpID0+IHZvaWQsXG4gICAgc2V0SGFzU3RhcnRUYWc6ICgpID0+IHZvaWQsXG4gICAgZ2V0SGFzU3RhcnRUYWc6ICgpID0+IGJvb2xlYW4sXG4gICAgZ2V0TnVtYmVyT2ZSZWdpb25zOiAoKSA9PiBudW1iZXIsXG4gICAgY2hlY2tLZXlFeGlzdHM6IChjaGVja0tleTogc3RyaW5nKSA9PiBib29sZWFuXG59XG5mdW5jdGlvbiBjcmVhdGVGaWxlRE9NTWFuYWdlcihwYXJlbnRNYW5hZ2VyOiBHbG9iYWxET01NYW5hZ2VyLCBmaWxlS2V5OiBzdHJpbmcpOiBGaWxlRE9NTWFuYWdlciB7XG4gICAgXG4gICAgbGV0IHJlZ2lvbk1hcDogTWFwPHN0cmluZywgUmVnaW9uRE9NTWFuYWdlcj4gPSBuZXcgTWFwKCk7XG4gICAgbGV0IGhhc1N0YXJ0VGFnOiBib29sZWFuID0gZmFsc2U7XG5cbiAgICBmdW5jdGlvbiByZW1vdmVSZWdpb24ocmVnaW9uS2V5OiBzdHJpbmcpOiB2b2lkIHtcblxuICAgICAgICBsZXQgcmVnaW9uTWFuYWdlciA9IHJlZ2lvbk1hcC5nZXQocmVnaW9uS2V5KTtcbiAgICAgICAgaWYocmVnaW9uTWFuYWdlcikge1xuICAgICAgICAgICAgcmVnaW9uTWFuYWdlci5kaXNwbGF5T3JpZ2luYWxFbGVtZW50cygpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmVnaW9uTWFwLmRlbGV0ZShyZWdpb25LZXkpO1xuICAgICAgICBcbiAgICAgICAgaWYocmVnaW9uTWFwLnNpemUgPT09IDApIHtcbiAgICAgICAgICAgIHBhcmVudE1hbmFnZXIucmVtb3ZlRmlsZU1hbmFnZXJDYWxsYmFjayhmaWxlS2V5KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNyZWF0ZVJlZ2lvbmFsTWFuYWdlcihyZWdpb25LZXk6IHN0cmluZywgZXJyb3JFbGVtZW50OiBIVE1MRWxlbWVudCwgcmVnaW9uRWxlbWVudDogSFRNTEVsZW1lbnQpIHtcblxuICAgICAgICAvL1RPRE86IFVzZSB0aGUgZXJyb3IgZWxlbWVudCB3aGVuZXZlciB0aGVyZSBpcyBhbiBlcnJvci5cblxuICAgICAgICBsZXQgcmVnb25hbE1hbmFnZXIgPSBjcmVhdGVSZWdpb25hbERvbU1hbmFnZXIodGhpcywgcmVnaW9uS2V5LCByZWdpb25FbGVtZW50KTtcbiAgICAgICAgcmVnaW9uTWFwLnNldChyZWdpb25LZXksIHJlZ29uYWxNYW5hZ2VyKTtcbiAgICAgICAgcmV0dXJuIHJlZ29uYWxNYW5hZ2VyO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldFJlZ2lvbmFsTWFuYWdlcihyZWdpb25LZXk6IHN0cmluZyk6IFJlZ2lvbkRPTU1hbmFnZXIgfCBudWxsIHtcblxuICAgICAgICBsZXQgcmVnb25hbE1hbmFnZXIgPSBudWxsO1xuICAgICAgICBpZihyZWdpb25NYXAuaGFzKHJlZ2lvbktleSkgPT09IHRydWUpIHtcbiAgICAgICAgICAgIHJlZ29uYWxNYW5hZ2VyID0gcmVnaW9uTWFwLmdldChyZWdpb25LZXkpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJlZ29uYWxNYW5hZ2VyO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHNldEhhc1N0YXJ0VGFnKCkge1xuICAgICAgICBoYXNTdGFydFRhZyA9IHRydWU7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0SGFzU3RhcnRUYWcoKSB7XG4gICAgICAgIHJldHVybiBoYXNTdGFydFRhZztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBnZXROdW1iZXJPZlJlZ2lvbnMoKSB7XG4gICAgICAgIHJldHVybiByZWdpb25NYXAuc2l6ZVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNoZWNrS2V5RXhpc3RzKGNoZWNrS2V5OiBzdHJpbmcpIHtcbiAgICAgICAgcmV0dXJuIHJlZ2lvbk1hcC5oYXMoY2hlY2tLZXkpO1xuICAgIH1cblxuICAgIHJldHVybiB7IHJlZ2lvbk1hcDogcmVnaW9uTWFwLCBcbiAgICAgICAgaGFzU3RhcnRUYWc6IGhhc1N0YXJ0VGFnLCAgXG4gICAgICAgIGNyZWF0ZVJlZ2lvbmFsTWFuYWdlcjogY3JlYXRlUmVnaW9uYWxNYW5hZ2VyLCBcbiAgICAgICAgZ2V0UmVnaW9uYWxNYW5hZ2VyOiBnZXRSZWdpb25hbE1hbmFnZXIsIFxuICAgICAgICByZW1vdmVSZWdpb246IHJlbW92ZVJlZ2lvbiwgXG4gICAgICAgIHNldEhhc1N0YXJ0VGFnOiBzZXRIYXNTdGFydFRhZywgXG4gICAgICAgIGdldEhhc1N0YXJ0VGFnOiBnZXRIYXNTdGFydFRhZyxcbiAgICAgICAgZ2V0TnVtYmVyT2ZSZWdpb25zOiBnZXROdW1iZXJPZlJlZ2lvbnMsXG4gICAgICAgIGNoZWNrS2V5RXhpc3RzOiBjaGVja0tleUV4aXN0c1xuICAgIH1cbn1cblxuZXhwb3J0IHR5cGUgTXVsdGlDb2x1bW5SZW5kZXJEYXRhID0geyBcbiAgICBwYXJlbnRSZW5kZXJFbGVtZW50OiBIVE1MRWxlbWVudCwgXG4gICAgcGFyZW50UmVuZGVyU2V0dGluZ3M6IE11bHRpQ29sdW1uU2V0dGluZ3MsXG4gICAgZG9tT2JqZWN0czogRE9NT2JqZWN0W11cbn1cblxuZXhwb3J0IHR5cGUgUmVnaW9uRE9NTWFuYWdlciA9IHtcblxuICAgIGFkZE9iamVjdDogKHNpYmxpbmdzQWJvdmU6IEhUTUxEaXZFbGVtZW50LCBvYmo6IERPTU9iamVjdCkgPT4gbnVtYmVyLFxuICAgIHJlbW92ZU9iamVjdDogKG9iamVjdEtleTogc3RyaW5nKSA9PiB2b2lkLFxuICAgIHVwZGF0ZUVsZW1lbnRUYWc6IChvYmplY3RVSUQ6IHN0cmluZywgbmV3VGFnOiBET01PYmplY3RUYWcpID0+IHZvaWQsXG4gICAgc2V0RWxlbWVudFRvU2V0dGluZ3NCbG9jazogKG9iamVjdFVJRDogc3RyaW5nLCBzZXR0aW5nc1RleHQ6IHN0cmluZykgPT4gdm9pZCxcbiAgICBnZXRSZWdpb25SZW5kZXJEYXRhOiAoKSA9PiBNdWx0aUNvbHVtblJlbmRlckRhdGEsXG4gICAgZGlzcGxheU9yaWdpbmFsRWxlbWVudHM6ICgpID0+IHZvaWRcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZVJlZ2lvbmFsRG9tTWFuYWdlcihmaWxlTWFuYWdlcjogRmlsZURPTU1hbmFnZXIsIHJlZ2lvbktleTogc3RyaW5nLCBzdGFydFJlZ2lvbkVsZW1lbnQ6IEhUTUxFbGVtZW50KTogUmVnaW9uRE9NTWFuYWdlciB7XG5cbiAgICAvKipcbiAgICAgKiBXZSB1c2UgYSBsaXN0IGFuZCBhIG1hcCB0byBoZWxwIGtlZXAgdHJhY2sgb2YgdGhlIG9iamVjdHMuIFJlcXVpcmVzXG4gICAgICogbW9yZSBtZW1vcnkgYnV0IG1ha2VzIHByb2Nlc3NpbmcgdGhpbmdzIGEgbGl0dGxlIGNsZWFuZXIgYW5kIHByZXN1bWFibHlcbiAgICAgKiBmYXN0ZXIuXG4gICAgICogXG4gICAgICogVXNlIHRoZSBtYXAgdG8gbG9vayB1cCBvYmplY3QgYnkga2V5IGFuZCB0aGUgbGlzdCBpcyB1c2VkIHRvIHRyYWNrIG9iamVjdHNcbiAgICAgKiBpbiB0aGUgb3JkZXIgdGhleSBhcmUgaW4gdGhlIGRvY3VtZW50LlxuICAgICAqL1xuICAgIGxldCBkb21MaXN0OiBET01PYmplY3RbXSA9IFtdXG4gICAgbGV0IGRvbU9iamVjdE1hcDogTWFwPHN0cmluZywgRE9NT2JqZWN0PiA9IG5ldyBNYXAoKTtcbiAgICBsZXQgcmVnaW9uUGFyZW50OiBIVE1MRWxlbWVudCA9IHN0YXJ0UmVnaW9uRWxlbWVudDtcbiAgICBsZXQgcmVnaW9uU2V0dGluZ3M6IERPTVJlZ2lvblNldHRpbmdzT2JqZWN0W10gPSBbXTtcblxuICAgIGZ1bmN0aW9uIGFkZE9iamVjdChzaWJsaW5nc0Fib3ZlOiBIVE1MRGl2RWxlbWVudCwgb2JqOiBET01PYmplY3QpOiBudW1iZXIge1xuXG4gICAgICAgIGxldCBhZGRBdEluZGV4ID0gc2libGluZ3NBYm92ZS5jaGlsZHJlbi5sZW5ndGg7XG5cbiAgICAgICAgLy8gY29uc29sZS5sb2coXCJBdHRlbXB0aW5nIHRvIGFkZDpcIiwgb2JqLCBgYXQgaW5kZXg6ICR7YWRkQXRJbmRleH1gKTtcblxuICAgICAgICBkb21MaXN0LnNwbGljZShhZGRBdEluZGV4LCAwLCBvYmopO1xuICAgICAgICBkb21PYmplY3RNYXAuc2V0KG9iai5VSUQsIG9iaik7XG5cbiAgICAgICAgLy8gLyoqXG4gICAgICAgIC8vICAqIE1ha2UgYSBjb3B5IG9mIHRoZSBsaXN0IHRvIGxvZywgb25seSBiZWNhdXNlXG4gICAgICAgIC8vICAqIGNvbnNvbGUgbG9nIHVwZGF0ZXMgaXRzIHJlZmVyZW5jZXMgd2l0aCB1cGRhdGVzIGluIG1lbW9yeS5cbiAgICAgICAgLy8gICovXG4gICAgICAgIC8vIGxldCB4ID0gZG9tTGlzdC5zbGljZSgwKTtcbiAgICAgICAgLy8gY29uc29sZS5sb2coeCk7XG5cbiAgICAgICAgcmV0dXJuIGFkZEF0SW5kZXg7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcmVtb3ZlT2JqZWN0KG9iamVjdFVJRDogc3RyaW5nKTogdm9pZCB7XG5cbiAgICAgICAgLy8gLyoqXG4gICAgICAgIC8vICAqIE1ha2UgYSBjb3B5IG9mIHRoZSBsaXN0IHRvIGxvZ1xuICAgICAgICAvLyAgKi9cbiAgICAgICAgLy8gbGV0IHggPSBkb21MaXN0LnNsaWNlKDApO1xuICAgICAgICAvLyBjb25zb2xlLmxvZyh4KTtcblxuICAgICAgICAvLyBHZXQgdGhlIG9iamVjdCBieSBrZXksIHJlbW92ZSBpdCBmcm9tIHRoZSBtYXAgYW5kIHRoZW5cbiAgICAgICAgLy8gZnJvbSB0aGUgbGlzdC5cbiAgICAgICAgbGV0IG9iaiA9IGRvbU9iamVjdE1hcC5nZXQob2JqZWN0VUlEKTtcbiAgICAgICAgZG9tT2JqZWN0TWFwLmRlbGV0ZShvYmplY3RVSUQpO1xuICAgICAgICBcbiAgICAgICAgaWYoZG9tTGlzdC5jb250YWlucyhvYmopKSB7XG4gICAgICAgICAgICBkb21MaXN0LnJlbW92ZShvYmopO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gSWYgdGhlIG9iamVjdCBpcyBhIHNldHRpbmdzIG9iamVjdCB3ZSBuZWVkIHRvIHJlbW92ZSBmcm9tIHRoZSBcbiAgICAgICAgLy8gc2V0dGluZ3MgbGlzdC5cbiAgICAgICAgaWYob2JqLnRhZyA9PT0gRE9NT2JqZWN0VGFnLnJlZ2lvblNldHRpbmdzKSB7XG4gICAgICAgICAgICBsZXQgc2V0dGluZ3NPYmogPSBvYmogYXMgRE9NUmVnaW9uU2V0dGluZ3NPYmplY3Q7XG4gICAgICAgICAgICBpZihyZWdpb25TZXR0aW5ncy5jb250YWlucyhzZXR0aW5nc09iaikpIHtcbiAgICAgICAgICAgICAgICByZWdpb25TZXR0aW5ncy5yZW1vdmUoc2V0dGluZ3NPYmopO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYoZG9tTGlzdC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIGZpbGVNYW5hZ2VyLnJlbW92ZVJlZ2lvbihyZWdpb25LZXkpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8geCA9IGRvbUxpc3Quc2xpY2UoMCk7XG4gICAgICAgIC8vIGNvbnNvbGUubG9nKHgpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHVwZGF0ZUVsZW1lbnRUYWcob2JqZWN0VUlEOiBzdHJpbmcsIG5ld1RhZzogRE9NT2JqZWN0VGFnKTogdm9pZCB7XG5cbiAgICAgICAgbGV0IG9iaiA9IGRvbU9iamVjdE1hcC5nZXQob2JqZWN0VUlEKTtcbiAgICAgICAgbGV0IGluZGV4ID0gZG9tTGlzdC5pbmRleE9mKG9iaik7XG4gICAgICAgIGlmKGluZGV4ICE9PSAtMSkge1xuICAgICAgICAgICAgZG9tTGlzdFtpbmRleF0udGFnID0gbmV3VGFnO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gc2V0RWxlbWVudFRvU2V0dGluZ3NCbG9jayhvYmplY3RVSUQ6IHN0cmluZywgc2V0dGluZ3NUZXh0OiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgXG5cbiAgICAgICAgbGV0IG9iaiA9IGRvbU9iamVjdE1hcC5nZXQob2JqZWN0VUlEKTtcbiAgICAgICAgbGV0IGluZGV4ID0gZG9tTGlzdC5pbmRleE9mKG9iaik7XG4gICAgICAgIGlmKGluZGV4ICE9PSAtMSkge1xuICAgICAgICAgICAgbGV0IHNldHRpbmdzOiBNdWx0aUNvbHVtblNldHRpbmdzID0gcGFyc2VDb2x1bW5TZXR0aW5ncyhzZXR0aW5nc1RleHQpO1xuICAgICAgICAgICAgbGV0IHJlZ2lvblNldHRpbmdzT2JqOiBET01SZWdpb25TZXR0aW5nc09iamVjdCA9IG5ldyBET01SZWdpb25TZXR0aW5nc09iamVjdChkb21MaXN0W2luZGV4XSwgc2V0dGluZ3MpO1xuICAgICAgICAgICAgXG4gICAgICAgICAgICBkb21PYmplY3RNYXAuc2V0KHJlZ2lvblNldHRpbmdzT2JqLlVJRCwgcmVnaW9uU2V0dGluZ3NPYmopO1xuICAgICAgICAgICAgZG9tTGlzdFtpbmRleF0gPSByZWdpb25TZXR0aW5nc09iajtcblxuICAgICAgICAgICAgcmVnaW9uU2V0dGluZ3MucHVzaChyZWdpb25TZXR0aW5nc09iailcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYW4gb2JqZWN0IGNvbnRhaW5pbmcgYWxsIG5lY2Vzc2FyeSBpbmZvcm1hdGlvbiBmb3IgdGhlIHJlZ2lvblxuICAgICAqIHRvIGJlIHJlbmRlcmVkIHRvIHRoZSBwcmV2aWV3IHBhbmUuXG4gICAgICogXG4gICAgICogQHJldHVybnMgYSBNdWx0aUNvbHVtblJlbmRlckRhdGEgb2JqZWN0IHdpdGggdGhlIHJvb3QgRE9NIGVsZW1lbnQsIHNldHRpbmdzIG9iamVjdCwgYW5kIFxuICAgICAqIGFsbCBjaGlsZCBvYmplY3RzIGluIHRoZSBvcmRlciB0aGV5IHNob3VsZCBiZSByZW5kZXJlZC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRSZWdpb25SZW5kZXJEYXRhKCk6IE11bHRpQ29sdW1uUmVuZGVyRGF0YSB7XG5cbiAgICAgICAgLy8gU2V0IGRlZmF1bHRzIGJlZm9yZSBhdHRlbXB0aW5nIHRvIGdldCBzZXR0aW5ncy5cbiAgICAgICAgbGV0IHNldHRpbmdzOiBNdWx0aUNvbHVtblNldHRpbmdzID0ge251bWJlck9mQ29sdW1uczogMiwgY29sdW1uTGF5b3V0OiBDb2x1bW5MYXlvdXQuc3RhbmRhcmQsIGRyYXdCb3JkZXI6IHRydWUsIGRyYXdTaGFkb3c6IHRydWV9O1xuICAgICAgICBpZihyZWdpb25TZXR0aW5ncy5sZW5ndGggPiAwKSB7XG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogU2luY2Ugd2UgYXBwZW5kIHNldHRpbmdzIG9udG8gdGhlIGVuZCBvZiB0aGUgYXJyYXkgd2Ugd2FudCB0aGUgbGFzdFxuICAgICAgICAgICAgICogaXRlbSBpbiB0aGUgYXJyYXkgYXMgdGhhdCB3b3VsZCBiZSB0aGUgbW9zdCByZWNlbnQgc2V0dGluZ3Mgd2UgcGFyc2VkLlxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBzZXR0aW5ncyA9IHJlZ2lvblNldHRpbmdzW3JlZ2lvblNldHRpbmdzLmxlbmd0aCAtIDFdLnJlZ2lvblNldHRpbmdzO1xuICAgICAgICB9XG4gICAgICAgIFxuICAgICAgICByZXR1cm4geyBcbiAgICAgICAgICAgIHBhcmVudFJlbmRlckVsZW1lbnQ6IHJlZ2lvblBhcmVudCwgXG4gICAgICAgICAgICBwYXJlbnRSZW5kZXJTZXR0aW5nczogc2V0dGluZ3MsXG4gICAgICAgICAgICBkb21PYmplY3RzOiBkb21MaXN0XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhpcyBmdWN0aW9uIGlzIGNhbGxlZCB3aGVuIGEgc3RhcnQgdGFnIGlzIHJlbW92ZWQgZnJvbSB2aWV3IG1lYW5pbmdcbiAgICAgKiBvdXIgcGFyZW50IGVsZW1lbnQgc3RvcmluZyB0aGUgbXVsdGktY29sdW1uIHJlZ2lvbiBpcyByZW1vdmVkLiBJdCBcbiAgICAgKiByZW1vdmVzIHRoZSBDU1MgY2xhc3MgZnJvbSBhbGwgb2YgdGhlIGVsZW1lbnRzIHNvIHRoZXkgd2lsbCBiZVxuICAgICAqIHJlLXJlbmRlcmVkIGluIHRoZSBwcmV2aWV3IHdpbmRvdy5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBkaXNwbGF5T3JpZ2luYWxFbGVtZW50cygpIHtcblxuICAgICAgICBmb3IobGV0IGkgPSAwOyBpIDwgZG9tTGlzdC5sZW5ndGg7IGkrKykge1xuXG4gICAgICAgICAgICBkb21MaXN0W2ldLmVsZW1lbnQucmVtb3ZlQ2xhc3MoXCJtdWx0aUNvbHVtbkRhdGFIaWRkZW5cIik7XG4gICAgICAgIH1cbiAgICAgICAgZm9yKGxldCBpID0gMDsgaSA8IHJlZ2lvblNldHRpbmdzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICByZWdpb25TZXR0aW5nc1tpXS5lbGVtZW50LnJlbW92ZUNsYXNzKFwibXVsdGlDb2x1bW5EYXRhSGlkZGVuXCIpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHsgYWRkT2JqZWN0OiBhZGRPYmplY3QsIFxuICAgICAgICAgICAgIHJlbW92ZU9iamVjdDogcmVtb3ZlT2JqZWN0LCBcbiAgICAgICAgICAgICB1cGRhdGVFbGVtZW50VGFnOiB1cGRhdGVFbGVtZW50VGFnLCBcbiAgICAgICAgICAgICBzZXRFbGVtZW50VG9TZXR0aW5nc0Jsb2NrOiBzZXRFbGVtZW50VG9TZXR0aW5nc0Jsb2NrLFxuICAgICAgICAgICAgIGdldFJlZ2lvblJlbmRlckRhdGE6IGdldFJlZ2lvblJlbmRlckRhdGEsXG4gICAgICAgICAgICAgZGlzcGxheU9yaWdpbmFsRWxlbWVudHM6IGRpc3BsYXlPcmlnaW5hbEVsZW1lbnRzXG4gICAgfVxufVxuIiwiLypcclxuICogRmlsZTogbXVsdGktY29sdW1uLW1hcmtkb3duL3NyYy9tYWluLnRzXHJcbiAqIENyZWF0ZWQgRGF0ZTogVHVlc2RheSwgT2N0b2JlciA1dGggMjAyMSwgMTowOSBwbVxyXG4gKiBBdXRob3I6IENhbWVyb24gUm9iaW5zb25cclxuICogXHJcbiAqIENvcHlyaWdodCAoYykgMjAyMiBDYW1lcm9uIFJvYmluc29uXHJcbiAqL1xyXG5cclxuaW1wb3J0IHsgTm90aWNlLCBQbHVnaW4sICBNYXJrZG93blJlbmRlckNoaWxkLCBNYXJrZG93blJlbmRlcmVyIH0gZnJvbSAnb2JzaWRpYW4nO1xyXG5pbXBvcnQgKiBhcyBtdWx0aUNvbHVtblBhcnNlciBmcm9tICcuL3V0aWxpdGllcy90ZXh0UGFyc2VyJztcclxuaW1wb3J0IHsgUmVnaW9uRE9NTWFuYWdlciwgTXVsdGlDb2x1bW5SZW5kZXJEYXRhLCBHbG9iYWxET01NYW5hZ2VyIH0gZnJvbSAnLi9kb21fbWFuYWdlci9kb21NYW5hZ2VyJztcclxuaW1wb3J0IHsgRE9NT2JqZWN0LCBET01PYmplY3RUYWcgfSBmcm9tICcuL2RvbV9tYW5hZ2VyL2RvbU9iamVjdCc7XHJcbmltcG9ydCB7IE11bHRpQ29sdW1uU2V0dGluZ3MsIENvbHVtbkxheW91dCB9IGZyb20gXCIuL3JlZ2lvblNldHRpbmdzXCI7XHJcblxyXG5pbXBvcnQgeyBnZXRVSUQgfSBmcm9tICcuL3V0aWxpdGllcy91dGlscyc7XHJcblxyXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBNdWx0aUNvbHVtbk1hcmtkb3duIGV4dGVuZHMgUGx1Z2luIHtcclxuXHQvLyBzZXR0aW5nczogU3BsaXRDb2x1bW5NYXJrZG93blNldHRpbmdzO1xyXG5cclxuICAgIGdsb2JhbE1hbmFnZXI6IEdsb2JhbERPTU1hbmFnZXIgPSBuZXcgR2xvYmFsRE9NTWFuYWdlcigpO1xyXG4gICAgXHJcblx0YXN5bmMgb25sb2FkKCkge1xyXG5cclxuICAgICAgICBjb25zb2xlLmxvZyhcIkxvYWRpbmcgbXVsdGktY29sdW1uIG1hcmtkb3duXCIpO1xyXG5cclxuICAgICAgICB0aGlzLnNldHVwTWFya2Rvd25Qb3N0UHJvY2Vzc29yKCk7XHJcblxyXG4gICAgICAgIC8vVE9ETzogU2V0IHVwIHRoaXMgYXMgYSBtb2RhbCB0byBzZXQgc2V0dGluZ3MgYXV0b21hdGljYWxseVxyXG4gICAgICAgIHRoaXMuYWRkQ29tbWFuZCh7ICAgICAgICAgICAgXHJcbiAgICAgICAgICAgIGlkOiBgaW5zZXJ0LW11bHRpLWNvbHVtbi1yZWdpb25gLFxyXG4gICAgICAgICAgICBuYW1lOiBgSW5zZXJ0IE11bHRpLUNvbHVtbiBSZWdpb25gLFxyXG4gICAgICAgICAgICBlZGl0b3JDYWxsYmFjazogKGVkaXRvciwgdmlldykgPT4ge1xyXG5cclxuICAgICAgICAgICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgICAgICAgICAgZWRpdG9yLmdldERvYygpLnJlcGxhY2VTZWxlY3Rpb24oXHJcbmBcclxuPT09IG11bHRpLWNvbHVtbi1zdGFydDogSURfJHtnZXRVSUQoNCl9XHJcblxcYFxcYFxcYGNvbHVtbi1zZXR0aW5nc1xyXG5OdW1iZXIgb2YgQ29sdW1uczogMlxyXG5MYXJnZXN0IENvbHVtbjogc3RhbmRhcmRcclxuXFxgXFxgXFxgXHJcblxyXG49PT0gZW5kLWNvbHVtbiA9PT1cclxuXHJcbj09PSBtdWx0aS1jb2x1bW4tZW5kXHJcblxyXG4ke2VkaXRvci5nZXREb2MoKS5nZXRTZWxlY3Rpb24oKX1gXHJcbiAgICAgICAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcclxuICAgICAgICAgICAgICAgICAgICBuZXcgTm90aWNlKFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBcIkVuY291bnRlcmVkIGFuIGVycm9yIGluc2VydGluZyBhIG11bHRpLWNvbHVtbiByZWdpb24uIFBsZWFzZSB0cnkgYWdhaW4gbGF0ZXIuXCJcclxuICAgICAgICAgICAgICAgICAgICApO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfSk7XHJcblxyXG4gICAgICAgIHRoaXMuYWRkQ29tbWFuZCh7ICAgICAgICAgICAgXHJcbiAgICAgICAgICAgIGlkOiBgYWRkLUlEcy1Uby1tdWx0aS1jb2x1bW4tcmVnaW9uYCxcclxuICAgICAgICAgICAgbmFtZTogYEZpeCBNaXNzaW5nIElEcyBmb3IgTXVsdGktQ29sdW1uIFJlZ2lvbnNgLFxyXG4gICAgICAgICAgICBlZGl0b3JDYWxsYmFjazogKGVkaXRvciwgdmlldykgPT4ge1xyXG5cclxuICAgICAgICAgICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgICAgICAgICAgLyoqXHJcbiAgICAgICAgICAgICAgICAgICAgICogTm90IHN1cmUgaWYgdGhlcmUgaXMgYW4gZWFzaWVyIHdheSB0byBkbyB0aGlzLlxyXG4gICAgICAgICAgICAgICAgICAgICAqIFxyXG4gICAgICAgICAgICAgICAgICAgICAqIEdldCBhbGwgb2YgdGhlIGxpbmVzIG9mIHRoZSBkb2N1bWVudCBzcGxpdCBieSBuZXdsaW5lcy5cclxuICAgICAgICAgICAgICAgICAgICAgKi9cclxuICAgICAgICAgICAgICAgICAgICBsZXQgbGluZXMgPSBlZGl0b3IuZ2V0UmFuZ2UoeyBsaW5lOiAwLCBjaDogMCB9LCB7IGxpbmU6IGVkaXRvci5nZXREb2MoKS5saW5lQ291bnQoKSwgY2g6IDB9KS5zcGxpdChcIlxcblwiKTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgLyoqXHJcbiAgICAgICAgICAgICAgICAgICAgICogTG9vcCB0aHJvdWdoIGFsbCBvZiB0aGUgbGluZXMgY2hlY2tpbmcgaWYgdGhlIGxpbmUgaXMgYSBcclxuICAgICAgICAgICAgICAgICAgICAgKiBzdGFydCB0YWcgYW5kIGlmIHNvIGlzIGl0IG1pc3NpbmcgYW4gSUQuXHJcbiAgICAgICAgICAgICAgICAgICAgICovXHJcbiAgICAgICAgICAgICAgICAgICAgbGV0IGxpbmVzV2l0aG91dElEcyA9IFtdXHJcbiAgICAgICAgICAgICAgICAgICAgbGV0IHRleHRXaXRob3V0SURzID0gW11cclxuICAgICAgICAgICAgICAgICAgICBmb3IobGV0IGkgPSAwOyBpIDwgbGluZXMubGVuZ3RoOyBpKyspIHtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBkYXRhID0gbXVsdGlDb2x1bW5QYXJzZXIuaXNTdGFydFRhZ1dpdGhJRChsaW5lc1tpXSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKGRhdGEuaXNTdGFydFRhZyA9PT0gdHJ1ZSAmJiBkYXRhLmhhc0tleSA9PT0gZmFsc2UpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmVzV2l0aG91dElEcy5wdXNoKGkpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGV4dFdpdGhvdXRJRHMucHVzaChsaW5lc1tpXSlcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIH0gICAgICAgICAgICAgICAgICAgIFxyXG5cclxuICAgICAgICAgICAgICAgICAgICBpZihsaW5lc1dpdGhvdXRJRHMubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ldyBOb3RpY2UgKFwiRm91bmQgMCBtaXNzaW5nIElEcyBpbiB0aGUgY3VycmVudCBkb2N1bWVudC5cIik7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIC8qKlxyXG4gICAgICAgICAgICAgICAgICAgICAqIE5vdyBsb29wIHRocm91Z2ggZWFjaCBsaW5lIHRoYXQgaXMgbWlzc2luZyBhbiBJRCBhbmRcclxuICAgICAgICAgICAgICAgICAgICAgKiBnZW5lcmF0ZSBhIHJhbmRvbSBJRCBhbmQgcmVwbGFjZSB0aGUgb3JpZ2luYWwgdGV4dC5cclxuICAgICAgICAgICAgICAgICAgICAgKi9cclxuICAgICAgICAgICAgICAgICAgICBmb3IobGV0IGkgPSAwOyBpIDwgbGluZXNXaXRob3V0SURzLmxlbmd0aDsgaSsrKSB7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgb3JpZ2luYWxUZXh0ID0gdGV4dFdpdGhvdXRJRHNbaV1cclxuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHRleHQgPSBvcmlnaW5hbFRleHQ7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRleHQgPSB0ZXh0LnRyaW1FbmQoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYodGV4dC5jaGFyQXQodGV4dC5sZW5ndGggLSAxKSA9PT0gXCI6XCIpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRleHQgPSB0ZXh0LnNsaWNlKDAsIHRleHQubGVuZ3RoLTEpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRleHQgPSBgJHt0ZXh0fTogSURfJHtnZXRVSUQoNCl9YDtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGVkaXRvci5yZXBsYWNlUmFuZ2UodGV4dCwgeyBsaW5lOiBsaW5lc1dpdGhvdXRJRHNbaV0sIGNoOiAwIH0sIFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHsgbGluZTogbGluZXNXaXRob3V0SURzW2ldLCBjaDogb3JpZ2luYWxUZXh0Lmxlbmd0aH0pO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICBuZXcgTm90aWNlIChgUmVwbGFjZWQgJHtsaW5lc1dpdGhvdXRJRHMubGVuZ3RofSBtaXNzaW5nIElEKHMpIGluIHRoZSBjdXJyZW50IGRvY3VtZW50LmApO1xyXG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xyXG4gICAgICAgICAgICAgICAgICAgIG5ldyBOb3RpY2UoXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIFwiRW5jb3VudGVyZWQgYW4gZXJyb3IgYWRkaWduIElEcyB0byBtdWx0aS1jb2x1bW4gcmVnaW9ucy4gUGxlYXNlIHRyeSBhZ2FpbiBsYXRlci5cIlxyXG4gICAgICAgICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9KTtcclxuXHR9XHJcblxyXG4gICAgc2V0dXBNYXJrZG93blBvc3RQcm9jZXNzb3IoKSB7XHJcblxyXG4gICAgICAgIHRoaXMucmVnaXN0ZXJNYXJrZG93blBvc3RQcm9jZXNzb3IoYXN5bmMgKGVsLCBjdHgpID0+IHtcclxuXHJcbiAgICAgICAgICAgIC8vIEdldCB0aGUgaW5mbyBmb3Igb3VyIGN1cnJlbnQgY29udGV4dCBhbmQgdGhlbiBjaGVja1xyXG4gICAgICAgICAgICAvLyBpZiB0aGUgZW50aXJlIHRleHQgY29udGFpbnMgYSBzdGFydCB0YWcuIElmIHRoZXJlIGlzXHJcbiAgICAgICAgICAgIC8vIG5vIHN0YXJ0IHRhZyBpbiB0aGUgZG9jdW1lbnQgd2UgY2FuIGp1c3QgcmV0dXJuIGFuZFxyXG4gICAgICAgICAgICAvLyBpZ25vcmUgdGhlIHJlc3Qgb2YgdGhlIHBhcnNpbmcuXHJcbiAgICAgICAgICAgIGxldCBpbmZvID0gY3R4LmdldFNlY3Rpb25JbmZvKGVsKTtcclxuXHJcbiAgICAgICAgICAgIC8qKlxyXG4gICAgICAgICAgICAgKiBXZSBuZWVkIHRoZSBjb250ZXh0IGluZm8gdG8gcHJvcGVybHkgcGFyc2Ugc28gcmV0dXJuaW5nIGhlcmUgXHJcbiAgICAgICAgICAgICAqIGluZm8gaXMgbnVsbC4gVE9ETzogU2V0IGVycm9yIGluIHZpZXcgaWYgdGhpcyBvY2N1cnMuXHJcbiAgICAgICAgICAgICAqL1xyXG4gICAgICAgICAgICBpZighaW5mbykge1xyXG5cclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgY29uc3Qgc291cmNlUGF0aCA9IGN0eC5zb3VyY2VQYXRoO1xyXG5cclxuICAgICAgICAgICAgbGV0IGZpbGVET01NYW5hZ2VyID0gdGhpcy5nbG9iYWxNYW5hZ2VyLmdldEZpbGVNYW5hZ2VyKHNvdXJjZVBhdGgpO1xyXG4gICAgICAgICAgICBpZihmaWxlRE9NTWFuYWdlciA9PT0gbnVsbCkge1xyXG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coXCJGb3VuZCBudWxsIERPTSBtYW5hZ2VyLiBDb3VsZCBub3QgcHJvY2VzcyBtdWx0aS1jb2x1bW4gbWFya2Rvd24uXCIpXHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIC8qKlxyXG4gICAgICAgICAgICAgKiBJZiB3ZSBlbmNvdW50ZXIgYSBzdGFydCB0YWcgb24gdGhlIGRvY3VtZW50IHdlIHNldCB0aGUgZmxhZyB0byBzdGFydFxyXG4gICAgICAgICAgICAgKiBwYXJzaW5nIHRoZSByZXN0IG9mIHRoZSBkb2N1bWVudC5cclxuICAgICAgICAgICAgICovXHJcbiAgICAgICAgICAgIGlmKG11bHRpQ29sdW1uUGFyc2VyLmNvbnRhaW5zU3RhcnRUYWcoZWwudGV4dENvbnRlbnQpKSB7XHJcbiAgICAgICAgICAgICAgICBmaWxlRE9NTWFuYWdlci5zZXRIYXNTdGFydFRhZygpO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAvKiogXHJcbiAgICAgICAgICAgICAqIElmIHRoZSBkb2N1bWVudCBkb2VzIG5vdCBjb250YWluIGFueSBzdGFydCB0YWdzIHdlIGlnbm9yZSB0aGVcclxuICAgICAgICAgICAgICogcmVzdCBvZiB0aGUgcGFyc2luZy4gVGhpcyBpcyBvbmx5IHNldCB0byB0cnVlIG9uY2UgdGhlIGZpcnN0XHJcbiAgICAgICAgICAgICAqIHN0YXJ0IHRhZyBlbGVtZW50IGlzIHBhcnNlZCBhYm92ZS5cclxuICAgICAgICAgICAgICovXHJcbiAgICAgICAgICAgIGlmKGZpbGVET01NYW5hZ2VyLmdldEhhc1N0YXJ0VGFnKCkgPT09IGZhbHNlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAvKipcclxuICAgICAgICAgICAgICogVGFrZSB0aGUgaW5mbyBwcm92aWRlZCBhbmQgZ2VuZXJhdGUgdGhlIHJlcXVpcmVkIHZhcmlhYmxlcyBmcm9tIFxyXG4gICAgICAgICAgICAgKiB0aGUgbGluZSBzdGFydCBhbmQgZW5kIHZhbHVlcy5cclxuICAgICAgICAgICAgICovXHJcbiAgICAgICAgICAgIGxldCBsaW5lc09mRWxlbWVudCA9IGluZm8udGV4dC5zcGxpdChcIlxcblwiKS5zcGxpY2UoaW5mby5saW5lU3RhcnQsIChpbmZvLmxpbmVFbmQgKyAxIC0gaW5mby5saW5lU3RhcnQpKTtcclxuICAgICAgICAgICAgbGV0IGVsZW1lbnRUZXh0U3BhY2VkID0gbGluZXNPZkVsZW1lbnQucmVkdWNlKChwcmV2LCBjdXJyKSA9PiB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gcHJldiArIFwiXFxuXCIgKyBjdXJyO1xyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgbGV0IGVsZW1lbnRUZXh0ID0gbGluZXNPZkVsZW1lbnQucmVkdWNlKChwcmV2LCBjdXJyKSA9PiB7IFxyXG4gICAgICAgICAgICAgICAgLy8gVE9ETzogVGhpcyBjYW4gcHJvYmFibHkgYmUgcmVtb3ZlZCBhcyBpdCBpcyBvbmx5IHVzZWQgdG8gaWRlbnRpZnkgRE9NT2JqZWN0cy5cclxuICAgICAgICAgICAgICAgIHJldHVybiBwcmV2ICsgY3VycjtcclxuICAgICAgICAgICAgfSk7XHJcblxyXG4gICAgICAgICAgICAvKipcclxuICAgICAgICAgICAgICogSWYgdGhlIGN1cnJlbnQgbGluZSBpcyBhIHN0YXJ0IHRhZyB3ZSB3YW50IHRvIHNldCB1cCB0aGVcclxuICAgICAgICAgICAgICogcmVnaW9uIG1hbmFnZXIuIFRoZSByZWdpb25hbCBtYW5hZ2VyIHRha2VzIGNhcmVcclxuICAgICAgICAgICAgICogb2YgYWxsIGl0ZW1zIGJldHdlZW4gaXQncyBzdGFydCBhbmQgZW5kIHRhZ3Mgd2hpbGUgdGhlXHJcbiAgICAgICAgICAgICAqIGZpbGUgbWFuYWdlciB3ZSBnb3QgYWJvdmUgYWJvdmUgdGFrZXMgY2FyZSBvZiBhbGwgcmVnaW9uYWwgXHJcbiAgICAgICAgICAgICAqIG1hbmFnZXJzIGluIGVhY2ggZmlsZS5cclxuICAgICAgICAgICAgICovXHJcbiAgICAgICAgICAgIGlmKG11bHRpQ29sdW1uUGFyc2VyLmNvbnRhaW5zU3RhcnRUYWcoZWwudGV4dENvbnRlbnQpKSB7XHJcblxyXG4gICAgICAgICAgICAgICAgLyoqIFxyXG4gICAgICAgICAgICAgICAgICogU2V0IHVwIHRoZSBjdXJyZW50IGVsZW1lbnQgdG8gYWN0IGFzIHRoZSBwYXJlbnQgZm9yIHRoZSBcclxuICAgICAgICAgICAgICAgICAqIG11bHRpLWNvbHVtbiByZWdpb24uXHJcbiAgICAgICAgICAgICAgICAgKi9cclxuICAgICAgICAgICAgICAgIGVsLmlkID0gYFR3b0NvbHVtbkNvbnRhaW5lci0ke2dldFVJRCgpfWBcclxuICAgICAgICAgICAgICAgIGVsLmNoaWxkcmVuWzBdLmRldGFjaCgpO1xyXG4gICAgICAgICAgICAgICAgZWwuY2xhc3NMaXN0LmFkZChcIm11bHRpQ29sdW1uQ29udGFpbmVyXCIpXHJcbiAgICAgICAgICAgICAgICBsZXQgcmVuZGVyRXJyb3JSZWdpb24gPSBlbC5jcmVhdGVEaXYoe1xyXG4gICAgICAgICAgICAgICAgICAgIGNsczogYG11bHRpQ29sdW1uRXJyb3JNZXNzYWdlYCxcclxuICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgICAgbGV0IHJlbmRlckNvbHVtblJlZ2lvbiA9IGVsLmNyZWF0ZURpdih7XHJcbiAgICAgICAgICAgICAgICAgICAgY2xzOiBgUmVuZGVyQ29sUmVnaW9uYFxyXG4gICAgICAgICAgICAgICAgfSlcclxuXHJcbiAgICAgICAgICAgICAgICBsZXQgc3RhcnRCbG9ja0RhdGEgPSBtdWx0aUNvbHVtblBhcnNlci5nZXRTdGFydEJsb2NrQWJvdmVMaW5lKGxpbmVzT2ZFbGVtZW50KVxyXG4gICAgICAgICAgICAgICAgbGV0IHJlZ2lvbktleSA9IHN0YXJ0QmxvY2tEYXRhLnN0YXJ0QmxvY2tLZXk7XHJcbiAgICAgICAgICAgICAgICBpZihmaWxlRE9NTWFuYWdlci5jaGVja0tleUV4aXN0cyhyZWdpb25LZXkpID09PSB0cnVlKSB7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIGxldCB7IG51bWJlck9mVGFncywga2V5cyB9ID0gbXVsdGlDb2x1bW5QYXJzZXIuY291bnRTdGFydFRhZ3MoaW5mby50ZXh0KTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgbGV0IGluZGV4ID0gMDtcclxuICAgICAgICAgICAgICAgICAgICBmb3IoOyBpbmRleCA8IG51bWJlck9mVGFnczsgaW5kZXgrKykge1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gQmVjYXVzZSB3ZSBjaGVja2VkIGlmIGtleSBleGlzdHMgb25lIG9mIHRoZXNlIGhhcyB0byBtYXRjaC5cclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYoa2V5c1tpbmRleF0gPT09IHJlZ2lvbktleSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIGlmKGtleXNbaW5kZXhdID09PSBcIlwiICkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICByZW5kZXJFcnJvclJlZ2lvbi5pbm5lclRleHQgPSBcIkZvdW5kIG11bHRpcGxlIHJlZ2lvbnMgd2l0aCBlbXB0eSBJRHMuIFBsZWFzZSBzZXQgYSB1bmlxdWUgSUQgYWZ0ZXIgZWFjaCBzdGFydCB0YWcuXFxuRUc6ICc9PT0gbXVsdGktY29sdW1uLXN0YXJ0OiByYW5kb21JRCdcXG5PciB1c2UgJ0ZpeCBNaXNzaW5nIElEcycgaW4gdGhlIGNvbW1hbmQgcGFsZXR0ZSBhbmQgcmVsb2FkIHRoZSBkb2N1bWVudC5cIlxyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgcmVuZGVyRXJyb3JSZWdpb24uaW5uZXJUZXh0ID0gXCJSZWdpb24gSUQgYWxyZWFkeSBleGlzdHMgaW4gZG9jdW1lbnQsIHBsZWFzZSBzZXQgYSB1bmlxdWUgSUQuXFxuRUc6ICc9PT0gbXVsdGktY29sdW1uLXN0YXJ0OiByYW5kb21JRCdcIlxyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIGxldCBlbGVtZW50TWFya2Rvd25SZW5kZXJlciA9IG5ldyBNYXJrZG93blJlbmRlckNoaWxkKGVsKTtcclxuICAgICAgICAgICAgICAgIGZpbGVET01NYW5hZ2VyLmNyZWF0ZVJlZ2lvbmFsTWFuYWdlcihyZWdpb25LZXksIHJlbmRlckVycm9yUmVnaW9uLCByZW5kZXJDb2x1bW5SZWdpb24pO1xyXG4gICAgICAgICAgICAgICAgZWxlbWVudE1hcmtkb3duUmVuZGVyZXIub251bmxvYWQgPSAoKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYoZmlsZURPTU1hbmFnZXIpIHtcclxuICAgIFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBmaWxlRE9NTWFuYWdlci5yZW1vdmVSZWdpb24oc3RhcnRCbG9ja0RhdGEuc3RhcnRCbG9ja0tleSk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfTtcclxuICAgICAgICAgICAgICAgIGN0eC5hZGRDaGlsZChlbGVtZW50TWFya2Rvd25SZW5kZXJlcik7XHJcblxyXG4gICAgICAgICAgICAgICAgLyoqXHJcbiAgICAgICAgICAgICAgICAgKiBOb3cgd2UgaGF2ZSBjcmVhdGVkIG91ciByZWdpb25hbCBtYW5hZ2VyIGFuZCBkZWZpbmVkIHdoYXQgZWxlbWVudHMgXHJcbiAgICAgICAgICAgICAgICAgKiBuZWVkIHRvIGJlIHJlbmRlcmVkIGludG8uIFNvIHdlIGNhbiByZXR1cm4gd2l0aG91dCBhbnkgbW9yZSBwcm9jZXNzaW5nLlxyXG4gICAgICAgICAgICAgICAgICovXHJcbiAgICAgICAgICAgICAgICByZXR1cm5cclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgLyoqXHJcbiAgICAgICAgICAgICAqIEdldCBhIGxpc3Qgb2YgYWxsIG9mIHRoZSBsaW5lcyBhYm92ZSBvdXIgY3VycmVudCBlbGVtZW50LlxyXG4gICAgICAgICAgICAgKiBXZSB3aWxsIHVzZSB0aGlzIHRvIGRldGVybWluZSBpZiB0aGUgZWxlbWVudCBpcyB3aXRoaW4gYSBibG9jayBzb1xyXG4gICAgICAgICAgICAgKiB3ZSBjYW4gb3RoZXJ3aXNlIGlnbm9yZSB0aGUgZWxlbWVudCBhbmQga2VlcCBjb21wdXRlIHRpbWUgZG93bi5cclxuICAgICAgICAgICAgICovXHJcbiAgICAgICAgICAgIGxldCBsaW5lc0Fib3ZlQXJyYXkgPSBpbmZvLnRleHQuc3BsaXQoXCJcXG5cIikuc2xpY2UoMCwgaW5mby5saW5lU3RhcnQpXHJcbiAgICAgICAgICAgIGxldCB0ZXh0QWJvdmVBcnJheSA9IGxpbmVzQWJvdmVBcnJheS5yZWR1Y2UoKHByZXYsIGN1cnIpID0+IHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBwcmV2ICsgXCJcXG5cIiArIGN1cnJcclxuICAgICAgICAgICAgfSwgXCJcIilcclxuXHJcbiAgICAgICAgICAgIC8qKlxyXG4gICAgICAgICAgICAgKiBBIGxpbmUgYWJvdmUgdXMgY29udGFpbnMgYSBzdGFydCB0YWcgbm93IHNlZSBpZiB3ZSdyZSB3aXRoaW4gdGhhdFxyXG4gICAgICAgICAgICAgKiBibG9jay5cclxuICAgICAgICAgICAgICovXHJcbiAgICAgICAgICAgIGxldCBzdGFydEJvY2tBYm92ZSA9IG11bHRpQ29sdW1uUGFyc2VyLmdldFN0YXJ0QmxvY2tBYm92ZUxpbmUobGluZXNBYm92ZUFycmF5KTtcclxuICAgICAgICAgICAgaWYoc3RhcnRCb2NrQWJvdmUgPT0gbnVsbCkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIFxyXG4gICAgICAgICAgICAvKipcclxuICAgICAgICAgICAgICogSGVyZSB3ZSBub3cga25vdyB3ZSdyZSB3aXRoaW4gYSByZWdpb25hbCBibG9jay5cclxuICAgICAgICAgICAgICovXHJcblxyXG4gICAgICAgICAgICAvLyBOb3cgd2Ugb25seSB3YW50IHRvIHdvcmsgd2l0aCB0aGUgbGluZXMgd2l0aGluIHRoZSBjdXJyZW50IHJlZ2lvbi5cclxuICAgICAgICAgICAgbGluZXNBYm92ZUFycmF5ID0gc3RhcnRCb2NrQWJvdmUubGluZXNBYm92ZUFycmF5O1xyXG4gICAgICAgICAgICBsZXQgcmVnaW9uYWxNYW5hZ2VyOiBSZWdpb25ET01NYW5hZ2VyID0gZmlsZURPTU1hbmFnZXIuZ2V0UmVnaW9uYWxNYW5hZ2VyKHN0YXJ0Qm9ja0Fib3ZlLnN0YXJ0QmxvY2tLZXkpO1xyXG5cclxuICAgICAgICAgICAgLyoqXHJcbiAgICAgICAgICAgICAqIElmIHdlIGNhbiBub3QgZ2V0IHRoZSBzdGFydCBibG9jayBhbmQgdGhpcyByZWdpb24ncyBkb20gbWFuYWdlciBcclxuICAgICAgICAgICAgICogd2UgY2FuIG5vdCBjb250aW51ZSBzb21ldGhpbmcgaGFzIGdvbmUgd3JvbmcuXHJcbiAgICAgICAgICAgICAqL1xyXG4gICAgICAgICAgICBpZihyZWdpb25hbE1hbmFnZXIgPT09IG51bGwpIHtcclxuICAgICAgICAgICAgICAgIHJldHVyblxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIFxyXG4gICAgICAgICAgICAvKipcclxuICAgICAgICAgICAgICogTm93IHdlIHRha2UgdGhlIGxpbmVzIGFib3ZlIG91ciBjdXJyZW50IGVsZW1lbnQgdXAgdW50aWwgdGhlXHJcbiAgICAgICAgICAgICAqIHN0YXJ0IHJlZ2lvbiB0YWcgYW5kIHJlbmRlciB0aGF0IGludG8gYW4gSFRNTCBlbGVtZW50LiBXZSB3aWxsIFxyXG4gICAgICAgICAgICAgKiB1c2UgdGhpcyBlbGVtZW50IHRvIGRldGVybWluZSB3aGVyZSB0byBwbGFjZSBvdXIgY3VycmVudCBlbGVtZW50LlxyXG4gICAgICAgICAgICAgKi9cclxuICAgICAgICAgICAgbGV0IHNpYmxpbmdzQWJvdmU6IEhUTUxEaXZFbGVtZW50ID0gZmluZFNpYmxpbmdzQWJvdmVFbChsaW5lc0Fib3ZlQXJyYXksIHNvdXJjZVBhdGgpO1xyXG5cclxuICAgICAgICAgICAgLyoqXHJcbiAgICAgICAgICAgICAqIFNldCB1cCBvdXIgZG9tIG9iamVjdCB0byBiZSBhZGRlZCB0byB0aGUgbWFuYWdlci5cclxuICAgICAgICAgICAgICovXHJcbiAgICAgICAgICAgIGxldCBjdXJyZW50T2JqZWN0OiBET01PYmplY3QgPSBuZXcgRE9NT2JqZWN0KGVsZW1lbnRUZXh0LCBlbClcclxuXHJcbiAgICAgICAgICAgIC8qKlxyXG4gICAgICAgICAgICAgKiBOb3cgd2UgYWRkIHRoZSBvYmplY3QgdG8gdGhlIG1hbmFnZXIgYW5kIHRoZW4gc2V0dXAgdGhlXHJcbiAgICAgICAgICAgICAqIGNhbGxiYWNrIGZvciB3aGVuIHRoZSBvYmplY3QgaXMgcmVtb3ZlZCBmcm9tIHZpZXcgdGhhdCB3aWxsIHJlbW92ZSBcclxuICAgICAgICAgICAgICogdGhlIGl0ZW0gZnJvbSB0aGUgbWFuYWdlci5cclxuICAgICAgICAgICAgICovXHJcbiAgICAgICAgICAgIHJlZ2lvbmFsTWFuYWdlci5hZGRPYmplY3Qoc2libGluZ3NBYm92ZSwgY3VycmVudE9iamVjdCk7XHJcblxyXG4gICAgICAgICAgICBsZXQgZWxlbWVudE1hcmtkb3duUmVuZGVyZXIgPSBuZXcgTWFya2Rvd25SZW5kZXJDaGlsZChlbCk7XHJcbiAgICAgICAgICAgIGVsZW1lbnRNYXJrZG93blJlbmRlcmVyLm9udW5sb2FkID0gKCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgaWYocmVnaW9uYWxNYW5hZ2VyKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgXHJcbiAgICAgICAgICAgICAgICAgICAgLy8gV2UgY2FuIGF0dGVtcHQgdG8gdXBkYXRlIHRoZSB2aWV3IGhlcmUgYWZ0ZXIgdGhlIGl0ZW0gaXMgcmVtb3ZlZFxyXG4gICAgICAgICAgICAgICAgICAgIC8vIGJ1dCBuZWVkIHRvIGdldCB0aGUgaXRlbSdzIHBhcmVudCBlbGVtZW50IGJlZm9yZSByZW1vdmluZyBvYmplY3QgZnJvbSBtYW5hZ2VyLlxyXG4gICAgICAgICAgICAgICAgICAgIGxldCByZWdpb25SZW5kZXJEYXRhOiBNdWx0aUNvbHVtblJlbmRlckRhdGEgPSByZWdpb25hbE1hbmFnZXIuZ2V0UmVnaW9uUmVuZGVyRGF0YSgpO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICByZWdpb25hbE1hbmFnZXIucmVtb3ZlT2JqZWN0KGN1cnJlbnRPYmplY3QuVUlEKTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgLyoqXHJcbiAgICAgICAgICAgICAgICAgICAgICogTmVlZCB0byBjaGVjayBoZXJlIGlmIGVsZW1lbnQgaXMgbnVsbCBhcyB0aGlzIGNsb3N1cmUgd2lsbCBiZSBjYWxsZWRcclxuICAgICAgICAgICAgICAgICAgICAgKiByZXBlYXRlZGx5IG9uIGZpbGUgY2hhbmdlLlxyXG4gICAgICAgICAgICAgICAgICAgICAqL1xyXG4gICAgICAgICAgICAgICAgICAgIGlmKHJlZ2lvblJlbmRlckRhdGEucGFyZW50UmVuZGVyRWxlbWVudCA9PT0gbnVsbCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMucmVuZGVyQ29sdW1uTWFya2Rvd24ocmVnaW9uUmVuZGVyRGF0YS5wYXJlbnRSZW5kZXJFbGVtZW50LCByZWdpb25SZW5kZXJEYXRhLmRvbU9iamVjdHMsIHJlZ2lvblJlbmRlckRhdGEucGFyZW50UmVuZGVyU2V0dGluZ3MpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9O1xyXG4gICAgICAgICAgICBjdHguYWRkQ2hpbGQoZWxlbWVudE1hcmtkb3duUmVuZGVyZXIpO1xyXG5cclxuICAgICAgICAgICAgLyoqXHJcbiAgICAgICAgICAgICAqIE5vdyB3ZSBjaGVjayBpZiBvdXIgY3VycmVudCBlbGVtZW50IGlzIGEgc3BlY2lhbCBmbGFnIHNvIHdlIGNhblxyXG4gICAgICAgICAgICAgKiBwcm9wZXJseSBzZXQgdGhlIGVsZW1lbnQgdGFnIHdpdGhpbiB0aGUgcmVnaW9uYWwgbWFuYWdlci5cclxuICAgICAgICAgICAgICovXHJcbiAgICAgICAgICAgIGlmKG11bHRpQ29sdW1uUGFyc2VyLmNvbnRhaW5zRW5kVGFnKGVsLnRleHRDb250ZW50KSA9PT0gdHJ1ZSkge1xyXG5cclxuICAgICAgICAgICAgICAgIHJlZ2lvbmFsTWFuYWdlci51cGRhdGVFbGVtZW50VGFnKGN1cnJlbnRPYmplY3QuVUlELCBET01PYmplY3RUYWcuZW5kUmVnaW9uKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBlbHNlIGlmKG11bHRpQ29sdW1uUGFyc2VyLmNvbnRhaW5zQ29sRW5kVGFnKGVsZW1lbnRUZXh0U3BhY2VkKSA9PT0gdHJ1ZSkge1xyXG5cclxuICAgICAgICAgICAgICAgIHJlZ2lvbmFsTWFuYWdlci51cGRhdGVFbGVtZW50VGFnKGN1cnJlbnRPYmplY3QuVUlELCBET01PYmplY3RUYWcuY29sdW1uQnJlYWspO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGVsc2UgaWYobXVsdGlDb2x1bW5QYXJzZXIuY29udGFpbnNDb2xTZXR0aW5nc1RhZyhlbGVtZW50VGV4dFNwYWNlZCkgPT09IHRydWUpIHtcclxuXHJcbiAgICAgICAgICAgICAgICByZWdpb25hbE1hbmFnZXIuc2V0RWxlbWVudFRvU2V0dGluZ3NCbG9jayhjdXJyZW50T2JqZWN0LlVJRCwgZWxlbWVudFRleHRTcGFjZWQpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIFxyXG4gICAgICAgICAgICAvKipcclxuICAgICAgICAgICAgICogVXNlIG91ciByZWdpb25hbCBtYW5hZ2VyIHRvIGdldCBldmVyeXRoaW5nIG5lZWRlZCB0byByZW5kZXIgdGhlIHJlZ2lvbi5cclxuICAgICAgICAgICAgICovXHJcbiAgICAgICAgICAgIGxldCBwYXJlbnRFbGVtZW50RGF0YTogTXVsdGlDb2x1bW5SZW5kZXJEYXRhID0gcmVnaW9uYWxNYW5hZ2VyLmdldFJlZ2lvblJlbmRlckRhdGEoKTtcclxuICAgIFxyXG4gICAgICAgICAgICAvKipcclxuICAgICAgICAgICAgICogV2Ugd2FudCB0byBoaWRlIGFsbCBvZiB0aGUgb3JpZ2luYWwgZWxlbWVudHMgdGhhdCBhcmUgbm93IGdvaW5nIHRvIGJlXHJcbiAgICAgICAgICAgICAqIHJlbmRlcmVkIHdpdGhpbiBvdXIgbXV0bGktY29sdW1uIHJlZ2lvblxyXG4gICAgICAgICAgICAgKi9cclxuICAgICAgICAgICAgZWwuYWRkQ2xhc3MoXCJtdWx0aUNvbHVtbkRhdGFIaWRkZW5cIik7XHJcblxyXG4gICAgICAgICAgICB0aGlzLnJlbmRlckNvbHVtbk1hcmtkb3duKHBhcmVudEVsZW1lbnREYXRhLnBhcmVudFJlbmRlckVsZW1lbnQsIHBhcmVudEVsZW1lbnREYXRhLmRvbU9iamVjdHMsIHBhcmVudEVsZW1lbnREYXRhLnBhcmVudFJlbmRlclNldHRpbmdzKTtcclxuXHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFRoaXMgZnVuY3Rpb24gdGFrZXMgaW4gdGhlIGRhdGEgZm9yIHRoZSBtdWx0aS1jb2x1bW4gcmVnaW9uIGFuZCBzZXRzIHVwIHRoZSBcclxuICAgICAqIHVzZXIgZGVmaW5lZCBudW1iZXIgb2YgY2hpbGRyZW4gd2l0aCB0aGUgcHJvcGVyIGNzcyBjbGFzc2VzIHRvIGJlIHJlbmRlcmVkIHByb3Blcmx5LlxyXG4gICAgICogXHJcbiAgICAgKiBAcGFyYW0gcGFyZW50RWxlbWVudCBUaGUgZWxlbWVudCB0aGF0IHRoZSBtdWx0aS1jb2x1bW4gcmVnaW9uIHdpbGwgYmUgcmVuZGVyZWQgdW5kZXIuXHJcbiAgICAgKiBAcGFyYW0gcmVnaW9uRWxlbWVudHMgVGhlIGxpc3Qgb2YgRE9NIG9iamVjdHMgdGhhdCB3aWxsIGJlIGNvcHBpZWQgdW5kZXIgdGhlIHBhcmVudCBvYmplY3RcclxuICAgICAqIEBwYXJhbSBzZXR0aW5ncyBUaGUgc2V0dGluZ3MgdGhlIHVzZXIgaGFzIGRlZmluZWQgZm9yIHRoZSByZWdpb24uXHJcbiAgICAgKi9cclxuICAgIHJlbmRlckNvbHVtbk1hcmtkb3duKHBhcmVudEVsZW1lbnQ6IEhUTUxFbGVtZW50LCByZWdpb25FbGVtZW50czogRE9NT2JqZWN0W10sIHNldHRpbmdzOiBNdWx0aUNvbHVtblNldHRpbmdzKSB7XHJcblxyXG4gICAgICAgIGxldCBtdWx0aUNvbHVtblBhcmVudCA9IGNyZWF0ZURpdih7XHJcbiAgICAgICAgICAgIGNsczogYG11bHRpQ29sdW1uUGFyZW50IHJvd0NgLFxyXG4gICAgICAgIH0pO1xyXG4gICAgICAgIGlmKHNldHRpbmdzLmRyYXdTaGFkb3cgPT09IHRydWUpIHtcclxuICAgICAgICAgICAgbXVsdGlDb2x1bW5QYXJlbnQuYWRkQ2xhc3MoXCJtdWx0aUNvbHVtblBhcmVudFNoYWRvd1wiKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8qKlxyXG4gICAgICAgICAqIFBhc3Mgb3VyIHBhcmVudCBkaXYgYW5kIHNldHRpbmdzIHRvIHBhcnNlciB0byBjcmVhdGUgdGhlIHJlcXVpcmVkXHJcbiAgICAgICAgICogY29sdW1uIGRpdnMgYXMgY2hpbGRyZW4gb2YgdGhlIHBhcmVudC5cclxuICAgICAgICAgKi9cclxuICAgICAgICBsZXQgY29sdW1uQ29udGVudERpdnMgPSBnZXRDb2x1bW5Db250ZW50RGl2cyhzZXR0aW5ncywgbXVsdGlDb2x1bW5QYXJlbnQpO1xyXG4gICAgICAgIGZvcihsZXQgaSA9IDA7IGkgPCBjb2x1bW5Db250ZW50RGl2cy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICBpZihzZXR0aW5ncy5kcmF3Qm9yZGVyID09PSB0cnVlKSB7XHJcbiAgICAgICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2c1tpXS5hZGRDbGFzcyhcImNvbHVtbkJvcmRlclwiKTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgaWYoc2V0dGluZ3MuZHJhd1NoYWRvdyA9PT0gdHJ1ZSkge1xyXG4gICAgICAgICAgICAgICAgY29sdW1uQ29udGVudERpdnNbaV0uYWRkQ2xhc3MoXCJjb2x1bW5TaGFkb3dcIik7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIENyZWF0ZSBtYXJrZG93biByZW5kZXJlciB0byBwYXJzZSB0aGUgcGFzc2VkIG1hcmtkb3duXHJcbiAgICAgICAgLy8gYmV0d2VlbiB0aGUgdGFncy5cclxuICAgICAgICBsZXQgbWFya2Rvd25SZW5kZXJDaGlsZCA9IG5ldyBNYXJrZG93blJlbmRlckNoaWxkKFxyXG4gICAgICAgICAgICBtdWx0aUNvbHVtblBhcmVudFxyXG4gICAgICAgICk7XHJcblxyXG4gICAgICAgIC8vIFJlbW92ZSBldmVyeSBvdGhlciBjaGlsZCBmcm9tIHRoZSBwYXJlbnQgc28gXHJcbiAgICAgICAgLy8gd2UgZG9udCBlbmQgdXAgd2l0aCBtdWx0aXBsZSBzZXRzIG9mIGRhdGEuIFRoaXMgc2hvdWxkXHJcbiAgICAgICAgLy8gcmVhbGx5IG9ubHkgbmVlZCB0byBsb29wIG9uY2UgZm9yIGkgPSAwIGJ1dCBsb29wIGp1c3RcclxuICAgICAgICAvLyBpbiBjYXNlLlxyXG4gICAgICAgIGZvcihsZXQgaSA9IHBhcmVudEVsZW1lbnQuY2hpbGRyZW4ubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcclxuICAgICAgICAgICAgcGFyZW50RWxlbWVudC5jaGlsZHJlbltpXS5kZXRhY2goKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgcGFyZW50RWxlbWVudC5hcHBlbmRDaGlsZChtYXJrZG93blJlbmRlckNoaWxkLmNvbnRhaW5lckVsKTtcclxuXHJcbiAgICAgICAgbGV0IGNvbHVtbkluZGV4ID0gMDtcclxuICAgICAgICBmb3IobGV0IGkgPSAwOyBpIDwgcmVnaW9uRWxlbWVudHMubGVuZ3RoOyBpKyspIHtcclxuXHJcbiAgICAgICAgICAgIC8vIFdlIHdhbnQgdG8gc2tpcCBjb2x1bW4gYnJlYWsgdGFncyBidXQgb25seSBpZiB3ZSBoYXZlIGNvbHVtbnMgXHJcbiAgICAgICAgICAgIC8vIGxlZnQgdG8gZW50ZXIgZGF0YSBmb3IuXHJcbiAgICAgICAgICAgIGlmKHJlZ2lvbkVsZW1lbnRzW2ldLnRhZyA9PT0gRE9NT2JqZWN0VGFnLmNvbHVtbkJyZWFrICYmIFxyXG4gICAgICAgICAgICAgICAoY29sdW1uSW5kZXggKyAxKSA8IHNldHRpbmdzLm51bWJlck9mQ29sdW1ucykge1xyXG5cclxuICAgICAgICAgICAgICAgIGNvbHVtbkluZGV4Kys7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgZWxzZSBpZiAocmVnaW9uRWxlbWVudHNbaV0udGFnICE9PSBET01PYmplY3RUYWcuc3RhcnRSZWdpb24gJiYgXHJcbiAgICAgICAgICAgICAgICAgICAgIHJlZ2lvbkVsZW1lbnRzW2ldLnRhZyAhPT0gRE9NT2JqZWN0VGFnLmVuZFJlZ2lvbiAmJiBcclxuICAgICAgICAgICAgICAgICAgICAgcmVnaW9uRWxlbWVudHNbaV0udGFnICE9PSBET01PYmplY3RUYWcucmVnaW9uU2V0dGluZ3MpIHtcclxuXHJcbiAgICAgICAgICAgICAgICAvKipcclxuICAgICAgICAgICAgICAgICAqIE1ha2UgYSBkZWVwIGNvcHkgb2YgdGhlIGVsZW1lbnQgc28gd2UgY2FuIHJlbW92ZSB0aGUgaGlkZGVuIGNsYXNzIGJlZm9yZVxyXG4gICAgICAgICAgICAgICAgICogYXBwZW5kaW5nIHRvIG91ciBjb2x1bW4gZGl2LlxyXG4gICAgICAgICAgICAgICAgICovXHJcbiAgICAgICAgICAgICAgICBsZXQgY2xvbmVkRWxlbWVudCA9IHJlZ2lvbkVsZW1lbnRzW2ldLmVsZW1lbnQuY2xvbmVOb2RlKHRydWUpIGFzIEhUTUxFbGVtZW50O1xyXG4gICAgICAgICAgICAgICAgY2xvbmVkRWxlbWVudC5yZW1vdmVDbGFzcyhcIm11bHRpQ29sdW1uRGF0YUhpZGRlblwiKTtcclxuICAgICAgICAgICAgICAgIGNsb25lZEVsZW1lbnQuc3R5bGUuZGlzcGxheSA9IFwiYmxvY2tcIlxyXG5cclxuICAgICAgICAgICAgICAgIGNvbHVtbkNvbnRlbnREaXZzW2NvbHVtbkluZGV4XS5hcHBlbmRDaGlsZChjbG9uZWRFbGVtZW50KTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgIH1cclxufVxyXG5cclxuLyoqXHJcbiAqIFNldHMgdXAgdGhlIENTUyBjbGFzc2VzIGFuZCB0aGUgbnVtYmVyIG9mIGNvbHVtbnMgYmFzZWQgb24gdGhlIHBhc3NlZCBzZXR0aW5ncy5cclxuICogQHBhcmFtIHNldHRpbmdzIFRoZSB1c2VyIGRlZmluZWQgc2V0dGluZ3MgdGhhdCBkZXRlcm1pbmUgd2hhdCBDU1MgaXMgc2V0IGhlcmUuXHJcbiAqIEBwYXJhbSBtdWx0aUNvbHVtblBhcmVudCBUaGUgcGFyZW50IG9iamVjdCB0aGF0IHRoZSBjb2x1bW4gZGl2cyB3aWxsIGJlIGNyZWF0ZWQgdW5kZXIuXHJcbiAqIEByZXR1cm5zIFRoZSBsaXN0IG9mIGNvbHVtbiBkaXZzIGNyZWF0ZWQgdW5kZXIgdGhlIHBhc3NlZCBwYXJlbnQgZWxlbWVudC5cclxuICovXHJcbmZ1bmN0aW9uIGdldENvbHVtbkNvbnRlbnREaXZzKHNldHRpbmdzOiBNdWx0aUNvbHVtblNldHRpbmdzLCBtdWx0aUNvbHVtblBhcmVudDogSFRNTERpdkVsZW1lbnQpOiBIVE1MRGl2RWxlbWVudFtdIHtcclxuXHJcbiAgICBsZXQgY29sdW1uQ29udGVudERpdnM6IEhUTUxEaXZFbGVtZW50W10gPSBbXVxyXG4gICAgaWYoc2V0dGluZ3MubnVtYmVyT2ZDb2x1bW5zID09PSAyKSB7XHJcblxyXG4gICAgICAgIHN3aXRjaChzZXR0aW5ncy5jb2x1bW5MYXlvdXQpIHtcclxuICAgICAgICAgICAgY2FzZShDb2x1bW5MYXlvdXQuc3RhbmRhcmQpOlxyXG4gICAgICAgICAgICBjYXNlKENvbHVtbkxheW91dC5taWRkbGUpOlxyXG4gICAgICAgICAgICBjYXNlKENvbHVtbkxheW91dC5jZW50ZXIpOlxyXG4gICAgICAgICAgICBjYXNlKENvbHVtbkxheW91dC50aGlyZCk6XHJcbiAgICAgICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2cy5wdXNoKG11bHRpQ29sdW1uUGFyZW50LmNyZWF0ZURpdih7XHJcbiAgICAgICAgICAgICAgICAgICAgY2xzOiBgY29sdW1uQ29udGVudCB0d29FcXVhbENvbHVtbnNfTGVmdGBcclxuICAgICAgICAgICAgICAgIH0pKTtcclxuICAgICAgICAgICAgICAgIGNvbHVtbkNvbnRlbnREaXZzLnB1c2gobXVsdGlDb2x1bW5QYXJlbnQuY3JlYXRlRGl2KHtcclxuICAgICAgICAgICAgICAgICAgICBjbHM6IGBjb2x1bW5Db250ZW50IHR3b0VxdWFsQ29sdW1uc19SaWdodGBcclxuICAgICAgICAgICAgICAgIH0pKTtcclxuICAgICAgICAgICAgICAgIGJyZWFrO1xyXG5cclxuICAgICAgICAgICAgY2FzZShDb2x1bW5MYXlvdXQubGVmdCk6XHJcbiAgICAgICAgICAgIGNhc2UoQ29sdW1uTGF5b3V0LmZpcnN0KTpcclxuICAgICAgICAgICAgICAgIGNvbHVtbkNvbnRlbnREaXZzLnB1c2gobXVsdGlDb2x1bW5QYXJlbnQuY3JlYXRlRGl2KHtcclxuICAgICAgICAgICAgICAgICAgICBjbHM6IGBjb2x1bW5Db250ZW50IHR3b0NvbHVtbnNIZWF2eUxlZnRfTGVmdGBcclxuICAgICAgICAgICAgICAgIH0pKTtcclxuICAgICAgICAgICAgICAgIGNvbHVtbkNvbnRlbnREaXZzLnB1c2gobXVsdGlDb2x1bW5QYXJlbnQuY3JlYXRlRGl2KHtcclxuICAgICAgICAgICAgICAgICAgICBjbHM6IGBjb2x1bW5Db250ZW50IHR3b0NvbHVtbnNIZWF2eUxlZnRfUmlnaHRgXHJcbiAgICAgICAgICAgICAgICB9KSk7XHJcbiAgICAgICAgICAgICAgICBicmVhaztcclxuXHJcbiAgICAgICAgICAgIGNhc2UoQ29sdW1uTGF5b3V0LnJpZ2h0KTpcclxuICAgICAgICAgICAgY2FzZShDb2x1bW5MYXlvdXQuc2Vjb25kKTpcclxuICAgICAgICAgICAgY2FzZShDb2x1bW5MYXlvdXQubGFzdCk6XHJcbiAgICAgICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2cy5wdXNoKG11bHRpQ29sdW1uUGFyZW50LmNyZWF0ZURpdih7XHJcbiAgICAgICAgICAgICAgICAgICAgY2xzOiBgY29sdW1uQ29udGVudCB0d29Db2x1bW5zSGVhdnlSaWdodF9MZWZ0YFxyXG4gICAgICAgICAgICAgICAgfSkpO1xyXG4gICAgICAgICAgICAgICAgY29sdW1uQ29udGVudERpdnMucHVzaChtdWx0aUNvbHVtblBhcmVudC5jcmVhdGVEaXYoe1xyXG4gICAgICAgICAgICAgICAgICAgIGNsczogYGNvbHVtbkNvbnRlbnQgdHdvQ29sdW1uc0hlYXZ5UmlnaHRfUmlnaHRgXHJcbiAgICAgICAgICAgICAgICB9KSk7XHJcbiAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICB9XHJcbiAgICB9XHJcbiAgICBlbHNlIGlmKHNldHRpbmdzLm51bWJlck9mQ29sdW1ucyA9PT0gMykge1xyXG5cclxuICAgICAgICBzd2l0Y2goc2V0dGluZ3MuY29sdW1uTGF5b3V0KSB7XHJcbiAgICAgICAgICAgIGNhc2UoQ29sdW1uTGF5b3V0LnN0YW5kYXJkKTpcclxuICAgICAgICAgICAgICAgIGNvbHVtbkNvbnRlbnREaXZzLnB1c2gobXVsdGlDb2x1bW5QYXJlbnQuY3JlYXRlRGl2KHtcclxuICAgICAgICAgICAgICAgICAgICBjbHM6IGBjb2x1bW5Db250ZW50IHRocmVlRXF1YWxDb2x1bW5zX0xlZnRgXHJcbiAgICAgICAgICAgICAgICB9KSk7XHJcbiAgICAgICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2cy5wdXNoKG11bHRpQ29sdW1uUGFyZW50LmNyZWF0ZURpdih7XHJcbiAgICAgICAgICAgICAgICAgICAgY2xzOiBgY29sdW1uQ29udGVudCB0aHJlZUVxdWFsQ29sdW1uc19NaWRkbGVgXHJcbiAgICAgICAgICAgICAgICB9KSk7XHJcbiAgICAgICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2cy5wdXNoKG11bHRpQ29sdW1uUGFyZW50LmNyZWF0ZURpdih7XHJcbiAgICAgICAgICAgICAgICAgICAgY2xzOiBgY29sdW1uQ29udGVudCB0aHJlZUVxdWFsQ29sdW1uc19SaWdodGBcclxuICAgICAgICAgICAgICAgIH0pKTtcclxuICAgICAgICAgICAgICAgIGJyZWFrO1xyXG5cclxuICAgICAgICAgICAgY2FzZShDb2x1bW5MYXlvdXQubGVmdCk6XHJcbiAgICAgICAgICAgIGNhc2UoQ29sdW1uTGF5b3V0LmZpcnN0KTpcclxuICAgICAgICAgICAgICAgIGNvbHVtbkNvbnRlbnREaXZzLnB1c2gobXVsdGlDb2x1bW5QYXJlbnQuY3JlYXRlRGl2KHtcclxuICAgICAgICAgICAgICAgICAgICBjbHM6IGBjb2x1bW5Db250ZW50IHRocmVDb2x1bW5zSGVhdnlMZWZ0X0xlZnRgXHJcbiAgICAgICAgICAgICAgICB9KSk7XHJcbiAgICAgICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2cy5wdXNoKG11bHRpQ29sdW1uUGFyZW50LmNyZWF0ZURpdih7XHJcbiAgICAgICAgICAgICAgICAgICAgY2xzOiBgY29sdW1uQ29udGVudCB0aHJlQ29sdW1uc0hlYXZ5TGVmdF9NaWRkbGVgXHJcbiAgICAgICAgICAgICAgICB9KSk7XHJcbiAgICAgICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2cy5wdXNoKG11bHRpQ29sdW1uUGFyZW50LmNyZWF0ZURpdih7XHJcbiAgICAgICAgICAgICAgICAgICAgY2xzOiBgY29sdW1uQ29udGVudCB0aHJlQ29sdW1uc0hlYXZ5TGVmdF9SaWdodGBcclxuICAgICAgICAgICAgICAgIH0pKTtcclxuICAgICAgICAgICAgICAgIGJyZWFrO1xyXG5cclxuICAgICAgICAgICAgY2FzZShDb2x1bW5MYXlvdXQubWlkZGxlKTpcclxuICAgICAgICAgICAgY2FzZShDb2x1bW5MYXlvdXQuY2VudGVyKTpcclxuICAgICAgICAgICAgY2FzZShDb2x1bW5MYXlvdXQuc2Vjb25kKTpcclxuICAgICAgICAgICAgICAgIGNvbHVtbkNvbnRlbnREaXZzLnB1c2gobXVsdGlDb2x1bW5QYXJlbnQuY3JlYXRlRGl2KHtcclxuICAgICAgICAgICAgICAgICAgICBjbHM6IGBjb2x1bW5Db250ZW50IHRocmVDb2x1bW5zSGVhdnlNaWRkbGVfTGVmdGBcclxuICAgICAgICAgICAgICAgIH0pKTtcclxuICAgICAgICAgICAgICAgIGNvbHVtbkNvbnRlbnREaXZzLnB1c2gobXVsdGlDb2x1bW5QYXJlbnQuY3JlYXRlRGl2KHtcclxuICAgICAgICAgICAgICAgICAgICBjbHM6IGBjb2x1bW5Db250ZW50IHRocmVDb2x1bW5zSGVhdnlNaWRkbGVfTWlkZGxlYFxyXG4gICAgICAgICAgICAgICAgfSkpO1xyXG4gICAgICAgICAgICAgICAgY29sdW1uQ29udGVudERpdnMucHVzaChtdWx0aUNvbHVtblBhcmVudC5jcmVhdGVEaXYoe1xyXG4gICAgICAgICAgICAgICAgICAgIGNsczogYGNvbHVtbkNvbnRlbnQgdGhyZUNvbHVtbnNIZWF2eU1pZGRsZV9SaWdodGBcclxuICAgICAgICAgICAgICAgIH0pKTtcclxuICAgICAgICAgICAgICAgIGJyZWFrO1xyXG5cclxuICAgICAgICAgICAgY2FzZShDb2x1bW5MYXlvdXQucmlnaHQpOlxyXG4gICAgICAgICAgICBjYXNlKENvbHVtbkxheW91dC50aGlyZCk6XHJcbiAgICAgICAgICAgIGNhc2UoQ29sdW1uTGF5b3V0Lmxhc3QpOlxyXG4gICAgICAgICAgICAgICAgY29sdW1uQ29udGVudERpdnMucHVzaChtdWx0aUNvbHVtblBhcmVudC5jcmVhdGVEaXYoe1xyXG4gICAgICAgICAgICAgICAgICAgIGNsczogYGNvbHVtbkNvbnRlbnQgdGhyZUNvbHVtbnNIZWF2eVJpZ2h0X0xlZnRgXHJcbiAgICAgICAgICAgICAgICB9KSk7XHJcbiAgICAgICAgICAgICAgICBjb2x1bW5Db250ZW50RGl2cy5wdXNoKG11bHRpQ29sdW1uUGFyZW50LmNyZWF0ZURpdih7XHJcbiAgICAgICAgICAgICAgICAgICAgY2xzOiBgY29sdW1uQ29udGVudCB0aHJlQ29sdW1uc0hlYXZ5UmlnaHRfTWlkZGxlYFxyXG4gICAgICAgICAgICAgICAgfSkpO1xyXG4gICAgICAgICAgICAgICAgY29sdW1uQ29udGVudERpdnMucHVzaChtdWx0aUNvbHVtblBhcmVudC5jcmVhdGVEaXYoe1xyXG4gICAgICAgICAgICAgICAgICAgIGNsczogYGNvbHVtbkNvbnRlbnQgdGhyZUNvbHVtbnNIZWF2eVJpZ2h0X1JpZ2h0YFxyXG4gICAgICAgICAgICAgICAgfSkpO1xyXG4gICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBjb2x1bW5Db250ZW50RGl2cztcclxufVxyXG5cclxuXHJcbmV4cG9ydCB0eXBlIG5lYXJieVNpYmxpbmdzID0geyBcclxuICAgIHNpYmxpbmdzQWJvdmU6IEhUTUxEaXZFbGVtZW50LFxyXG4gICAgY3VycmVudE9iamVjdDogRE9NT2JqZWN0LCBcclxufVxyXG5mdW5jdGlvbiBmaW5kU2libGluZ3NBYm92ZUVsKGxpbmVzQWJvdmU6IHN0cmluZ1tdLCBzb3VyY2VQYXRoOiBzdHJpbmcpOiBIVE1MRGl2RWxlbWVudCB7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBXZSByZS1yZW5kZXIgYWxsIG9mIHRoZSBpdGVtcyBhYm92ZSBvdXIgZWxlbWVudCwgdW50aWwgdGhlIHN0YXJ0IHRhZywgXHJcbiAgICAgKiBzbyB3ZSBjYW4gZGV0ZXJtaW5lIHdoZXJlIHRvIHBsYWNlIHRoZSBuZXcgaXRlbSBpbiB0aGUgbWFuYWdlci5cclxuICAgICAqIFxyXG4gICAgICogVE9ETzogQ2FuIHJlZHVjZSB0aGUgYW1vdW50IG5lZWRpbmcgdG8gYmUgcmVuZGVyZWQgYnkgb25seSByZW5kZXJpbmcgdG9cclxuICAgICAqIHRoZSBzdGFydCB0YWcgb3IgYSBjb2x1bW4tYnJlYWsgd2hpY2hldmVyIGlzIGNsb3Nlci5cclxuICAgICAqL1xyXG4gICAgbGV0IHNpYmxpbmdzQWJvdmUgPSBjcmVhdGVEaXYoKTtcclxuICAgIGxldCBtYXJrZG93blJlbmRlckNoaWxkID0gbmV3IE1hcmtkb3duUmVuZGVyQ2hpbGQoXHJcbiAgICAgICAgc2libGluZ3NBYm92ZVxyXG4gICAgKTtcclxuICAgIE1hcmtkb3duUmVuZGVyZXIucmVuZGVyTWFya2Rvd24oXHJcbiAgICAgICAgbGluZXNBYm92ZS5yZWR1Y2UoKHByZXYsIGN1cnJlbnQpID0+IHtcclxuICAgICAgICAgICAgcmV0dXJuIHByZXYgKyBcIlxcblwiICArIGN1cnJlbnQ7XHJcbiAgICAgICAgfSwgXCJcIiksXHJcbiAgICAgICAgc2libGluZ3NBYm92ZSxcclxuICAgICAgICBzb3VyY2VQYXRoLFxyXG4gICAgICAgIG1hcmtkb3duUmVuZGVyQ2hpbGRcclxuICAgICk7XHJcblxyXG4gICAgcmV0dXJuIHNpYmxpbmdzQWJvdmU7XHJcbn0iXSwibmFtZXMiOlsiUGx1Z2luIiwiTm90aWNlIiwibXVsdGlDb2x1bW5QYXJzZXIuaXNTdGFydFRhZ1dpdGhJRCIsIm11bHRpQ29sdW1uUGFyc2VyLmNvbnRhaW5zU3RhcnRUYWciLCJtdWx0aUNvbHVtblBhcnNlci5nZXRTdGFydEJsb2NrQWJvdmVMaW5lIiwibXVsdGlDb2x1bW5QYXJzZXIuY291bnRTdGFydFRhZ3MiLCJNYXJrZG93blJlbmRlckNoaWxkIiwibXVsdGlDb2x1bW5QYXJzZXIuY29udGFpbnNFbmRUYWciLCJtdWx0aUNvbHVtblBhcnNlci5jb250YWluc0NvbEVuZFRhZyIsIm11bHRpQ29sdW1uUGFyc2VyLmNvbnRhaW5zQ29sU2V0dGluZ3NUYWciLCJNYXJrZG93blJlbmRlcmVyIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBdURBO0FBQ08sU0FBUyxTQUFTLENBQUMsT0FBTyxFQUFFLFVBQVUsRUFBRSxDQUFDLEVBQUUsU0FBUyxFQUFFO0FBQzdELElBQUksU0FBUyxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsT0FBTyxLQUFLLFlBQVksQ0FBQyxHQUFHLEtBQUssR0FBRyxJQUFJLENBQUMsQ0FBQyxVQUFVLE9BQU8sRUFBRSxFQUFFLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFO0FBQ2hILElBQUksT0FBTyxLQUFLLENBQUMsS0FBSyxDQUFDLEdBQUcsT0FBTyxDQUFDLEVBQUUsVUFBVSxPQUFPLEVBQUUsTUFBTSxFQUFFO0FBQy9ELFFBQVEsU0FBUyxTQUFTLENBQUMsS0FBSyxFQUFFLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxFQUFFLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRTtBQUNuRyxRQUFRLFNBQVMsUUFBUSxDQUFDLEtBQUssRUFBRSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxFQUFFLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRTtBQUN0RyxRQUFRLFNBQVMsSUFBSSxDQUFDLE1BQU0sRUFBRSxFQUFFLE1BQU0sQ0FBQyxJQUFJLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsR0FBRyxLQUFLLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsUUFBUSxDQUFDLENBQUMsRUFBRTtBQUN0SCxRQUFRLElBQUksQ0FBQyxDQUFDLFNBQVMsR0FBRyxTQUFTLENBQUMsS0FBSyxDQUFDLE9BQU8sRUFBRSxVQUFVLElBQUksRUFBRSxDQUFDLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztBQUM5RSxLQUFLLENBQUMsQ0FBQztBQUNQOztBQzdFQTs7Ozs7OztBQVFBLElBQVksWUFPWDtB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
|