matrix-react-sdk
Version:
SDK for matrix.org using React
379 lines (375 loc) • 67.7 kB
JavaScript
"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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