UNPKG

matrix-react-sdk

Version:
444 lines (383 loc) 57.1 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _react = _interopRequireDefault(require("react")); var _languageHandler = require("../../../../../languageHandler"); var _MatrixClientPeg = require("../../../../../MatrixClientPeg"); var sdk = _interopRequireWildcard(require("../../../../..")); var _LabelledToggleSwitch = _interopRequireDefault(require("../../../elements/LabelledToggleSwitch")); var _Modal = _interopRequireDefault(require("../../../../../Modal")); var _QuestionDialog = _interopRequireDefault(require("../../../dialogs/QuestionDialog")); var _StyledRadioGroup = _interopRequireDefault(require("../../../elements/StyledRadioGroup")); var _SettingLevel = require("../../../../../settings/SettingLevel"); var _SettingsStore = _interopRequireDefault(require("../../../../../settings/SettingsStore")); var _UIFeature = require("../../../../../settings/UIFeature"); var _replaceableComponent = require("../../../../../utils/replaceableComponent"); var _dec, _class, _temp; // Knock and private are reserved keywords which are not yet implemented. var JoinRule; (function (JoinRule) { JoinRule["Public"] = "public"; JoinRule["Knock"] = "knock"; JoinRule["Invite"] = "invite"; JoinRule["Private"] = "private"; })(JoinRule || (JoinRule = {})); var GuestAccess; (function (GuestAccess) { GuestAccess["CanJoin"] = "can_join"; GuestAccess["Forbidden"] = "forbidden"; })(GuestAccess || (GuestAccess = {})); var HistoryVisibility; (function (HistoryVisibility) { HistoryVisibility["Invited"] = "invited"; HistoryVisibility["Joined"] = "joined"; HistoryVisibility["Shared"] = "shared"; HistoryVisibility["WorldReadable"] = "world_readable"; })(HistoryVisibility || (HistoryVisibility = {})); let SecurityRoomSettingsTab = (_dec = (0, _replaceableComponent.replaceableComponent)("views.settings.tabs.room.SecurityRoomSettingsTab"), _dec(_class = (_temp = class SecurityRoomSettingsTab extends _react.default.Component /*:: <IProps, IState>*/ { constructor(props) { super(props); (0, _defineProperty2.default)(this, "onStateEvent", (e /*: MatrixEvent*/ ) => { const refreshWhenTypes = ['m.room.join_rules', 'm.room.guest_access', 'm.room.history_visibility', 'm.room.encryption']; if (refreshWhenTypes.includes(e.getType())) this.forceUpdate(); }); (0, _defineProperty2.default)(this, "onEncryptionChange", (e /*: React.ChangeEvent*/ ) => { _Modal.default.createTrackedDialog('Enable encryption', '', _QuestionDialog.default, { title: (0, _languageHandler._t)('Enable encryption?'), description: (0, _languageHandler._t)("Once enabled, encryption for a room cannot be disabled. Messages sent in an encrypted " + "room cannot be seen by the server, only by the participants of the room. Enabling encryption " + "may prevent many bots and bridges from working correctly. <a>Learn more about encryption.</a>", {}, { a: sub => /*#__PURE__*/_react.default.createElement("a", { href: "https://element.io/help#encryption", rel: "noreferrer noopener", target: "_blank" }, sub) }), onFinished: confirm => { if (!confirm) { this.setState({ encrypted: false }); return; } const beforeEncrypted = this.state.encrypted; this.setState({ encrypted: true }); _MatrixClientPeg.MatrixClientPeg.get().sendStateEvent(this.props.roomId, "m.room.encryption", { algorithm: "m.megolm.v1.aes-sha2" }).catch(e => { console.error(e); this.setState({ encrypted: beforeEncrypted }); }); } }); }); (0, _defineProperty2.default)(this, "fixGuestAccess", (e /*: React.MouseEvent*/ ) => { e.preventDefault(); e.stopPropagation(); const joinRule = JoinRule.Invite; const guestAccess = GuestAccess.CanJoin; const beforeJoinRule = this.state.joinRule; const beforeGuestAccess = this.state.guestAccess; this.setState({ joinRule, guestAccess }); const client = _MatrixClientPeg.MatrixClientPeg.get(); client.sendStateEvent(this.props.roomId, "m.room.join_rules", { join_rule: joinRule }, "").catch(e => { console.error(e); this.setState({ joinRule: beforeJoinRule }); }); client.sendStateEvent(this.props.roomId, "m.room.guest_access", { guest_access: guestAccess }, "").catch(e => { console.error(e); this.setState({ guestAccess: beforeGuestAccess }); }); }); (0, _defineProperty2.default)(this, "onRoomAccessRadioToggle", (roomAccess /*: string*/ ) => { // join_rule // INVITE | PUBLIC // ----------------------+---------------- // guest CAN_JOIN | inv_only | pub_with_guest // access ----------------------+---------------- // FORBIDDEN | inv_only | pub_no_guest // ----------------------+---------------- // we always set guests can_join here as it makes no sense to have // an invite-only room that guests can't join. If you explicitly // invite them, you clearly want them to join, whether they're a // guest or not. In practice, guest_access should probably have // been implemented as part of the join_rules enum. let joinRule = JoinRule.Invite; let guestAccess = GuestAccess.CanJoin; switch (roomAccess) { case "invite_only": // no change - use defaults above break; case "public_no_guests": joinRule = JoinRule.Public; guestAccess = GuestAccess.Forbidden; break; case "public_with_guests": joinRule = JoinRule.Public; guestAccess = GuestAccess.CanJoin; break; } const beforeJoinRule = this.state.joinRule; const beforeGuestAccess = this.state.guestAccess; this.setState({ joinRule, guestAccess }); const client = _MatrixClientPeg.MatrixClientPeg.get(); client.sendStateEvent(this.props.roomId, "m.room.join_rules", { join_rule: joinRule }, "").catch(e => { console.error(e); this.setState({ joinRule: beforeJoinRule }); }); client.sendStateEvent(this.props.roomId, "m.room.guest_access", { guest_access: guestAccess }, "").catch(e => { console.error(e); this.setState({ guestAccess: beforeGuestAccess }); }); }); (0, _defineProperty2.default)(this, "onHistoryRadioToggle", (history /*: HistoryVisibility*/ ) => { const beforeHistory = this.state.history; this.setState({ history: history }); _MatrixClientPeg.MatrixClientPeg.get().sendStateEvent(this.props.roomId, "m.room.history_visibility", { history_visibility: history }, "").catch(e => { console.error(e); this.setState({ history: beforeHistory }); }); }); (0, _defineProperty2.default)(this, "updateBlacklistDevicesFlag", (checked /*: boolean*/ ) => { _MatrixClientPeg.MatrixClientPeg.get().getRoom(this.props.roomId).setBlacklistUnverifiedDevices(checked); }); this.state = { joinRule: JoinRule.Invite, guestAccess: GuestAccess.CanJoin, history: HistoryVisibility.Shared, hasAliases: false, encrypted: false }; } // TODO: [REACT-WARNING] Move this to constructor async UNSAFE_componentWillMount() { // eslint-disable-line camelcase _MatrixClientPeg.MatrixClientPeg.get().on("RoomState.events", this.onStateEvent); const room = _MatrixClientPeg.MatrixClientPeg.get().getRoom(this.props.roomId); const state = room.currentState; const joinRule /*: JoinRule*/ = this.pullContentPropertyFromEvent(state.getStateEvents("m.room.join_rules", ""), 'join_rule', JoinRule.Invite); const guestAccess /*: GuestAccess*/ = this.pullContentPropertyFromEvent(state.getStateEvents("m.room.guest_access", ""), 'guest_access', GuestAccess.Forbidden); const history /*: HistoryVisibility*/ = this.pullContentPropertyFromEvent(state.getStateEvents("m.room.history_visibility", ""), 'history_visibility', HistoryVisibility.Shared); const encrypted = _MatrixClientPeg.MatrixClientPeg.get().isRoomEncrypted(this.props.roomId); this.setState({ joinRule, guestAccess, history, encrypted }); const hasAliases = await this.hasAliases(); this.setState({ hasAliases }); } pullContentPropertyFromEvent(event /*: MatrixEvent*/ , key /*: string*/ , defaultValue /*: T*/ ) /*: T*/ { if (!event || !event.getContent()) return defaultValue; return event.getContent()[key] || defaultValue; } componentWillUnmount() { _MatrixClientPeg.MatrixClientPeg.get().removeListener("RoomState.events", this.onStateEvent); } async hasAliases() /*: Promise<boolean>*/ { const cli = _MatrixClientPeg.MatrixClientPeg.get(); if (await cli.doesServerSupportUnstableFeature("org.matrix.msc2432")) { const response = await cli.unstableGetLocalAliases(this.props.roomId); const localAliases = response.aliases; return Array.isArray(localAliases) && localAliases.length !== 0; } else { const room = cli.getRoom(this.props.roomId); const aliasEvents = room.currentState.getStateEvents("m.room.aliases") || []; const hasAliases = !!aliasEvents.find(ev => (ev.getContent().aliases || []).length > 0); return hasAliases; } } renderRoomAccess() { const client = _MatrixClientPeg.MatrixClientPeg.get(); const room = client.getRoom(this.props.roomId); const joinRule = this.state.joinRule; const guestAccess = this.state.guestAccess; const canChangeAccess = room.currentState.mayClientSendStateEvent("m.room.join_rules", client) && room.currentState.mayClientSendStateEvent("m.room.guest_access", client); let guestWarning = null; if (joinRule !== 'public' && guestAccess === 'forbidden') { guestWarning = /*#__PURE__*/_react.default.createElement("div", { className: "mx_SecurityRoomSettingsTab_warning" }, /*#__PURE__*/_react.default.createElement("img", { src: require("../../../../../../res/img/warning.svg"), width: 15, height: 15 }), /*#__PURE__*/_react.default.createElement("span", null, (0, _languageHandler._t)("Guests cannot join this room even if explicitly invited."), "\xA0", /*#__PURE__*/_react.default.createElement("a", { href: "", onClick: this.fixGuestAccess }, (0, _languageHandler._t)("Click here to fix")))); } let aliasWarning = null; if (joinRule === 'public' && !this.state.hasAliases) { aliasWarning = /*#__PURE__*/_react.default.createElement("div", { className: "mx_SecurityRoomSettingsTab_warning" }, /*#__PURE__*/_react.default.createElement("img", { src: require("../../../../../../res/img/warning.svg"), width: 15, height: 15 }), /*#__PURE__*/_react.default.createElement("span", null, (0, _languageHandler._t)("To link to this room, please add an address."))); } return /*#__PURE__*/_react.default.createElement("div", null, guestWarning, aliasWarning, /*#__PURE__*/_react.default.createElement(_StyledRadioGroup.default, { name: "roomVis", value: joinRule, onChange: this.onRoomAccessRadioToggle, definitions: [{ value: "invite_only", disabled: !canChangeAccess, label: (0, _languageHandler._t)('Only people who have been invited'), checked: joinRule !== "public" }, { value: "public_no_guests", disabled: !canChangeAccess, label: (0, _languageHandler._t)('Anyone who knows the room\'s link, apart from guests'), checked: joinRule === "public" && guestAccess !== "can_join" }, { value: "public_with_guests", disabled: !canChangeAccess, label: (0, _languageHandler._t)("Anyone who knows the room's link, including guests"), checked: joinRule === "public" && guestAccess === "can_join" }] })); } renderHistory() { const client = _MatrixClientPeg.MatrixClientPeg.get(); const history = this.state.history; const state = client.getRoom(this.props.roomId).currentState; const canChangeHistory = state.mayClientSendStateEvent('m.room.history_visibility', client); return /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("div", null, (0, _languageHandler._t)('Changes to who can read history will only apply to future messages in this room. ' + 'The visibility of existing history will be unchanged.')), /*#__PURE__*/_react.default.createElement(_StyledRadioGroup.default, { name: "historyVis", value: history, onChange: this.onHistoryRadioToggle, definitions: [{ value: HistoryVisibility.WorldReadable, disabled: !canChangeHistory, label: (0, _languageHandler._t)("Anyone") }, { value: HistoryVisibility.Shared, disabled: !canChangeHistory, label: (0, _languageHandler._t)('Members only (since the point in time of selecting this option)') }, { value: HistoryVisibility.Invited, disabled: !canChangeHistory, label: (0, _languageHandler._t)('Members only (since they were invited)') }, { value: HistoryVisibility.Joined, disabled: !canChangeHistory, label: (0, _languageHandler._t)('Members only (since they joined)') }] })); } render() { const SettingsFlag = sdk.getComponent("elements.SettingsFlag"); const client = _MatrixClientPeg.MatrixClientPeg.get(); const room = client.getRoom(this.props.roomId); const isEncrypted = this.state.encrypted; const hasEncryptionPermission = room.currentState.mayClientSendStateEvent("m.room.encryption", client); const canEnableEncryption = !isEncrypted && hasEncryptionPermission; let encryptionSettings = null; if (isEncrypted && _SettingsStore.default.isEnabled("blacklistUnverifiedDevices")) { encryptionSettings = /*#__PURE__*/_react.default.createElement(SettingsFlag, { name: "blacklistUnverifiedDevices", level: _SettingLevel.SettingLevel.ROOM_DEVICE, onChange: this.updateBlacklistDevicesFlag, roomId: this.props.roomId }); } let historySection = /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("span", { className: "mx_SettingsTab_subheading" }, (0, _languageHandler._t)("Who can read history?")), /*#__PURE__*/_react.default.createElement("div", { className: "mx_SettingsTab_section mx_SettingsTab_subsectionText" }, this.renderHistory())); if (!_SettingsStore.default.getValue(_UIFeature.UIFeature.RoomHistorySettings)) { historySection = null; } return /*#__PURE__*/_react.default.createElement("div", { className: "mx_SettingsTab mx_SecurityRoomSettingsTab" }, /*#__PURE__*/_react.default.createElement("div", { className: "mx_SettingsTab_heading" }, (0, _languageHandler._t)("Security & Privacy")), /*#__PURE__*/_react.default.createElement("span", { className: "mx_SettingsTab_subheading" }, (0, _languageHandler._t)("Encryption")), /*#__PURE__*/_react.default.createElement("div", { className: "mx_SettingsTab_section mx_SecurityRoomSettingsTab_encryptionSection" }, /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("div", { className: "mx_SettingsTab_subsectionText" }, /*#__PURE__*/_react.default.createElement("span", null, (0, _languageHandler._t)("Once enabled, encryption cannot be disabled."))), /*#__PURE__*/_react.default.createElement(_LabelledToggleSwitch.default, { value: isEncrypted, onChange: this.onEncryptionChange, label: (0, _languageHandler._t)("Encrypted"), disabled: !canEnableEncryption })), encryptionSettings), /*#__PURE__*/_react.default.createElement("span", { className: "mx_SettingsTab_subheading" }, (0, _languageHandler._t)("Who can access this room?")), /*#__PURE__*/_react.default.createElement("div", { className: "mx_SettingsTab_section mx_SettingsTab_subsectionText" }, this.renderRoomAccess()), historySection); } }, _temp)) || _class); exports.default = SecurityRoomSettingsTab; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9jb21wb25lbnRzL3ZpZXdzL3NldHRpbmdzL3RhYnMvcm9vbS9TZWN1cml0eVJvb21TZXR0aW5nc1RhYi50c3giXSwibmFtZXMiOlsiSm9pblJ1bGUiLCJHdWVzdEFjY2VzcyIsIkhpc3RvcnlWaXNpYmlsaXR5IiwiU2VjdXJpdHlSb29tU2V0dGluZ3NUYWIiLCJSZWFjdCIsIkNvbXBvbmVudCIsImNvbnN0cnVjdG9yIiwicHJvcHMiLCJlIiwicmVmcmVzaFdoZW5UeXBlcyIsImluY2x1ZGVzIiwiZ2V0VHlwZSIsImZvcmNlVXBkYXRlIiwiTW9kYWwiLCJjcmVhdGVUcmFja2VkRGlhbG9nIiwiUXVlc3Rpb25EaWFsb2ciLCJ0aXRsZSIsImRlc2NyaXB0aW9uIiwiYSIsInN1YiIsIm9uRmluaXNoZWQiLCJjb25maXJtIiwic2V0U3RhdGUiLCJlbmNyeXB0ZWQiLCJiZWZvcmVFbmNyeXB0ZWQiLCJzdGF0ZSIsIk1hdHJpeENsaWVudFBlZyIsImdldCIsInNlbmRTdGF0ZUV2ZW50Iiwicm9vbUlkIiwiYWxnb3JpdGhtIiwiY2F0Y2giLCJjb25zb2xlIiwiZXJyb3IiLCJwcmV2ZW50RGVmYXVsdCIsInN0b3BQcm9wYWdhdGlvbiIsImpvaW5SdWxlIiwiSW52aXRlIiwiZ3Vlc3RBY2Nlc3MiLCJDYW5Kb2luIiwiYmVmb3JlSm9pblJ1bGUiLCJiZWZvcmVHdWVzdEFjY2VzcyIsImNsaWVudCIsImpvaW5fcnVsZSIsImd1ZXN0X2FjY2VzcyIsInJvb21BY2Nlc3MiLCJQdWJsaWMiLCJGb3JiaWRkZW4iLCJoaXN0b3J5IiwiYmVmb3JlSGlzdG9yeSIsImhpc3RvcnlfdmlzaWJpbGl0eSIsImNoZWNrZWQiLCJnZXRSb29tIiwic2V0QmxhY2tsaXN0VW52ZXJpZmllZERldmljZXMiLCJTaGFyZWQiLCJoYXNBbGlhc2VzIiwiVU5TQUZFX2NvbXBvbmVudFdpbGxNb3VudCIsIm9uIiwib25TdGF0ZUV2ZW50Iiwicm9vbSIsImN1cnJlbnRTdGF0ZSIsInB1bGxDb250ZW50UHJvcGVydHlGcm9tRXZlbnQiLCJnZXRTdGF0ZUV2ZW50cyIsImlzUm9vbUVuY3J5cHRlZCIsImV2ZW50Iiwia2V5IiwiZGVmYXVsdFZhbHVlIiwiZ2V0Q29udGVudCIsImNvbXBvbmVudFdpbGxVbm1vdW50IiwicmVtb3ZlTGlzdGVuZXIiLCJjbGkiLCJkb2VzU2VydmVyU3VwcG9ydFVuc3RhYmxlRmVhdHVyZSIsInJlc3BvbnNlIiwidW5zdGFibGVHZXRMb2NhbEFsaWFzZXMiLCJsb2NhbEFsaWFzZXMiLCJhbGlhc2VzIiwiQXJyYXkiLCJpc0FycmF5IiwibGVuZ3RoIiwiYWxpYXNFdmVudHMiLCJmaW5kIiwiZXYiLCJyZW5kZXJSb29tQWNjZXNzIiwiY2FuQ2hhbmdlQWNjZXNzIiwibWF5Q2xpZW50U2VuZFN0YXRlRXZlbnQiLCJndWVzdFdhcm5pbmciLCJyZXF1aXJlIiwiZml4R3Vlc3RBY2Nlc3MiLCJhbGlhc1dhcm5pbmciLCJvblJvb21BY2Nlc3NSYWRpb1RvZ2dsZSIsInZhbHVlIiwiZGlzYWJsZWQiLCJsYWJlbCIsInJlbmRlckhpc3RvcnkiLCJjYW5DaGFuZ2VIaXN0b3J5Iiwib25IaXN0b3J5UmFkaW9Ub2dnbGUiLCJXb3JsZFJlYWRhYmxlIiwiSW52aXRlZCIsIkpvaW5lZCIsInJlbmRlciIsIlNldHRpbmdzRmxhZyIsInNkayIsImdldENvbXBvbmVudCIsImlzRW5jcnlwdGVkIiwiaGFzRW5jcnlwdGlvblBlcm1pc3Npb24iLCJjYW5FbmFibGVFbmNyeXB0aW9uIiwiZW5jcnlwdGlvblNldHRpbmdzIiwiU2V0dGluZ3NTdG9yZSIsImlzRW5hYmxlZCIsIlNldHRpbmdMZXZlbCIsIlJPT01fREVWSUNFIiwidXBkYXRlQmxhY2tsaXN0RGV2aWNlc0ZsYWciLCJoaXN0b3J5U2VjdGlvbiIsImdldFZhbHVlIiwiVUlGZWF0dXJlIiwiUm9vbUhpc3RvcnlTZXR0aW5ncyIsIm9uRW5jcnlwdGlvbkNoYW5nZSJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7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YyxHQUFHLElBQWpCO0FBQ0g7O0FBRUQsd0JBQ0k7QUFBSyxNQUFBLFNBQVMsRUFBQztBQUFmLG9CQUNJO0FBQUssTUFBQSxTQUFTLEVBQUM7QUFBZixPQUF5Qyx5QkFBRyxvQkFBSCxDQUF6QyxDQURKLGVBR0k7QUFBTSxNQUFBLFNBQVMsRUFBQztBQUFoQixPQUE2Qyx5QkFBRyxZQUFILENBQTdDLENBSEosZUFJSTtBQUFLLE1BQUEsU0FBUyxFQUFDO0FBQWYsb0JBQ0ksdURBQ0k7QUFBSyxNQUFBLFNBQVMsRUFBQztBQUFmLG9CQUNJLDJDQUFPLHlCQUFHLDhDQUFILENBQVAsQ0FESixDQURKLGVBSUksNkJBQUMsNkJBQUQ7QUFBc0IsTUFBQSxLQUFLLEVBQUVULFdBQTdCO0FBQTBDLE1BQUEsUUFBUSxFQUFFLEtBQUthLGtCQUF6RDtBQUNJLE1BQUEsS0FBSyxFQUFFLHlCQUFHLFdBQUgsQ0FEWDtBQUM0QixNQUFBLFFBQVEsRUFBRSxDQUFDWDtBQUR2QyxNQUpKLENBREosRUFTS0Msa0JBVEwsQ0FKSixlQWdCSTtBQUFNLE1BQUEsU0FBUyxFQUFDO0FBQWhCLE9BQTZDLHlCQUFHLDJCQUFILENBQTdDLENBaEJKLGVBaUJJO0FBQUssTUFBQSxTQUFTLEVBQUM7QUFBZixPQUNLLEtBQUt4QixnQkFBTCxFQURMLENBakJKLEVBcUJLOEIsY0FyQkwsQ0FESjtBQXlCSDs7QUFsV2dGLEMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuQ29weXJpZ2h0IDIwMTktMjAyMSBUaGUgTWF0cml4Lm9yZyBGb3VuZGF0aW9uIEMuSS5DLlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiovXG5cbmltcG9ydCBSZWFjdCBmcm9tICdyZWFjdCc7XG5pbXBvcnQgeyBNYXRyaXhFdmVudCB9IGZyb20gXCJtYXRyaXgtanMtc2RrL3NyYy9tb2RlbHMvZXZlbnRcIjtcbmltcG9ydCB7X3R9IGZyb20gXCIuLi8uLi8uLi8uLi8uLi9sYW5ndWFnZUhhbmRsZXJcIjtcbmltcG9ydCB7TWF0cml4Q2xpZW50UGVnfSBmcm9tIFwiLi4vLi4vLi4vLi4vLi4vTWF0cml4Q2xpZW50UGVnXCI7XG5pbXBvcnQgKiBhcyBzZGsgZnJvbSBcIi4uLy4uLy4uLy4uLy4uXCI7XG5pbXBvcnQgTGFiZWxsZWRUb2dnbGVTd2l0Y2ggZnJvbSBcIi4uLy4uLy4uL2VsZW1lbnRzL0xhYmVsbGVkVG9nZ2xlU3dpdGNoXCI7XG5pbXBvcnQgTW9kYWwgZnJvbSBcIi4uLy4uLy4uLy4uLy4uL01vZGFsXCI7XG5pbXBvcnQgUXVlc3Rpb25EaWFsb2cgZnJvbSBcIi4uLy4uLy4uL2RpYWxvZ3MvUXVlc3Rpb25EaWFsb2dcIjtcbmltcG9ydCBTdHlsZWRSYWRpb0dyb3VwIGZyb20gJy4uLy4uLy4uL2VsZW1lbnRzL1N0eWxlZFJhZGlvR3JvdXAnO1xuaW1wb3J0IHtTZXR0aW5nTGV2ZWx9IGZyb20gXCIuLi8uLi8uLi8uLi8uLi9zZXR0aW5ncy9TZXR0aW5nTGV2ZWxcIjtcbmltcG9ydCBTZXR0aW5nc1N0b3JlIGZyb20gXCIuLi8uLi8uLi8uLi8uLi9zZXR0aW5ncy9TZXR0aW5nc1N0b3JlXCI7XG5pbXBvcnQge1VJRmVhdHVyZX0gZnJvbSBcIi4uLy4uLy4uLy4uLy4uL3NldHRpbmdzL1VJRmVhdHVyZVwiO1xuaW1wb3J0IHsgcmVwbGFjZWFibGVDb21wb25lbnQgfSBmcm9tIFwiLi4vLi4vLi4vLi4vLi4vdXRpbHMvcmVwbGFjZWFibGVDb21wb25lbnRcIjtcblxuLy8gS25vY2sgYW5kIHByaXZhdGUgYXJlIHJlc2VydmVkIGtleXdvcmRzIHdoaWNoIGFyZSBub3QgeWV0IGltcGxlbWVudGVkLlxuZW51bSBKb2luUnVsZSB7XG4gICAgUHVibGljID0gXCJwdWJsaWNcIixcbiAgICBLbm9jayA9IFwia25vY2tcIixcbiAgICBJbnZpdGUgPSBcImludml0ZVwiLFxuICAgIFByaXZhdGUgPSBcInByaXZhdGVcIixcbn1cblxuZW51bSBHdWVzdEFjY2VzcyB7XG4gICAgQ2FuSm9pbiA9IFwiY2FuX2pvaW5cIixcbiAgICBGb3JiaWRkZW4gPSBcImZvcmJpZGRlblwiLFxufVxuXG5lbnVtIEhpc3RvcnlWaXNpYmlsaXR5IHtcbiAgICBJbnZpdGVkID0gXCJpbnZpdGVkXCIsXG4gICAgSm9pbmVkID0gXCJqb2luZWRcIixcbiAgICBTaGFyZWQgPSBcInNoYXJlZFwiLFxuICAgIFdvcmxkUmVhZGFibGUgPSBcIndvcmxkX3JlYWRhYmxlXCIsXG59XG5cbmludGVyZmFjZSBJUHJvcHMge1xuICAgIHJvb21JZDogc3RyaW5nO1xufVxuXG5pbnRlcmZhY2UgSVN0YXRlIHtcbiAgICBqb2luUnVsZTogSm9pblJ1bGU7XG4gICAgZ3Vlc3RBY2Nlc3M6IEd1ZXN0QWNjZXNzO1xuICAgIGhpc3Rvcnk6IEhpc3RvcnlWaXNpYmlsaXR5O1xuICAgIGhhc0FsaWFzZXM6IGJvb2xlYW47XG4gICAgZW5jcnlwdGVkOiBib29sZWFuO1xufVxuXG5AcmVwbGFjZWFibGVDb21wb25lbnQoXCJ2aWV3cy5zZXR0aW5ncy50YWJzLnJvb20uU2VjdXJpdHlSb29tU2V0dGluZ3NUYWJcIilcbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFNlY3VyaXR5Um9vbVNldHRpbmdzVGFiIGV4dGVuZHMgUmVhY3QuQ29tcG9uZW50PElQcm9wcywgSVN0YXRlPiB7XG4gICAgY29uc3RydWN0b3IocHJvcHMpIHtcbiAgICAgICAgc3VwZXIocHJvcHMpO1xuXG4gICAgICAgIHRoaXMuc3RhdGUgPSB7XG4gICAgICAgICAgICBqb2luUnVsZTogSm9pblJ1bGUuSW52aXRlLFxuICAgICAgICAgICAgZ3Vlc3RBY2Nlc3M6IEd1ZXN0QWNjZXNzLkNhbkpvaW4sXG4gICAgICAgICAgICBoaXN0b3J5OiBIaXN0b3J5VmlzaWJpbGl0eS5TaGFyZWQsXG4gICAgICAgICAgICBoYXNBbGlhc2VzOiBmYWxzZSxcbiAgICAgICAgICAgIGVuY3J5cHRlZDogZmFsc2UsXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgLy8gVE9ETzogW1JFQUNULVdBUk5JTkddIE1vdmUgdGhpcyB0byBjb25zdHJ1Y3RvclxuICAgIGFzeW5jIFVOU0FGRV9jb21wb25lbnRXaWxsTW91bnQoKSB7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgY2FtZWxjYXNlXG4gICAgICAgIE1hdHJpeENsaWVudFBlZy5nZXQoKS5vbihcIlJvb21TdGF0ZS5ldmVudHNcIiwgdGhpcy5vblN0YXRlRXZlbnQpO1xuXG4gICAgICAgIGNvbnN0IHJvb20gPSBNYXRyaXhDbGllbnRQZWcuZ2V0KCkuZ2V0Um9vbSh0aGlzLnByb3BzLnJvb21JZCk7XG4gICAgICAgIGNvbnN0IHN0YXRlID0gcm9vbS5jdXJyZW50U3RhdGU7XG5cbiAgICAgICAgY29uc3Qgam9pblJ1bGU6IEpvaW5SdWxlID0gdGhpcy5wdWxsQ29udGVudFByb3BlcnR5RnJvbUV2ZW50KFxuICAgICAgICAgICAgc3RhdGUuZ2V0U3RhdGVFdmVudHMoXCJtLnJvb20uam9pbl9ydWxlc1wiLCBcIlwiKSxcbiAgICAgICAgICAgICdqb2luX3J1bGUnLFxuICAgICAgICAgICAgSm9pblJ1bGUuSW52aXRlLFxuICAgICAgICApO1xuICAgICAgICBjb25zdCBndWVzdEFjY2VzczogR3Vlc3RBY2Nlc3MgPSB0aGlzLnB1bGxDb250ZW50UHJvcGVydHlGcm9tRXZlbnQoXG4gICAgICAgICAgICBzdGF0ZS5nZXRTdGF0ZUV2ZW50cyhcIm0ucm9vbS5ndWVzdF9hY2Nlc3NcIiwgXCJcIiksXG4gICAgICAgICAgICAnZ3Vlc3RfYWNjZXNzJyxcbiAgICAgICAgICAgIEd1ZXN0QWNjZXNzLkZvcmJpZGRlbixcbiAgICAgICAgKTtcbiAgICAgICAgY29uc3QgaGlzdG9yeTogSGlzdG9yeVZpc2liaWxpdHkgPSB0aGlzLnB1bGxDb250ZW50UHJvcGVydHlGcm9tRXZlbnQoXG4gICAgICAgICAgICBzdGF0ZS5nZXRTdGF0ZUV2ZW50cyhcIm0ucm9vbS5oaXN0b3J5X3Zpc2liaWxpdHlcIiwgXCJcIiksXG4gICAgICAgICAgICAnaGlzdG9yeV92aXNpYmlsaXR5JyxcbiAgICAgICAgICAgIEhpc3RvcnlWaXNpYmlsaXR5LlNoYXJlZCxcbiAgICAgICAgKTtcbiAgICAgICAgY29uc3QgZW5jcnlwdGVkID0gTWF0cml4Q2xpZW50UGVnLmdldCgpLmlzUm9vbUVuY3J5cHRlZCh0aGlzLnByb3BzLnJvb21JZCk7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe2pvaW5SdWxlLCBndWVzdEFjY2VzcywgaGlzdG9yeSwgZW5jcnlwdGVkfSk7XG4gICAgICAgIGNvbnN0IGhhc0FsaWFzZXMgPSBhd2FpdCB0aGlzLmhhc0FsaWFzZXMoKTtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7aGFzQWxpYXNlc30pO1xuICAgIH1cblxuICAgIHByaXZhdGUgcHVsbENvbnRlbnRQcm9wZXJ0eUZyb21FdmVudDxUPihldmVudDogTWF0cml4RXZlbnQsIGtleTogc3RyaW5nLCBkZWZhdWx0VmFsdWU6IFQpOiBUIHtcbiAgICAgICAgaWYgKCFldmVudCB8fCAhZXZlbnQuZ2V0Q29udGVudCgpKSByZXR1cm4gZGVmYXVsdFZhbHVlO1xuICAgICAgICByZXR1cm4gZXZlbnQuZ2V0Q29udGVudCgpW2tleV0gfHwgZGVmYXVsdFZhbHVlO1xuICAgIH1cblxuICAgIGNvbXBvbmVudFdpbGxVbm1vdW50KCkge1xuICAgICAgICBNYXRyaXhDbGllbnRQZWcuZ2V0KCkucmVtb3ZlTGlzdGVuZXIoXCJSb29tU3RhdGUuZXZlbnRzXCIsIHRoaXMub25TdGF0ZUV2ZW50KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIG9uU3RhdGVFdmVudCA9IChlOiBNYXRyaXhFdmVudCkgPT4ge1xuICAgICAgICBjb25zdCByZWZyZXNoV2hlblR5cGVzID0gW1xuICAgICAgICAgICAgJ20ucm9vbS5qb2luX3J1bGVzJyxcbiAgICAgICAgICAgICdtLnJvb20uZ3Vlc3RfYWNjZXNzJyxcbiAgICAgICAgICAgICdtLnJvb20uaGlzdG9yeV92aXNpYmlsaXR5JyxcbiAgICAgICAgICAgICdtLnJvb20uZW5jcnlwdGlvbicsXG4gICAgICAgIF07XG4gICAgICAgIGlmIChyZWZyZXNoV2hlblR5cGVzLmluY2x1ZGVzKGUuZ2V0VHlwZSgpKSkgdGhpcy5mb3JjZVVwZGF0ZSgpO1xuICAgIH07XG5cbiAgICBwcml2YXRlIG9uRW5jcnlwdGlvbkNoYW5nZSA9IChlOiBSZWFjdC5DaGFuZ2VFdmVudCkgPT4ge1xuICAgICAgICBNb2RhbC5jcmVhdGVUcmFja2VkRGlhbG9nKCdFbmFibGUgZW5jcnlwdGlvbicsICcnLCBRdWVzdGlvbkRpYWxvZywge1xuICAgICAgICAgICAgdGl0bGU6IF90KCdFbmFibGUgZW5jcnlwdGlvbj8nKSxcbiAgICAgICAgICAgIGRlc2NyaXB0aW9uOiBfdChcbiAgICAgICAgICAgICAgICBcIk9uY2UgZW5hYmxlZCwgZW5jcnlwdGlvbiBmb3IgYSByb29tIGNhbm5vdCBiZSBkaXNhYmxlZC4gTWVzc2FnZXMgc2VudCBpbiBhbiBlbmNyeXB0ZWQgXCIgK1xuICAgICAgICAgICAgICAgIFwicm9vbSBjYW5ub3QgYmUgc2VlbiBieSB0aGUgc2VydmVyLCBvbmx5IGJ5IHRoZSBwYXJ0aWNpcGFudHMgb2YgdGhlIHJvb20uIEVuYWJsaW5nIGVuY3J5cHRpb24gXCIgK1xuICAgICAgICAgICAgICAgIFwibWF5IHByZXZlbnQgbWFueSBib3RzIGFuZCBicmlkZ2VzIGZyb20gd29ya2luZyBjb3JyZWN0bHkuIDxhPkxlYXJuIG1vcmUgYWJvdXQgZW5jcnlwdGlvbi48L2E+XCIsXG4gICAgICAgICAgICAgICAge30sXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICBhOiBzdWIgPT4gPGEgaHJlZj1cImh0dHBzOi8vZWxlbWVudC5pby9oZWxwI2VuY3J5cHRpb25cIlxuICAgICAgICAgICAgICAgICAgICAgICAgcmVsPVwibm9yZWZlcnJlciBub29wZW5lclwiIHRhcmdldD1cIl9ibGFua1wiXG4gICAgICAgICAgICAgICAgICAgID57c3VifTwvYT4sXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICksXG4gICAgICAgICAgICBvbkZpbmlzaGVkOiAoY29uZmlybSkgPT4ge1xuICAgICAgICAgICAgICAgIGlmICghY29uZmlybSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnNldFN0YXRlKHtlbmNyeXB0ZWQ6IGZhbHNlfSk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBjb25zdCBiZWZvcmVFbmNyeXB0ZWQgPSB0aGlzLnN0YXRlLmVuY3J5cHRlZDtcbiAgICAgICAgICAgICAgICB0aGlzLnNldFN0YXRlKHtlbmNyeXB0ZWQ6IHRydWV9KTtcbiAgICAgICAgICAgICAgICBNYXRyaXhDbGllbnRQZWcuZ2V0KCkuc2VuZFN0YXRlRXZlbnQoXG4gICAgICAgICAgICAgICAgICAgIHRoaXMucHJvcHMucm9vbUlkLCBcIm0ucm9vbS5lbmNyeXB0aW9uXCIsXG4gICAgICAgICAgICAgICAgICAgIHsgYWxnb3JpdGhtOiBcIm0ubWVnb2xtLnYxLmFlcy1zaGEyXCIgfSxcbiAgICAgICAgICAgICAgICApLmNhdGNoKChlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZSk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoe2VuY3J5cHRlZDogYmVmb3JlRW5jcnlwdGVkfSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgcHJpdmF0ZSBmaXhHdWVzdEFjY2VzcyA9IChlOiBSZWFjdC5Nb3VzZUV2ZW50KSA9PiB7XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcblxuICAgICAgICBjb25zdCBqb2luUnVsZSA9IEpvaW5SdWxlLkludml0ZTtcbiAgICAgICAgY29uc3QgZ3Vlc3RBY2Nlc3MgPSBHdWVzdEFjY2Vzcy5DYW5Kb2luO1xuXG4gICAgICAgIGNvbnN0IGJlZm9yZUpvaW5SdWxlID0gdGhpcy5zdGF0ZS5qb2luUnVsZTtcbiAgICAgICAgY29uc3QgYmVmb3JlR3Vlc3RBY2Nlc3MgPSB0aGlzLnN0YXRlLmd1ZXN0QWNjZXNzO1xuICAgICAgICB0aGlzLnNldFN0YXRlKHtqb2luUnVsZSwgZ3Vlc3RBY2Nlc3N9KTtcblxuICAgICAgICBjb25zdCBjbGllbnQgPSBNYXRyaXhDbGllbnRQZWcuZ2V0KCk7XG4gICAgICAgIGNsaWVudC5zZW5kU3RhdGVFdmVudCh0aGlzLnByb3BzLnJvb21JZCwgXCJtLnJvb20uam9pbl9ydWxlc1wiLCB7am9pbl9ydWxlOiBqb2luUnVsZX0sIFwiXCIpLmNhdGNoKChlKSA9PiB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKGUpO1xuICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7am9pblJ1bGU6IGJlZm9yZUpvaW5SdWxlfSk7XG4gICAgICAgIH0pO1xuICAgICAgICBjbGllbnQuc2VuZFN0YXRlRXZlbnQodGhpcy5wcm9wcy5yb29tSWQsIFwibS5yb29tLmd1ZXN0X2FjY2Vzc1wiLCB7Z3Vlc3RfYWNjZXNzOiBndWVzdEFjY2Vzc30sIFwiXCIpLmNhdGNoKChlKSA9PiB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKGUpO1xuICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7Z3Vlc3RBY2Nlc3M6IGJlZm9yZUd1ZXN0QWNjZXNzfSk7XG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICBwcml2YXRlIG9uUm9vbUFjY2Vzc1JhZGlvVG9nZ2xlID0gKHJvb21BY2Nlc3M6IHN0cmluZykgPT4ge1xuICAgICAgICAvLyAgICAgICAgICAgICAgICAgICAgICAgICBqb2luX3J1bGVcbiAgICAgICAgLy8gICAgICAgICAgICAgICAgICAgICAgSU5WSVRFICB8ICBQVUJMSUNcbiAgICAgICAgLy8gICAgICAgIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLVxuICAgICAgICAvLyBndWVzdCAgQ0FOX0pPSU4gICB8IGludl9vbmx5IHwgcHViX3dpdGhfZ3Vlc3RcbiAgICAgICAgLy8gYWNjZXNzIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLVxuICAgICAgICAvLyAgICAgICAgRk9SQklEREVOICB8IGludl9vbmx5IHwgcHViX25vX2d1ZXN0XG4gICAgICAgIC8vICAgICAgICAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS1cblxuICAgICAgICAvLyB3ZSBhbHdheXMgc2V0IGd1ZXN0cyBjYW5fam9pbiBoZXJlIGFzIGl0IG1ha2VzIG5vIHNlbnNlIHRvIGhhdmVcbiAgICAgICAgLy8gYW4gaW52aXRlLW9ubHkgcm9vbSB0aGF0IGd1ZXN0cyBjYW4ndCBqb2luLiAgSWYgeW91IGV4cGxpY2l0bHlcbiAgICAgICAgLy8gaW52aXRlIHRoZW0sIHlvdSBjbGVhcmx5IHdhbnQgdGhlbSB0byBqb2luLCB3aGV0aGVyIHRoZXkncmUgYVxuICAgICAgICAvLyBndWVzdCBvciBub3QuICBJbiBwcmFjdGljZSwgZ3Vlc3RfYWNjZXNzIHNob3VsZCBwcm9iYWJseSBoYXZlXG4gICAgICAgIC8vIGJlZW4gaW1wbGVtZW50ZWQgYXMgcGFydCBvZiB0aGUgam9pbl9ydWxlcyBlbnVtLlxuICAgICAgICBsZXQgam9pblJ1bGUgPSBKb2luUnVsZS5JbnZpdGU7XG4gICAgICAgIGxldCBndWVzdEFjY2VzcyA9IEd1ZXN0QWNjZXNzLkNhbkpvaW47XG5cbiAgICAgICAgc3dpdGNoIChyb29tQWNjZXNzKSB7XG4gICAgICAgICAgICBjYXNlIFwiaW52aXRlX29ubHlcIjpcbiAgICAgICAgICAgICAgICAvLyBubyBjaGFuZ2UgLSB1c2UgZGVmYXVsdHMgYWJvdmVcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgXCJwdWJsaWNfbm9fZ3Vlc3RzXCI6XG4gICAgICAgICAgICAgICAgam9pblJ1bGUgPSBKb2luUnVsZS5QdWJsaWM7XG4gICAgICAgICAgICAgICAgZ3Vlc3RBY2Nlc3MgPSBHdWVzdEFjY2Vzcy5Gb3JiaWRkZW47XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFwicHVibGljX3dpdGhfZ3Vlc3RzXCI6XG4gICAgICAgICAgICAgICAgam9pblJ1bGUgPSBKb2luUnVsZS5QdWJsaWM7XG4gICAgICAgICAgICAgICAgZ3Vlc3RBY2Nlc3MgPSBHdWVzdEFjY2Vzcy5DYW5Kb2luO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgYmVmb3JlSm9pblJ1bGUgPSB0aGlzLnN0YXRlLmpvaW5SdWxlO1xuICAgICAgICBjb25zdCBiZWZvcmVHdWVzdEFjY2VzcyA9IHRoaXMuc3RhdGUuZ3Vlc3RBY2Nlc3M7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe2pvaW5SdWxlLCBndWVzdEFjY2Vzc30pO1xuXG4gICAgICAgIGNvbnN0IGNsaWVudCA9IE1hdHJpeENsaWVudFBlZy5nZXQoKTtcbiAgICAgICAgY2xpZW50LnNlbmRTdGF0ZUV2ZW50KHRoaXMucHJvcHMucm9vbUlkLCBcIm0ucm9vbS5qb2luX3J1bGVzXCIsIHtqb2luX3J1bGU6IGpvaW5SdWxlfSwgXCJcIikuY2F0Y2goKGUpID0+IHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZSk7XG4gICAgICAgICAgICB0aGlzLnNldFN0YXRlKHtqb2luUnVsZTogYmVmb3JlSm9pblJ1bGV9KTtcbiAgICAgICAgfSk7XG4gICAgICAgIGNsaWVudC5zZW5kU3RhdGVFdmVudCh0aGlzLnByb3BzLnJvb21JZCwgXCJtLnJvb20uZ3Vlc3RfYWNjZXNzXCIsIHtndWVzdF9hY2Nlc3M6IGd1ZXN0QWNjZXNzfSwgXCJcIikuY2F0Y2goKGUpID0+IHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZSk7XG4gICAgICAgICAgICB0aGlzLnNldFN0YXRlKHtndWVzdEFjY2VzczogYmVmb3JlR3Vlc3RBY2Nlc3N9KTtcbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIHByaXZhdGUgb25IaXN0b3J5UmFkaW9Ub2dnbGUgPSAoaGlzdG9yeTogSGlzdG9yeVZpc2liaWxpdHkpID0+IHtcbiAgICAgICAgY29uc3QgYmVmb3JlSGlzdG9yeSA9IHRoaXMuc3RhdGUuaGlzdG9yeTtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7aGlzdG9yeTogaGlzdG9yeX0pO1xuICAgICAgICBNYXRyaXhDbGllbnRQZWcuZ2V0KCkuc2VuZFN0YXRlRXZlbnQodGhpcy5wcm9wcy5yb29tSWQsIFwibS5yb29tLmhpc3RvcnlfdmlzaWJpbGl0eVwiLCB7XG4gICAgICAgICAgICBoaXN0b3J5X3Zpc2liaWxpdHk6IGhpc3RvcnksXG4gICAgICAgIH0sIFwiXCIpLmNhdGNoKChlKSA9PiB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKGUpO1xuICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7aGlzdG9yeTogYmVmb3JlSGlzdG9yeX0pO1xuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgcHJpdmF0ZSB1cGRhdGVCbGFja2xpc3REZXZpY2VzRmxhZyA9IChjaGVja2VkOiBib29sZWFuKSA9PiB7XG4gICAgICAgIE1hdHJpeENsaWVudFBlZy5nZXQoKS5nZXRSb29tKHRoaXMucHJvcHMucm9vbUlkKS5zZXRCbGFja2xpc3RVbnZlcmlmaWVkRGV2aWNlcyhjaGVja2VkKTtcbiAgICB9O1xuXG4gICAgcHJpdmF0ZSBhc3luYyBoYXNBbGlhc2VzKCk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgICAgICBjb25zdCBjbGkgPSBNYXRyaXhDbGllbnRQZWcuZ2V0KCk7XG4gICAgICAgIGlmIChhd2FpdCBjbGkuZG9lc1NlcnZlclN1cHBvcnRVbnN0YWJsZUZlYXR1cmUoXCJvcmcubWF0cml4Lm1zYzI0MzJcIikpIHtcbiAgICAgICAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgY2xpLnVuc3RhYmxlR2V0TG9jYWxBbGlhc2VzKHRoaXMucHJvcHMucm9vbUlkKTtcbiAgICAgICAgICAgIGNvbnN0IGxvY2FsQWxpYXNlcyA9IHJlc3BvbnNlLmFsaWFzZXM7XG4gICAgICAgICAgICByZXR1cm4gQXJyYXkuaXNBcnJheShsb2NhbEFsaWFzZXMpICYmIGxvY2FsQWxpYXNlcy5sZW5ndGggIT09IDA7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zdCByb29tID0gY2xpLmdldFJvb20odGhpcy5wcm9wcy5yb29tSWQpO1xuICAgICAgICAgICAgY29uc3QgYWxpYXNFdmVudHMgPSByb29tLmN1cnJlbnRTdGF0ZS5nZXRTdGF0ZUV2ZW50cyhcIm0ucm9vbS5hbGlhc2VzXCIpIHx8IFtdO1xuICAgICAgICAgICAgY29uc3QgaGFzQWxpYXNlcyA9ICEhYWxpYXNFdmVudHMuZmluZCgoZXYpID0+IChldi5nZXRDb250ZW50KCkuYWxpYXNlcyB8fCBbXSkubGVuZ3RoID4gMCk7XG4gICAgICAgICAgICByZXR1cm4gaGFzQWxpYXNlcztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgcmVuZGVyUm9vbUFjY2VzcygpIHtcbiAgICAgICAgY29uc3QgY2xpZW50ID0gTWF0cml4Q2xpZW50UGVnLmdldCgpO1xuICAgICAgICBjb25zdCByb29tID0gY2xpZW50LmdldFJvb20odGhpcy5wcm9wcy5yb29tSWQpO1xuICAgICAgICBjb25zdCBqb2luUnVsZSA9IHRoaXMuc3RhdGUuam9pblJ1bGU7XG4gICAgICAgIGNvbnN0IGd1ZXN0QWNjZXNzID0gdGhpcy5zdGF0ZS5ndWVzdEFjY2VzcztcblxuICAgICAgICBjb25zdCBjYW5DaGFuZ2VBY2Nlc3MgPSByb29tLmN1cnJlbnRTdGF0ZS5tYXlDbGllbnRTZW5kU3RhdGVFdmVudChcIm0ucm9vbS5qb2luX3J1bGVzXCIsIGNsaWVudClcbiAgICAgICAgICAgICYmIHJvb20uY3VycmVudFN0YXRlLm1heUNsaWVudFNlbmRTdGF0ZUV2ZW50KFwibS5yb29tLmd1ZXN0X2FjY2Vzc1wiLCBjbGllbnQpO1xuXG4gICAgICAgIGxldCBndWVzdFdhcm5pbmcgPSBudWxsO1xuICAgICAgICBpZiAoam9pblJ1bGUgIT09ICdwdWJsaWMnICYmIGd1ZXN0QWNjZXNzID09PSAnZm9yYmlkZGVuJykge1xuICAgICAgICAgICAgZ3Vlc3RXYXJuaW5nID0gKFxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3NOYW1lPSdteF9TZWN1cml0eVJvb21TZXR0aW5nc1RhYl93YXJuaW5nJz5cbiAgICAgICAgICAgICAgICAgICAgPGltZyBzcmM9e3JlcXVpcmUoXCIuLi8uLi8uLi8uLi8uLi8uLi9yZXMvaW1nL3dhcm5pbmcuc3ZnXCIpfSB3aWR0aD17MTV9IGhlaWdodD17MTV9IC8+XG4gICAgICAgICAgICAgICAgICAgIDxzcGFuPlxuICAgICAgICAgICAgICAgICAgICAgICAge190KFwiR3Vlc3RzIGNhbm5vdCBqb2luIHRoaXMgcm9vbSBldmVuIGlmIGV4cGxpY2l0bHkgaW52aXRlZC5cIil9Jm5ic3A7XG4gICAgICAgICAgICAgICAgICAgICAgICA8YSBocmVmPVwiXCIgb25DbGljaz17dGhpcy5maXhHdWVzdEFjY2Vzc30+e190KFwiQ2xpY2sgaGVyZSB0byBmaXhcIil9PC9hPlxuICAgICAgICAgICAgICAgICAgICA8L3NwYW4+XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGFsaWFzV2FybmluZyA9IG51bGw7XG4gICAgICAgIGlmIChqb2luUnVsZSA9PT0gJ3B1YmxpYycgJiYgIXRoaXMuc3RhdGUuaGFzQWxpYXNlcykge1xuICAgICAgICAgICAgYWxpYXNXYXJuaW5nID0gKFxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3NOYW1lPSdteF9TZWN1cml0eVJvb21TZXR0aW5nc1RhYl93YXJuaW5nJz5cbiAgICAgICAgICAgICAgICAgICAgPGltZyBzcmM9e3JlcXVpcmUoXCIuLi8uLi8uLi8uLi8uLi8uLi9yZXMvaW1nL3dhcm5pbmcuc3ZnXCIpfSB3aWR0aD17MTV9IGhlaWdodD17MTV9IC8+XG4gICAgICAgICAgICAgICAgICAgIDxzcGFuPlxuICAgICAgICAgICAgICAgICAgICAgICAge190KFwiVG8gbGluayB0byB0aGlzIHJvb20sIHBsZWFzZSBhZGQgYW4gYWRkcmVzcy5cIil9XG4gICAgICAgICAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgPGRpdj5cbiAgICAgICAgICAgICAgICB7Z3Vlc3RXYXJuaW5nfVxuICAgICAgICAgICAgICAgIHthbGlhc1dhcm5pbmd9XG4gICAgICAgICAgICAgICAgPFN0eWxlZFJhZGlvR3JvdXBcbiAgICAgICAgICAgICAgICAgICAgbmFtZT1cInJvb21WaXNcIlxuICAgICAgICAgICAgICAgICAgICB2YWx1ZT17am9pblJ1bGV9XG4gICAgICAgICAgICAgICAgICAgIG9uQ2hhbmdlPXt0aGlzLm9uUm9vbUFjY2Vzc1JhZGlvVG9nZ2xlfVxuICAgICAgICAgICAgICAgICAgICBkZWZpbml0aW9ucz17W1xuICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiBcImludml0ZV9vbmx5XCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlzYWJsZWQ6ICFjYW5DaGFuZ2VBY2Nlc3MsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWw6IF90KCdPbmx5IHBlb3BsZSB