matrix-react-sdk
Version:
SDK for matrix.org using React
360 lines (352 loc) • 62.5 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _react = _interopRequireWildcard(require("react"));
var React = _react;
var _classnames = _interopRequireDefault(require("classnames"));
var _dispatcher = _interopRequireDefault(require("../../dispatcher/dispatcher"));
var _languageHandler = require("../../languageHandler");
var _RoomList = _interopRequireDefault(require("../views/rooms/RoomList"));
var _LegacyCallHandler = _interopRequireDefault(require("../../LegacyCallHandler"));
var _RoomSublist = require("../views/rooms/RoomSublist");
var _actions = require("../../dispatcher/actions");
var _RoomSearch = _interopRequireDefault(require("./RoomSearch"));
var _SpaceStore = _interopRequireDefault(require("../../stores/spaces/SpaceStore"));
var _spaces = require("../../stores/spaces");
var _KeyBindingsManager = require("../../KeyBindingsManager");
var _UIStore = _interopRequireDefault(require("../../stores/UIStore"));
var _RoomListHeader = _interopRequireDefault(require("../views/rooms/RoomListHeader"));
var _BreadcrumbsStore = require("../../stores/BreadcrumbsStore");
var _RoomListStore = _interopRequireWildcard(require("../../stores/room-list/RoomListStore"));
var _AsyncStore = require("../../stores/AsyncStore");
var _IndicatorScrollbar = _interopRequireDefault(require("./IndicatorScrollbar"));
var _RoomBreadcrumbs = _interopRequireDefault(require("../views/rooms/RoomBreadcrumbs"));
var _KeyboardShortcuts = require("../../accessibility/KeyboardShortcuts");
var _UIComponents = require("../../customisations/helpers/UIComponents");
var _UIFeature = require("../../settings/UIFeature");
var _AccessibleButton = _interopRequireDefault(require("../views/elements/AccessibleButton"));
var _PosthogTrackers = _interopRequireDefault(require("../../PosthogTrackers"));
var _PageTypes = _interopRequireDefault(require("../../PageTypes"));
var _UserOnboardingButton = require("../views/user-onboarding/UserOnboardingButton");
var _LandmarkNavigation = require("../../accessibility/LandmarkNavigation");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
/*
Copyright 2024 New Vector Ltd.
Copyright 2020 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
Please see LICENSE files in the repository root for full details.
*/
var BreadcrumbsMode = /*#__PURE__*/function (BreadcrumbsMode) {
BreadcrumbsMode[BreadcrumbsMode["Disabled"] = 0] = "Disabled";
BreadcrumbsMode[BreadcrumbsMode["Legacy"] = 1] = "Legacy";
return BreadcrumbsMode;
}(BreadcrumbsMode || {});
class LeftPanel extends React.Component {
constructor(props) {
super(props);
(0, _defineProperty2.default)(this, "listContainerRef", /*#__PURE__*/(0, _react.createRef)());
(0, _defineProperty2.default)(this, "roomListRef", /*#__PURE__*/(0, _react.createRef)());
(0, _defineProperty2.default)(this, "focusedElement", null);
(0, _defineProperty2.default)(this, "isDoingStickyHeaders", false);
(0, _defineProperty2.default)(this, "updateActiveSpace", activeSpace => {
this.setState({
activeSpace
});
});
(0, _defineProperty2.default)(this, "onDialPad", () => {
_dispatcher.default.fire(_actions.Action.OpenDialPad);
});
(0, _defineProperty2.default)(this, "onExplore", ev => {
_dispatcher.default.fire(_actions.Action.ViewRoomDirectory);
_PosthogTrackers.default.trackInteraction("WebLeftPanelExploreRoomsButton", ev);
});
(0, _defineProperty2.default)(this, "refreshStickyHeaders", () => {
if (!this.listContainerRef.current) return; // ignore: no headers to sticky
this.handleStickyHeaders(this.listContainerRef.current);
});
(0, _defineProperty2.default)(this, "onBreadcrumbsUpdate", () => {
const newVal = LeftPanel.breadcrumbsMode;
if (newVal !== this.state.showBreadcrumbs) {
this.setState({
showBreadcrumbs: newVal
});
// Update the sticky headers too as the breadcrumbs will be popping in or out.
if (!this.listContainerRef.current) return; // ignore: no headers to sticky
this.handleStickyHeaders(this.listContainerRef.current);
}
});
(0, _defineProperty2.default)(this, "onScroll", ev => {
const list = ev.target;
this.handleStickyHeaders(list);
});
(0, _defineProperty2.default)(this, "onFocus", ev => {
this.focusedElement = ev.target;
});
(0, _defineProperty2.default)(this, "onBlur", () => {
this.focusedElement = null;
});
(0, _defineProperty2.default)(this, "onKeyDown", (ev, state) => {
if (!this.focusedElement) return;
const action = (0, _KeyBindingsManager.getKeyBindingsManager)().getRoomListAction(ev);
switch (action) {
case _KeyboardShortcuts.KeyBindingAction.NextRoom:
if (!state) {
ev.stopPropagation();
ev.preventDefault();
this.roomListRef.current?.focus();
}
break;
}
const navAction = (0, _KeyBindingsManager.getKeyBindingsManager)().getNavigationAction(ev);
if (navAction === _KeyboardShortcuts.KeyBindingAction.PreviousLandmark || navAction === _KeyboardShortcuts.KeyBindingAction.NextLandmark) {
ev.stopPropagation();
ev.preventDefault();
_LandmarkNavigation.LandmarkNavigation.findAndFocusNextLandmark(_LandmarkNavigation.Landmark.ROOM_SEARCH, navAction === _KeyboardShortcuts.KeyBindingAction.PreviousLandmark);
}
});
this.state = {
activeSpace: _SpaceStore.default.instance.activeSpace,
showBreadcrumbs: LeftPanel.breadcrumbsMode
};
_BreadcrumbsStore.BreadcrumbsStore.instance.on(_AsyncStore.UPDATE_EVENT, this.onBreadcrumbsUpdate);
_RoomListStore.default.instance.on(_RoomListStore.LISTS_UPDATE_EVENT, this.onBreadcrumbsUpdate);
_SpaceStore.default.instance.on(_spaces.UPDATE_SELECTED_SPACE, this.updateActiveSpace);
}
static get breadcrumbsMode() {
return !_BreadcrumbsStore.BreadcrumbsStore.instance.visible ? BreadcrumbsMode.Disabled : BreadcrumbsMode.Legacy;
}
componentDidMount() {
if (this.listContainerRef.current) {
_UIStore.default.instance.trackElementDimensions("ListContainer", this.listContainerRef.current);
// Using the passive option to not block the main thread
// https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#improving_scrolling_performance_with_passive_listeners
this.listContainerRef.current.addEventListener("scroll", this.onScroll, {
passive: true
});
}
_UIStore.default.instance.on("ListContainer", this.refreshStickyHeaders);
}
componentWillUnmount() {
_BreadcrumbsStore.BreadcrumbsStore.instance.off(_AsyncStore.UPDATE_EVENT, this.onBreadcrumbsUpdate);
_RoomListStore.default.instance.off(_RoomListStore.LISTS_UPDATE_EVENT, this.onBreadcrumbsUpdate);
_SpaceStore.default.instance.off(_spaces.UPDATE_SELECTED_SPACE, this.updateActiveSpace);
_UIStore.default.instance.stopTrackingElementDimensions("ListContainer");
_UIStore.default.instance.removeListener("ListContainer", this.refreshStickyHeaders);
this.listContainerRef.current?.removeEventListener("scroll", this.onScroll);
}
componentDidUpdate(prevProps, prevState) {
if (prevState.activeSpace !== this.state.activeSpace) {
this.refreshStickyHeaders();
}
}
handleStickyHeaders(list) {
if (this.isDoingStickyHeaders) return;
this.isDoingStickyHeaders = true;
window.requestAnimationFrame(() => {
this.doStickyHeaders(list);
this.isDoingStickyHeaders = false;
});
}
doStickyHeaders(list) {
if (!list.parentElement) return;
const topEdge = list.scrollTop;
const bottomEdge = list.offsetHeight + list.scrollTop;
const sublists = list.querySelectorAll(".mx_RoomSublist:not(.mx_RoomSublist_hidden)");
// We track which styles we want on a target before making the changes to avoid
// excessive layout updates.
const targetStyles = new Map();
let lastTopHeader;
let firstBottomHeader;
for (const sublist of sublists) {
const header = sublist.querySelector(".mx_RoomSublist_stickable");
if (!header) continue; // this should never occur
header.style.removeProperty("display"); // always clear display:none first
// When an element is <=40% off screen, make it take over
const offScreenFactor = 0.4;
const isOffTop = sublist.offsetTop + offScreenFactor * _RoomSublist.HEADER_HEIGHT <= topEdge;
const isOffBottom = sublist.offsetTop + offScreenFactor * _RoomSublist.HEADER_HEIGHT >= bottomEdge;
if (isOffTop || sublist === sublists[0]) {
targetStyles.set(header, {
stickyTop: true
});
if (lastTopHeader) {
lastTopHeader.style.display = "none";
targetStyles.set(lastTopHeader, {
makeInvisible: true
});
}
lastTopHeader = header;
} else if (isOffBottom && !firstBottomHeader) {
targetStyles.set(header, {
stickyBottom: true
});
firstBottomHeader = header;
} else {
targetStyles.set(header, {}); // nothing == clear
}
}
// Run over the style changes and make them reality. We check to see if we're about to
// cause a no-op update, as adding/removing properties that are/aren't there cause
// layout updates.
for (const header of targetStyles.keys()) {
const style = targetStyles.get(header);
if (style.makeInvisible) {
// we will have already removed the 'display: none', so add it back.
header.style.display = "none";
continue; // nothing else to do, even if sticky somehow
}
if (style.stickyTop) {
if (!header.classList.contains("mx_RoomSublist_headerContainer_stickyTop")) {
header.classList.add("mx_RoomSublist_headerContainer_stickyTop");
}
const newTop = `${list.parentElement.offsetTop}px`;
if (header.style.top !== newTop) {
header.style.top = newTop;
}
} else {
if (header.classList.contains("mx_RoomSublist_headerContainer_stickyTop")) {
header.classList.remove("mx_RoomSublist_headerContainer_stickyTop");
}
if (header.style.top) {
header.style.removeProperty("top");
}
}
if (style.stickyBottom) {
if (!header.classList.contains("mx_RoomSublist_headerContainer_stickyBottom")) {
header.classList.add("mx_RoomSublist_headerContainer_stickyBottom");
}
const offset = _UIStore.default.instance.windowHeight - (list.parentElement.offsetTop + list.parentElement.offsetHeight);
const newBottom = `${offset}px`;
if (header.style.bottom !== newBottom) {
header.style.bottom = newBottom;
}
} else {
if (header.classList.contains("mx_RoomSublist_headerContainer_stickyBottom")) {
header.classList.remove("mx_RoomSublist_headerContainer_stickyBottom");
}
if (header.style.bottom) {
header.style.removeProperty("bottom");
}
}
if (style.stickyTop || style.stickyBottom) {
if (!header.classList.contains("mx_RoomSublist_headerContainer_sticky")) {
header.classList.add("mx_RoomSublist_headerContainer_sticky");
}
const listDimensions = _UIStore.default.instance.getElementDimensions("ListContainer");
if (listDimensions) {
const headerRightMargin = 15; // calculated from margins and widths to align with non-sticky tiles
const headerStickyWidth = listDimensions.width - headerRightMargin;
const newWidth = `${headerStickyWidth}px`;
if (header.style.width !== newWidth) {
header.style.width = newWidth;
}
}
} else if (!style.stickyTop && !style.stickyBottom) {
if (header.classList.contains("mx_RoomSublist_headerContainer_sticky")) {
header.classList.remove("mx_RoomSublist_headerContainer_sticky");
}
if (header.style.width) {
header.style.removeProperty("width");
}
}
}
// add appropriate sticky classes to wrapper so it has
// the necessary top/bottom padding to put the sticky header in
const listWrapper = list.parentElement; // .mx_LeftPanel_roomListWrapper
if (!listWrapper) return;
if (lastTopHeader) {
listWrapper.classList.add("mx_LeftPanel_roomListWrapper_stickyTop");
} else {
listWrapper.classList.remove("mx_LeftPanel_roomListWrapper_stickyTop");
}
if (firstBottomHeader) {
listWrapper.classList.add("mx_LeftPanel_roomListWrapper_stickyBottom");
} else {
listWrapper.classList.remove("mx_LeftPanel_roomListWrapper_stickyBottom");
}
}
renderBreadcrumbs() {
if (this.state.showBreadcrumbs === BreadcrumbsMode.Legacy && !this.props.isMinimized) {
return /*#__PURE__*/React.createElement(_IndicatorScrollbar.default, {
role: "navigation",
"aria-label": (0, _languageHandler._t)("a11y|recent_rooms"),
className: "mx_LeftPanel_breadcrumbsContainer mx_AutoHideScrollbar",
verticalScrollsHorizontally: true
}, /*#__PURE__*/React.createElement(_RoomBreadcrumbs.default, null));
}
}
renderSearchDialExplore() {
let dialPadButton;
// If we have dialer support, show a button to bring up the dial pad
// to start a new call
if (_LegacyCallHandler.default.instance.getSupportsPstnProtocol()) {
dialPadButton = /*#__PURE__*/React.createElement(_AccessibleButton.default, {
className: (0, _classnames.default)("mx_LeftPanel_dialPadButton", {}),
onClick: this.onDialPad,
title: (0, _languageHandler._t)("left_panel|open_dial_pad")
});
}
let rightButton;
if (this.state.activeSpace === _spaces.MetaSpace.Home && (0, _UIComponents.shouldShowComponent)(_UIFeature.UIComponent.ExploreRooms)) {
rightButton = /*#__PURE__*/React.createElement(_AccessibleButton.default, {
className: "mx_LeftPanel_exploreButton",
onClick: this.onExplore,
title: (0, _languageHandler._t)("action|explore_rooms")
});
}
return /*#__PURE__*/React.createElement("div", {
className: "mx_LeftPanel_filterContainer",
onFocus: this.onFocus,
onBlur: this.onBlur,
onKeyDown: this.onKeyDown,
role: "search"
}, /*#__PURE__*/React.createElement(_RoomSearch.default, {
isMinimized: this.props.isMinimized
}), dialPadButton, rightButton);
}
render() {
const roomList = /*#__PURE__*/React.createElement(_RoomList.default, {
onKeyDown: this.onKeyDown,
resizeNotifier: this.props.resizeNotifier,
onFocus: this.onFocus,
onBlur: this.onBlur,
isMinimized: this.props.isMinimized,
activeSpace: this.state.activeSpace,
onResize: this.refreshStickyHeaders,
onListCollapse: this.refreshStickyHeaders,
ref: this.roomListRef
});
const containerClasses = (0, _classnames.default)({
mx_LeftPanel: true,
mx_LeftPanel_minimized: this.props.isMinimized
});
const roomListClasses = (0, _classnames.default)("mx_LeftPanel_actualRoomListContainer", "mx_AutoHideScrollbar");
return /*#__PURE__*/React.createElement("div", {
className: containerClasses
}, /*#__PURE__*/React.createElement("div", {
className: "mx_LeftPanel_roomListContainer"
}, (0, _UIComponents.shouldShowComponent)(_UIFeature.UIComponent.FilterContainer) && this.renderSearchDialExplore(), this.renderBreadcrumbs(), !this.props.isMinimized && /*#__PURE__*/React.createElement(_RoomListHeader.default, {
onVisibilityChange: this.refreshStickyHeaders
}), /*#__PURE__*/React.createElement(_UserOnboardingButton.UserOnboardingButton, {
selected: this.props.pageType === _PageTypes.default.HomePage,
minimized: this.props.isMinimized
}), /*#__PURE__*/React.createElement("nav", {
className: "mx_LeftPanel_roomListWrapper",
"aria-label": (0, _languageHandler._t)("common|rooms")
}, /*#__PURE__*/React.createElement("div", {
className: roomListClasses,
ref: this.listContainerRef
// Firefox sometimes makes this element focusable due to
// overflow:scroll;, so force it out of tab order.
,
tabIndex: -1
}, roomList))));
}
}
exports.default = LeftPanel;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfcmVhY3QiLCJfaW50ZXJvcFJlcXVpcmVXaWxkY2FyZCIsInJlcXVpcmUiLCJSZWFjdCIsIl9jbGFzc25hbWVzIiwiX2ludGVyb3BSZXF1aXJlRGVmYXVsdCIsIl9kaXNwYXRjaGVyIiwiX2xhbmd1YWdlSGFuZGxlciIsIl9Sb29tTGlzdCIsIl9MZWdhY3lDYWxsSGFuZGxlciIsIl9Sb29tU3VibGlzdCIsIl9hY3Rpb25zIiwiX1Jvb21TZWFyY2giLCJfU3BhY2VTdG9yZSIsIl9zcGFjZXMiLCJfS2V5QmluZGluZ3NNYW5hZ2VyIiwiX1VJU3RvcmUiLCJfUm9vbUxpc3RIZWFkZXIiLCJfQnJlYWRjcnVtYnNTdG9yZSIsIl9Sb29tTGlzdFN0b3JlIiwiX0FzeW5jU3RvcmUiLCJfSW5kaWNhdG9yU2Nyb2xsYmFyIiwiX1Jvb21CcmVhZGNydW1icyIsIl9LZXlib2FyZFNob3J0Y3V0cyIsIl9VSUNvbXBvbmVudHMiLCJfVUlGZWF0dXJlIiwiX0FjY2Vzc2libGVCdXR0b24iLCJfUG9zdGhvZ1RyYWNrZXJzIiwiX1BhZ2VUeXBlcyIsIl9Vc2VyT25ib2FyZGluZ0J1dHRvbiIsIl9MYW5kbWFya05hdmlnYXRpb24iLCJfZ2V0UmVxdWlyZVdpbGRjYXJkQ2FjaGUiLCJlIiwiV2Vha01hcCIsInIiLCJ0IiwiX19lc01vZHVsZSIsImRlZmF1bHQiLCJoYXMiLCJnZXQiLCJuIiwiX19wcm90b19fIiwiYSIsIk9iamVjdCIsImRlZmluZVByb3BlcnR5IiwiZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yIiwidSIsImhhc093blByb3BlcnR5IiwiY2FsbCIsImkiLCJzZXQiLCJCcmVhZGNydW1ic01vZGUiLCJMZWZ0UGFuZWwiLCJDb21wb25lbnQiLCJjb25zdHJ1Y3RvciIsInByb3BzIiwiX2RlZmluZVByb3BlcnR5MiIsImNyZWF0ZVJlZiIsImFjdGl2ZVNwYWNlIiwic2V0U3RhdGUiLCJkaXMiLCJmaXJlIiwiQWN0aW9uIiwiT3BlbkRpYWxQYWQiLCJldiIsIlZpZXdSb29tRGlyZWN0b3J5IiwiUG9zdGhvZ1RyYWNrZXJzIiwidHJhY2tJbnRlcmFjdGlvbiIsImxpc3RDb250YWluZXJSZWYiLCJjdXJyZW50IiwiaGFuZGxlU3RpY2t5SGVhZGVycyIsIm5ld1ZhbCIsImJyZWFkY3J1bWJzTW9kZSIsInN0YXRlIiwic2hvd0JyZWFkY3J1bWJzIiwibGlzdCIsInRhcmdldCIsImZvY3VzZWRFbGVtZW50IiwiYWN0aW9uIiwiZ2V0S2V5QmluZGluZ3NNYW5hZ2VyIiwiZ2V0Um9vbUxpc3RBY3Rpb24iLCJLZXlCaW5kaW5nQWN0aW9uIiwiTmV4dFJvb20iLCJzdG9wUHJvcGFnYXRpb24iLCJwcmV2ZW50RGVmYXVsdCIsInJvb21MaXN0UmVmIiwiZm9jdXMiLCJuYXZBY3Rpb24iLCJnZXROYXZpZ2F0aW9uQWN0aW9uIiwiUHJldmlvdXNMYW5kbWFyayIsIk5leHRMYW5kbWFyayIsIkxhbmRtYXJrTmF2aWdhdGlvbiIsImZpbmRBbmRGb2N1c05leHRMYW5kbWFyayIsIkxhbmRtYXJrIiwiUk9PTV9TRUFSQ0giLCJTcGFjZVN0b3JlIiwiaW5zdGFuY2UiLCJCcmVhZGNydW1ic1N0b3JlIiwib24iLCJVUERBVEVfRVZFTlQiLCJvbkJyZWFkY3J1bWJzVXBkYXRlIiwiUm9vbUxpc3RTdG9yZSIsIkxJU1RTX1VQREFURV9FVkVOVCIsIlVQREFURV9TRUxFQ1RFRF9TUEFDRSIsInVwZGF0ZUFjdGl2ZVNwYWNlIiwidmlzaWJsZSIsIkRpc2FibGVkIiwiTGVnYWN5IiwiY29tcG9uZW50RGlkTW91bnQiLCJVSVN0b3JlIiwidHJhY2tFbGVtZW50RGltZW5zaW9ucyIsImFkZEV2ZW50TGlzdGVuZXIiLCJvblNjcm9sbCIsInBhc3NpdmUiLCJyZWZyZXNoU3RpY2t5SGVhZGVycyIsImNvbXBvbmVudFdpbGxVbm1vdW50Iiwib2ZmIiwic3RvcFRyYWNraW5nRWxlbWVudERpbWVuc2lvbnMiLCJyZW1vdmVMaXN0ZW5lciIsInJlbW92ZUV2ZW50TGlzdGVuZXIiLCJjb21wb25lbnREaWRVcGRhdGUiLCJwcmV2UHJvcHMiLCJwcmV2U3RhdGUiLCJpc0RvaW5nU3RpY2t5SGVhZGVycyIsIndpbmRvdyIsInJlcXVlc3RBbmltYXRpb25GcmFtZSIsImRvU3RpY2t5SGVhZGVycyIsInBhcmVudEVsZW1lbnQiLCJ0b3BFZGdlIiwic2Nyb2xsVG9wIiwiYm90dG9tRWRnZSIsIm9mZnNldEhlaWdodCIsInN1Ymxpc3RzIiwicXVlcnlTZWxlY3RvckFsbCIsInRhcmdldFN0eWxlcyIsIk1hcCIsImxhc3RUb3BIZWFkZXIiLCJmaXJzdEJvdHRvbUhlYWRlciIsInN1Ymxpc3QiLCJoZWFkZXIiLCJxdWVyeVNlbGVjdG9yIiwic3R5bGUiLCJyZW1vdmVQcm9wZXJ0eSIsIm9mZlNjcmVlbkZhY3RvciIsImlzT2ZmVG9wIiwib2Zmc2V0VG9wIiwiSEVBREVSX0hFSUdIVCIsImlzT2ZmQm90dG9tIiwic3RpY2t5VG9wIiwiZGlzcGxheSIsIm1ha2VJbnZpc2libGUiLCJzdGlja3lCb3R0b20iLCJrZXlzIiwiY2xhc3NMaXN0IiwiY29udGFpbnMiLCJhZGQiLCJuZXdUb3AiLCJ0b3AiLCJyZW1vdmUiLCJvZmZzZXQiLCJ3aW5kb3dIZWlnaHQiLCJuZXdCb3R0b20iLCJib3R0b20iLCJsaXN0RGltZW5zaW9ucyIsImdldEVsZW1lbnREaW1lbnNpb25zIiwiaGVhZGVyUmlnaHRNYXJnaW4iLCJoZWFkZXJTdGlja3lXaWR0aCIsIndpZHRoIiwibmV3V2lkdGgiLCJsaXN0V3JhcHBlciIsInJlbmRlckJyZWFkY3J1bWJzIiwiaXNNaW5pbWl6ZWQiLCJjcmVhdGVFbGVtZW50Iiwicm9sZSIsIl90IiwiY2xhc3NOYW1lIiwidmVydGljYWxTY3JvbGxzSG9yaXpvbnRhbGx5IiwicmVuZGVyU2VhcmNoRGlhbEV4cGxvcmUiLCJkaWFsUGFkQnV0dG9uIiwiTGVnYWN5Q2FsbEhhbmRsZXIiLCJnZXRTdXBwb3J0c1BzdG5Qcm90b2NvbCIsImNsYXNzTmFtZXMiLCJvbkNsaWNrIiwib25EaWFsUGFkIiwidGl0bGUiLCJyaWdodEJ1dHRvbiIsIk1ldGFTcGFjZSIsIkhvbWUiLCJzaG91bGRTaG93Q29tcG9uZW50IiwiVUlDb21wb25lbnQiLCJFeHBsb3JlUm9vbXMiLCJvbkV4cGxvcmUiLCJvbkZvY3VzIiwib25CbHVyIiwib25LZXlEb3duIiwicmVuZGVyIiwicm9vbUxpc3QiLCJyZXNpemVOb3RpZmllciIsIm9uUmVzaXplIiwib25MaXN0Q29sbGFwc2UiLCJyZWYiLCJjb250YWluZXJDbGFzc2VzIiwibXhfTGVmdFBhbmVsIiwibXhfTGVmdFBhbmVsX21pbmltaXplZCIsInJvb21MaXN0Q2xhc3NlcyIsIkZpbHRlckNvbnRhaW5lciIsIm9uVmlzaWJpbGl0eUNoYW5nZSIsIlVzZXJPbmJvYXJkaW5nQnV0dG9uIiwic2VsZWN0ZWQiLCJwYWdlVHlwZSIsIlBhZ2VUeXBlIiwiSG9tZVBhZ2UiLCJtaW5pbWl6ZWQiLCJ0YWJJbmRleCIsImV4cG9ydHMiXSwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvY29tcG9uZW50cy9zdHJ1Y3R1cmVzL0xlZnRQYW5lbC50c3giXSwic291cmNlc0NvbnRlbnQiOlsiLypcbkNvcHlyaWdodCAyMDI0IE5ldyBWZWN0b3IgTHRkLlxuQ29weXJpZ2h0IDIwMjAgVGhlIE1hdHJpeC5vcmcgRm91bmRhdGlvbiBDLkkuQy5cblxuU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFHUEwtMy4wLW9ubHkgT1IgR1BMLTMuMC1vbmx5XG5QbGVhc2Ugc2VlIExJQ0VOU0UgZmlsZXMgaW4gdGhlIHJlcG9zaXRvcnkgcm9vdCBmb3IgZnVsbCBkZXRhaWxzLlxuKi9cblxuaW1wb3J0ICogYXMgUmVhY3QgZnJvbSBcInJlYWN0XCI7XG5pbXBvcnQgeyBjcmVhdGVSZWYgfSBmcm9tIFwicmVhY3RcIjtcbmltcG9ydCBjbGFzc05hbWVzIGZyb20gXCJjbGFzc25hbWVzXCI7XG5cbmltcG9ydCBkaXMgZnJvbSBcIi4uLy4uL2Rpc3BhdGNoZXIvZGlzcGF0Y2hlclwiO1xuaW1wb3J0IHsgX3QgfSBmcm9tIFwiLi4vLi4vbGFuZ3VhZ2VIYW5kbGVyXCI7XG5pbXBvcnQgUm9vbUxpc3QgZnJvbSBcIi4uL3ZpZXdzL3Jvb21zL1Jvb21MaXN0XCI7XG5pbXBvcnQgTGVnYWN5Q2FsbEhhbmRsZXIgZnJvbSBcIi4uLy4uL0xlZ2FjeUNhbGxIYW5kbGVyXCI7XG5pbXBvcnQgeyBIRUFERVJfSEVJR0hUIH0gZnJvbSBcIi4uL3ZpZXdzL3Jvb21zL1Jvb21TdWJsaXN0XCI7XG5pbXBvcnQgeyBBY3Rpb24gfSBmcm9tIFwiLi4vLi4vZGlzcGF0Y2hlci9hY3Rpb25zXCI7XG5pbXBvcnQgUm9vbVNlYXJjaCBmcm9tIFwiLi9Sb29tU2VhcmNoXCI7XG5pbXBvcnQgUmVzaXplTm90aWZpZXIgZnJvbSBcIi4uLy4uL3V0aWxzL1Jlc2l6ZU5vdGlmaWVyXCI7XG5pbXBvcnQgU3BhY2VTdG9yZSBmcm9tIFwiLi4vLi4vc3RvcmVzL3NwYWNlcy9TcGFjZVN0b3JlXCI7XG5pbXBvcnQgeyBNZXRhU3BhY2UsIFNwYWNlS2V5LCBVUERBVEVfU0VMRUNURURfU1BBQ0UgfSBmcm9tIFwiLi4vLi4vc3RvcmVzL3NwYWNlc1wiO1xuaW1wb3J0IHsgZ2V0S2V5QmluZGluZ3NNYW5hZ2VyIH0gZnJvbSBcIi4uLy4uL0tleUJpbmRpbmdzTWFuYWdlclwiO1xuaW1wb3J0IFVJU3RvcmUgZnJvbSBcIi4uLy4uL3N0b3Jlcy9VSVN0b3JlXCI7XG5pbXBvcnQgeyBJU3RhdGUgYXMgSVJvdmluZ1RhYkluZGV4U3RhdGUgfSBmcm9tIFwiLi4vLi4vYWNjZXNzaWJpbGl0eS9Sb3ZpbmdUYWJJbmRleFwiO1xuaW1wb3J0IFJvb21MaXN0SGVhZGVyIGZyb20gXCIuLi92aWV3cy9yb29tcy9Sb29tTGlzdEhlYWRlclwiO1xuaW1wb3J0IHsgQnJlYWRjcnVtYnNTdG9yZSB9IGZyb20gXCIuLi8uLi9zdG9yZXMvQnJlYWRjcnVtYnNTdG9yZVwiO1xuaW1wb3J0IFJvb21MaXN0U3RvcmUsIHsgTElTVFNfVVBEQVRFX0VWRU5UIH0gZnJvbSBcIi4uLy4uL3N0b3Jlcy9yb29tLWxpc3QvUm9vbUxpc3RTdG9yZVwiO1xuaW1wb3J0IHsgVVBEQVRFX0VWRU5UIH0gZnJvbSBcIi4uLy4uL3N0b3Jlcy9Bc3luY1N0b3JlXCI7XG5pbXBvcnQgSW5kaWNhdG9yU2Nyb2xsYmFyIGZyb20gXCIuL0luZGljYXRvclNjcm9sbGJhclwiO1xuaW1wb3J0IFJvb21CcmVhZGNydW1icyBmcm9tIFwiLi4vdmlld3Mvcm9vbXMvUm9vbUJyZWFkY3J1bWJzXCI7XG5pbXBvcnQgeyBLZXlCaW5kaW5nQWN0aW9uIH0gZnJvbSBcIi4uLy4uL2FjY2Vzc2liaWxpdHkvS2V5Ym9hcmRTaG9ydGN1dHNcIjtcbmltcG9ydCB7IHNob3VsZFNob3dDb21wb25lbnQgfSBmcm9tIFwiLi4vLi4vY3VzdG9taXNhdGlvbnMvaGVscGVycy9VSUNvbXBvbmVudHNcIjtcbmltcG9ydCB7IFVJQ29tcG9uZW50IH0gZnJvbSBcIi4uLy4uL3NldHRpbmdzL1VJRmVhdHVyZVwiO1xuaW1wb3J0IEFjY2Vzc2libGVCdXR0b24sIHsgQnV0dG9uRXZlbnQgfSBmcm9tIFwiLi4vdmlld3MvZWxlbWVudHMvQWNjZXNzaWJsZUJ1dHRvblwiO1xuaW1wb3J0IFBvc3Rob2dUcmFja2VycyBmcm9tIFwiLi4vLi4vUG9zdGhvZ1RyYWNrZXJzXCI7XG5pbXBvcnQgUGFnZVR5cGUgZnJvbSBcIi4uLy4uL1BhZ2VUeXBlc1wiO1xuaW1wb3J0IHsgVXNlck9uYm9hcmRpbmdCdXR0b24gfSBmcm9tIFwiLi4vdmlld3MvdXNlci1vbmJvYXJkaW5nL1VzZXJPbmJvYXJkaW5nQnV0dG9uXCI7XG5pbXBvcnQgeyBMYW5kbWFyaywgTGFuZG1hcmtOYXZpZ2F0aW9uIH0gZnJvbSBcIi4uLy4uL2FjY2Vzc2liaWxpdHkvTGFuZG1hcmtOYXZpZ2F0aW9uXCI7XG5cbmludGVyZmFjZSBJUHJvcHMge1xuICAgIGlzTWluaW1pemVkOiBib29sZWFuO1xuICAgIHBhZ2VUeXBlOiBQYWdlVHlwZTtcbiAgICByZXNpemVOb3RpZmllcjogUmVzaXplTm90aWZpZXI7XG59XG5cbmVudW0gQnJlYWRjcnVtYnNNb2RlIHtcbiAgICBEaXNhYmxlZCxcbiAgICBMZWdhY3ksXG59XG5cbmludGVyZmFjZSBJU3RhdGUge1xuICAgIHNob3dCcmVhZGNydW1iczogQnJlYWRjcnVtYnNNb2RlO1xuICAgIGFjdGl2ZVNwYWNlOiBTcGFjZUtleTtcbn1cblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgTGVmdFBhbmVsIGV4dGVuZHMgUmVhY3QuQ29tcG9uZW50PElQcm9wcywgSVN0YXRlPiB7XG4gICAgcHJpdmF0ZSBsaXN0Q29udGFpbmVyUmVmID0gY3JlYXRlUmVmPEhUTUxEaXZFbGVtZW50PigpO1xuICAgIHByaXZhdGUgcm9vbUxpc3RSZWYgPSBjcmVhdGVSZWY8Um9vbUxpc3Q+KCk7XG4gICAgcHJpdmF0ZSBmb2N1c2VkRWxlbWVudDogRWxlbWVudCB8IG51bGwgPSBudWxsO1xuICAgIHByaXZhdGUgaXNEb2luZ1N0aWNreUhlYWRlcnMgPSBmYWxzZTtcblxuICAgIHB1YmxpYyBjb25zdHJ1Y3Rvcihwcm9wczogSVByb3BzKSB7XG4gICAgICAgIHN1cGVyKHByb3BzKTtcblxuICAgICAgICB0aGlzLnN0YXRlID0ge1xuICAgICAgICAgICAgYWN0aXZlU3BhY2U6IFNwYWNlU3RvcmUuaW5zdGFuY2UuYWN0aXZlU3BhY2UsXG4gICAgICAgICAgICBzaG93QnJlYWRjcnVtYnM6IExlZnRQYW5lbC5icmVhZGNydW1ic01vZGUsXG4gICAgICAgIH07XG5cbiAgICAgICAgQnJlYWRjcnVtYnNTdG9yZS5pbnN0YW5jZS5vbihVUERBVEVfRVZFTlQsIHRoaXMub25CcmVhZGNydW1ic1VwZGF0ZSk7XG4gICAgICAgIFJvb21MaXN0U3RvcmUuaW5zdGFuY2Uub24oTElTVFNfVVBEQVRFX0VWRU5ULCB0aGlzLm9uQnJlYWRjcnVtYnNVcGRhdGUpO1xuICAgICAgICBTcGFjZVN0b3JlLmluc3RhbmNlLm9uKFVQREFURV9TRUxFQ1RFRF9TUEFDRSwgdGhpcy51cGRhdGVBY3RpdmVTcGFjZSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdGF0aWMgZ2V0IGJyZWFkY3J1bWJzTW9kZSgpOiBCcmVhZGNydW1ic01vZGUge1xuICAgICAgICByZXR1cm4gIUJyZWFkY3J1bWJzU3RvcmUuaW5zdGFuY2UudmlzaWJsZSA/IEJyZWFkY3J1bWJzTW9kZS5EaXNhYmxlZCA6IEJyZWFkY3J1bWJzTW9kZS5MZWdhY3k7XG4gICAgfVxuXG4gICAgcHVibGljIGNvbXBvbmVudERpZE1vdW50KCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy5saXN0Q29udGFpbmVyUmVmLmN1cnJlbnQpIHtcbiAgICAgICAgICAgIFVJU3RvcmUuaW5zdGFuY2UudHJhY2tFbGVtZW50RGltZW5zaW9ucyhcIkxpc3RDb250YWluZXJcIiwgdGhpcy5saXN0Q29udGFpbmVyUmVmLmN1cnJlbnQpO1xuICAgICAgICAgICAgLy8gVXNpbmcgdGhlIHBhc3NpdmUgb3B0aW9uIHRvIG5vdCBibG9jayB0aGUgbWFpbiB0aHJlYWRcbiAgICAgICAgICAgIC8vIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9FdmVudFRhcmdldC9hZGRFdmVudExpc3RlbmVyI2ltcHJvdmluZ19zY3JvbGxpbmdfcGVyZm9ybWFuY2Vfd2l0aF9wYXNzaXZlX2xpc3RlbmVyc1xuICAgICAgICAgICAgdGhpcy5saXN0Q29udGFpbmVyUmVmLmN1cnJlbnQuYWRkRXZlbnRMaXN0ZW5lcihcInNjcm9sbFwiLCB0aGlzLm9uU2Nyb2xsLCB7IHBhc3NpdmU6IHRydWUgfSk7XG4gICAgICAgIH1cbiAgICAgICAgVUlTdG9yZS5pbnN0YW5jZS5vbihcIkxpc3RDb250YWluZXJcIiwgdGhpcy5yZWZyZXNoU3RpY2t5SGVhZGVycyk7XG4gICAgfVxuXG4gICAgcHVibGljIGNvbXBvbmVudFdpbGxVbm1vdW50KCk6IHZvaWQge1xuICAgICAgICBCcmVhZGNydW1ic1N0b3JlLmluc3RhbmNlLm9mZihVUERBVEVfRVZFTlQsIHRoaXMub25CcmVhZGNydW1ic1VwZGF0ZSk7XG4gICAgICAgIFJvb21MaXN0U3RvcmUuaW5zdGFuY2Uub2ZmKExJU1RTX1VQREFURV9FVkVOVCwgdGhpcy5vbkJyZWFkY3J1bWJzVXBkYXRlKTtcbiAgICAgICAgU3BhY2VTdG9yZS5pbnN0YW5jZS5vZmYoVVBEQVRFX1NFTEVDVEVEX1NQQUNFLCB0aGlzLnVwZGF0ZUFjdGl2ZVNwYWNlKTtcbiAgICAgICAgVUlTdG9yZS5pbnN0YW5jZS5zdG9wVHJhY2tpbmdFbGVtZW50RGltZW5zaW9ucyhcIkxpc3RDb250YWluZXJcIik7XG4gICAgICAgIFVJU3RvcmUuaW5zdGFuY2UucmVtb3ZlTGlzdGVuZXIoXCJMaXN0Q29udGFpbmVyXCIsIHRoaXMucmVmcmVzaFN0aWNreUhlYWRlcnMpO1xuICAgICAgICB0aGlzLmxpc3RDb250YWluZXJSZWYuY3VycmVudD8ucmVtb3ZlRXZlbnRMaXN0ZW5lcihcInNjcm9sbFwiLCB0aGlzLm9uU2Nyb2xsKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgY29tcG9uZW50RGlkVXBkYXRlKHByZXZQcm9wczogSVByb3BzLCBwcmV2U3RhdGU6IElTdGF0ZSk6IHZvaWQge1xuICAgICAgICBpZiAocHJldlN0YXRlLmFjdGl2ZVNwYWNlICE9PSB0aGlzLnN0YXRlLmFjdGl2ZVNwYWNlKSB7XG4gICAgICAgICAgICB0aGlzLnJlZnJlc2hTdGlja3lIZWFkZXJzKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIHVwZGF0ZUFjdGl2ZVNwYWNlID0gKGFjdGl2ZVNwYWNlOiBTcGFjZUtleSk6IHZvaWQgPT4ge1xuICAgICAgICB0aGlzLnNldFN0YXRlKHsgYWN0aXZlU3BhY2UgfSk7XG4gICAgfTtcblxuICAgIHByaXZhdGUgb25EaWFsUGFkID0gKCk6IHZvaWQgPT4ge1xuICAgICAgICBkaXMuZmlyZShBY3Rpb24uT3BlbkRpYWxQYWQpO1xuICAgIH07XG5cbiAgICBwcml2YXRlIG9uRXhwbG9yZSA9IChldjogQnV0dG9uRXZlbnQpOiB2b2lkID0+IHtcbiAgICAgICAgZGlzLmZpcmUoQWN0aW9uLlZpZXdSb29tRGlyZWN0b3J5KTtcbiAgICAgICAgUG9zdGhvZ1RyYWNrZXJzLnRyYWNrSW50ZXJhY3Rpb24oXCJXZWJMZWZ0UGFuZWxFeHBsb3JlUm9vbXNCdXR0b25cIiwgZXYpO1xuICAgIH07XG5cbiAgICBwcml2YXRlIHJlZnJlc2hTdGlja3lIZWFkZXJzID0gKCk6IHZvaWQgPT4ge1xuICAgICAgICBpZiAoIXRoaXMubGlzdENvbnRhaW5lclJlZi5jdXJyZW50KSByZXR1cm47IC8vIGlnbm9yZTogbm8gaGVhZGVycyB0byBzdGlja3lcbiAgICAgICAgdGhpcy5oYW5kbGVTdGlja3lIZWFkZXJzKHRoaXMubGlzdENvbnRhaW5lclJlZi5jdXJyZW50KTtcbiAgICB9O1xuXG4gICAgcHJpdmF0ZSBvbkJyZWFkY3J1bWJzVXBkYXRlID0gKCk6IHZvaWQgPT4ge1xuICAgICAgICBjb25zdCBuZXdWYWwgPSBMZWZ0UGFuZWwuYnJlYWRjcnVtYnNNb2RlO1xuICAgICAgICBpZiAobmV3VmFsICE9PSB0aGlzLnN0YXRlLnNob3dCcmVhZGNydW1icykge1xuICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7IHNob3dCcmVhZGNydW1iczogbmV3VmFsIH0pO1xuXG4gICAgICAgICAgICAvLyBVcGRhdGUgdGhlIHN0aWNreSBoZWFkZXJzIHRvbyBhcyB0aGUgYnJlYWRjcnVtYnMgd2lsbCBiZSBwb3BwaW5nIGluIG9yIG91dC5cbiAgICAgICAgICAgIGlmICghdGhpcy5saXN0Q29udGFpbmVyUmVmLmN1cnJlbnQpIHJldHVybjsgLy8gaWdub3JlOiBubyBoZWFkZXJzIHRvIHN0aWNreVxuICAgICAgICAgICAgdGhpcy5oYW5kbGVTdGlja3lIZWFkZXJzKHRoaXMubGlzdENvbnRhaW5lclJlZi5jdXJyZW50KTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBwcml2YXRlIGhhbmRsZVN0aWNreUhlYWRlcnMobGlzdDogSFRNTERpdkVsZW1lbnQpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMuaXNEb2luZ1N0aWNreUhlYWRlcnMpIHJldHVybjtcbiAgICAgICAgdGhpcy5pc0RvaW5nU3RpY2t5SGVhZGVycyA9IHRydWU7XG4gICAgICAgIHdpbmRvdy5yZXF1ZXN0QW5pbWF0aW9uRnJhbWUoKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5kb1N0aWNreUhlYWRlcnMobGlzdCk7XG4gICAgICAgICAgICB0aGlzLmlzRG9pbmdTdGlja3lIZWFkZXJzID0gZmFsc2U7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgZG9TdGlja3lIZWFkZXJzKGxpc3Q6IEhUTUxEaXZFbGVtZW50KTogdm9pZCB7XG4gICAgICAgIGlmICghbGlzdC5wYXJlbnRFbGVtZW50KSByZXR1cm47XG4gICAgICAgIGNvbnN0IHRvcEVkZ2UgPSBsaXN0LnNjcm9sbFRvcDtcbiAgICAgICAgY29uc3QgYm90dG9tRWRnZSA9IGxpc3Qub2Zmc2V0SGVpZ2h0ICsgbGlzdC5zY3JvbGxUb3A7XG4gICAgICAgIGNvbnN0IHN1Ymxpc3RzID0gbGlzdC5xdWVyeVNlbGVjdG9yQWxsPEhUTUxEaXZFbGVtZW50PihcIi5teF9Sb29tU3VibGlzdDpub3QoLm14X1Jvb21TdWJsaXN0X2hpZGRlbilcIik7XG5cbiAgICAgICAgLy8gV2UgdHJhY2sgd2hpY2ggc3R5bGVzIHdlIHdhbnQgb24gYSB0YXJnZXQgYmVmb3JlIG1ha2luZyB0aGUgY2hhbmdlcyB0byBhdm9pZFxuICAgICAgICAvLyBleGNlc3NpdmUgbGF5b3V0IHVwZGF0ZXMuXG4gICAgICAgIGNvbnN0IHRhcmdldFN0eWxlcyA9IG5ldyBNYXA8XG4gICAgICAgICAgICBIVE1MRGl2RWxlbWVudCxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBzdGlja3lUb3A/OiBib29sZWFuO1xuICAgICAgICAgICAgICAgIHN0aWNreUJvdHRvbT86IGJvb2xlYW47XG4gICAgICAgICAgICAgICAgbWFrZUludmlzaWJsZT86IGJvb2xlYW47XG4gICAgICAgICAgICB9XG4gICAgICAgID4oKTtcblxuICAgICAgICBsZXQgbGFzdFRvcEhlYWRlcjogSFRNTERpdkVsZW1lbnQgfCB1bmRlZmluZWQ7XG4gICAgICAgIGxldCBmaXJzdEJvdHRvbUhlYWRlcjogSFRNTERpdkVsZW1lbnQgfCB1bmRlZmluZWQ7XG4gICAgICAgIGZvciAoY29uc3Qgc3VibGlzdCBvZiBzdWJsaXN0cykge1xuICAgICAgICAgICAgY29uc3QgaGVhZGVyID0gc3VibGlzdC5xdWVyeVNlbGVjdG9yPEhUTUxEaXZFbGVtZW50PihcIi5teF9Sb29tU3VibGlzdF9zdGlja2FibGVcIik7XG4gICAgICAgICAgICBpZiAoIWhlYWRlcikgY29udGludWU7IC8vIHRoaXMgc2hvdWxkIG5ldmVyIG9jY3VyXG4gICAgICAgICAgICBoZWFkZXIuc3R5bGUucmVtb3ZlUHJvcGVydHkoXCJkaXNwbGF5XCIpOyAvLyBhbHdheXMgY2xlYXIgZGlzcGxheTpub25lIGZpcnN0XG5cbiAgICAgICAgICAgIC8vIFdoZW4gYW4gZWxlbWVudCBpcyA8PTQwJSBvZmYgc2NyZWVuLCBtYWtlIGl0IHRha2Ugb3ZlclxuICAgICAgICAgICAgY29uc3Qgb2ZmU2NyZWVuRmFjdG9yID0gMC40O1xuICAgICAgICAgICAgY29uc3QgaXNPZmZUb3AgPSBzdWJsaXN0Lm9mZnNldFRvcCArIG9mZlNjcmVlbkZhY3RvciAqIEhFQURFUl9IRUlHSFQgPD0gdG9wRWRnZTtcbiAgICAgICAgICAgIGNvbnN0IGlzT2ZmQm90dG9tID0gc3VibGlzdC5vZmZzZXRUb3AgKyBvZmZTY3JlZW5GYWN0b3IgKiBIRUFERVJfSEVJR0hUID49IGJvdHRvbUVkZ2U7XG5cbiAgICAgICAgICAgIGlmIChpc09mZlRvcCB8fCBzdWJsaXN0ID09PSBzdWJsaXN0c1swXSkge1xuICAgICAgICAgICAgICAgIHRhcmdldFN0eWxlcy5zZXQoaGVhZGVyLCB7IHN0aWNreVRvcDogdHJ1ZSB9KTtcbiAgICAgICAgICAgICAgICBpZiAobGFzdFRvcEhlYWRlcikge1xuICAgICAgICAgICAgICAgICAgICBsYXN0VG9wSGVhZGVyLnN0eWxlLmRpc3BsYXkgPSBcIm5vbmVcIjtcbiAgICAgICAgICAgICAgICAgICAgdGFyZ2V0U3R5bGVzLnNldChsYXN0VG9wSGVhZGVyLCB7IG1ha2VJbnZpc2libGU6IHRydWUgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGxhc3RUb3BIZWFkZXIgPSBoZWFkZXI7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGlzT2ZmQm90dG9tICYmICFmaXJzdEJvdHRvbUhlYWRlcikge1xuICAgICAgICAgICAgICAgIHRhcmdldFN0eWxlcy5zZXQoaGVhZGVyLCB7IHN0aWNreUJvdHRvbTogdHJ1ZSB9KTtcbiAgICAgICAgICAgICAgICBmaXJzdEJvdHRvbUhlYWRlciA9IGhlYWRlcjtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGFyZ2V0U3R5bGVzLnNldChoZWFkZXIsIHt9KTsgLy8gbm90aGluZyA9PSBjbGVhclxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gUnVuIG92ZXIgdGhlIHN0eWxlIGNoYW5nZXMgYW5kIG1ha2UgdGhlbSByZWFsaXR5LiBXZSBjaGVjayB0byBzZWUgaWYgd2UncmUgYWJvdXQgdG9cbiAgICAgICAgLy8gY2F1c2UgYSBuby1vcCB1cGRhdGUsIGFzIGFkZGluZy9yZW1vdmluZyBwcm9wZXJ0aWVzIHRoYXQgYXJlL2FyZW4ndCB0aGVyZSBjYXVzZVxuICAgICAgICAvLyBsYXlvdXQgdXBkYXRlcy5cbiAgICAgICAgZm9yIChjb25zdCBoZWFkZXIgb2YgdGFyZ2V0U3R5bGVzLmtleXMoKSkge1xuICAgICAgICAgICAgY29uc3Qgc3R5bGUgPSB0YXJnZXRTdHlsZXMuZ2V0KGhlYWRlcikhO1xuXG4gICAgICAgICAgICBpZiAoc3R5bGUubWFrZUludmlzaWJsZSkge1xuICAgICAgICAgICAgICAgIC8vIHdlIHdpbGwgaGF2ZSBhbHJlYWR5IHJlbW92ZWQgdGhlICdkaXNwbGF5OiBub25lJywgc28gYWRkIGl0IGJhY2suXG4gICAgICAgICAgICAgICAgaGVhZGVyLnN0eWxlLmRpc3BsYXkgPSBcIm5vbmVcIjtcbiAgICAgICAgICAgICAgICBjb250aW51ZTsgLy8gbm90aGluZyBlbHNlIHRvIGRvLCBldmVuIGlmIHN0aWNreSBzb21laG93XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChzdHlsZS5zdGlja3lUb3ApIHtcbiAgICAgICAgICAgICAgICBpZiAoIWhlYWRlci5jbGFzc0xpc3QuY29udGFpbnMoXCJteF9Sb29tU3VibGlzdF9oZWFkZXJDb250YWluZXJfc3RpY2t5VG9wXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGhlYWRlci5jbGFzc0xpc3QuYWRkKFwibXhfUm9vbVN1Ymxpc3RfaGVhZGVyQ29udGFpbmVyX3N0aWNreVRvcFwiKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBjb25zdCBuZXdUb3AgPSBgJHtsaXN0LnBhcmVudEVsZW1lbnQub2Zmc2V0VG9wfXB4YDtcbiAgICAgICAgICAgICAgICBpZiAoaGVhZGVyLnN0eWxlLnRvcCAhPT0gbmV3VG9wKSB7XG4gICAgICAgICAgICAgICAgICAgIGhlYWRlci5zdHlsZS50b3AgPSBuZXdUb3A7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAoaGVhZGVyLmNsYXNzTGlzdC5jb250YWlucyhcIm14X1Jvb21TdWJsaXN0X2hlYWRlckNvbnRhaW5lcl9zdGlja3lUb3BcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgaGVhZGVyLmNsYXNzTGlzdC5yZW1vdmUoXCJteF9Sb29tU3VibGlzdF9oZWFkZXJDb250YWluZXJfc3RpY2t5VG9wXCIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoaGVhZGVyLnN0eWxlLnRvcCkge1xuICAgICAgICAgICAgICAgICAgICBoZWFkZXIuc3R5bGUucmVtb3ZlUHJvcGVydHkoXCJ0b3BcIik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoc3R5bGUuc3RpY2t5Qm90dG9tKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFoZWFkZXIuY2xhc3NMaXN0LmNvbnRhaW5zKFwibXhfUm9vbVN1Ymxpc3RfaGVhZGVyQ29udGFpbmVyX3N0aWNreUJvdHRvbVwiKSkge1xuICAgICAgICAgICAgICAgICAgICBoZWFkZXIuY2xhc3NMaXN0LmFkZChcIm14X1Jvb21TdWJsaXN0X2hlYWRlckNvbnRhaW5lcl9zdGlja3lCb3R0b21cIik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgY29uc3Qgb2Zmc2V0ID1cbiAgICAgICAgICAgICAgICAgICAgVUlTdG9yZS5pbnN0YW5jZS53aW5kb3dIZWlnaHQgLSAobGlzdC5wYXJlbnRFbGVtZW50Lm9mZnNldFRvcCArIGxpc3QucGFyZW50RWxlbWVudC5vZmZzZXRIZWlnaHQpO1xuICAgICAgICAgICAgICAgIGNvbnN0IG5ld0JvdHRvbSA9IGAke29mZnNldH1weGA7XG4gICAgICAgICAgICAgICAgaWYgKGhlYWRlci5zdHlsZS5ib3R0b20gIT09IG5ld0JvdHRvbSkge1xuICAgICAgICAgICAgICAgICAgICBoZWFkZXIuc3R5bGUuYm90dG9tID0gbmV3Qm90dG9tO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKGhlYWRlci5jbGFzc0xpc3QuY29udGFpbnMoXCJteF9Sb29tU3VibGlzdF9oZWFkZXJDb250YWluZXJfc3RpY2t5Qm90dG9tXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGhlYWRlci5jbGFzc0xpc3QucmVtb3ZlKFwibXhfUm9vbVN1Ymxpc3RfaGVhZGVyQ29udGFpbmVyX3N0aWNreUJvdHRvbVwiKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGhlYWRlci5zdHlsZS5ib3R0b20pIHtcbiAgICAgICAgICAgICAgICAgICAgaGVhZGVyLnN0eWxlLnJlbW92ZVByb3BlcnR5KFwiYm90dG9tXCIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHN0eWxlLnN0aWNreVRvcCB8fCBzdHlsZS5zdGlja3lCb3R0b20pIHtcbiAgICAgICAgICAgICAgICBpZiAoIWhlYWRlci5jbGFzc0xpc3QuY29udGFpbnMoXCJteF9Sb29tU3VibGlzdF9oZWFkZXJDb250YWluZXJfc3RpY2t5XCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGhlYWRlci5jbGFzc0xpc3QuYWRkKFwibXhfUm9vbVN1Ymxpc3RfaGVhZGVyQ29udGFpbmVyX3N0aWNreVwiKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBjb25zdCBsaXN0RGltZW5zaW9ucyA9IFVJU3RvcmUuaW5zdGFuY2UuZ2V0RWxlbWVudERpbWVuc2lvbnMoXCJMaXN0Q29udGFpbmVyXCIpO1xuICAgICAgICAgICAgICAgIGlmIChsaXN0RGltZW5zaW9ucykge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBoZWFkZXJSaWdodE1hcmdpbiA9IDE1OyAvLyBjYWxjdWxhdGVkIGZyb20gbWFyZ2lucyBhbmQgd2lkdGhzIHRvIGFsaWduIHdpdGggbm9uLXN0aWNreSB0aWxlc1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBoZWFkZXJTdGlja3lXaWR0aCA9IGxpc3REaW1lbnNpb25zLndpZHRoIC0gaGVhZGVyUmlnaHRNYXJnaW47XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IG5ld1dpZHRoID0gYCR7aGVhZGVyU3RpY2t5V2lkdGh9cHhgO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaGVhZGVyLnN0eWxlLndpZHRoICE9PSBuZXdXaWR0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaGVhZGVyLnN0eWxlLndpZHRoID0gbmV3V2lkdGg7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2UgaWYgKCFzdHlsZS5zdGlja3lUb3AgJiYgIXN0eWxlLnN0aWNreUJvdHRvbSkge1xuICAgICAgICAgICAgICAgIGlmIChoZWFkZXIuY2xhc3NMaXN0LmNvbnRhaW5zKFwibXhfUm9vbVN1Ymxpc3RfaGVhZGVyQ29udGFpbmVyX3N0aWNreVwiKSkge1xuICAgICAgICAgICAgICAgICAgICBoZWFkZXIuY2xhc3NMaXN0LnJlbW92ZShcIm14X1Jvb21TdWJsaXN0X2hlYWRlckNvbnRhaW5lcl9zdGlja3lcIik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGhlYWRlci5zdHlsZS53aWR0aCkge1xuICAgICAgICAgICAgICAgICAgICBoZWFkZXIuc3R5bGUucmVtb3ZlUHJvcGVydHkoXCJ3aWR0aFwiKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBhZGQgYXBwcm9wcmlhdGUgc3RpY2t5IGNsYXNzZXMgdG8gd3JhcHBlciBzbyBpdCBoYXNcbiAgICAgICAgLy8gdGhlIG5lY2Vzc2FyeSB0b3AvYm90dG9tIHBhZGRpbmcgdG8gcHV0IHRoZSBzdGlja3kgaGVhZGVyIGluXG4gICAgICAgIGNvbnN0IGxpc3RXcmFwcGVyID0gbGlzdC5wYXJlbnRFbGVtZW50OyAvLyAubXhfTGVmdFBhbmVsX3Jvb21MaXN0V3JhcHBlclxuICAgICAgICBpZiAoIWxpc3RXcmFwcGVyKSByZXR1cm47XG4gICAgICAgIGlmIChsYXN0VG9wSGVhZGVyKSB7XG4gICAgICAgICAgICBsaXN0V3JhcHBlci5jbGFzc0xpc3QuYWRkKFwibXhfTGVmdFBhbmVsX3Jvb21MaXN0V3JhcHBlcl9zdGlja3lUb3BcIik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBsaXN0V3JhcHBlci5jbGFzc0xpc3QucmVtb3ZlKFwibXhfTGVmdFBhbmVsX3Jvb21MaXN0V3JhcHBlcl9zdGlja3lUb3BcIik7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGZpcnN0Qm90dG9tSGVhZGVyKSB7XG4gICAgICAgICAgICBsaXN0V3JhcHBlci5jbGFzc0xpc3QuYWRkKFwibXhfTGVmdFBhbmVsX3Jvb21MaXN0V3JhcHBlcl9zdGlja3lCb3R0b21cIik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBsaXN0V3JhcHBlci5jbGFzc0xpc3QucmVtb3ZlKFwibXhfTGVmdFBhbmVsX3Jvb21MaXN0V3JhcHBlcl9zdGlja3lCb3R0b21cIik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIG9uU2Nyb2xsID0gKGV2OiBFdmVudCk6IHZvaWQgPT4ge1xuICAgICAgICBjb25zdCBsaXN0ID0gZXYudGFyZ2V0IGFzIEhUTUxEaXZFbGVtZW50O1xuICAgICAgICB0aGlzLmhhbmRsZVN0aWNreUhlYWRlcnMobGlzdCk7XG4gICAgfTtcblxuICAgIHByaXZhdGUgb25Gb2N1cyA9IChldjogUmVhY3QuRm9jdXNFdmVudCk6IHZvaWQgPT4ge1xuICAgICAgICB0aGlzLmZvY3VzZWRFbGVtZW50ID0gZXYudGFyZ2V0O1xuICAgIH07XG5cbiAgICBwcml2YXRlIG9uQmx1ciA9ICgpOiB2b2lkID0+IHtcbiAgICAgICAgdGhpcy5mb2N1c2VkRWxlbWVudCA9IG51bGw7XG4gICAgfTtcblxuICAgIHByaXZhdGUgb25LZXlEb3duID0gKGV2OiBSZWFjdC5LZXlib2FyZEV2ZW50LCBzdGF0ZT86IElSb3ZpbmdUYWJJbmRleFN0YXRlKTogdm9pZCA9PiB7XG4gICAgICAgIGlmICghdGhpcy5mb2N1c2VkRWxlbWVudCkgcmV0dXJuO1xuXG4gICAgICAgIGNvbnN0IGFjdGlvbiA9IGdldEtleUJpbmRpbmdzTWFuYWdlcigpLmdldFJvb21MaXN0QWN0aW9uKGV2KTtcbiAgICAgICAgc3dpdGNoIChhY3Rpb24pIHtcbiAgICAgICAgICAgIGNhc2UgS2V5QmluZGluZ0FjdGlvbi5OZXh0Um9vbTpcbiAgICAgICAgICAgICAgICBpZiAoIXN0YXRlKSB7XG4gICAgICAgICAgICAgICAgICAgIGV2LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICAgICAgICAgICAgICBldi5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnJvb21MaXN0UmVmLmN1cnJlbnQ/LmZvY3VzKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgbmF2QWN0aW9uID0gZ2V0S2V5QmluZGluZ3NNYW5hZ2VyKCkuZ2V0TmF2aWdhdGlvbkFjdGlvbihldik7XG4gICAgICAgIGlmIChuYXZBY3Rpb24gPT09IEtleUJpbmRpbmdBY3Rpb24uUHJldmlvdXNMYW5kbWFyayB8fCBuYXZBY3Rpb24gPT09IEtleUJpbmRpbmdBY3Rpb24uTmV4dExhbmRtYXJrKSB7XG4gICAgICAgICAgICBldi5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgICAgIGV2LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICBMYW5kbWFya05hdmlnYXRpb24uZmluZEFuZEZvY3VzTmV4dExhbmRtYXJrKFxuICAgICAgICAgICAgICAgIExhbmRtYXJrLlJPT01fU0VBUkNILFxuICAgICAgICAgICAgICAgIG5hdkFjdGlvbiA9PT0gS2V5QmluZGluZ0FjdGlvbi5QcmV2aW91c0xhbmRtYXJrLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBwcml2YXRlIHJlbmRlckJyZWFkY3J1bWJzKCk6IFJlYWN0LlJlYWN0Tm9kZSB7XG4gICAgICAgIGlmICh0aGlzLnN0YXRlLnNob3dCcmVhZGNydW1icyA9PT0gQnJlYWRjcnVtYnNNb2RlLkxlZ2FjeSAmJiAhdGhpcy5wcm9wcy5pc01pbmltaXplZCkge1xuICAgICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgICAgICA8SW5kaWNhdG9yU2Nyb2xsYmFyXG4gICAgICAgICAgICAgICAgICAgIHJvbGU9XCJuYXZpZ2F0aW9uXCJcbiAgICAgICAgICAgICAgICAgICAgYXJpYS1sYWJlbD17X3QoXCJhMTF5fHJlY2VudF9yb29tc1wiKX1cbiAgICAgICAgICAgICAgICAgICAgY2xhc3NOYW1lPVwibXhfTGVmdFBhbmVsX2JyZWFkY3J1bWJzQ29udGFpbmVyIG14X0F1dG9IaWRlU2Nyb2xsYmFyXCJcbiAgICAgICAgICAgICAgICAgICAgdmVydGljYWxTY3JvbGxzSG9yaXpvbnRhbGx5PXt0cnVlfVxuICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAgPFJvb21CcmVhZGNydW1icyAvPlxuICAgICAgICAgICAgICAgIDwvSW5kaWNhdG9yU2Nyb2xsYmFyPlxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgcmVuZGVyU2VhcmNoRGlhbEV4cGxvcmUoKTogUmVhY3QuUmVhY3ROb2RlIHtcbiAgICAgICAgbGV0IGRpYWxQYWRCdXR0b246IEpTWC5FbGVtZW50IHwgdW5kZWZpbmVkO1xuXG4gICAgICAgIC8vIElmIHdlIGhhdmUgZGlhbGVyIHN1cHBvcnQsIHNob3cgYSBidXR0b24gdG8gYnJpbmcgdXAgdGhlIGRpYWwgcGFkXG4gICAgICAgIC8vIHRvIHN0YXJ0IGEgbmV3IGNhbGxcbiAgICAgICAgaWYgKExlZ2FjeUNhbGxIYW5kbGVyLmluc3RhbmNlLmdldFN1cHBvcnRzUHN0blByb3RvY29sKCkpIHtcbiAgICAgICAgICAgIGRpYWxQYWRCdXR0b24gPSAoXG4gICAgICAgICAgICAgICAgPEFjY2Vzc2libGVCdXR0b25cbiAgICAgICAgICAgICAgICAgICAgY2xhc3NOYW1lPXtjbGFzc05hbWVzKFwibXhfTGVmdFBhbmVsX2RpYWxQYWRCdXR0b25cIiwge30pfVxuICAgICAgICAgICAgICAgICAgICBvbkNsaWNrPXt0aGlzLm9uRGlhbFBhZH1cbiAgICAgICAgICAgICAgICAgICAgdGl0bGU9e190KFwibGVmdF9wYW5lbHxvcGVuX2RpYWxfcGFkXCIpfVxuICAgICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHJpZ2h0QnV0dG9uOiBKU1guRWxlbWVudCB8IHVuZGVmaW5lZDtcbiAgICAgICAgaWYgKHRoaXMuc3RhdGUuYWN0aXZlU3BhY2UgPT09IE1ldGFTcGFjZS5Ib21lICYmIHNob3VsZFNob3dDb21wb25lbnQoVUlDb21wb25lbnQuRXhwbG9yZVJvb21zKSkge1xuICAgICAgICAgICAgcmlnaHRCdXR0b24gPSAoXG4gICAgICAgICAgICAgICAgPEFjY2Vzc2libGVCdXR0b25cbiAgICAgICAgICAgICAgICAgICAgY2xhc3NOYW1lPVwibXhfTGVmdFBhbmVsX2V4cGxvcmVCdXR0b25cIlxuICAgICAgICAgICAgICAgICAgICBvbkNsaWNrPXt0aGlzLm9uRXhwbG9yZX1cbiAgICAgICAgICAgICAgICAgICAgdGl0bGU9e190KFwiYWN0aW9ufGV4cGxvcmVfcm9vbXNcIil9XG4gICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgPGRpdlxuICAgICAgICAgICAgICAgIGNsYXNzTmFtZT1cIm14X0xlZnRQYW5lbF9maWx0ZXJDb250YWluZXJcIlxuICAgICAgICAgICAgICAgIG9uRm9jdXM9e3RoaXMub25Gb2N1c31cbiAgICAgICAgICAgICAgICBvbkJsdXI9e3RoaXMub25CbHVyfVxuICAgICAgICAgICAgICAgIG9uS2V5RG93bj17dGhpcy5vbktleURvd259XG4gICAgICAgICAgICAgICAgcm9sZT1cInNlYXJjaFwiXG4gICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgPFJvb21TZWFyY2ggaXNNaW5pbWl6ZWQ9e3RoaXMucHJvcHMuaXNNaW5pbWl6ZWR9IC8+XG5cbiAgICAgICAgICAgICAgICB7ZGlhbFBhZEJ1dHRvbn1cbiAgICAgICAgICAgICAgICB7cmlnaHRCdXR0b259XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgcmVuZGVyKCk6IFJlYWN0LlJlYWN0Tm9kZSB7XG4gICAgICAgIGNvbnN0IHJvb21MaXN0ID0gKFxuICAgICAgICAgICAgPFJvb21MaXN0XG4gICAgICAgICAgICAgICAgb25LZXlEb3duPXt0aGlzLm9uS2V5RG93bn1cbiAgICAgICAgICAgICAgICByZXNpemVOb3RpZmllcj17dGhpcy5wcm9wcy5yZXNpemVOb3RpZmllcn1cbiAgICAgICAgICAgICAgICBvbkZvY3VzPXt0aGlzLm9uRm9jdXN9XG4gICAgICAgICAgICAgICAgb25CbHVyPXt0aGlzLm9uQmx1cn1cbiAgICAgICAgICAgICAgICBpc01pbmltaXplZD17dGhpcy5wcm9wcy5pc01pbmltaXplZH1cbiAgICAgICAgICAgICAgICBhY3RpdmVTcGFjZT17dGhpcy5zdGF0ZS5hY3RpdmVTcGFjZX1cbiAgICAgICAgICAgICAgICBvblJlc2l6ZT17dGhpcy5yZWZyZXNoU3RpY2t5SGVhZGVyc31cbiAgICAgICAgICAgICAgICBvbkxpc3RDb2xsYXBzZT17dGhpcy5yZWZyZXNoU3RpY2t5SGVhZGVyc31cbiAgICAgICAgICAgICAgICByZWY9e3RoaXMucm9vbUxpc3RSZWZ9XG4gICAgICAgICAgICAvPlxuICAgICAgICApO1xuXG4gICAgICAgIGNvbnN0IGNvbnRhaW5lckNsYXNzZXMgPSBjbGFzc05hbWVzKHtcbiAgICAgICAgICAgIG14X0xlZnRQYW5lbDogdHJ1ZSxcbiAgICAgICAgICAgIG14X0xlZnRQYW5lbF9taW5pbWl6ZWQ6IHRoaXMucHJvcHMuaXNNaW5pbWl6ZWQsXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGNvbnN0IHJvb21MaXN0Q2xhc3NlcyA9IGNsYXNzTmFtZXMoXCJteF9MZWZ0UGFuZWxfYWN0dWFsUm9vbUxpc3RDb250YWluZXJcIiwgXCJteF9BdXRvSGlkZVNjcm9sbGJhclwiKTtcblxuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgPGRpdiBjbGFzc05hbWU9e2NvbnRhaW5lckNsYXNzZXN9PlxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3NOYW1lPVwibXhfTGVmdFBhbmVsX3Jvb21MaXN0Q29udGFpbmVyXCI+XG4gICAgICAgICAgICAgICAgICAgIHtzaG91bGRTaG93Q29tcG9uZW50KFVJQ29tcG9uZW50LkZpbHRlckNvbnRhaW5lcikgJiYgdGhpcy5yZW5kZXJTZWFyY2hEaWFsRXhwbG9yZSgpfVxuICAgICAgICAgICAgICAgICAgICB7dGhpcy5yZW5kZXJCcmVhZGNydW1icygpfVxuICAgICAgICAgICAgICAgICAgICB7IXRoaXMucHJvcHMuaXNNaW5pbWl6ZWQgJiYgPFJvb21MaXN0SGVhZGVyIG9uVmlzaWJpbGl0eUNoYW5nZT17dGhpcy5yZWZyZXNoU3RpY2t5SGVhZGVyc30gLz59XG4gICAgICAgICAgICAgICAgICAgIDxVc2VyT25ib2FyZGluZ0J1dHRvblxuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZWN0ZWQ9e3RoaXMucHJvcHMucGFnZVR5cGUgPT09IFBhZ2VUeXBlLkhvbWVQYWdlfVxuICAgICAgICAgICAgICAgICAgICAgICAgbWluaW1pemVkPXt0aGlzLnByb3BzLmlzTWluaW1pemVkfVxuICAgICAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICAgICAgICA8bmF2IGNsYXNzTmFtZT1cIm14X0xlZnRQYW5lbF9yb29tTGlzdFdyYXBwZXJcIiBhcmlhLWxhYmVsPXtfdChcImNvbW1vbnxyb29tc1wiKX0+XG4gICAgICAgICAgICAgICAgICAgICAgICA8ZGl2XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3NOYW1lPXtyb29tTGlzdENsYXNzZXN9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVmPXt0aGlzLmxpc3RDb250YWluZXJSZWZ9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRmlyZWZveCBzb21ldGltZXMgbWFrZXMgdGhpcyBlbGVtZW50IGZvY3VzYWJsZSBkdWUgdG9cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBvdmVyZmxvdzpzY3JvbGw7LCBzbyBmb3JjZSBpdCBvdXQgb2YgdGFiIG9yZGVyLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhYkluZGV4PXstMX1cbiAgICAgICAgICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB7cm9vbUxpc3R9XG4gICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgPC9uYXY+XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgKTtcbiAgICB9XG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7O0FBUUEsSUFBQUEsTUFBQSxHQUFBQyx1QkFBQSxDQUFBQyxPQUFBO0FBQStCLElBQUFDLEtBQUEsR0FBQUgsTUFBQTtBQUUvQixJQUFBSSxXQUFBLEdBQUFDLHNCQUFBLENBQUFILE9BQUE7QUFFQSxJQUFBSSxXQUFBLEdBQUFELHNCQUFBLENBQUFILE9BQUE7QUFDQSxJQUFBSyxnQkFBQSxHQUFBTCxPQUFBO0FBQ0EsSUFBQU0sU0FBQSxHQUFBSCxzQkFBQSxDQUFBSCxPQUFBO0FBQ0EsSUFBQU8sa0JBQUEsR0FBQUosc0JBQUEsQ0FBQUgsT0FBQTtBQUNBLElBQUFRLFlBQUEsR0FBQVIsT0FBQTtBQUNBLElBQUFTLFFBQUEsR0FBQVQsT0FBQTtBQUNBLElBQUFVLFdBQUEsR0FBQVAsc0JBQUEsQ0FBQUgsT0FBQTtBQUVBLElBQUFXLFdBQUEsR0FBQVIsc0JBQUEsQ0FBQUgsT0FBQTtBQUNBLElBQUFZLE9BQUEsR0FBQVosT0FBQTtBQUNBLElBQUFhLG1CQUFBLEdBQUFiLE9BQUE7QUFDQSxJQUFBYyxRQUFBLEdBQUFYLHNCQUFBLENBQUFILE9BQUE7QUFFQSxJ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