UNPKG

matrix-react-sdk

Version:
278 lines (271 loc) 58.2 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _react = _interopRequireWildcard(require("react")); var _matrix = require("matrix-js-sdk/src/matrix"); var _StyledRadioGroup = _interopRequireDefault(require("../elements/StyledRadioGroup")); var _languageHandler = require("../../../languageHandler"); var _AccessibleButton = _interopRequireDefault(require("../elements/AccessibleButton")); var _RoomAvatar = _interopRequireDefault(require("../avatars/RoomAvatar")); var _SpaceStore = _interopRequireDefault(require("../../../stores/spaces/SpaceStore")); var _Modal = _interopRequireDefault(require("../../../Modal")); var _ManageRestrictedJoinRuleDialog = _interopRequireDefault(require("../dialogs/ManageRestrictedJoinRuleDialog")); var _RoomUpgradeWarningDialog = _interopRequireDefault(require("../dialogs/RoomUpgradeWarningDialog")); var _RoomUpgrade = require("../../../utils/RoomUpgrade"); var _arrays = require("../../../utils/arrays"); var _useLocalEcho = require("../../../hooks/useLocalEcho"); var _dispatcher = _interopRequireDefault(require("../../../dispatcher/dispatcher")); var _RoomSettingsDialog = require("../dialogs/RoomSettingsDialog"); var _actions = require("../../../dispatcher/actions"); var _PreferredRoomVersions = require("../../../utils/PreferredRoomVersions"); var _SettingsStore = _interopRequireDefault(require("../../../settings/SettingsStore")); var _LabelledCheckbox = _interopRequireDefault(require("../elements/LabelledCheckbox")); 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. */ const JoinRuleSettings = ({ room, promptUpgrade, aliasWarning, onError, beforeChange, closeSettingsFn }) => { const cli = room.client; const askToJoinEnabled = _SettingsStore.default.getValue("feature_ask_to_join"); const roomSupportsKnock = (0, _PreferredRoomVersions.doesRoomVersionSupport)(room.getVersion(), _PreferredRoomVersions.PreferredRoomVersions.KnockRooms); const preferredKnockVersion = !roomSupportsKnock && promptUpgrade ? _PreferredRoomVersions.PreferredRoomVersions.KnockRooms : undefined; const roomSupportsRestricted = (0, _PreferredRoomVersions.doesRoomVersionSupport)(room.getVersion(), _PreferredRoomVersions.PreferredRoomVersions.RestrictedRooms); const preferredRestrictionVersion = !roomSupportsRestricted && promptUpgrade ? _PreferredRoomVersions.PreferredRoomVersions.RestrictedRooms : undefined; const disabled = !room.currentState.mayClientSendStateEvent(_matrix.EventType.RoomJoinRules, cli); const [content, setContent] = (0, _useLocalEcho.useLocalEcho)(() => room.currentState.getStateEvents(_matrix.EventType.RoomJoinRules, "")?.getContent(), content => cli.sendStateEvent(room.roomId, _matrix.EventType.RoomJoinRules, content, ""), onError); const { join_rule: joinRule = _matrix.JoinRule.Invite } = content || {}; const restrictedAllowRoomIds = joinRule === _matrix.JoinRule.Restricted ? content?.allow?.filter(o => o.type === _matrix.RestrictedAllowType.RoomMembership).map(o => o.room_id) : undefined; const [isPublicKnockRoom, setIsPublicKnockRoom] = (0, _react.useState)(false); (0, _react.useEffect)(() => { if (joinRule === _matrix.JoinRule.Knock) { cli.getRoomDirectoryVisibility(room.roomId).then(({ visibility }) => setIsPublicKnockRoom(visibility === _matrix.Visibility.Public)).catch(onError); } }, [cli, joinRule, onError, room.roomId]); const onIsPublicKnockRoomChange = checked => { cli.setRoomDirectoryVisibility(room.roomId, checked ? _matrix.Visibility.Public : _matrix.Visibility.Private).then(() => setIsPublicKnockRoom(checked)).catch(onError); }; const editRestrictedRoomIds = async () => { let selected = restrictedAllowRoomIds; if (!selected?.length && _SpaceStore.default.instance.activeSpaceRoom) { selected = [_SpaceStore.default.instance.activeSpaceRoom.roomId]; } const { finished } = _Modal.default.createDialog(_ManageRestrictedJoinRuleDialog.default, { room, selected }, "mx_ManageRestrictedJoinRuleDialog_wrapper"); const [roomIds] = await finished; return roomIds; }; const upgradeRequiredDialog = (targetVersion, description) => { _Modal.default.createDialog(_RoomUpgradeWarningDialog.default, { roomId: room.roomId, targetVersion, description, doUpgrade: async (opts, fn) => { const roomId = await (0, _RoomUpgrade.upgradeRoom)(room, targetVersion, opts.invite, true, true, true, progress => { const total = 2 + progress.updateSpacesTotal + progress.inviteUsersTotal; if (!progress.roomUpgraded) { fn((0, _languageHandler._t)("room_settings|security|join_rule_upgrade_upgrading_room"), 0, total); } else if (!progress.roomSynced) { fn((0, _languageHandler._t)("room_settings|security|join_rule_upgrade_awaiting_room"), 1, total); } else if (progress.inviteUsersProgress !== undefined && progress.inviteUsersProgress < progress.inviteUsersTotal) { fn((0, _languageHandler._t)("room_settings|security|join_rule_upgrade_sending_invites", { progress: progress.inviteUsersProgress, count: progress.inviteUsersTotal }), 2 + progress.inviteUsersProgress, total); } else if (progress.updateSpacesProgress !== undefined && progress.updateSpacesProgress < progress.updateSpacesTotal) { fn((0, _languageHandler._t)("room_settings|security|join_rule_upgrade_updating_spaces", { progress: progress.updateSpacesProgress, count: progress.updateSpacesTotal }), 2 + (progress.inviteUsersProgress ?? 0) + progress.updateSpacesProgress, total); } }); closeSettingsFn(); // switch to the new room in the background _dispatcher.default.dispatch({ action: _actions.Action.ViewRoom, room_id: roomId, metricsTrigger: undefined // other }); // open new settings on this tab _dispatcher.default.dispatch({ action: "open_room_settings", initial_tab_id: _RoomSettingsDialog.RoomSettingsTab.Security }); } }); }; const upgradeRequiredPill = /*#__PURE__*/_react.default.createElement("span", { className: "mx_JoinRuleSettings_upgradeRequired" }, (0, _languageHandler._t)("room_settings|security|join_rule_upgrade_required")); const definitions = [{ value: _matrix.JoinRule.Invite, label: (0, _languageHandler._t)("room_settings|security|join_rule_invite"), description: (0, _languageHandler._t)("room_settings|security|join_rule_invite_description"), checked: joinRule === _matrix.JoinRule.Invite || joinRule === _matrix.JoinRule.Restricted && !restrictedAllowRoomIds?.length }, { value: _matrix.JoinRule.Public, label: (0, _languageHandler._t)("common|public"), description: /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, (0, _languageHandler._t)("room_settings|security|join_rule_public_description"), aliasWarning) }]; if (roomSupportsRestricted || preferredRestrictionVersion || joinRule === _matrix.JoinRule.Restricted) { let description; if (joinRule === _matrix.JoinRule.Restricted && restrictedAllowRoomIds?.length) { // only show the first 4 spaces we know about, so that the UI doesn't grow out of proportion there are lots. const shownSpaces = restrictedAllowRoomIds.map(roomId => cli.getRoom(roomId)).filter(room => room?.isSpaceRoom()).slice(0, 4); let moreText; if (shownSpaces.length < restrictedAllowRoomIds.length) { if (shownSpaces.length > 0) { moreText = (0, _languageHandler._t)("room_settings|security|join_rule_restricted_n_more", { count: restrictedAllowRoomIds.length - shownSpaces.length }); } else { moreText = (0, _languageHandler._t)("room_settings|security|join_rule_restricted_summary", { count: restrictedAllowRoomIds.length }); } } const onRestrictedRoomIdsChange = newAllowRoomIds => { if (!(0, _arrays.arrayHasDiff)(restrictedAllowRoomIds || [], newAllowRoomIds)) return; if (!newAllowRoomIds.length) { setContent({ join_rule: _matrix.JoinRule.Invite }); return; } setContent({ join_rule: _matrix.JoinRule.Restricted, allow: newAllowRoomIds.map(roomId => ({ type: _matrix.RestrictedAllowType.RoomMembership, room_id: roomId })) }); }; const onEditRestrictedClick = async () => { const restrictedAllowRoomIds = await editRestrictedRoomIds(); if (!Array.isArray(restrictedAllowRoomIds)) return; if (restrictedAllowRoomIds.length > 0) { onRestrictedRoomIdsChange(restrictedAllowRoomIds); } else { onChange(_matrix.JoinRule.Invite); } }; description = /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("span", null, (0, _languageHandler._t)("room_settings|security|join_rule_restricted_description", {}, { a: sub => /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, { disabled: disabled, onClick: onEditRestrictedClick, kind: "link_inline" }, sub) })), /*#__PURE__*/_react.default.createElement("div", { className: "mx_JoinRuleSettings_spacesWithAccess" }, /*#__PURE__*/_react.default.createElement("h4", null, (0, _languageHandler._t)("room_settings|security|join_rule_restricted_description_spaces")), shownSpaces.map(room => { return /*#__PURE__*/_react.default.createElement("span", { key: room.roomId }, /*#__PURE__*/_react.default.createElement(_RoomAvatar.default, { room: room, size: "32px" }), room.name); }), moreText && /*#__PURE__*/_react.default.createElement("span", null, moreText))); } else if (_SpaceStore.default.instance.activeSpaceRoom) { description = (0, _languageHandler._t)("room_settings|security|join_rule_restricted_description_active_space", {}, { spaceName: () => /*#__PURE__*/_react.default.createElement("strong", null, _SpaceStore.default.instance.activeSpaceRoom.name) }); } else { description = (0, _languageHandler._t)("room_settings|security|join_rule_restricted_description_prompt"); } definitions.splice(1, 0, { value: _matrix.JoinRule.Restricted, label: /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, (0, _languageHandler._t)("room_settings|security|join_rule_restricted"), preferredRestrictionVersion && upgradeRequiredPill), description, // if there are 0 allowed spaces then render it as invite only instead checked: joinRule === _matrix.JoinRule.Restricted && !!restrictedAllowRoomIds?.length }); } if (askToJoinEnabled && (roomSupportsKnock || preferredKnockVersion)) { definitions.push({ value: _matrix.JoinRule.Knock, label: /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, (0, _languageHandler._t)("room_settings|security|join_rule_knock"), preferredKnockVersion && upgradeRequiredPill), description: /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, (0, _languageHandler._t)("room_settings|security|join_rule_knock_description"), /*#__PURE__*/_react.default.createElement(_LabelledCheckbox.default, { className: "mx_JoinRuleSettings_labelledCheckbox", disabled: joinRule !== _matrix.JoinRule.Knock, label: room.isSpaceRoom() ? (0, _languageHandler._t)("room_settings|security|publish_space") : (0, _languageHandler._t)("room_settings|security|publish_room"), onChange: onIsPublicKnockRoomChange, value: isPublicKnockRoom })) }); } const onChange = async joinRule => { const beforeJoinRule = content?.join_rule; let restrictedAllowRoomIds; if (joinRule === _matrix.JoinRule.Restricted) { if (beforeJoinRule === _matrix.JoinRule.Restricted || roomSupportsRestricted) { // Have the user pick which spaces to allow joins from restrictedAllowRoomIds = await editRestrictedRoomIds(); if (!Array.isArray(restrictedAllowRoomIds)) return; } else if (preferredRestrictionVersion) { // Block this action on a room upgrade otherwise it'd make their room unjoinable const targetVersion = preferredRestrictionVersion; let warning; const userId = cli.getUserId(); const unableToUpdateSomeParents = Array.from(_SpaceStore.default.instance.getKnownParents(room.roomId)).some(roomId => !cli.getRoom(roomId)?.currentState.maySendStateEvent(_matrix.EventType.SpaceChild, userId)); if (unableToUpdateSomeParents) { warning = /*#__PURE__*/_react.default.createElement("strong", null, (0, _languageHandler._t)("room_settings|security|join_rule_restricted_upgrade_warning")); } upgradeRequiredDialog(targetVersion, /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, (0, _languageHandler._t)("room_settings|security|join_rule_restricted_upgrade_description"), warning)); return; } // when setting to 0 allowed rooms/spaces set to invite only instead as per the note if (!restrictedAllowRoomIds?.length) { joinRule = _matrix.JoinRule.Invite; } } else if (joinRule === _matrix.JoinRule.Knock) { if (preferredKnockVersion) { upgradeRequiredDialog(preferredKnockVersion); return; } } if (beforeJoinRule === joinRule && !restrictedAllowRoomIds) return; if (beforeChange && !(await beforeChange(joinRule))) return; const newContent = { join_rule: joinRule }; // pre-set the accepted spaces with the currently viewed one as per the microcopy if (joinRule === _matrix.JoinRule.Restricted) { newContent.allow = restrictedAllowRoomIds?.map(roomId => ({ type: _matrix.RestrictedAllowType.RoomMembership, room_id: roomId })); } setContent(newContent); }; return /*#__PURE__*/_react.default.createElement(_StyledRadioGroup.default, { name: "joinRule", value: joinRule, onChange: onChange, definitions: definitions, disabled: disabled, className: "mx_JoinRuleSettings_radioButton" }); }; var _default = exports.default = JoinRuleSettings; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfcmVhY3QiLCJfaW50ZXJvcFJlcXVpcmVXaWxkY2FyZCIsInJlcXVpcmUiLCJfbWF0cml4IiwiX1N0eWxlZFJhZGlvR3JvdXAiLCJfaW50ZXJvcFJlcXVpcmVEZWZhdWx0IiwiX2xhbmd1YWdlSGFuZGxlciIsIl9BY2Nlc3NpYmxlQnV0dG9uIiwiX1Jvb21BdmF0YXIiLCJfU3BhY2VTdG9yZSIsIl9Nb2RhbCIsIl9NYW5hZ2VSZXN0cmljdGVkSm9pblJ1bGVEaWFsb2ciLCJfUm9vbVVwZ3JhZGVXYXJuaW5nRGlhbG9nIiwiX1Jvb21VcGdyYWRlIiwiX2FycmF5cyIsIl91c2VMb2NhbEVjaG8iLCJfZGlzcGF0Y2hlciIsIl9Sb29tU2V0dGluZ3NEaWFsb2ciLCJfYWN0aW9ucyIsIl9QcmVmZXJyZWRSb29tVmVyc2lvbnMiLCJfU2V0dGluZ3NTdG9yZSIsIl9MYWJlbGxlZENoZWNrYm94IiwiX2dldFJlcXVpcmVXaWxkY2FyZENhY2hlIiwiZSIsIldlYWtNYXAiLCJyIiwidCIsIl9fZXNNb2R1bGUiLCJkZWZhdWx0IiwiaGFzIiwiZ2V0IiwibiIsIl9fcHJvdG9fXyIsImEiLCJPYmplY3QiLCJkZWZpbmVQcm9wZXJ0eSIsImdldE93blByb3BlcnR5RGVzY3JpcHRvciIsInUiLCJoYXNPd25Qcm9wZXJ0eSIsImNhbGwiLCJpIiwic2V0IiwiSm9pblJ1bGVTZXR0aW5ncyIsInJvb20iLCJwcm9tcHRVcGdyYWRlIiwiYWxpYXNXYXJuaW5nIiwib25FcnJvciIsImJlZm9yZUNoYW5nZSIsImNsb3NlU2V0dGluZ3NGbiIsImNsaSIsImNsaWVudCIsImFza1RvSm9pbkVuYWJsZWQiLCJTZXR0aW5nc1N0b3JlIiwiZ2V0VmFsdWUiLCJyb29tU3VwcG9ydHNLbm9jayIsImRvZXNSb29tVmVyc2lvblN1cHBvcnQiLCJnZXRWZXJzaW9uIiwiUHJlZmVycmVkUm9vbVZlcnNpb25zIiwiS25vY2tSb29tcyIsInByZWZlcnJlZEtub2NrVmVyc2lvbiIsInVuZGVmaW5lZCIsInJvb21TdXBwb3J0c1Jlc3RyaWN0ZWQiLCJSZXN0cmljdGVkUm9vbXMiLCJwcmVmZXJyZWRSZXN0cmljdGlvblZlcnNpb24iLCJkaXNhYmxlZCIsImN1cnJlbnRTdGF0ZSIsIm1heUNsaWVudFNlbmRTdGF0ZUV2ZW50IiwiRXZlbnRUeXBlIiwiUm9vbUpvaW5SdWxlcyIsImNvbnRlbnQiLCJzZXRDb250ZW50IiwidXNlTG9jYWxFY2hvIiwiZ2V0U3RhdGVFdmVudHMiLCJnZXRDb250ZW50Iiwic2VuZFN0YXRlRXZlbnQiLCJyb29tSWQiLCJqb2luX3J1bGUiLCJqb2luUnVsZSIsIkpvaW5SdWxlIiwiSW52aXRlIiwicmVzdHJpY3RlZEFsbG93Um9vbUlkcyIsIlJlc3RyaWN0ZWQiLCJhbGxvdyIsImZpbHRlciIsIm8iLCJ0eXBlIiwiUmVzdHJpY3RlZEFsbG93VHlwZSIsIlJvb21NZW1iZXJzaGlwIiwibWFwIiwicm9vbV9pZCIsImlzUHVibGljS25vY2tSb29tIiwic2V0SXNQdWJsaWNLbm9ja1Jvb20iLCJ1c2VTdGF0ZSIsInVzZUVmZmVjdCIsIktub2NrIiwiZ2V0Um9vbURpcmVjdG9yeVZpc2liaWxpdHkiLCJ0aGVuIiwidmlzaWJpbGl0eSIsIlZpc2liaWxpdHkiLCJQdWJsaWMiLCJjYXRjaCIsIm9uSXNQdWJsaWNLbm9ja1Jvb21DaGFuZ2UiLCJjaGVja2VkIiwic2V0Um9vbURpcmVjdG9yeVZpc2liaWxpdHkiLCJQcml2YXRlIiwiZWRpdFJlc3RyaWN0ZWRSb29tSWRzIiwic2VsZWN0ZWQiLCJsZW5ndGgiLCJTcGFjZVN0b3JlIiwiaW5zdGFuY2UiLCJhY3RpdmVTcGFjZVJvb20iLCJmaW5pc2hlZCIsIk1vZGFsIiwiY3JlYXRlRGlhbG9nIiwiTWFuYWdlUmVzdHJpY3RlZEpvaW5SdWxlRGlhbG9nIiwicm9vbUlkcyIsInVwZ3JhZGVSZXF1aXJlZERpYWxvZyIsInRhcmdldFZlcnNpb24iLCJkZXNjcmlwdGlvbiIsIlJvb21VcGdyYWRlV2FybmluZ0RpYWxvZyIsImRvVXBncmFkZSIsIm9wdHMiLCJmbiIsInVwZ3JhZGVSb29tIiwiaW52aXRlIiwicHJvZ3Jlc3MiLCJ0b3RhbCIsInVwZGF0ZVNwYWNlc1RvdGFsIiwiaW52aXRlVXNlcnNUb3RhbCIsInJvb21VcGdyYWRlZCIsIl90Iiwicm9vbVN5bmNlZCIsImludml0ZVVzZXJzUHJvZ3Jlc3MiLCJjb3VudCIsInVwZGF0ZVNwYWNlc1Byb2dyZXNzIiwiZGlzIiwiZGlzcGF0Y2giLCJhY3Rpb24iLCJBY3Rpb24iLCJWaWV3Um9vbSIsIm1ldHJpY3NUcmlnZ2VyIiwiaW5pdGlhbF90YWJfaWQiLCJSb29tU2V0dGluZ3NUYWIiLCJTZWN1cml0eSIsInVwZ3JhZGVSZXF1aXJlZFBpbGwiLCJjcmVhdGVFbGVtZW50IiwiY2xhc3NOYW1lIiwiZGVmaW5pdGlvbnMiLCJ2YWx1ZSIsImxhYmVsIiwiRnJhZ21lbnQiLCJzaG93blNwYWNlcyIsImdldFJvb20iLCJpc1NwYWNlUm9vbSIsInNsaWNlIiwibW9yZVRleHQiLCJvblJlc3RyaWN0ZWRSb29tSWRzQ2hhbmdlIiwibmV3QWxsb3dSb29tSWRzIiwiYXJyYXlIYXNEaWZmIiwib25FZGl0UmVzdHJpY3RlZENsaWNrIiwiQXJyYXkiLCJpc0FycmF5Iiwib25DaGFuZ2UiLCJzdWIiLCJvbkNsaWNrIiwia2luZCIsImtleSIsInNpemUiLCJuYW1lIiwic3BhY2VOYW1lIiwic3BsaWNlIiwicHVzaCIsImJlZm9yZUpvaW5SdWxlIiwid2FybmluZyIsInVzZXJJZCIsImdldFVzZXJJZCIsInVuYWJsZVRvVXBkYXRlU29tZVBhcmVudHMiLCJmcm9tIiwiZ2V0S25vd25QYXJlbnRzIiwic29tZSIsIm1heVNlbmRTdGF0ZUV2ZW50IiwiU3BhY2VDaGlsZCIsIm5ld0NvbnRlbnQiLCJfZGVmYXVsdCIsImV4cG9ydHMiXSwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvY29tcG9uZW50cy92aWV3cy9zZXR0aW5ncy9Kb2luUnVsZVNldHRpbmdzLnRzeCJdLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuQ29weXJpZ2h0IDIwMjQgTmV3IFZlY3RvciBMdGQuXG5Db3B5cmlnaHQgMjAyMSBUaGUgTWF0cml4Lm9yZyBGb3VuZGF0aW9uIEMuSS5DLlxuXG5TUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQUdQTC0zLjAtb25seSBPUiBHUEwtMy4wLW9ubHlcblBsZWFzZSBzZWUgTElDRU5TRSBmaWxlcyBpbiB0aGUgcmVwb3NpdG9yeSByb290IGZvciBmdWxsIGRldGFpbHMuXG4qL1xuXG5pbXBvcnQgUmVhY3QsIHsgUmVhY3ROb2RlLCB1c2VFZmZlY3QsIHVzZVN0YXRlIH0gZnJvbSBcInJlYWN0XCI7XG5pbXBvcnQgeyBKb2luUnVsZSwgUmVzdHJpY3RlZEFsbG93VHlwZSwgUm9vbSwgRXZlbnRUeXBlLCBWaXNpYmlsaXR5IH0gZnJvbSBcIm1hdHJpeC1qcy1zZGsvc3JjL21hdHJpeFwiO1xuaW1wb3J0IHsgUm9vbUpvaW5SdWxlc0V2ZW50Q29udGVudCB9IGZyb20gXCJtYXRyaXgtanMtc2RrL3NyYy90eXBlc1wiO1xuXG5pbXBvcnQgU3R5bGVkUmFkaW9Hcm91cCwgeyBJRGVmaW5pdGlvbiB9IGZyb20gXCIuLi9lbGVtZW50cy9TdHlsZWRSYWRpb0dyb3VwXCI7XG5pbXBvcnQgeyBfdCB9IGZyb20gXCIuLi8uLi8uLi9sYW5ndWFnZUhhbmRsZXJcIjtcbmltcG9ydCBBY2Nlc3NpYmxlQnV0dG9uIGZyb20gXCIuLi9lbGVtZW50cy9BY2Nlc3NpYmxlQnV0dG9uXCI7XG5pbXBvcnQgUm9vbUF2YXRhciBmcm9tIFwiLi4vYXZhdGFycy9Sb29tQXZhdGFyXCI7XG5pbXBvcnQgU3BhY2VTdG9yZSBmcm9tIFwiLi4vLi4vLi4vc3RvcmVzL3NwYWNlcy9TcGFjZVN0b3JlXCI7XG5pbXBvcnQgTW9kYWwgZnJvbSBcIi4uLy4uLy4uL01vZGFsXCI7XG5pbXBvcnQgTWFuYWdlUmVzdHJpY3RlZEpvaW5SdWxlRGlhbG9nIGZyb20gXCIuLi9kaWFsb2dzL01hbmFnZVJlc3RyaWN0ZWRKb2luUnVsZURpYWxvZ1wiO1xuaW1wb3J0IFJvb21VcGdyYWRlV2FybmluZ0RpYWxvZywgeyBJRmluaXNoZWRPcHRzIH0gZnJvbSBcIi4uL2RpYWxvZ3MvUm9vbVVwZ3JhZGVXYXJuaW5nRGlhbG9nXCI7XG5pbXBvcnQgeyB1cGdyYWRlUm9vbSB9IGZyb20gXCIuLi8uLi8uLi91dGlscy9Sb29tVXBncmFkZVwiO1xuaW1wb3J0IHsgYXJyYXlIYXNEaWZmIH0gZnJvbSBcIi4uLy4uLy4uL3V0aWxzL2FycmF5c1wiO1xuaW1wb3J0IHsgdXNlTG9jYWxFY2hvIH0gZnJvbSBcIi4uLy4uLy4uL2hvb2tzL3VzZUxvY2FsRWNob1wiO1xuaW1wb3J0IGRpcyBmcm9tIFwiLi4vLi4vLi4vZGlzcGF0Y2hlci9kaXNwYXRjaGVyXCI7XG5pbXBvcnQgeyBSb29tU2V0dGluZ3NUYWIgfSBmcm9tIFwiLi4vZGlhbG9ncy9Sb29tU2V0dGluZ3NEaWFsb2dcIjtcbmltcG9ydCB7IEFjdGlvbiB9IGZyb20gXCIuLi8uLi8uLi9kaXNwYXRjaGVyL2FjdGlvbnNcIjtcbmltcG9ydCB7IFZpZXdSb29tUGF5bG9hZCB9IGZyb20gXCIuLi8uLi8uLi9kaXNwYXRjaGVyL3BheWxvYWRzL1ZpZXdSb29tUGF5bG9hZFwiO1xuaW1wb3J0IHsgZG9lc1Jvb21WZXJzaW9uU3VwcG9ydCwgUHJlZmVycmVkUm9vbVZlcnNpb25zIH0gZnJvbSBcIi4uLy4uLy4uL3V0aWxzL1ByZWZlcnJlZFJvb21WZXJzaW9uc1wiO1xuaW1wb3J0IFNldHRpbmdzU3RvcmUgZnJvbSBcIi4uLy4uLy4uL3NldHRpbmdzL1NldHRpbmdzU3RvcmVcIjtcbmltcG9ydCBMYWJlbGxlZENoZWNrYm94IGZyb20gXCIuLi9lbGVtZW50cy9MYWJlbGxlZENoZWNrYm94XCI7XG5cbmV4cG9ydCBpbnRlcmZhY2UgSm9pblJ1bGVTZXR0aW5nc1Byb3BzIHtcbiAgICByb29tOiBSb29tO1xuICAgIHByb21wdFVwZ3JhZGU/OiBib29sZWFuO1xuICAgIGNsb3NlU2V0dGluZ3NGbigpOiB2b2lkO1xuICAgIG9uRXJyb3IoZXJyb3I6IHVua25vd24pOiB2b2lkO1xuICAgIGJlZm9yZUNoYW5nZT8oam9pblJ1bGU6IEpvaW5SdWxlKTogUHJvbWlzZTxib29sZWFuPjsgLy8gaWYgcmV0dXJucyBmYWxzZSB0aGVuIGFib3J0cyB0aGUgY2hhbmdlXG4gICAgYWxpYXNXYXJuaW5nPzogUmVhY3ROb2RlO1xufVxuXG5jb25zdCBKb2luUnVsZVNldHRpbmdzOiBSZWFjdC5GQzxKb2luUnVsZVNldHRpbmdzUHJvcHM+ID0gKHtcbiAgICByb29tLFxuICAgIHByb21wdFVwZ3JhZGUsXG4gICAgYWxpYXNXYXJuaW5nLFxuICAgIG9uRXJyb3IsXG4gICAgYmVmb3JlQ2hhbmdlLFxuICAgIGNsb3NlU2V0dGluZ3NGbixcbn0pID0+IHtcbiAgICBjb25zdCBjbGkgPSByb29tLmNsaWVudDtcblxuICAgIGNvbnN0IGFza1RvSm9pbkVuYWJsZWQgPSBTZXR0aW5nc1N0b3JlLmdldFZhbHVlKFwiZmVhdHVyZV9hc2tfdG9fam9pblwiKTtcbiAgICBjb25zdCByb29tU3VwcG9ydHNLbm9jayA9IGRvZXNSb29tVmVyc2lvblN1cHBvcnQocm9vbS5nZXRWZXJzaW9uKCksIFByZWZlcnJlZFJvb21WZXJzaW9ucy5Lbm9ja1Jvb21zKTtcbiAgICBjb25zdCBwcmVmZXJyZWRLbm9ja1ZlcnNpb24gPSAhcm9vbVN1cHBvcnRzS25vY2sgJiYgcHJvbXB0VXBncmFkZSA/IFByZWZlcnJlZFJvb21WZXJzaW9ucy5Lbm9ja1Jvb21zIDogdW5kZWZpbmVkO1xuXG4gICAgY29uc3Qgcm9vbVN1cHBvcnRzUmVzdHJpY3RlZCA9IGRvZXNSb29tVmVyc2lvblN1cHBvcnQocm9vbS5nZXRWZXJzaW9uKCksIFByZWZlcnJlZFJvb21WZXJzaW9ucy5SZXN0cmljdGVkUm9vbXMpO1xuICAgIGNvbnN0IHByZWZlcnJlZFJlc3RyaWN0aW9uVmVyc2lvbiA9XG4gICAgICAgICFyb29tU3VwcG9ydHNSZXN0cmljdGVkICYmIHByb21wdFVwZ3JhZGUgPyBQcmVmZXJyZWRSb29tVmVyc2lvbnMuUmVzdHJpY3RlZFJvb21zIDogdW5kZWZpbmVkO1xuXG4gICAgY29uc3QgZGlzYWJsZWQgPSAhcm9vbS5jdXJyZW50U3RhdGUubWF5Q2xpZW50U2VuZFN0YXRlRXZlbnQoRXZlbnRUeXBlLlJvb21Kb2luUnVsZXMsIGNsaSk7XG5cbiAgICBjb25zdCBbY29udGVudCwgc2V0Q29udGVudF0gPSB1c2VMb2NhbEVjaG88Um9vbUpvaW5SdWxlc0V2ZW50Q29udGVudCB8IHVuZGVmaW5lZCwgUm9vbUpvaW5SdWxlc0V2ZW50Q29udGVudD4oXG4gICAgICAgICgpID0+IHJvb20uY3VycmVudFN0YXRlLmdldFN0YXRlRXZlbnRzKEV2ZW50VHlwZS5Sb29tSm9pblJ1bGVzLCBcIlwiKT8uZ2V0Q29udGVudCgpLFxuICAgICAgICAoY29udGVudCkgPT4gY2xpLnNlbmRTdGF0ZUV2ZW50KHJvb20ucm9vbUlkLCBFdmVudFR5cGUuUm9vbUpvaW5SdWxlcywgY29udGVudCwgXCJcIiksXG4gICAgICAgIG9uRXJyb3IsXG4gICAgKTtcblxuICAgIGNvbnN0IHsgam9pbl9ydWxlOiBqb2luUnVsZSA9IEpvaW5SdWxlLkludml0ZSB9ID0gY29udGVudCB8fCB7fTtcbiAgICBjb25zdCByZXN0cmljdGVkQWxsb3dSb29tSWRzID1cbiAgICAgICAgam9pblJ1bGUgPT09IEpvaW5SdWxlLlJlc3RyaWN0ZWRcbiAgICAgICAgICAgID8gY29udGVudD8uYWxsb3c/LmZpbHRlcigobykgPT4gby50eXBlID09PSBSZXN0cmljdGVkQWxsb3dUeXBlLlJvb21NZW1iZXJzaGlwKS5tYXAoKG8pID0+IG8ucm9vbV9pZClcbiAgICAgICAgICAgIDogdW5kZWZpbmVkO1xuXG4gICAgY29uc3QgW2lzUHVibGljS25vY2tSb29tLCBzZXRJc1B1YmxpY0tub2NrUm9vbV0gPSB1c2VTdGF0ZShmYWxzZSk7XG5cbiAgICB1c2VFZmZlY3QoKCkgPT4ge1xuICAgICAgICBpZiAoam9pblJ1bGUgPT09IEpvaW5SdWxlLktub2NrKSB7XG4gICAgICAgICAgICBjbGkuZ2V0Um9vbURpcmVjdG9yeVZpc2liaWxpdHkocm9vbS5yb29tSWQpXG4gICAgICAgICAgICAgICAgLnRoZW4oKHsgdmlzaWJpbGl0eSB9KSA9PiBzZXRJc1B1YmxpY0tub2NrUm9vbSh2aXNpYmlsaXR5ID09PSBWaXNpYmlsaXR5LlB1YmxpYykpXG4gICAgICAgICAgICAgICAgLmNhdGNoKG9uRXJyb3IpO1xuICAgICAgICB9XG4gICAgfSwgW2NsaSwgam9pblJ1bGUsIG9uRXJyb3IsIHJvb20ucm9vbUlkXSk7XG5cbiAgICBjb25zdCBvbklzUHVibGljS25vY2tSb29tQ2hhbmdlID0gKGNoZWNrZWQ6IGJvb2xlYW4pOiB2b2lkID0+IHtcbiAgICAgICAgY2xpLnNldFJvb21EaXJlY3RvcnlWaXNpYmlsaXR5KHJvb20ucm9vbUlkLCBjaGVja2VkID8gVmlzaWJpbGl0eS5QdWJsaWMgOiBWaXNpYmlsaXR5LlByaXZhdGUpXG4gICAgICAgICAgICAudGhlbigoKSA9PiBzZXRJc1B1YmxpY0tub2NrUm9vbShjaGVja2VkKSlcbiAgICAgICAgICAgIC5jYXRjaChvbkVycm9yKTtcbiAgICB9O1xuXG4gICAgY29uc3QgZWRpdFJlc3RyaWN0ZWRSb29tSWRzID0gYXN5bmMgKCk6IFByb21pc2U8c3RyaW5nW10gfCB1bmRlZmluZWQ+ID0+IHtcbiAgICAgICAgbGV0IHNlbGVjdGVkID0gcmVzdHJpY3RlZEFsbG93Um9vbUlkcztcbiAgICAgICAgaWYgKCFzZWxlY3RlZD8ubGVuZ3RoICYmIFNwYWNlU3RvcmUuaW5zdGFuY2UuYWN0aXZlU3BhY2VSb29tKSB7XG4gICAgICAgICAgICBzZWxlY3RlZCA9IFtTcGFjZVN0b3JlLmluc3RhbmNlLmFjdGl2ZVNwYWNlUm9vbS5yb29tSWRdO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgeyBmaW5pc2hlZCB9ID0gTW9kYWwuY3JlYXRlRGlhbG9nKFxuICAgICAgICAgICAgTWFuYWdlUmVzdHJpY3RlZEpvaW5SdWxlRGlhbG9nLFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHJvb20sXG4gICAgICAgICAgICAgICAgc2VsZWN0ZWQsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgXCJteF9NYW5hZ2VSZXN0cmljdGVkSm9pblJ1bGVEaWFsb2dfd3JhcHBlclwiLFxuICAgICAgICApO1xuXG4gICAgICAgIGNvbnN0IFtyb29tSWRzXSA9IGF3YWl0IGZpbmlzaGVkO1xuICAgICAgICByZXR1cm4gcm9vbUlkcztcbiAgICB9O1xuXG4gICAgY29uc3QgdXBncmFkZVJlcXVpcmVkRGlhbG9nID0gKHRhcmdldFZlcnNpb246IHN0cmluZywgZGVzY3JpcHRpb24/OiBSZWFjdE5vZGUpOiB2b2lkID0+IHtcbiAgICAgICAgTW9kYWwuY3JlYXRlRGlhbG9nKFJvb21VcGdyYWRlV2FybmluZ0RpYWxvZywge1xuICAgICAgICAgICAgcm9vbUlkOiByb29tLnJvb21JZCxcbiAgICAgICAgICAgIHRhcmdldFZlcnNpb24sXG4gICAgICAgICAgICBkZXNjcmlwdGlvbixcbiAgICAgICAgICAgIGRvVXBncmFkZTogYXN5bmMgKFxuICAgICAgICAgICAgICAgIG9wdHM6IElGaW5pc2hlZE9wdHMsXG4gICAgICAgICAgICAgICAgZm46IChwcm9ncmVzc1RleHQ6IHN0cmluZywgcHJvZ3Jlc3M6IG51bWJlciwgdG90YWw6IG51bWJlcikgPT4gdm9pZCxcbiAgICAgICAgICAgICk6IFByb21pc2U8dm9pZD4gPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHJvb21JZCA9IGF3YWl0IHVwZ3JhZGVSb29tKHJvb20sIHRhcmdldFZlcnNpb24sIG9wdHMuaW52aXRlLCB0cnVlLCB0cnVlLCB0cnVlLCAocHJvZ3Jlc3MpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgdG90YWwgPSAyICsgcHJvZ3Jlc3MudXBkYXRlU3BhY2VzVG90YWwgKyBwcm9ncmVzcy5pbnZpdGVVc2Vyc1RvdGFsO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIXByb2dyZXNzLnJvb21VcGdyYWRlZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZm4oX3QoXCJyb29tX3NldHRpbmdzfHNlY3VyaXR5fGpvaW5fcnVsZV91cGdyYWRlX3VwZ3JhZGluZ19yb29tXCIpLCAwLCB0b3RhbCk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIXByb2dyZXNzLnJvb21TeW5jZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZuKF90KFwicm9vbV9zZXR0aW5nc3xzZWN1cml0eXxqb2luX3J1bGVfdXBncmFkZV9hd2FpdGluZ19yb29tXCIpLCAxLCB0b3RhbCk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgICAgICAgICAgICAgICAgICBwcm9ncmVzcy5pbnZpdGVVc2Vyc1Byb2dyZXNzICE9PSB1bmRlZmluZWQgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIHByb2dyZXNzLmludml0ZVVzZXJzUHJvZ3Jlc3MgPCBwcm9ncmVzcy5pbnZpdGVVc2Vyc1RvdGFsXG4gICAgICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZm4oXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgX3QoXCJyb29tX3NldHRpbmdzfHNlY3VyaXR5fGpvaW5fcnVsZV91cGdyYWRlX3NlbmRpbmdfaW52aXRlc1wiLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb2dyZXNzOiBwcm9ncmVzcy5pbnZpdGVVc2Vyc1Byb2dyZXNzLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb3VudDogcHJvZ3Jlc3MuaW52aXRlVXNlcnNUb3RhbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAyICsgcHJvZ3Jlc3MuaW52aXRlVXNlcnNQcm9ncmVzcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b3RhbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgICAgICAgICAgICAgICAgICBwcm9ncmVzcy51cGRhdGVTcGFjZXNQcm9ncmVzcyAhPT0gdW5kZWZpbmVkICYmXG4gICAgICAgICAgICAgICAgICAgICAgICBwcm9ncmVzcy51cGRhdGVTcGFjZXNQcm9ncmVzcyA8IHByb2dyZXNzLnVwZGF0ZVNwYWNlc1RvdGFsXG4gICAgICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZm4oXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgX3QoXCJyb29tX3NldHRpbmdzfHNlY3VyaXR5fGpvaW5fcnVsZV91cGdyYWRlX3VwZGF0aW5nX3NwYWNlc1wiLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb2dyZXNzOiBwcm9ncmVzcy51cGRhdGVTcGFjZXNQcm9ncmVzcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY291bnQ6IHByb2dyZXNzLnVwZGF0ZVNwYWNlc1RvdGFsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDIgKyAocHJvZ3Jlc3MuaW52aXRlVXNlcnNQcm9ncmVzcyA/PyAwKSArIHByb2dyZXNzLnVwZGF0ZVNwYWNlc1Byb2dyZXNzLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvdGFsLFxuICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgY2xvc2VTZXR0aW5nc0ZuKCk7XG5cbiAgICAgICAgICAgICAgICAvLyBzd2l0Y2ggdG8gdGhlIG5ldyByb29tIGluIHRoZSBiYWNrZ3JvdW5kXG4gICAgICAgICAgICAgICAgZGlzLmRpc3BhdGNoPFZpZXdSb29tUGF5bG9hZD4oe1xuICAgICAgICAgICAgICAgICAgICBhY3Rpb246IEFjdGlvbi5WaWV3Um9vbSxcbiAgICAgICAgICAgICAgICAgICAgcm9vbV9pZDogcm9vbUlkLFxuICAgICAgICAgICAgICAgICAgICBtZXRyaWNzVHJpZ2dlcjogdW5kZWZpbmVkLCAvLyBvdGhlclxuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgLy8gb3BlbiBuZXcgc2V0dGluZ3Mgb24gdGhpcyB0YWJcbiAgICAgICAgICAgICAgICBkaXMuZGlzcGF0Y2goe1xuICAgICAgICAgICAgICAgICAgICBhY3Rpb246IFwib3Blbl9yb29tX3NldHRpbmdzXCIsXG4gICAgICAgICAgICAgICAgICAgIGluaXRpYWxfdGFiX2lkOiBSb29tU2V0dGluZ3NUYWIuU2VjdXJpdHksXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgY29uc3QgdXBncmFkZVJlcXVpcmVkUGlsbCA9IChcbiAgICAgICAgPHNwYW4gY2xhc3NOYW1lPVwibXhfSm9pblJ1bGVTZXR0aW5nc191cGdyYWRlUmVxdWlyZWRcIj5cbiAgICAgICAgICAgIHtfdChcInJvb21fc2V0dGluZ3N8c2VjdXJpdHl8am9pbl9ydWxlX3VwZ3JhZGVfcmVxdWlyZWRcIil9XG4gICAgICAgIDwvc3Bhbj5cbiAgICApO1xuXG4gICAgY29uc3QgZGVmaW5pdGlvbnM6IElEZWZpbml0aW9uPEpvaW5SdWxlPltdID0gW1xuICAgICAgICB7XG4gICAgICAgICAgICB2YWx1ZTogSm9pblJ1bGUuSW52aXRlLFxuICAgICAgICAgICAgbGFiZWw6IF90KFwicm9vbV9zZXR0aW5nc3xzZWN1cml0eXxqb2luX3J1bGVfaW52aXRlXCIpLFxuICAgICAgICAgICAgZGVzY3JpcHRpb246IF90KFwicm9vbV9zZXR0aW5nc3xzZWN1cml0eXxqb2luX3J1bGVfaW52aXRlX2Rlc2NyaXB0aW9uXCIpLFxuICAgICAgICAgICAgY2hlY2tlZDpcbiAgICAgICAgICAgICAgICBqb2luUnVsZSA9PT0gSm9pblJ1bGUuSW52aXRlIHx8IChqb2luUnVsZSA9PT0gSm9pblJ1bGUuUmVzdHJpY3RlZCAmJiAhcmVzdHJpY3RlZEFsbG93Um9vbUlkcz8ubGVuZ3RoKSxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgICAgdmFsdWU6IEpvaW5SdWxlLlB1YmxpYyxcbiAgICAgICAgICAgIGxhYmVsOiBfdChcImNvbW1vbnxwdWJsaWNcIiksXG4gICAgICAgICAgICBkZXNjcmlwdGlvbjogKFxuICAgICAgICAgICAgICAgIDw+XG4gICAgICAgICAgICAgICAgICAgIHtfdChcInJvb21fc2V0dGluZ3N8c2VjdXJpdHl8am9pbl9ydWxlX3B1YmxpY19kZXNjcmlwdGlvblwiKX1cbiAgICAgICAgICAgICAgICAgICAge2FsaWFzV2FybmluZ31cbiAgICAgICAgICAgICAgICA8Lz5cbiAgICAgICAgICAgICksXG4gICAgICAgIH0sXG4gICAgXTtcblxuICAgIGlmIChyb29tU3VwcG9ydHNSZXN0cmljdGVkIHx8IHByZWZlcnJlZFJlc3RyaWN0aW9uVmVyc2lvbiB8fCBqb2luUnVsZSA9PT0gSm9pblJ1bGUuUmVzdHJpY3RlZCkge1xuICAgICAgICBsZXQgZGVzY3JpcHRpb247XG4gICAgICAgIGlmIChqb2luUnVsZSA9PT0gSm9pblJ1bGUuUmVzdHJpY3RlZCAmJiByZXN0cmljdGVkQWxsb3dSb29tSWRzPy5sZW5ndGgpIHtcbiAgICAgICAgICAgIC8vIG9ubHkgc2hvdyB0aGUgZmlyc3QgNCBzcGFjZXMgd2Uga25vdyBhYm91dCwgc28gdGhhdCB0aGUgVUkgZG9lc24ndCBncm93IG91dCBvZiBwcm9wb3J0aW9uIHRoZXJlIGFyZSBsb3RzLlxuICAgICAgICAgICAgY29uc3Qgc2hvd25TcGFjZXMgPSByZXN0cmljdGVkQWxsb3dSb29tSWRzXG4gICAgICAgICAgICAgICAgLm1hcCgocm9vbUlkKSA9PiBjbGkuZ2V0Um9vbShyb29tSWQpKVxuICAgICAgICAgICAgICAgIC5maWx0ZXIoKHJvb20pID0+IHJvb20/LmlzU3BhY2VSb29tKCkpXG4gICAgICAgICAgICAgICAgLnNsaWNlKDAsIDQpIGFzIFJvb21bXTtcblxuICAgICAgICAgICAgbGV0IG1vcmVUZXh0O1xuICAgICAgICAgICAgaWYgKHNob3duU3BhY2VzLmxlbmd0aCA8IHJlc3RyaWN0ZWRBbGxvd1Jvb21JZHMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgaWYgKHNob3duU3BhY2VzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgbW9yZVRleHQgPSBfdChcInJvb21fc2V0dGluZ3N8c2VjdXJpdHl8am9pbl9ydWxlX3Jlc3RyaWN0ZWRfbl9tb3JlXCIsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50OiByZXN0cmljdGVkQWxsb3dSb29tSWRzLmxlbmd0aCAtIHNob3duU3BhY2VzLmxlbmd0aCxcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbW9yZVRleHQgPSBfdChcInJvb21fc2V0dGluZ3N8c2VjdXJpdHl8am9pbl9ydWxlX3Jlc3RyaWN0ZWRfc3VtbWFyeVwiLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb3VudDogcmVzdHJpY3RlZEFsbG93Um9vbUlkcy5sZW5ndGgsXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3Qgb25SZXN0cmljdGVkUm9vbUlkc0NoYW5nZSA9IChuZXdBbGxvd1Jvb21JZHM6IHN0cmluZ1tdKTogdm9pZCA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKCFhcnJheUhhc0RpZmYocmVzdHJpY3RlZEFsbG93Um9vbUlkcyB8fCBbXSwgbmV3QWxsb3dSb29tSWRzKSkgcmV0dXJuO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFuZXdBbGxvd1Jvb21JZHMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHNldENvbnRlbnQoe1xuICAgICAgICAgICAgICAgICAgICAgICAgam9pbl9ydWxlOiBKb2luUnVsZS5JbnZpdGUsXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgc2V0Q29udGVudCh7XG4gICAgICAgICAgICAgICAgICAgIGpvaW5fcnVsZTogSm9pblJ1bGUuUmVzdHJpY3RlZCxcbiAgICAgICAgICAgICAgICAgICAgYWxsb3c6IG5ld0FsbG93Um9vbUlkcy5tYXAoKHJvb21JZCkgPT4gKHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6IFJlc3RyaWN0ZWRBbGxvd1R5cGUuUm9vbU1lbWJlcnNoaXAsXG4gICAgICAgICAgICAgICAgICAgICAgICByb29tX2lkOiByb29tSWQsXG4gICAgICAgICAgICAgICAgICAgIH0pKSxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGNvbnN0IG9uRWRpdFJlc3RyaWN0ZWRDbGljayA9IGFzeW5jICgpOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCByZXN0cmljdGVkQWxsb3dSb29tSWRzID0gYXdhaXQgZWRpdFJlc3RyaWN0ZWRSb29tSWRzKCk7XG4gICAgICAgICAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KHJlc3RyaWN0ZWRBbGxvd1Jvb21JZHMpKSByZXR1cm47XG4gICAgICAgICAgICAgICAgaWYgKHJlc3RyaWN0ZWRBbGxvd1Jvb21JZHMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICBvblJlc3RyaWN0ZWRSb29tSWRzQ2hhbmdlKHJlc3RyaWN0ZWRBbGxvd1Jvb21JZHMpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG9uQ2hhbmdlKEpvaW5SdWxlLkludml0ZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgZGVzY3JpcHRpb24gPSAoXG4gICAgICAgICAgICAgICAgPGRpdj5cbiAgICAgICAgICAgICAgICAgICAgPHNwYW4+XG4gICAgICAgICAgICAgICAgICAgICAgICB7X3QoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJyb29tX3NldHRpbmdzfHNlY3VyaXR5fGpvaW5fcnVsZV9yZXN0cmljdGVkX2Rlc2NyaXB0aW9uXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAge30sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhOiAoc3ViKSA9PiAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8QWNjZXNzaWJsZUJ1dHRvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpc2FibGVkPXtkaXNhYmxlZH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbkNsaWNrPXtvbkVkaXRSZXN0cmljdGVkQ2xpY2t9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAga2luZD1cImxpbmtfaW5saW5lXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7c3VifVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9BY2Nlc3NpYmxlQnV0dG9uPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICApfVxuICAgICAgICAgICAgICAgICAgICA8L3NwYW4+XG5cbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJteF9Kb2luUnVsZVNldHRpbmdzX3NwYWNlc1dpdGhBY2Nlc3NcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxoND57X3QoXCJyb29tX3NldHRpbmdzfHNlY3VyaXR5fGpvaW5fcnVsZV9yZXN0cmljdGVkX2Rlc2NyaXB0aW9uX3NwYWNlc1wiKX08L2g0PlxuICAgICAgICAgICAgICAgICAgICAgICAge3Nob3duU3BhY2VzLm1hcCgocm9vbSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGtleT17cm9vbS5yb29tSWR9PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPFJvb21BdmF0YXIgcm9vbT17cm9vbX0gc2l6ZT1cIjMycHhcIiAvPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge3Jvb20ubmFtZX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KX1cbiAgICAgICAgICAgICAgICAgICAgICAgIHttb3JlVGV4dCAmJiA8c3Bhbj57bW9yZVRleHR9PC9zcGFuPn1cbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICApO1xuICAgICAgICB9IGVsc2UgaWYgKFNwYWNlU3RvcmUuaW5zdGFuY2UuYWN0aXZlU3BhY2VSb29tKSB7XG4gICAgICAgICAgICBkZXNjcmlwdGlvbiA9IF90KFxuICAgICAgICAgICAgICAgIFwicm9vbV9zZXR0aW5nc3xzZWN1cml0eXxqb2luX3J1bGVfcmVzdHJpY3RlZF9kZXNjcmlwdGlvbl9hY3RpdmVfc3BhY2VcIixcbiAgICAgICAgICAgICAgICB7fSxcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIHNwYWNlTmFtZTogKCkgPT4gPHN0cm9uZz57U3BhY2VTdG9yZS5pbnN0YW5jZS5hY3RpdmVTcGFjZVJvb20hLm5hbWV9PC9zdHJvbmc+LFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZGVzY3JpcHRpb24gPSBfdChcInJvb21fc2V0dGluZ3N8c2VjdXJpdHl8am9pbl9ydWxlX3Jlc3RyaWN0ZWRfZGVzY3JpcHRpb25fcHJvbXB0XCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgZGVmaW5pdGlvbnMuc3BsaWNlKDEsIDAsIHtcbiAgICAgICAgICAgIHZhbHVlOiBKb2luUnVsZS5SZXN0cmljdGVkLFxuICAgICAgICAgICAgbGFiZWw6IChcbiAgICAgICAgICAgICAgICA8PlxuICAgICAgICAgICAgICAgICAgICB7X3QoXCJyb29tX3NldHRpbmdzfHNlY3VyaXR5fGpvaW5fcnVsZV9yZXN0cmljdGVkXCIpfVxuICAgICAgICAgICAgICAgICAgICB7cHJlZmVycmVkUmVzdHJpY3Rpb25WZXJzaW9uICYmIHVwZ3JhZGVSZXF1aXJlZFBpbGx9XG4gICAgICAgICAgICAgICAgPC8+XG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgZGVzY3JpcHRpb24sXG4gICAgICAgICAgICAvLyBpZiB0aGVyZSBhcmUgMCBhbGxvd2VkIHNwYWNlcyB0aGVuIHJlbmRlciBpdCBhcyBpbnZpdGUgb25seSBpbnN0ZWFkXG4gICAgICAgICAgICBjaGVja2VkOiBqb2luUnVsZSA9PT0gSm9pblJ1bGUuUmVzdHJpY3RlZCAmJiAhIXJlc3RyaWN0ZWRBbGxvd1Jvb21JZHM/Lmxlbmd0aCxcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgaWYgKGFza1RvSm9pbkVuYWJsZWQgJiYgKHJvb21TdXBwb3J0c0tub2NrIHx8IHByZWZlcnJlZEtub2NrVmVyc2lvbikpIHtcbiAgICAgICAgZGVmaW5pdGlvbnMucHVzaCh7XG4gICAgICAgICAgICB2YWx1ZTogSm9pblJ1bGUuS25vY2ssXG4gICAgICAgICAgICBsYWJlbDogKFxuICAgICAgICAgICAgICAgIDw+XG4gICAgICAgICAgICAgICAgICAgIHtfdChcInJvb21fc2V0dGluZ3N8c2VjdXJpdHl8am9pbl9ydWxlX2tub2NrXCIpfVxuICAgICAgICAgICAgICAgICAgICB7cHJlZmVycmVkS25vY2tWZXJzaW9uICYmIHVwZ3JhZGVSZXF1aXJlZFBpbGx9XG4gICAgICAgICAgICAgICAgPC8+XG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgZGVzY3JpcHRpb246IChcbiAgICAgICAgICAgICAgICA8PlxuICAgICAgICAgICAgICAgICAgICB7X3QoXCJyb29tX3NldHRpbmdzfHNlY3VyaXR5fGpvaW5fcnVsZV9rbm9ja19kZXNjcmlwdGlvblwiKX1cbiAgICAgICAgICAgICAgICAgICAgPExhYmVsbGVkQ2hlY2tib3hcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzTmFtZT1cIm14X0pvaW5SdWxlU2V0dGluZ3NfbGFiZWxsZWRDaGVja2JveFwiXG4gICAgICAgICAgICAgICAgICAgICAgICBkaXNhYmxlZD17am9pblJ1bGUgIT09IEpvaW5SdWxlLktub2NrfVxuICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWw9e1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvb20uaXNTcGFjZVJvb20oKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA/IF90KFwicm9vbV9zZXR0aW5nc3xzZWN1cml0eXxwdWJsaXNoX3NwYWNlXCIpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogX3QoXCJyb29tX3NldHRpbmdzfHNlY3VyaXR5fHB1Ymxpc2hfcm9vbVwiKVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgb25DaGFuZ2U9e29uSXNQdWJsaWNLbm9ja1Jvb21DaGFuZ2V9XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZT17aXNQdWJsaWNLbm9ja1Jvb219XG4gICAgICAgICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICAgICAgPC8+XG4gICAgICAgICAgICApLFxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBjb25zdCBvbkNoYW5nZSA9IGFzeW5jIChqb2luUnVsZTogSm9pblJ1bGUpOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgICAgICAgY29uc3QgYmVmb3JlSm9pblJ1bGUgPSBjb250ZW50Py5qb2luX3J1bGU7XG5cbiAgICAgICAgbGV0IHJlc3RyaWN0ZWRBbGxvd1Jvb21JZHM6IHN0cmluZ1tdIHwgdW5kZWZpbmVkO1xuICAgICAgICBpZiAoam9pblJ1bGUgPT09IEpvaW5SdWxlLlJlc3RyaWN0ZWQpIHtcbiAgICAgICAgICAgIGlmIChiZWZvcmVKb2luUnVsZSA9PT0gSm9pblJ1bGUuUmVzdHJpY3RlZCB8fCByb29tU3VwcG9ydHNSZXN0cmljdGVkKSB7XG4gICAgICAgICAgICAgICAgLy8gSGF2ZSB0aGUgdXNlciBwaWNrIHdoaWNoIHNwYWNlcyB0byBhbGxvdyBqb2lucyBmcm9tXG4gICAgICAgICAgICAgICAgcmVzdHJpY3RlZEFsbG93Um9vbUlkcyA9IGF3YWl0IGVkaXRSZXN0cmljdGVkUm9vbUlkcygpO1xuICAgICAgICAgICAgICAgIGlmICghQXJyYXkuaXNBcnJheShyZXN0cmljdGVkQWxsb3dSb29tSWRzKSkgcmV0dXJuO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChwcmVmZXJyZWRSZXN0cmljdGlvblZlcnNpb24pIHtcbiAgICAgICAgICAgICAgICAvLyBCbG9jayB0aGlzIGFjdGlvbiBvbiBhIHJvb20gdXBncmFkZSBvdGhlcndpc2UgaXQnZCBtYWtlIHRoZWlyIHJvb20gdW5qb2luYWJsZVxuICAgICAgICAgICAgICAgIGNvbnN0IHRhcmdldFZlcnNpb24gPSBwcmVmZXJyZWRSZXN0cmljdGlvblZlcnNpb247XG5cbiAgICAgICAgICAgICAgICBsZXQgd2FybmluZzogSlNYLkVsZW1lbnQgfCB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgY29uc3QgdXNlcklkID0gY2xpLmdldFVzZXJJZCgpITtcbiAgICAgICAgICAgICAgICBjb25zdCB1bmFibGVUb1VwZGF0ZVNvbWVQYXJlbnRzID0gQXJyYXkuZnJvbShTcGFjZVN0b3JlLmluc3RhbmNlLmdldEtub3duUGFyZW50cyhyb29tLnJvb21JZCkpLnNvbWUoXG4gICAgICAgICAgICAgICAgICAgIChyb29tSWQpID0+ICFjbGkuZ2V0Um9vbShyb29tSWQpPy5jdXJyZW50U3RhdGUubWF5U2VuZFN0YXRlRXZlbnQoRXZlbnRUeXBlLlNwYWNlQ2hpbGQsIHVzZXJJZCksXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICBpZiAodW5hYmxlVG9VcGRhdGVTb21lUGFyZW50cykge1xuICAgICAgICAgICAgICAgICAgICB3YXJuaW5nID0gPHN0cm9uZz57X3QoXCJyb29tX3NldHRpbmdzfHNlY3VyaXR5fGpvaW5fcnVsZV9yZXN0cmljdGVkX3VwZ3JhZGVfd2FybmluZ1wiKX08L3N0cm9uZz47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdXBncmFkZVJlcXVpcmVkRGlhbG9nKFxuICAgICAgICAgICAgICAgICAgICB0YXJnZXRWZXJzaW9uLFxuICAgICAgICAgICAgICAgICAgICA8PlxuICAgICAgICAgICAgICAgICAgICAgICAge190KFwicm9vbV9zZXR0aW5nc3xzZWN1cml0eXxqb2luX3J1bGVfcmVzdHJpY3RlZF91cGdyYWRlX2Rlc2NyaXB0aW9uXCIpfVxuICAgICAgICAgICAgICAgICAgICAgICAge3dhcm5pbmd9XG4gICAgICAgICAgICAgICAgICAgIDwvPixcbiAgICAgICAgICAgICAgICApO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyB3aGVuIHNldHRpbmcgdG8gMCBhbGxvd2VkIHJvb21zL3NwYWNlcyBzZXQgdG8gaW52aXRlIG9ubHkgaW5zdGVhZCBhcyBwZXIgdGhlIG5vdGVcbiAgICAgICAgICAgIGlmICghcmVzdHJpY3RlZEFsbG93Um9vbUlkcz8ubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgam9pblJ1bGUgPSBKb2luUnVsZS5JbnZpdGU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoam9pblJ1bGUgPT09IEpvaW5SdWxlLktub2NrKSB7XG4gICAgICAgICAgICBpZiAocHJlZmVycmVkS25vY2tWZXJzaW9uKSB7XG4gICAgICAgICAgICAgICAgdXBncmFkZVJlcXVpcmVkRGlhbG9nKHByZWZlcnJlZEtub2NrVmVyc2lvbik7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGJlZm9yZUpvaW5SdWxlID09PSBqb2luUnVsZSAmJiAhcmVzdHJpY3RlZEFsbG93Um9vbUlkcykgcmV0dXJuO1xuICAgICAgICBpZiAoYmVmb3JlQ2hhbmdlICYmICEoYXdhaXQgYmVmb3JlQ2hhbmdlKGpvaW5SdWxlKSkpIHJldHVybjtcblxuICAgICAgICBjb25zdCBuZXdDb250ZW50OiBSb29tSm9pblJ1bGVzRXZlbnRDb250ZW50ID0ge1xuICAgICAgICAgICAgam9pbl9ydWxlOiBqb2luUnVsZSxcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBwcmUtc2V0IHRoZSBhY2NlcHRlZCBzcGFjZXMgd2l0aCB0aGUgY3VycmVudGx5IHZpZXdlZCBvbmUgYXMgcGVyIHRoZSBtaWNyb2NvcHlcbiAgICAgICAgaWYgKGpvaW5SdWxlID09PSBKb2luUnVsZS5SZXN0cmljdGVkKSB7XG4gICAgICAgICAgICBuZXdDb250ZW50LmFsbG93ID0gcmVzdHJpY3RlZEFsbG93Um9vbUlkcz8ubWFwKChyb29tSWQpID0+ICh7XG4gICAgICAgICAgICAgICAgdHlwZTogUmVzdHJpY3RlZEFsbG93VHlwZS5Sb29tTWVtYmVyc2hpcCxcbiAgICAgICAgICAgICAgICByb29tX2lkOiByb29tSWQsXG4gICAgICAgICAgICB9KSk7XG4gICAgICAgIH1cblxuICAgICAgICBzZXRDb250ZW50KG5ld0NvbnRlbnQpO1xuICAgIH07XG5cbiAgICByZXR1cm4gKFxuICAgICAgICA8U3R5bGVkUmFkaW9Hcm91cFxuICAgICAgICAgICAgbmFtZT1cImpvaW5SdWxlXCJcbiAgICAgICAgICAgIHZhbHVlPXtqb2luUnVsZX1cbiAgICAgICAgICAgIG9uQ2hhbmdlPXtvbkNoYW5nZX1cbiAgICAgICAgICAgIGRlZmluaXRpb25zPXtkZWZpbml0aW9uc31cbiAgICAgICAgICAgIGRpc2FibGVkPXtkaXNhYmxlZH1cbiAgICAgICAgICAgIGNsYXNzTmFtZT1cIm14X0pvaW5SdWxlU2V0dGluZ3NfcmFkaW9CdXR0b25cIlxuICAgICAgICAvPlxuICAgICk7XG59O1xuXG5leHBvcnQgZGVmYXVsdCBKb2luUnVsZVNldHRpbmdzO1xuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBUUEsSUFBQUEsTUFBQSxHQUFBQyx1QkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQUMsT0FBQSxHQUFBRCxPQUFBO0FBR0EsSUFBQUUsaUJBQUEsR0FBQUMsc0JBQUEsQ0FBQUgsT0FBQTtBQUNBLElBQUFJLGdCQUFBLEdBQUFKLE9BQUE7QUFDQSxJQUFBSyxpQkFBQSxHQUFBRixzQkFBQSxDQUFBSCxPQUFBO0FBQ0EsSUFBQU0sV0FBQSxHQUFBSCxzQkFBQSxDQUFBSCxPQUFBO0FBQ0EsSUFBQU8sV0FBQSxHQUFBSixzQkFBQSxDQUFBSCxPQUFBO0FBQ0EsSUFBQVEsTUFBQSxHQUFBTCxzQkFBQSxDQUFBSCxPQUFBO0FBQ0EsSUFBQVMsK0JBQUEsR0FBQU4sc0JBQUEsQ0FBQUgsT0FBQTtBQUNBLElBQUFVLHlCQUFBLEdBQUFQLHNCQUFBLENBQUFILE9BQUE7QUFDQSxJQUFBVyxZQUFBLEdBQUFYLE9BQUE7QUFDQSxJQUFBWSxPQUFBLEdBQUFaLE9BQUE7QUFDQSxJQUFBYSxhQUFBLEdBQUFiLE9B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