UNPKG

matrix-react-sdk

Version:
379 lines (375 loc) 67.7 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.defaultSpacesRenderer = exports.defaultRoomsRenderer = exports.defaultDmsRenderer = exports.default = exports.SubspaceSelector = exports.Entry = exports.AddExistingToSpace = void 0; var _react = _interopRequireWildcard(require("react")); var _classnames = _interopRequireDefault(require("classnames")); var _matrix = require("matrix-js-sdk/src/matrix"); var _types = require("matrix-js-sdk/src/types"); var _utils = require("matrix-js-sdk/src/utils"); var _logger = require("matrix-js-sdk/src/logger"); var _languageHandler = require("../../../languageHandler"); var _BaseDialog = _interopRequireDefault(require("./BaseDialog")); var _Dropdown = _interopRequireDefault(require("../elements/Dropdown")); var _SearchBox = _interopRequireDefault(require("../../structures/SearchBox")); var _SpaceStore = _interopRequireDefault(require("../../../stores/spaces/SpaceStore")); var _RoomAvatar = _interopRequireDefault(require("../avatars/RoomAvatar")); var _Rooms = require("../../../Rooms"); var _AccessibleButton = _interopRequireDefault(require("../elements/AccessibleButton")); var _AutoHideScrollbar = _interopRequireDefault(require("../../structures/AutoHideScrollbar")); var _DMRoomMap = _interopRequireDefault(require("../../../utils/DMRoomMap")); var _Permalinks = require("../../../utils/permalinks/Permalinks"); var _StyledCheckbox = _interopRequireDefault(require("../elements/StyledCheckbox")); var _MatrixClientContext = _interopRequireDefault(require("../../../contexts/MatrixClientContext")); var _RecentAlgorithm = require("../../../stores/room-list/algorithms/tag-sorting/RecentAlgorithm"); var _ProgressBar = _interopRequireDefault(require("../elements/ProgressBar")); var _DecoratedRoomAvatar = _interopRequireDefault(require("../avatars/DecoratedRoomAvatar")); var _QueryMatcher = _interopRequireDefault(require("../../../autocomplete/QueryMatcher")); var _LazyRenderList = _interopRequireDefault(require("../elements/LazyRenderList")); var _useSettings = require("../../../hooks/useSettings"); var _arrays = require("../../../utils/arrays"); 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 2021 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. */ // These values match CSS const ROW_HEIGHT = 32 + 12; const HEADER_HEIGHT = 15; const GROUP_MARGIN = 24; const Entry = ({ room, checked, onChange }) => { return /*#__PURE__*/_react.default.createElement("label", { className: "mx_AddExistingToSpace_entry" }, room?.isSpaceRoom() ? /*#__PURE__*/_react.default.createElement(_RoomAvatar.default, { room: room, size: "32px" }) : /*#__PURE__*/_react.default.createElement(_DecoratedRoomAvatar.default, { room: room, size: "32px" }), /*#__PURE__*/_react.default.createElement("span", { className: "mx_AddExistingToSpace_entry_name" }, room.name), /*#__PURE__*/_react.default.createElement(_StyledCheckbox.default, { onChange: onChange ? e => onChange(e.currentTarget.checked) : undefined, checked: checked, disabled: !onChange })); }; exports.Entry = Entry; const getScrollState = ({ scrollTop, height }, numItems, ...prevGroupSizes) => { let heightBefore = 0; prevGroupSizes.forEach(size => { heightBefore += GROUP_MARGIN + HEADER_HEIGHT + size * ROW_HEIGHT; }); const viewportTop = scrollTop; const viewportBottom = viewportTop + height; const listTop = heightBefore + HEADER_HEIGHT; const listBottom = listTop + numItems * ROW_HEIGHT; const top = Math.max(viewportTop, listTop); const bottom = Math.min(viewportBottom, listBottom); // the viewport height and scrollTop passed to the LazyRenderList // is capped at the intersection with the real viewport, so lists // out of view are passed height 0, so they won't render any items. return { scrollTop: Math.max(0, scrollTop - listTop), height: Math.max(0, bottom - top) }; }; const AddExistingToSpace = ({ space, footerPrompt, emptySelectionButton, filterPlaceholder, roomsRenderer, dmsRenderer, spacesRenderer, onFinished }) => { const cli = (0, _react.useContext)(_MatrixClientContext.default); const msc3946ProcessDynamicPredecessor = (0, _useSettings.useSettingValue)("feature_dynamic_room_predecessors"); const visibleRooms = (0, _react.useMemo)(() => cli?.getVisibleRooms(msc3946ProcessDynamicPredecessor).filter(r => r.getMyMembership() === _types.KnownMembership.Join) ?? [], [cli, msc3946ProcessDynamicPredecessor]); const scrollRef = (0, _react.useRef)(null); const [scrollState, setScrollState] = (0, _react.useState)({ // these are estimates which update as soon as it mounts scrollTop: 0, height: 600 }); const [selectedToAdd, setSelectedToAdd] = (0, _react.useState)(new Set()); const [progress, setProgress] = (0, _react.useState)(null); const [error, setError] = (0, _react.useState)(false); const [query, setQuery] = (0, _react.useState)(""); const lcQuery = query.toLowerCase().trim(); const existingSubspacesSet = (0, _react.useMemo)(() => new Set(_SpaceStore.default.instance.getChildSpaces(space.roomId)), [space]); const existingRoomsSet = (0, _react.useMemo)(() => new Set(_SpaceStore.default.instance.getChildRooms(space.roomId)), [space]); const [spaces, rooms, dms] = (0, _react.useMemo)(() => { let rooms = visibleRooms; if (lcQuery) { const matcher = new _QueryMatcher.default(visibleRooms, { keys: ["name"], funcs: [r => (0, _arrays.filterBoolean)([r.getCanonicalAlias(), ...r.getAltAliases()])], shouldMatchWordsOnly: false }); rooms = matcher.match(lcQuery); } const joinRule = space.getJoinRule(); return (0, _RecentAlgorithm.sortRooms)(rooms).reduce((arr, room) => { if (room.isSpaceRoom()) { if (room !== space && !existingSubspacesSet.has(room)) { arr[0].push(room); } } else if (!existingRoomsSet.has(room)) { if (!_DMRoomMap.default.shared().getUserIdForRoomId(room.roomId)) { arr[1].push(room); } else if (joinRule !== "public") { // Only show DMs for non-public spaces as they make very little sense in spaces other than "Just Me" ones. arr[2].push(room); } } return arr; }, [[], [], []]); }, [visibleRooms, space, lcQuery, existingRoomsSet, existingSubspacesSet]); const addRooms = async () => { setError(false); setProgress(0); let error = false; for (const room of selectedToAdd) { const via = (0, _Permalinks.calculateRoomVia)(room); try { await _SpaceStore.default.instance.addRoomToSpace(space, room.roomId, via).catch(async e => { if (e.errcode === "M_LIMIT_EXCEEDED") { await (0, _utils.sleep)(e.data.retry_after_ms); await _SpaceStore.default.instance.addRoomToSpace(space, room.roomId, via); // retry return; } throw e; }); setProgress(i => (i ?? 0) + 1); } catch (e) { _logger.logger.error("Failed to add rooms to space", e); error = true; break; } } if (!error) { onFinished(true); } else { setError(error); } }; const busy = progress !== null; let footer; if (error) { footer = /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("img", { src: require("../../../../res/img/element-icons/warning-badge.svg").default, height: "24", width: "24", alt: "" }), /*#__PURE__*/_react.default.createElement("span", { className: "mx_AddExistingToSpaceDialog_error" }, /*#__PURE__*/_react.default.createElement("div", { className: "mx_AddExistingToSpaceDialog_errorHeading" }, (0, _languageHandler._t)("space|add_existing_room_space|error_heading")), /*#__PURE__*/_react.default.createElement("div", { className: "mx_AddExistingToSpaceDialog_errorCaption" }, (0, _languageHandler._t)("action|try_again"))), /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, { className: "mx_AddExistingToSpaceDialog_retryButton", onClick: addRooms }, (0, _languageHandler._t)("action|retry"))); } else if (busy) { footer = /*#__PURE__*/_react.default.createElement("span", null, /*#__PURE__*/_react.default.createElement(_ProgressBar.default, { value: progress, max: selectedToAdd.size }), /*#__PURE__*/_react.default.createElement("div", { className: "mx_AddExistingToSpaceDialog_progressText" }, (0, _languageHandler._t)("space|add_existing_room_space|progress_text", { count: selectedToAdd.size, progress }))); } else { let button = emptySelectionButton; if (!button || selectedToAdd.size > 0) { button = /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, { kind: "primary", disabled: selectedToAdd.size < 1, onClick: addRooms }, (0, _languageHandler._t)("action|add")); } footer = /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("span", null, footerPrompt), button); } const onChange = !busy && !error ? (checked, room) => { if (checked) { selectedToAdd.add(room); } else { selectedToAdd.delete(room); } setSelectedToAdd(new Set(selectedToAdd)); } : undefined; // only count spaces when alone as they're shown on a separate modal all on their own const numSpaces = spacesRenderer && !dmsRenderer && !roomsRenderer ? spaces.length : 0; const numRooms = roomsRenderer ? rooms.length : 0; const numDms = dmsRenderer ? dms.length : 0; let noResults = true; if (numSpaces > 0 || numRooms > 0 || numDms > 0) { noResults = false; } const onScroll = () => { const body = scrollRef.current?.containerRef.current; if (!body) return; setScrollState({ scrollTop: body.scrollTop, height: body.clientHeight }); }; const wrappedRef = body => { if (!body) return; setScrollState({ scrollTop: body.scrollTop, height: body.clientHeight }); }; const roomsScrollState = getScrollState(scrollState, numRooms); const spacesScrollState = getScrollState(scrollState, numSpaces, numRooms); const dmsScrollState = getScrollState(scrollState, numDms, numSpaces, numRooms); return /*#__PURE__*/_react.default.createElement("div", { className: "mx_AddExistingToSpace" }, /*#__PURE__*/_react.default.createElement(_SearchBox.default, { className: "mx_textinput_icon mx_textinput_search", placeholder: filterPlaceholder, onSearch: setQuery, autoFocus: true }), /*#__PURE__*/_react.default.createElement(_AutoHideScrollbar.default, { className: "mx_AddExistingToSpace_content", onScroll: onScroll, wrappedRef: wrappedRef, ref: scrollRef }, rooms.length > 0 && roomsRenderer ? roomsRenderer(rooms, selectedToAdd, roomsScrollState, onChange) : undefined, spaces.length > 0 && spacesRenderer ? spacesRenderer(spaces, selectedToAdd, spacesScrollState, onChange) : null, dms.length > 0 && dmsRenderer ? dmsRenderer(dms, selectedToAdd, dmsScrollState, onChange) : null, noResults ? /*#__PURE__*/_react.default.createElement("span", { className: "mx_AddExistingToSpace_noResults" }, (0, _languageHandler._t)("common|no_results")) : undefined), /*#__PURE__*/_react.default.createElement("div", { className: "mx_AddExistingToSpace_footer" }, footer)); }; exports.AddExistingToSpace = AddExistingToSpace; const defaultRendererFactory = title => (rooms, selectedToAdd, { scrollTop, height }, onChange) => /*#__PURE__*/_react.default.createElement("div", { className: "mx_AddExistingToSpace_section" }, /*#__PURE__*/_react.default.createElement("h3", null, (0, _languageHandler._t)(title)), /*#__PURE__*/_react.default.createElement(_LazyRenderList.default, { itemHeight: ROW_HEIGHT, items: rooms, scrollTop: scrollTop, height: height, renderItem: room => /*#__PURE__*/_react.default.createElement(Entry, { key: room.roomId, room: room, checked: selectedToAdd.has(room), onChange: onChange ? checked => { onChange(checked, room); } : undefined }) })); const defaultRoomsRenderer = exports.defaultRoomsRenderer = defaultRendererFactory((0, _languageHandler._td)("common|rooms")); const defaultSpacesRenderer = exports.defaultSpacesRenderer = defaultRendererFactory((0, _languageHandler._td)("common|spaces")); const defaultDmsRenderer = exports.defaultDmsRenderer = defaultRendererFactory((0, _languageHandler._td)("space|add_existing_room_space|dm_heading")); const SubspaceSelector = ({ title, space, value, onChange }) => { const options = (0, _react.useMemo)(() => { return [space, ..._SpaceStore.default.instance.getChildSpaces(space.roomId).filter(space => { return space.currentState.maySendStateEvent(_matrix.EventType.SpaceChild, space.client.getSafeUserId()); })]; }, [space]); let body; if (options.length > 1) { body = /*#__PURE__*/_react.default.createElement(_Dropdown.default, { id: "mx_SpaceSelectDropdown", className: "mx_SpaceSelectDropdown", onOptionChange: key => { onChange(options.find(space => space.roomId === key) || space); }, value: value.roomId, label: (0, _languageHandler._t)("space|add_existing_room_space|space_dropdown_label") }, options.map(space => { const classes = (0, _classnames.default)({ mx_SubspaceSelector_dropdownOptionActive: space === value }); return /*#__PURE__*/_react.default.createElement("div", { key: space.roomId, className: classes }, /*#__PURE__*/_react.default.createElement(_RoomAvatar.default, { room: space, size: "24px" }), space.name || (0, _Rooms.getDisplayAliasForRoom)(space) || space.roomId); })); } else { body = /*#__PURE__*/_react.default.createElement("div", { className: "mx_SubspaceSelector_onlySpace" }, space.name || (0, _Rooms.getDisplayAliasForRoom)(space) || space.roomId); } return /*#__PURE__*/_react.default.createElement("div", { className: "mx_SubspaceSelector" }, /*#__PURE__*/_react.default.createElement(_RoomAvatar.default, { room: value, size: "40px" }), /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("h1", null, title), body)); }; exports.SubspaceSelector = SubspaceSelector; const AddExistingToSpaceDialog = ({ space, onCreateRoomClick, onAddSubspaceClick, onFinished }) => { const [selectedSpace, setSelectedSpace] = (0, _react.useState)(space); return /*#__PURE__*/_react.default.createElement(_BaseDialog.default, { title: /*#__PURE__*/_react.default.createElement(SubspaceSelector, { title: (0, _languageHandler._t)("space|add_existing_room_space|space_dropdown_title"), space: space, value: selectedSpace, onChange: setSelectedSpace }), className: "mx_AddExistingToSpaceDialog", contentId: "mx_AddExistingToSpace", onFinished: onFinished, fixedWidth: false }, /*#__PURE__*/_react.default.createElement(_MatrixClientContext.default.Provider, { value: space.client }, /*#__PURE__*/_react.default.createElement(AddExistingToSpace, { space: space, onFinished: onFinished, footerPrompt: /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("div", null, (0, _languageHandler._t)("space|add_existing_room_space|create")), /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, { kind: "link", onClick: ev => { onCreateRoomClick(ev); onFinished(); } }, (0, _languageHandler._t)("space|add_existing_room_space|create_prompt"))), filterPlaceholder: (0, _languageHandler._t)("space|room_filter_placeholder"), roomsRenderer: defaultRoomsRenderer, spacesRenderer: () => /*#__PURE__*/_react.default.createElement("div", { className: "mx_AddExistingToSpace_section" }, /*#__PURE__*/_react.default.createElement("h3", null, (0, _languageHandler._t)("common|spaces")), /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, { kind: "link", onClick: () => { onAddSubspaceClick(); onFinished(); } }, (0, _languageHandler._t)("space|add_existing_room_space|subspace_moved_note"))), dmsRenderer: defaultDmsRenderer }))); }; var _default = exports.default = AddExistingToSpaceDialog; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfcmVhY3QiLCJfaW50ZXJvcFJlcXVpcmVXaWxkY2FyZCIsInJlcXVpcmUiLCJfY2xhc3NuYW1lcyIsIl9pbnRlcm9wUmVxdWlyZURlZmF1bHQiLCJfbWF0cml4IiwiX3R5cGVzIiwiX3V0aWxzIiwiX2xvZ2dlciIsIl9sYW5ndWFnZUhhbmRsZXIiLCJfQmFzZURpYWxvZyIsIl9Ecm9wZG93biIsIl9TZWFyY2hCb3giLCJfU3BhY2VTdG9yZSIsIl9Sb29tQXZhdGFyIiwiX1Jvb21zIiwiX0FjY2Vzc2libGVCdXR0b24iLCJfQXV0b0hpZGVTY3JvbGxiYXIiLCJfRE1Sb29tTWFwIiwiX1Blcm1hbGlua3MiLCJfU3R5bGVkQ2hlY2tib3giLCJfTWF0cml4Q2xpZW50Q29udGV4dCIsIl9SZWNlbnRBbGdvcml0aG0iLCJfUHJvZ3Jlc3NCYXIiLCJfRGVjb3JhdGVkUm9vbUF2YXRhciIsIl9RdWVyeU1hdGNoZXIiLCJfTGF6eVJlbmRlckxpc3QiLCJfdXNlU2V0dGluZ3MiLCJfYXJyYXlzIiwiX2dldFJlcXVpcmVXaWxkY2FyZENhY2hlIiwiZSIsIldlYWtNYXAiLCJyIiwidCIsIl9fZXNNb2R1bGUiLCJkZWZhdWx0IiwiaGFzIiwiZ2V0IiwibiIsIl9fcHJvdG9fXyIsImEiLCJPYmplY3QiLCJkZWZpbmVQcm9wZXJ0eSIsImdldE93blByb3BlcnR5RGVzY3JpcHRvciIsInUiLCJoYXNPd25Qcm9wZXJ0eSIsImNhbGwiLCJpIiwic2V0IiwiUk9XX0hFSUdIVCIsIkhFQURFUl9IRUlHSFQiLCJHUk9VUF9NQVJHSU4iLCJFbnRyeSIsInJvb20iLCJjaGVja2VkIiwib25DaGFuZ2UiLCJjcmVhdGVFbGVtZW50IiwiY2xhc3NOYW1lIiwiaXNTcGFjZVJvb20iLCJzaXplIiwibmFtZSIsImN1cnJlbnRUYXJnZXQiLCJ1bmRlZmluZWQiLCJkaXNhYmxlZCIsImV4cG9ydHMiLCJnZXRTY3JvbGxTdGF0ZSIsInNjcm9sbFRvcCIsImhlaWdodCIsIm51bUl0ZW1zIiwicHJldkdyb3VwU2l6ZXMiLCJoZWlnaHRCZWZvcmUiLCJmb3JFYWNoIiwidmlld3BvcnRUb3AiLCJ2aWV3cG9ydEJvdHRvbSIsImxpc3RUb3AiLCJsaXN0Qm90dG9tIiwidG9wIiwiTWF0aCIsIm1heCIsImJvdHRvbSIsIm1pbiIsIkFkZEV4aXN0aW5nVG9TcGFjZSIsInNwYWNlIiwiZm9vdGVyUHJvbXB0IiwiZW1wdHlTZWxlY3Rpb25CdXR0b24iLCJmaWx0ZXJQbGFjZWhvbGRlciIsInJvb21zUmVuZGVyZXIiLCJkbXNSZW5kZXJlciIsInNwYWNlc1JlbmRlcmVyIiwib25GaW5pc2hlZCIsImNsaSIsInVzZUNvbnRleHQiLCJNYXRyaXhDbGllbnRDb250ZXh0IiwibXNjMzk0NlByb2Nlc3NEeW5hbWljUHJlZGVjZXNzb3IiLCJ1c2VTZXR0aW5nVmFsdWUiLCJ2aXNpYmxlUm9vbXMiLCJ1c2VNZW1vIiwiZ2V0VmlzaWJsZVJvb21zIiwiZmlsdGVyIiwiZ2V0TXlNZW1iZXJzaGlwIiwiS25vd25NZW1iZXJzaGlwIiwiSm9pbiIsInNjcm9sbFJlZiIsInVzZVJlZiIsInNjcm9sbFN0YXRlIiwic2V0U2Nyb2xsU3RhdGUiLCJ1c2VTdGF0ZSIsInNlbGVjdGVkVG9BZGQiLCJzZXRTZWxlY3RlZFRvQWRkIiwiU2V0IiwicHJvZ3Jlc3MiLCJzZXRQcm9ncmVzcyIsImVycm9yIiwic2V0RXJyb3IiLCJxdWVyeSIsInNldFF1ZXJ5IiwibGNRdWVyeSIsInRvTG93ZXJDYXNlIiwidHJpbSIsImV4aXN0aW5nU3Vic3BhY2VzU2V0IiwiU3BhY2VTdG9yZSIsImluc3RhbmNlIiwiZ2V0Q2hpbGRTcGFjZXMiLCJyb29tSWQiLCJleGlzdGluZ1Jvb21zU2V0IiwiZ2V0Q2hpbGRSb29tcyIsInNwYWNlcyIsInJvb21zIiwiZG1zIiwibWF0Y2hlciIsIlF1ZXJ5TWF0Y2hlciIsImtleXMiLCJmdW5jcyIsImZpbHRlckJvb2xlYW4iLCJnZXRDYW5vbmljYWxBbGlhcyIsImdldEFsdEFsaWFzZXMiLCJzaG91bGRNYXRjaFdvcmRzT25seSIsIm1hdGNoIiwiam9pblJ1bGUiLCJnZXRKb2luUnVsZSIsInNvcnRSb29tcyIsInJlZHVjZSIsImFyciIsInB1c2giLCJETVJvb21NYXAiLCJzaGFyZWQiLCJnZXRVc2VySWRGb3JSb29tSWQiLCJhZGRSb29tcyIsInZpYSIsImNhbGN1bGF0ZVJvb21WaWEiLCJhZGRSb29tVG9TcGFjZSIsImNhdGNoIiwiZXJyY29kZSIsInNsZWVwIiwiZGF0YSIsInJldHJ5X2FmdGVyX21zIiwibG9nZ2VyIiwiYnVzeSIsImZvb3RlciIsIkZyYWdtZW50Iiwic3JjIiwid2lkdGgiLCJhbHQiLCJfdCIsIm9uQ2xpY2siLCJ2YWx1ZSIsImNvdW50IiwiYnV0dG9uIiwia2luZCIsImFkZCIsImRlbGV0ZSIsIm51bVNwYWNlcyIsImxlbmd0aCIsIm51bVJvb21zIiwibnVtRG1zIiwibm9SZXN1bHRzIiwib25TY3JvbGwiLCJib2R5IiwiY3VycmVudCIsImNvbnRhaW5lclJlZiIsImNsaWVudEhlaWdodCIsIndyYXBwZWRSZWYiLCJyb29tc1Njcm9sbFN0YXRlIiwic3BhY2VzU2Nyb2xsU3RhdGUiLCJkbXNTY3JvbGxTdGF0ZSIsInBsYWNlaG9sZGVyIiwib25TZWFyY2giLCJhdXRvRm9jdXMiLCJyZWYiLCJkZWZhdWx0UmVuZGVyZXJGYWN0b3J5IiwidGl0bGUiLCJpdGVtSGVpZ2h0IiwiaXRlbXMiLCJyZW5kZXJJdGVtIiwia2V5IiwiZGVmYXVsdFJvb21zUmVuZGVyZXIiLCJfdGQiLCJkZWZhdWx0U3BhY2VzUmVuZGVyZXIiLCJkZWZhdWx0RG1zUmVuZGVyZXIiLCJTdWJzcGFjZVNlbGVjdG9yIiwib3B0aW9ucyIsImN1cnJlbnRTdGF0ZSIsIm1heVNlbmRTdGF0ZUV2ZW50IiwiRXZlbnRUeXBlIiwiU3BhY2VDaGlsZCIsImNsaWVudCIsImdldFNhZmVVc2VySWQiLCJpZCIsIm9uT3B0aW9uQ2hhbmdlIiwiZmluZCIsImxhYmVsIiwibWFwIiwiY2xhc3NlcyIsImNsYXNzTmFtZXMiLCJteF9TdWJzcGFjZVNlbGVjdG9yX2Ryb3Bkb3duT3B0aW9uQWN0aXZlIiwiZ2V0RGlzcGxheUFsaWFzRm9yUm9vbSIsIkFkZEV4aXN0aW5nVG9TcGFjZURpYWxvZyIsIm9uQ3JlYXRlUm9vbUNsaWNrIiwib25BZGRTdWJzcGFjZUNsaWNrIiwic2VsZWN0ZWRTcGFjZSIsInNldFNlbGVjdGVkU3BhY2UiLCJjb250ZW50SWQiLCJmaXhlZFdpZHRoIiwiUHJvdmlkZXIiLCJldiIsIl9kZWZhdWx0Il0sInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2NvbXBvbmVudHMvdmlld3MvZGlhbG9ncy9BZGRFeGlzdGluZ1RvU3BhY2VEaWFsb2cudHN4Il0sInNvdXJjZXNDb250ZW50IjpbIi8qXG5Db3B5cmlnaHQgMjAyNCBOZXcgVmVjdG9yIEx0ZC5cbkNvcHlyaWdodCAyMDIxIFRoZSBNYXRyaXgub3JnIEZvdW5kYXRpb24gQy5JLkMuXG5cblNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBR1BMLTMuMC1vbmx5IE9SIEdQTC0zLjAtb25seVxuUGxlYXNlIHNlZSBMSUNFTlNFIGZpbGVzIGluIHRoZSByZXBvc2l0b3J5IHJvb3QgZm9yIGZ1bGwgZGV0YWlscy5cbiovXG5cbmltcG9ydCBSZWFjdCwgeyBSZWFjdEVsZW1lbnQsIFJlYWN0Tm9kZSwgdXNlQ29udGV4dCwgdXNlTWVtbywgdXNlUmVmLCB1c2VTdGF0ZSB9IGZyb20gXCJyZWFjdFwiO1xuaW1wb3J0IGNsYXNzTmFtZXMgZnJvbSBcImNsYXNzbmFtZXNcIjtcbmltcG9ydCB7IFJvb20sIEV2ZW50VHlwZSB9IGZyb20gXCJtYXRyaXgtanMtc2RrL3NyYy9tYXRyaXhcIjtcbmltcG9ydCB7IEtub3duTWVtYmVyc2hpcCB9IGZyb20gXCJtYXRyaXgtanMtc2RrL3NyYy90eXBlc1wiO1xuaW1wb3J0IHsgc2xlZXAgfSBmcm9tIFwibWF0cml4LWpzLXNkay9zcmMvdXRpbHNcIjtcbmltcG9ydCB7IGxvZ2dlciB9IGZyb20gXCJtYXRyaXgtanMtc2RrL3NyYy9sb2dnZXJcIjtcblxuaW1wb3J0IHsgX3QsIF90ZCwgVHJhbnNsYXRpb25LZXkgfSBmcm9tIFwiLi4vLi4vLi4vbGFuZ3VhZ2VIYW5kbGVyXCI7XG5pbXBvcnQgQmFzZURpYWxvZyBmcm9tIFwiLi9CYXNlRGlhbG9nXCI7XG5pbXBvcnQgRHJvcGRvd24gZnJvbSBcIi4uL2VsZW1lbnRzL0Ryb3Bkb3duXCI7XG5pbXBvcnQgU2VhcmNoQm94IGZyb20gXCIuLi8uLi9zdHJ1Y3R1cmVzL1NlYXJjaEJveFwiO1xuaW1wb3J0IFNwYWNlU3RvcmUgZnJvbSBcIi4uLy4uLy4uL3N0b3Jlcy9zcGFjZXMvU3BhY2VTdG9yZVwiO1xuaW1wb3J0IFJvb21BdmF0YXIgZnJvbSBcIi4uL2F2YXRhcnMvUm9vbUF2YXRhclwiO1xuaW1wb3J0IHsgZ2V0RGlzcGxheUFsaWFzRm9yUm9vbSB9IGZyb20gXCIuLi8uLi8uLi9Sb29tc1wiO1xuaW1wb3J0IEFjY2Vzc2libGVCdXR0b24sIHsgQnV0dG9uRXZlbnQgfSBmcm9tIFwiLi4vZWxlbWVudHMvQWNjZXNzaWJsZUJ1dHRvblwiO1xuaW1wb3J0IEF1dG9IaWRlU2Nyb2xsYmFyIGZyb20gXCIuLi8uLi9zdHJ1Y3R1cmVzL0F1dG9IaWRlU2Nyb2xsYmFyXCI7XG5pbXBvcnQgRE1Sb29tTWFwIGZyb20gXCIuLi8uLi8uLi91dGlscy9ETVJvb21NYXBcIjtcbmltcG9ydCB7IGNhbGN1bGF0ZVJvb21WaWEgfSBmcm9tIFwiLi4vLi4vLi4vdXRpbHMvcGVybWFsaW5rcy9QZXJtYWxpbmtzXCI7XG5pbXBvcnQgU3R5bGVkQ2hlY2tib3ggZnJvbSBcIi4uL2VsZW1lbnRzL1N0eWxlZENoZWNrYm94XCI7XG5pbXBvcnQgTWF0cml4Q2xpZW50Q29udGV4dCBmcm9tIFwiLi4vLi4vLi4vY29udGV4dHMvTWF0cml4Q2xpZW50Q29udGV4dFwiO1xuaW1wb3J0IHsgc29ydFJvb21zIH0gZnJvbSBcIi4uLy4uLy4uL3N0b3Jlcy9yb29tLWxpc3QvYWxnb3JpdGhtcy90YWctc29ydGluZy9SZWNlbnRBbGdvcml0aG1cIjtcbmltcG9ydCBQcm9ncmVzc0JhciBmcm9tIFwiLi4vZWxlbWVudHMvUHJvZ3Jlc3NCYXJcIjtcbmltcG9ydCBEZWNvcmF0ZWRSb29tQXZhdGFyIGZyb20gXCIuLi9hdmF0YXJzL0RlY29yYXRlZFJvb21BdmF0YXJcIjtcbmltcG9ydCBRdWVyeU1hdGNoZXIgZnJvbSBcIi4uLy4uLy4uL2F1dG9jb21wbGV0ZS9RdWVyeU1hdGNoZXJcIjtcbmltcG9ydCBMYXp5UmVuZGVyTGlzdCBmcm9tIFwiLi4vZWxlbWVudHMvTGF6eVJlbmRlckxpc3RcIjtcbmltcG9ydCB7IHVzZVNldHRpbmdWYWx1ZSB9IGZyb20gXCIuLi8uLi8uLi9ob29rcy91c2VTZXR0aW5nc1wiO1xuaW1wb3J0IHsgZmlsdGVyQm9vbGVhbiB9IGZyb20gXCIuLi8uLi8uLi91dGlscy9hcnJheXNcIjtcbmltcG9ydCB7IE5vbkVtcHR5QXJyYXkgfSBmcm9tIFwiLi4vLi4vLi4vQHR5cGVzL2NvbW1vblwiO1xuXG4vLyBUaGVzZSB2YWx1ZXMgbWF0Y2ggQ1NTXG5jb25zdCBST1dfSEVJR0hUID0gMzIgKyAxMjtcbmNvbnN0IEhFQURFUl9IRUlHSFQgPSAxNTtcbmNvbnN0IEdST1VQX01BUkdJTiA9IDI0O1xuXG5pbnRlcmZhY2UgSVByb3BzIHtcbiAgICBzcGFjZTogUm9vbTtcbiAgICBvbkNyZWF0ZVJvb21DbGljayhldjogQnV0dG9uRXZlbnQpOiB2b2lkO1xuICAgIG9uQWRkU3Vic3BhY2VDbGljaygpOiB2b2lkO1xuICAgIG9uRmluaXNoZWQoYWRkZWQ/OiBib29sZWFuKTogdm9pZDtcbn1cblxuZXhwb3J0IGNvbnN0IEVudHJ5OiBSZWFjdC5GQzx7XG4gICAgcm9vbTogUm9vbTtcbiAgICBjaGVja2VkOiBib29sZWFuO1xuICAgIG9uQ2hhbmdlPyh2YWx1ZTogYm9vbGVhbik6IHZvaWQ7XG59PiA9ICh7IHJvb20sIGNoZWNrZWQsIG9uQ2hhbmdlIH0pID0+IHtcbiAgICByZXR1cm4gKFxuICAgICAgICA8bGFiZWwgY2xhc3NOYW1lPVwibXhfQWRkRXhpc3RpbmdUb1NwYWNlX2VudHJ5XCI+XG4gICAgICAgICAgICB7cm9vbT8uaXNTcGFjZVJvb20oKSA/IChcbiAgICAgICAgICAgICAgICA8Um9vbUF2YXRhciByb29tPXtyb29tfSBzaXplPVwiMzJweFwiIC8+XG4gICAgICAgICAgICApIDogKFxuICAgICAgICAgICAgICAgIDxEZWNvcmF0ZWRSb29tQXZhdGFyIHJvb209e3Jvb219IHNpemU9XCIzMnB4XCIgLz5cbiAgICAgICAgICAgICl9XG4gICAgICAgICAgICA8c3BhbiBjbGFzc05hbWU9XCJteF9BZGRFeGlzdGluZ1RvU3BhY2VfZW50cnlfbmFtZVwiPntyb29tLm5hbWV9PC9zcGFuPlxuICAgICAgICAgICAgPFN0eWxlZENoZWNrYm94XG4gICAgICAgICAgICAgICAgb25DaGFuZ2U9e29uQ2hhbmdlID8gKGUpID0+IG9uQ2hhbmdlKGUuY3VycmVudFRhcmdldC5jaGVja2VkKSA6IHVuZGVmaW5lZH1cbiAgICAgICAgICAgICAgICBjaGVja2VkPXtjaGVja2VkfVxuICAgICAgICAgICAgICAgIGRpc2FibGVkPXshb25DaGFuZ2V9XG4gICAgICAgICAgICAvPlxuICAgICAgICA8L2xhYmVsPlxuICAgICk7XG59O1xuXG50eXBlIE9uQ2hhbmdlRm4gPSAoY2hlY2tlZDogYm9vbGVhbiwgcm9vbTogUm9vbSkgPT4gdm9pZDtcblxudHlwZSBSZW5kZXJlciA9IChcbiAgICByb29tczogUm9vbVtdLFxuICAgIHNlbGVjdGVkVG9BZGQ6IFNldDxSb29tPixcbiAgICBzY3JvbGxTdGF0ZTogSVNjcm9sbFN0YXRlLFxuICAgIG9uQ2hhbmdlOiB1bmRlZmluZWQgfCBPbkNoYW5nZUZuLFxuKSA9PiBSZWFjdE5vZGU7XG5cbmludGVyZmFjZSBJQWRkRXhpc3RpbmdUb1NwYWNlUHJvcHMge1xuICAgIHNwYWNlOiBSb29tO1xuICAgIGZvb3RlclByb21wdD86IFJlYWN0Tm9kZTtcbiAgICBmaWx0ZXJQbGFjZWhvbGRlcjogc3RyaW5nO1xuICAgIGVtcHR5U2VsZWN0aW9uQnV0dG9uPzogUmVhY3ROb2RlO1xuICAgIG9uRmluaXNoZWQoYWRkZWQ6IGJvb2xlYW4pOiB2b2lkO1xuICAgIHJvb21zUmVuZGVyZXI/OiBSZW5kZXJlcjtcbiAgICBzcGFjZXNSZW5kZXJlcj86IFJlbmRlcmVyO1xuICAgIGRtc1JlbmRlcmVyPzogUmVuZGVyZXI7XG59XG5cbmludGVyZmFjZSBJU2Nyb2xsU3RhdGUge1xuICAgIHNjcm9sbFRvcDogbnVtYmVyO1xuICAgIGhlaWdodDogbnVtYmVyO1xufVxuXG5jb25zdCBnZXRTY3JvbGxTdGF0ZSA9IChcbiAgICB7IHNjcm9sbFRvcCwgaGVpZ2h0IH06IElTY3JvbGxTdGF0ZSxcbiAgICBudW1JdGVtczogbnVtYmVyLFxuICAgIC4uLnByZXZHcm91cFNpemVzOiBudW1iZXJbXVxuKTogSVNjcm9sbFN0YXRlID0+IHtcbiAgICBsZXQgaGVpZ2h0QmVmb3JlID0gMDtcbiAgICBwcmV2R3JvdXBTaXplcy5mb3JFYWNoKChzaXplKSA9PiB7XG4gICAgICAgIGhlaWdodEJlZm9yZSArPSBHUk9VUF9NQVJHSU4gKyBIRUFERVJfSEVJR0hUICsgc2l6ZSAqIFJPV19IRUlHSFQ7XG4gICAgfSk7XG5cbiAgICBjb25zdCB2aWV3cG9ydFRvcCA9IHNjcm9sbFRvcDtcbiAgICBjb25zdCB2aWV3cG9ydEJvdHRvbSA9IHZpZXdwb3J0VG9wICsgaGVpZ2h0O1xuICAgIGNvbnN0IGxpc3RUb3AgPSBoZWlnaHRCZWZvcmUgKyBIRUFERVJfSEVJR0hUO1xuICAgIGNvbnN0IGxpc3RCb3R0b20gPSBsaXN0VG9wICsgbnVtSXRlbXMgKiBST1dfSEVJR0hUO1xuICAgIGNvbnN0IHRvcCA9IE1hdGgubWF4KHZpZXdwb3J0VG9wLCBsaXN0VG9wKTtcbiAgICBjb25zdCBib3R0b20gPSBNYXRoLm1pbih2aWV3cG9ydEJvdHRvbSwgbGlzdEJvdHRvbSk7XG4gICAgLy8gdGhlIHZpZXdwb3J0IGhlaWdodCBhbmQgc2Nyb2xsVG9wIHBhc3NlZCB0byB0aGUgTGF6eVJlbmRlckxpc3RcbiAgICAvLyBpcyBjYXBwZWQgYXQgdGhlIGludGVyc2VjdGlvbiB3aXRoIHRoZSByZWFsIHZpZXdwb3J0LCBzbyBsaXN0c1xuICAgIC8vIG91dCBvZiB2aWV3IGFyZSBwYXNzZWQgaGVpZ2h0IDAsIHNvIHRoZXkgd29uJ3QgcmVuZGVyIGFueSBpdGVtcy5cbiAgICByZXR1cm4ge1xuICAgICAgICBzY3JvbGxUb3A6IE1hdGgubWF4KDAsIHNjcm9sbFRvcCAtIGxpc3RUb3ApLFxuICAgICAgICBoZWlnaHQ6IE1hdGgubWF4KDAsIGJvdHRvbSAtIHRvcCksXG4gICAgfTtcbn07XG5cbmV4cG9ydCBjb25zdCBBZGRFeGlzdGluZ1RvU3BhY2U6IFJlYWN0LkZDPElBZGRFeGlzdGluZ1RvU3BhY2VQcm9wcz4gPSAoe1xuICAgIHNwYWNlLFxuICAgIGZvb3RlclByb21wdCxcbiAgICBlbXB0eVNlbGVjdGlvbkJ1dHRvbixcbiAgICBmaWx0ZXJQbGFjZWhvbGRlcixcbiAgICByb29tc1JlbmRlcmVyLFxuICAgIGRtc1JlbmRlcmVyLFxuICAgIHNwYWNlc1JlbmRlcmVyLFxuICAgIG9uRmluaXNoZWQsXG59KSA9PiB7XG4gICAgY29uc3QgY2xpID0gdXNlQ29udGV4dChNYXRyaXhDbGllbnRDb250ZXh0KTtcbiAgICBjb25zdCBtc2MzOTQ2UHJvY2Vzc0R5bmFtaWNQcmVkZWNlc3NvciA9IHVzZVNldHRpbmdWYWx1ZTxib29sZWFuPihcImZlYXR1cmVfZHluYW1pY19yb29tX3ByZWRlY2Vzc29yc1wiKTtcbiAgICBjb25zdCB2aXNpYmxlUm9vbXMgPSB1c2VNZW1vKFxuICAgICAgICAoKSA9PlxuICAgICAgICAgICAgY2xpXG4gICAgICAgICAgICAgICAgPy5nZXRWaXNpYmxlUm9vbXMobXNjMzk0NlByb2Nlc3NEeW5hbWljUHJlZGVjZXNzb3IpXG4gICAgICAgICAgICAgICAgLmZpbHRlcigocikgPT4gci5nZXRNeU1lbWJlcnNoaXAoKSA9PT0gS25vd25NZW1iZXJzaGlwLkpvaW4pID8/IFtdLFxuICAgICAgICBbY2xpLCBtc2MzOTQ2UHJvY2Vzc0R5bmFtaWNQcmVkZWNlc3Nvcl0sXG4gICAgKTtcblxuICAgIGNvbnN0IHNjcm9sbFJlZiA9IHVzZVJlZjxBdXRvSGlkZVNjcm9sbGJhcjxcImRpdlwiPj4obnVsbCk7XG4gICAgY29uc3QgW3Njcm9sbFN0YXRlLCBzZXRTY3JvbGxTdGF0ZV0gPSB1c2VTdGF0ZTxJU2Nyb2xsU3RhdGU+KHtcbiAgICAgICAgLy8gdGhlc2UgYXJlIGVzdGltYXRlcyB3aGljaCB1cGRhdGUgYXMgc29vbiBhcyBpdCBtb3VudHNcbiAgICAgICAgc2Nyb2xsVG9wOiAwLFxuICAgICAgICBoZWlnaHQ6IDYwMCxcbiAgICB9KTtcblxuICAgIGNvbnN0IFtzZWxlY3RlZFRvQWRkLCBzZXRTZWxlY3RlZFRvQWRkXSA9IHVzZVN0YXRlKG5ldyBTZXQ8Um9vbT4oKSk7XG4gICAgY29uc3QgW3Byb2dyZXNzLCBzZXRQcm9ncmVzc10gPSB1c2VTdGF0ZTxudW1iZXIgfCBudWxsPihudWxsKTtcbiAgICBjb25zdCBbZXJyb3IsIHNldEVycm9yXSA9IHVzZVN0YXRlKGZhbHNlKTtcbiAgICBjb25zdCBbcXVlcnksIHNldFF1ZXJ5XSA9IHVzZVN0YXRlKFwiXCIpO1xuICAgIGNvbnN0IGxjUXVlcnkgPSBxdWVyeS50b0xvd2VyQ2FzZSgpLnRyaW0oKTtcblxuICAgIGNvbnN0IGV4aXN0aW5nU3Vic3BhY2VzU2V0ID0gdXNlTWVtbygoKSA9PiBuZXcgU2V0KFNwYWNlU3RvcmUuaW5zdGFuY2UuZ2V0Q2hpbGRTcGFjZXMoc3BhY2Uucm9vbUlkKSksIFtzcGFjZV0pO1xuICAgIGNvbnN0IGV4aXN0aW5nUm9vbXNTZXQgPSB1c2VNZW1vKCgpID0+IG5ldyBTZXQoU3BhY2VTdG9yZS5pbnN0YW5jZS5nZXRDaGlsZFJvb21zKHNwYWNlLnJvb21JZCkpLCBbc3BhY2VdKTtcblxuICAgIGNvbnN0IFtzcGFjZXMsIHJvb21zLCBkbXNdID0gdXNlTWVtbygoKSA9PiB7XG4gICAgICAgIGxldCByb29tcyA9IHZpc2libGVSb29tcztcblxuICAgICAgICBpZiAobGNRdWVyeSkge1xuICAgICAgICAgICAgY29uc3QgbWF0Y2hlciA9IG5ldyBRdWVyeU1hdGNoZXI8Um9vbT4odmlzaWJsZVJvb21zLCB7XG4gICAgICAgICAgICAgICAga2V5czogW1wibmFtZVwiXSxcbiAgICAgICAgICAgICAgICBmdW5jczogWyhyKSA9PiBmaWx0ZXJCb29sZWFuKFtyLmdldENhbm9uaWNhbEFsaWFzKCksIC4uLnIuZ2V0QWx0QWxpYXNlcygpXSldLFxuICAgICAgICAgICAgICAgIHNob3VsZE1hdGNoV29yZHNPbmx5OiBmYWxzZSxcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICByb29tcyA9IG1hdGNoZXIubWF0Y2gobGNRdWVyeSk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBqb2luUnVsZSA9IHNwYWNlLmdldEpvaW5SdWxlKCk7XG4gICAgICAgIHJldHVybiBzb3J0Um9vbXMocm9vbXMpLnJlZHVjZTxbc3BhY2VzOiBSb29tW10sIHJvb21zOiBSb29tW10sIGRtczogUm9vbVtdXT4oXG4gICAgICAgICAgICAoYXJyLCByb29tKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKHJvb20uaXNTcGFjZVJvb20oKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAocm9vbSAhPT0gc3BhY2UgJiYgIWV4aXN0aW5nU3Vic3BhY2VzU2V0Lmhhcyhyb29tKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXJyWzBdLnB1c2gocm9vbSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFleGlzdGluZ1Jvb21zU2V0Lmhhcyhyb29tKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIURNUm9vbU1hcC5zaGFyZWQoKS5nZXRVc2VySWRGb3JSb29tSWQocm9vbS5yb29tSWQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcnJbMV0ucHVzaChyb29tKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChqb2luUnVsZSAhPT0gXCJwdWJsaWNcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gT25seSBzaG93IERNcyBmb3Igbm9uLXB1YmxpYyBzcGFjZXMgYXMgdGhleSBtYWtlIHZlcnkgbGl0dGxlIHNlbnNlIGluIHNwYWNlcyBvdGhlciB0aGFuIFwiSnVzdCBNZVwiIG9uZXMuXG4gICAgICAgICAgICAgICAgICAgICAgICBhcnJbMl0ucHVzaChyb29tKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gYXJyO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIFtbXSwgW10sIFtdXSxcbiAgICAgICAgKTtcbiAgICB9LCBbdmlzaWJsZVJvb21zLCBzcGFjZSwgbGNRdWVyeSwgZXhpc3RpbmdSb29tc1NldCwgZXhpc3RpbmdTdWJzcGFjZXNTZXRdKTtcblxuICAgIGNvbnN0IGFkZFJvb21zID0gYXN5bmMgKCk6IFByb21pc2U8dm9pZD4gPT4ge1xuICAgICAgICBzZXRFcnJvcihmYWxzZSk7XG4gICAgICAgIHNldFByb2dyZXNzKDApO1xuXG4gICAgICAgIGxldCBlcnJvciA9IGZhbHNlO1xuXG4gICAgICAgIGZvciAoY29uc3Qgcm9vbSBvZiBzZWxlY3RlZFRvQWRkKSB7XG4gICAgICAgICAgICBjb25zdCB2aWEgPSBjYWxjdWxhdGVSb29tVmlhKHJvb20pO1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBhd2FpdCBTcGFjZVN0b3JlLmluc3RhbmNlLmFkZFJvb21Ub1NwYWNlKHNwYWNlLCByb29tLnJvb21JZCwgdmlhKS5jYXRjaChhc3luYyAoZSk6IFByb21pc2U8dm9pZD4gPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZS5lcnJjb2RlID09PSBcIk1fTElNSVRfRVhDRUVERURcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXdhaXQgc2xlZXAoZS5kYXRhLnJldHJ5X2FmdGVyX21zKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IFNwYWNlU3RvcmUuaW5zdGFuY2UuYWRkUm9vbVRvU3BhY2Uoc3BhY2UsIHJvb20ucm9vbUlkLCB2aWEpOyAvLyByZXRyeVxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgZTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBzZXRQcm9ncmVzcygoaSkgPT4gKGkgPz8gMCkgKyAxKTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICBsb2dnZXIuZXJyb3IoXCJGYWlsZWQgdG8gYWRkIHJvb21zIHRvIHNwYWNlXCIsIGUpO1xuICAgICAgICAgICAgICAgIGVycm9yID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghZXJyb3IpIHtcbiAgICAgICAgICAgIG9uRmluaXNoZWQodHJ1ZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzZXRFcnJvcihlcnJvcik7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgY29uc3QgYnVzeSA9IHByb2dyZXNzICE9PSBudWxsO1xuXG4gICAgbGV0IGZvb3RlcjtcbiAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgZm9vdGVyID0gKFxuICAgICAgICAgICAgPD5cbiAgICAgICAgICAgICAgICA8aW1nXG4gICAgICAgICAgICAgICAgICAgIHNyYz17cmVxdWlyZShcIi4uLy4uLy4uLy4uL3Jlcy9pbWcvZWxlbWVudC1pY29ucy93YXJuaW5nLWJhZGdlLnN2Z1wiKS5kZWZhdWx0fVxuICAgICAgICAgICAgICAgICAgICBoZWlnaHQ9XCIyNFwiXG4gICAgICAgICAgICAgICAgICAgIHdpZHRoPVwiMjRcIlxuICAgICAgICAgICAgICAgICAgICBhbHQ9XCJcIlxuICAgICAgICAgICAgICAgIC8+XG5cbiAgICAgICAgICAgICAgICA8c3BhbiBjbGFzc05hbWU9XCJteF9BZGRFeGlzdGluZ1RvU3BhY2VEaWFsb2dfZXJyb3JcIj5cbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJteF9BZGRFeGlzdGluZ1RvU3BhY2VEaWFsb2dfZXJyb3JIZWFkaW5nXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICB7X3QoXCJzcGFjZXxhZGRfZXhpc3Rpbmdfcm9vbV9zcGFjZXxlcnJvcl9oZWFkaW5nXCIpfVxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJteF9BZGRFeGlzdGluZ1RvU3BhY2VEaWFsb2dfZXJyb3JDYXB0aW9uXCI+e190KFwiYWN0aW9ufHRyeV9hZ2FpblwiKX08L2Rpdj5cbiAgICAgICAgICAgICAgICA8L3NwYW4+XG5cbiAgICAgICAgICAgICAgICA8QWNjZXNzaWJsZUJ1dHRvbiBjbGFzc05hbWU9XCJteF9BZGRFeGlzdGluZ1RvU3BhY2VEaWFsb2dfcmV0cnlCdXR0b25cIiBvbkNsaWNrPXthZGRSb29tc30+XG4gICAgICAgICAgICAgICAgICAgIHtfdChcImFjdGlvbnxyZXRyeVwiKX1cbiAgICAgICAgICAgICAgICA8L0FjY2Vzc2libGVCdXR0b24+XG4gICAgICAgICAgICA8Lz5cbiAgICAgICAgKTtcbiAgICB9IGVsc2UgaWYgKGJ1c3kpIHtcbiAgICAgICAgZm9vdGVyID0gKFxuICAgICAgICAgICAgPHNwYW4+XG4gICAgICAgICAgICAgICAgPFByb2dyZXNzQmFyIHZhbHVlPXtwcm9ncmVzc30gbWF4PXtzZWxlY3RlZFRvQWRkLnNpemV9IC8+XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJteF9BZGRFeGlzdGluZ1RvU3BhY2VEaWFsb2dfcHJvZ3Jlc3NUZXh0XCI+XG4gICAgICAgICAgICAgICAgICAgIHtfdChcInNwYWNlfGFkZF9leGlzdGluZ19yb29tX3NwYWNlfHByb2dyZXNzX3RleHRcIiwge1xuICAgICAgICAgICAgICAgICAgICAgICAgY291bnQ6IHNlbGVjdGVkVG9BZGQuc2l6ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHByb2dyZXNzLFxuICAgICAgICAgICAgICAgICAgICB9KX1cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBsZXQgYnV0dG9uID0gZW1wdHlTZWxlY3Rpb25CdXR0b247XG4gICAgICAgIGlmICghYnV0dG9uIHx8IHNlbGVjdGVkVG9BZGQuc2l6ZSA+IDApIHtcbiAgICAgICAgICAgIGJ1dHRvbiA9IChcbiAgICAgICAgICAgICAgICA8QWNjZXNzaWJsZUJ1dHRvbiBraW5kPVwicHJpbWFyeVwiIGRpc2FibGVkPXtzZWxlY3RlZFRvQWRkLnNpemUgPCAxfSBvbkNsaWNrPXthZGRSb29tc30+XG4gICAgICAgICAgICAgICAgICAgIHtfdChcImFjdGlvbnxhZGRcIil9XG4gICAgICAgICAgICAgICAgPC9BY2Nlc3NpYmxlQnV0dG9uPlxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZvb3RlciA9IChcbiAgICAgICAgICAgIDw+XG4gICAgICAgICAgICAgICAgPHNwYW4+e2Zvb3RlclByb21wdH08L3NwYW4+XG5cbiAgICAgICAgICAgICAgICB7YnV0dG9ufVxuICAgICAgICAgICAgPC8+XG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgY29uc3Qgb25DaGFuZ2UgPVxuICAgICAgICAhYnVzeSAmJiAhZXJyb3JcbiAgICAgICAgICAgID8gKGNoZWNrZWQ6IGJvb2xlYW4sIHJvb206IFJvb20pID0+IHtcbiAgICAgICAgICAgICAgICAgIGlmIChjaGVja2VkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgc2VsZWN0ZWRUb0FkZC5hZGQocm9vbSk7XG4gICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgIHNlbGVjdGVkVG9BZGQuZGVsZXRlKHJvb20pO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgc2V0U2VsZWN0ZWRUb0FkZChuZXcgU2V0KHNlbGVjdGVkVG9BZGQpKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgOiB1bmRlZmluZWQ7XG5cbiAgICAvLyBvbmx5IGNvdW50IHNwYWNlcyB3aGVuIGFsb25lIGFzIHRoZXkncmUgc2hvd24gb24gYSBzZXBhcmF0ZSBtb2RhbCBhbGwgb24gdGhlaXIgb3duXG4gICAgY29uc3QgbnVtU3BhY2VzID0gc3BhY2VzUmVuZGVyZXIgJiYgIWRtc1JlbmRlcmVyICYmICFyb29tc1JlbmRlcmVyID8gc3BhY2VzLmxlbmd0aCA6IDA7XG4gICAgY29uc3QgbnVtUm9vbXMgPSByb29tc1JlbmRlcmVyID8gcm9vbXMubGVuZ3RoIDogMDtcbiAgICBjb25zdCBudW1EbXMgPSBkbXNSZW5kZXJlciA/IGRtcy5sZW5ndGggOiAwO1xuXG4gICAgbGV0IG5vUmVzdWx0cyA9IHRydWU7XG4gICAgaWYgKG51bVNwYWNlcyA+IDAgfHwgbnVtUm9vbXMgPiAwIHx8IG51bURtcyA+IDApIHtcbiAgICAgICAgbm9SZXN1bHRzID0gZmFsc2U7XG4gICAgfVxuXG4gICAgY29uc3Qgb25TY3JvbGwgPSAoKTogdm9pZCA9PiB7XG4gICAgICAgIGNvbnN0IGJvZHkgPSBzY3JvbGxSZWYuY3VycmVudD8uY29udGFpbmVyUmVmLmN1cnJlbnQ7XG4gICAgICAgIGlmICghYm9keSkgcmV0dXJuO1xuICAgICAgICBzZXRTY3JvbGxTdGF0ZSh7XG4gICAgICAgICAgICBzY3JvbGxUb3A6IGJvZHkuc2Nyb2xsVG9wLFxuICAgICAgICAgICAgaGVpZ2h0OiBib2R5LmNsaWVudEhlaWdodCxcbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIGNvbnN0IHdyYXBwZWRSZWYgPSAoYm9keTogSFRNTERpdkVsZW1lbnQgfCBudWxsKTogdm9pZCA9PiB7XG4gICAgICAgIGlmICghYm9keSkgcmV0dXJuO1xuICAgICAgICBzZXRTY3JvbGxTdGF0ZSh7XG4gICAgICAgICAgICBzY3JvbGxUb3A6IGJvZHkuc2Nyb2xsVG9wLFxuICAgICAgICAgICAgaGVpZ2h0OiBib2R5LmNsaWVudEhlaWdodCxcbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIGNvbnN0IHJvb21zU2Nyb2xsU3RhdGUgPSBnZXRTY3JvbGxTdGF0ZShzY3JvbGxTdGF0ZSwgbnVtUm9vbXMpO1xuICAgIGNvbnN0IHNwYWNlc1Njcm9sbFN0YXRlID0gZ2V0U2Nyb2xsU3RhdGUoc2Nyb2xsU3RhdGUsIG51bVNwYWNlcywgbnVtUm9vbXMpO1xuICAgIGNvbnN0IGRtc1Njcm9sbFN0YXRlID0gZ2V0U2Nyb2xsU3RhdGUoc2Nyb2xsU3RhdGUsIG51bURtcywgbnVtU3BhY2VzLCBudW1Sb29tcyk7XG5cbiAgICByZXR1cm4gKFxuICAgICAgICA8ZGl2IGNsYXNzTmFtZT1cIm14X0FkZEV4aXN0aW5nVG9TcGFjZVwiPlxuICAgICAgICAgICAgPFNlYXJjaEJveFxuICAgICAgICAgICAgICAgIGNsYXNzTmFtZT1cIm14X3RleHRpbnB1dF9pY29uIG14X3RleHRpbnB1dF9zZWFyY2hcIlxuICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyPXtmaWx0ZXJQbGFjZWhvbGRlcn1cbiAgICAgICAgICAgICAgICBvblNlYXJjaD17c2V0UXVlcnl9XG4gICAgICAgICAgICAgICAgYXV0b0ZvY3VzPXt0cnVlfVxuICAgICAgICAgICAgLz5cbiAgICAgICAgICAgIDxBdXRvSGlkZVNjcm9sbGJhclxuICAgICAgICAgICAgICAgIGNsYXNzTmFtZT1cIm14X0FkZEV4aXN0aW5nVG9TcGFjZV9jb250ZW50XCJcbiAgICAgICAgICAgICAgICBvblNjcm9sbD17b25TY3JvbGx9XG4gICAgICAgICAgICAgICAgd3JhcHBlZFJlZj17d3JhcHBlZFJlZn1cbiAgICAgICAgICAgICAgICByZWY9e3Njcm9sbFJlZn1cbiAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICB7cm9vbXMubGVuZ3RoID4gMCAmJiByb29tc1JlbmRlcmVyXG4gICAgICAgICAgICAgICAgICAgID8gcm9vbXNSZW5kZXJlcihyb29tcywgc2VsZWN0ZWRUb0FkZCwgcm9vbXNTY3JvbGxTdGF0ZSwgb25DaGFuZ2UpXG4gICAgICAgICAgICAgICAgICAgIDogdW5kZWZpbmVkfVxuXG4gICAgICAgICAgICAgICAge3NwYWNlcy5sZW5ndGggPiAwICYmIHNwYWNlc1JlbmRlcmVyXG4gICAgICAgICAgICAgICAgICAgID8gc3BhY2VzUmVuZGVyZXIoc3BhY2VzLCBzZWxlY3RlZFRvQWRkLCBzcGFjZXNTY3JvbGxTdGF0ZSwgb25DaGFuZ2UpXG4gICAgICAgICAgICAgICAgICAgIDogbnVsbH1cblxuICAgICAgICAgICAgICAgIHtkbXMubGVuZ3RoID4gMCAmJiBkbXNSZW5kZXJlciA/IGRtc1JlbmRlcmVyKGRtcywgc2VsZWN0ZWRUb0FkZCwgZG1zU2Nyb2xsU3RhdGUsIG9uQ2hhbmdlKSA6IG51bGx9XG5cbiAgICAgICAgICAgICAgICB7bm9SZXN1bHRzID8gKFxuICAgICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzc05hbWU9XCJteF9BZGRFeGlzdGluZ1RvU3BhY2Vfbm9SZXN1bHRzXCI+e190KFwiY29tbW9ufG5vX3Jlc3VsdHNcIil9PC9zcGFuPlxuICAgICAgICAgICAgICAgICkgOiB1bmRlZmluZWR9XG4gICAgICAgICAgICA8L0F1dG9IaWRlU2Nyb2xsYmFyPlxuXG4gICAgICAgICAgICA8ZGl2IGNsYXNzTmFtZT1cIm14X0FkZEV4aXN0aW5nVG9TcGFjZV9mb290ZXJcIj57Zm9vdGVyfTwvZGl2PlxuICAgICAgICA8L2Rpdj5cbiAgICApO1xufTtcblxuY29uc3QgZGVmYXVsdFJlbmRlcmVyRmFjdG9yeSA9XG4gICAgKHRpdGxlOiBUcmFuc2xhdGlvbktleSk6IFJlbmRlcmVyID0+XG4gICAgKHJvb21zLCBzZWxlY3RlZFRvQWRkLCB7IHNjcm9sbFRvcCwgaGVpZ2h0IH0sIG9uQ2hhbmdlKSA9PiAoXG4gICAgICAgIDxkaXYgY2xhc3NOYW1lPVwibXhfQWRkRXhpc3RpbmdUb1NwYWNlX3NlY3Rpb25cIj5cbiAgICAgICAgICAgIDxoMz57X3QodGl0bGUpfTwvaDM+XG4gICAgICAgICAgICA8TGF6eVJlbmRlckxpc3RcbiAgICAgICAgICAgICAgICBpdGVtSGVpZ2h0PXtST1dfSEVJR0hUfVxuICAgICAgICAgICAgICAgIGl0ZW1zPXtyb29tc31cbiAgICAgICAgICAgICAgICBzY3JvbGxUb3A9e3Njcm9sbFRvcH1cbiAgICAgICAgICAgICAgICBoZWlnaHQ9e2hlaWdodH1cbiAgICAgICAgICAgICAgICByZW5kZXJJdGVtPXsocm9vbSkgPT4gKFxuICAgICAgICAgICAgICAgICAgICA8RW50cnlcbiAgICAgICAgICAgICAgICAgICAgICAgIGtleT17cm9vbS5yb29tSWR9XG4gICAgICAgICAgICAgICAgICAgICAgICByb29tPXtyb29tfVxuICAgICAgICAgICAgICAgICAgICAgICAgY2hlY2tlZD17c2VsZWN0ZWRUb0FkZC5oYXMocm9vbSl9XG4gICAgICAgICAgICAgICAgICAgICAgICBvbkNoYW5nZT17XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb25DaGFuZ2VcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPyAoY2hlY2tlZDogYm9vbGVhbikgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbkNoYW5nZShjaGVja2VkLCByb29tKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogdW5kZWZpbmVkXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICAgICAgKX1cbiAgICAgICAgICAgIC8+XG4gICAgICAgIDwvZGl2PlxuICAgICk7XG5cbmV4cG9ydCBjb25zdCBkZWZhdWx0Um9vbXNSZW5kZXJlciA9IGRlZmF1bHRSZW5kZXJlckZhY3RvcnkoX3RkKFwiY29tbW9ufHJvb21zXCIpKTtcbmV4cG9ydCBjb25zdCBkZWZhdWx0U3BhY2VzUmVuZGVyZXIgPSBkZWZhdWx0UmVuZGVyZXJGYWN0b3J5KF90ZChcImNvbW1vbnxzcGFjZXNcIikpO1xuZXhwb3J0IGNvbnN0IGRlZmF1bHREbXNSZW5kZXJlciA9IGRlZmF1bHRSZW5kZXJlckZhY3RvcnkoX3RkKFwic3BhY2V8YWRkX2V4aXN0aW5nX3Jvb21fc3BhY2V8ZG1faGVhZGluZ1wiKSk7XG5cbmludGVyZmFjZSBJU3Vic3BhY2VTZWxlY3RvclByb3BzIHtcbiAgICB0aXRsZTogc3RyaW5nO1xuICAgIHNwYWNlOiBSb29tO1xuICAgIHZhbHVlOiBSb29tO1xuICAgIG9uQ2hhbmdlKHNwYWNlOiBSb29tKTogdm9pZDtcbn1cblxuZXhwb3J0IGNvbnN0IFN1YnNwYWNlU2VsZWN0b3I6IFJlYWN0LkZDPElTdWJzcGFjZVNlbGVjdG9yUHJvcHM+ID0gKHsgdGl0bGUsIHNwYWNlLCB2YWx1ZSwgb25DaGFuZ2UgfSkgPT4ge1xuICAgIGNvbnN0IG9wdGlvbnMgPSB1c2VNZW1vKCgpID0+IHtcbiAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICAgIHNwYWNlLFxuICAgICAgICAgICAgLi4uU3BhY2VTdG9yZS5pbnN0YW5jZS5nZXRDaGlsZFNwYWNlcyhzcGFjZS5yb29tSWQpLmZpbHRlcigoc3BhY2UpID0+IHtcbiAgICAgICAgICAgICAgICByZXR1cm4gc3BhY2UuY3VycmVudFN0YXRlLm1heVNlbmRTdGF0ZUV2ZW50KEV2ZW50VHlwZS5TcGFjZUNoaWxkLCBzcGFjZS5jbGllbnQuZ2V0U2FmZVVzZXJJZCgpKTtcbiAgICAgICAgICAgIH0pLFxuICAgICAgICBdO1xuICAgIH0sIFtzcGFjZV0pO1xuXG4gICAgbGV0IGJvZHk7XG4gICAgaWYgKG9wdGlvbnMubGVuZ3RoID4gMSkge1xuICAgICAgICBib2R5ID0gKFxuICAgICAgICAgICAgPERyb3Bkb3duXG4gICAgICAgICAgICAgICAgaWQ9XCJteF9TcGFjZVNlbGVjdERyb3Bkb3duXCJcbiAgICAgICAgICAgICAgICBjbGFzc05hbWU9XCJteF9TcGFjZVNlbGVjdERyb3Bkb3duXCJcbiAgICAgICAgICAgICAgICBvbk9wdGlvbkNoYW5nZT17KGtleTogc3RyaW5nKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIG9uQ2hhbmdlKG9wdGlvbnMuZmluZCgoc3BhY2UpID0+IHNwYWNlLnJvb21JZCA9PT0ga2V5KSB8fCBzcGFjZSk7XG4gICAgICAgICAgICAgICAgfX1cbiAgICAgICAgICAgICAgICB2YWx1ZT17dmFsdWUucm9vbUlkfVxuICAgICAgICAgICAgICAgIGxhYmVsPXtfdChcInNwYWNlfGFkZF9leGlzdGluZ19yb29tX3NwYWNlfHNwYWNlX2Ryb3Bkb3duX2xhYmVsXCIpfVxuICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgb3B0aW9ucy5tYXAoKHNwYWNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjbGFzc2VzID0gY2xhc3NOYW1lcyh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbXhfU3Vic3BhY2VTZWxlY3Rvcl9kcm9wZG93bk9wdGlvbkFjdGl2ZTogc3BhY2UgPT09IHZhbHVlLFxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYga2V5PXtzcGFjZS5yb29tSWR9IGNsYXNzTmFtZT17Y2xhc3Nlc30+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxSb29tQXZhdGFyIHJvb209e3NwYWNlfSBzaXplPVwiMjRweFwiIC8+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHtzcGFjZS5uYW1lIHx8IGdldERpc3BsYXlBbGlhc0ZvclJvb20oc3BhY2UpIHx8IHNwYWNlLnJvb21JZH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgIH0pIGFzIE5vbkVtcHR5QXJyYXk8UmVhY3RFbGVtZW50ICYgeyBrZXk6IHN0cmluZyB9PlxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIDwvRHJvcGRvd24+XG4gICAgICAgICk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgYm9keSA9IChcbiAgICAgICAgICAgIDxkaXYgY2xhc3NOYW1lPVwibXhfU3Vic3BhY2VTZWxlY3Rvcl9vbmx5U3BhY2VcIj5cbiAgICAgICAgICAgICAgICB7c3BhY2UubmFtZSB8fCBnZXREaXNwbGF5QWxpYXNGb3JSb29tKHNwYWNlKSB8fCBzcGFjZS5yb29tSWR9XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICByZXR1cm4gKFxuICAgICAgICA8ZGl2IGNsYXNzTmFtZT1cIm14X1N1YnNwYWNlU2VsZWN0b3JcIj5cbiAgICAgICAgICAgIDxSb29tQXZhdGFyIHJvb209e3ZhbHVlfSBzaXplPVwiNDBweFwiIC8+XG4gICAgICAgICAgICA8ZGl2PlxuICAgICAgICAgICAgICAgIDxoMT57dGl0bGV9PC9oMT5cbiAgICAgICAgICAgICAgICB7Ym9keX1cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Rpdj5cbiAgICApO1xufTtcblxuY29uc3QgQWRkRXhpc3RpbmdUb1NwYWNlRGlhbG9nOiBSZWFjdC5GQzxJUHJvcHM+ID0gKHsgc3BhY2UsIG9uQ3JlYXRlUm9vbUNsaWNrLCBvbkFkZFN1YnNwYWNlQ2xpY2ssIG9uRmluaXNoZWQgfSkgPT4ge1xuICAgIGNvbnN0IFtzZWxlY3RlZFNwYWNlLCBzZXRTZWxlY3RlZFNwYWNlXSA9IHVzZVN0YXRlKHNwYWNlKTtcblxuICAgIHJldHVybiAoXG4gICAgICAgIDxCYXNlRGlhbG9nXG4gICAgICAgICAgICB0aXRsZT17XG4gICAgICAgICAgICAgICAgPFN1YnNwYWNlU2VsZWN0b3JcbiAgICAgICAgICAgICAgICAgICAgdGl0bGU9e190KFwic3BhY2V8YWRkX2V4aXN0aW5nX3Jvb21fc3BhY2V8c3BhY2VfZHJvcGRvd25fdGl0bGVcIil9XG4gICAgICAgICAgICAgICAgICAgIHNwYWNlPXtzcGFjZX1cbiAgICAgICAgICAgICAgICAgICAgdmFsdWU9e3NlbGVjdGVkU3BhY2V9XG4gICAgICAgICAgICAgICAgICAgIG9uQ2hhbmdlPXtzZXRTZWxlY3RlZFNwYWNlfVxuICAgICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjbGFzc05hbWU9XCJteF9BZGRFeGlzdGluZ1RvU3BhY2VEaWFsb2dcIlxuICAgICAgICAgICAgY29udGVudElkPVwibXhfQWRkRXhpc3RpbmdUb1NwYWNlXCJcbiAgICAgICAgICAgIG9uRmluaXNoZWQ9e29uRmluaXNoZWR9XG4gICAgICAgICAgICBmaXhlZFdpZHRoPXtmYWxzZX1cbiAgICAgICAgPlxuICAgICAgICAgICAgPE1hdHJpeENsaWVudENvbnRleHQuUHJvdmlkZXIgdmFsdWU9e3NwYWNlLmNsaWVudH0+XG4gICAgICAgICAgICAgICAgPEFkZEV4aXN0aW5nVG9TcGFjZVxuICAgICAgICAgICAgICAgICAgICBzcGFjZT17c3BhY2V9XG4gICAgICAgICAgICAgICAgICAgIG9uRmluaXNoZWQ9e29uRmluaXNoZWR9XG4gICAgICAgICAgICAgICAgICAgIGZvb3RlclByb21wdD17XG4gICAgICAgICAgICAgICAgICAgICAgICA8PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXY+e190KFwic3BhY2V8YWRkX2V4aXN0aW5nX3Jvb21fc3BhY2V8Y3JlYXRlXCIpfTwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxBY2Nlc3NpYmxlQnV0dG9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGtpbmQ9XCJsaW5rXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb25DbGljaz17KGV2OiBCdXR0b25FdmVudCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb25DcmVhdGVSb29tQ2xpY2soZXYpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb25GaW5pc2hlZCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9fVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge190KFwic3BhY2V8YWRkX2V4aXN0aW5nX3Jvb21fc3BhY2V8Y3JlYXRlX3Byb21wdFwiKX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L0FjY2Vzc2libGVCdXR0b24+XG4gICAgICAgICAgICAgICAgICAgICAgICA8Lz5cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBmaWx0ZXJQbGFjZWhvbGRlcj17X3QoXCJzcGFjZXxyb29tX2ZpbHRlcl9wbGFjZWhvbGRlclwiKX1cbiAgICAgICAgICAgICAgICAgICAgcm9vbXNSZW5kZXJlcj17ZGVmYXVsdFJvb21zUmVuZGVyZXJ9XG4gICAgICAgICAgICAgICAgICAgIHNwYWNlc1JlbmRlcmVyPXsoKSA9PiAoXG4gICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzTmFtZT1cIm14X0FkZEV4aXN0aW5nVG9TcGFjZV9zZWN0aW9uXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGgzPntfdChcImNvbW1vbnxzcGFjZXNcIil9PC9oMz5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8QWNjZXNzaWJsZUJ1dHRvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBraW5kPVwibGlua1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9uQ2xpY2s9eygpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9uQWRkU3Vic3BhY2VDbGljaygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb25GaW5pc2hlZCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9fVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge190KFwic3BhY2V8YWRkX2V4aXN0aW5nX3Jvb21fc3BhY2V8c3Vic3BhY2VfbW92ZWRfbm90ZVwiKX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L0FjY2Vzc2libGVCdXR0b24+XG4gICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgKX1cbiAgICAgICAgICAgICAgICAgICAgZG1zUmVuZGVyZXI9e2RlZmF1bHREbXNSZW5kZXJlcn1cbiAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgPC9NYXRyaXhDbGllbnRDb250ZXh0LlByb3ZpZGVyPlxuICAgICAgICA8L0Jhc2VEaWFsb2c+XG4gICAgKTtcbn07XG5cbmV4cG9ydCBkZWZhdWx0IEFkZEV4aXN0aW5nVG9TcGFjZURpYWxvZztcbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQVFBLElBQUFBLE1BQUEsR0FBQUMsdUJBQUEsQ0FBQUMsT0FBQTtBQUNBLElBQUFDLFdBQUEsR0FBQUMsc0JBQUEsQ0FBQUYsT0FBQTtBQUNBLElBQUFHLE9BQUEsR0FBQUgsT0FBQTtBQUNBLElBQUFJLE1BQUEsR0FBQUosT0FBQTtBQUNBLElBQUFLLE1BQUEsR0FBQUwsT0FBQTtBQUNBLElBQUFNLE9BQUEsR0FBQU4sT0FBQTtBQUVBLElBQUFPLGdCQUFBLEdBQUFQLE9BQUE7QUFDQSxJQUFB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