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