UNPKG

matrix-react-sdk

Version:
360 lines (352 loc) 62.5 kB
"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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