matrix-react-sdk
Version:
SDK for matrix.org using React
331 lines (327 loc) • 63.7 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _react = _interopRequireDefault(require("react"));
var _matrix = require("matrix-js-sdk/src/matrix");
var _logger = require("matrix-js-sdk/src/logger");
var _warning = require("../../../../../../res/img/warning.svg");
var _languageHandler = require("../../../../../languageHandler");
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 _AccessibleButton = _interopRequireDefault(require("../../../elements/AccessibleButton"));
var _SettingsFlag = _interopRequireDefault(require("../../../elements/SettingsFlag"));
var _createRoom = _interopRequireDefault(require("../../../../../createRoom"));
var _CreateRoomDialog = _interopRequireDefault(require("../../../dialogs/CreateRoomDialog"));
var _JoinRuleSettings = _interopRequireDefault(require("../../JoinRuleSettings"));
var _ErrorDialog = _interopRequireDefault(require("../../../dialogs/ErrorDialog"));
var _SettingsFieldset = _interopRequireDefault(require("../../SettingsFieldset"));
var _ExternalLink = _interopRequireDefault(require("../../../elements/ExternalLink"));
var _PosthogTrackers = _interopRequireDefault(require("../../../../../PosthogTrackers"));
var _MatrixClientContext = _interopRequireDefault(require("../../../../../contexts/MatrixClientContext"));
var _SettingsSection = require("../../shared/SettingsSection");
var _SettingsTab = _interopRequireDefault(require("../SettingsTab"));
var _SdkConfig = _interopRequireDefault(require("../../../../../SdkConfig"));
var _shouldForceDisableEncryption = require("../../../../../utils/crypto/shouldForceDisableEncryption");
var _Caption = require("../../../typography/Caption");
var _crypto = require("../../../../../utils/crypto");
/*
Copyright 2024 New Vector Ltd.
Copyright 2019-2023 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.
*/
class SecurityRoomSettingsTab extends _react.default.Component {
constructor(props, context) {
super(props, context);
(0, _defineProperty2.default)(this, "onStateEvent", e => {
const refreshWhenTypes = [_matrix.EventType.RoomJoinRules, _matrix.EventType.RoomGuestAccess, _matrix.EventType.RoomHistoryVisibility, _matrix.EventType.RoomEncryption];
if (refreshWhenTypes.includes(e.getType())) this.forceUpdate();
});
(0, _defineProperty2.default)(this, "onEncryptionChange", async () => {
if (this.props.room.getJoinRule() === _matrix.JoinRule.Public) {
const dialog = _Modal.default.createDialog(_QuestionDialog.default, {
title: (0, _languageHandler._t)("room_settings|security|enable_encryption_public_room_confirm_title"),
description: /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("p", null, " ", (0, _languageHandler._t)("room_settings|security|enable_encryption_public_room_confirm_description_1", undefined, {
b: sub => /*#__PURE__*/_react.default.createElement("strong", null, sub)
}), " "), /*#__PURE__*/_react.default.createElement("p", null, " ", (0, _languageHandler._t)("room_settings|security|enable_encryption_public_room_confirm_description_2", undefined, {
a: sub => /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, {
kind: "link_inline",
onClick: () => {
dialog.close();
this.createNewRoom(false, true);
}
}, " ", sub, " ")
}), " "))
});
const {
finished
} = dialog;
const [confirm] = await finished;
if (!confirm) return;
}
_Modal.default.createDialog(_QuestionDialog.default, {
title: (0, _languageHandler._t)("room_settings|security|enable_encryption_confirm_title"),
description: (0, _languageHandler._t)("room_settings|security|enable_encryption_confirm_description", {}, {
a: sub => /*#__PURE__*/_react.default.createElement(_ExternalLink.default, {
href: _SdkConfig.default.get("help_encryption_url")
}, sub)
}),
onFinished: confirm => {
if (!confirm) {
this.setState({
encrypted: false
});
return;
}
const beforeEncrypted = this.state.encrypted;
this.setState({
encrypted: true
});
this.context.sendStateEvent(this.props.room.roomId, _matrix.EventType.RoomEncryption, {
algorithm: _crypto.MEGOLM_ENCRYPTION_ALGORITHM
}).catch(e => {
_logger.logger.error(e);
this.setState({
encrypted: beforeEncrypted
});
});
}
});
});
(0, _defineProperty2.default)(this, "onGuestAccessChange", allowed => {
const guestAccess = allowed ? _matrix.GuestAccess.CanJoin : _matrix.GuestAccess.Forbidden;
const beforeGuestAccess = this.state.guestAccess;
if (beforeGuestAccess === guestAccess) return;
this.setState({
guestAccess
});
this.context.sendStateEvent(this.props.room.roomId, _matrix.EventType.RoomGuestAccess, {
guest_access: guestAccess
}, "").catch(e => {
_logger.logger.error(e);
this.setState({
guestAccess: beforeGuestAccess
});
});
});
(0, _defineProperty2.default)(this, "createNewRoom", async (defaultPublic, defaultEncrypted) => {
const modal = _Modal.default.createDialog(_CreateRoomDialog.default, {
defaultPublic,
defaultEncrypted
});
_PosthogTrackers.default.trackInteraction("WebRoomSettingsSecurityTabCreateNewRoomButton");
const [shouldCreate, opts] = await modal.finished;
if (shouldCreate) {
await (0, _createRoom.default)(this.context, opts);
}
return shouldCreate;
});
(0, _defineProperty2.default)(this, "onHistoryRadioToggle", history => {
const beforeHistory = this.state.history;
if (beforeHistory === history) return;
this.setState({
history: history
});
this.context.sendStateEvent(this.props.room.roomId, _matrix.EventType.RoomHistoryVisibility, {
history_visibility: history
}, "").catch(e => {
_logger.logger.error(e);
this.setState({
history: beforeHistory
});
});
});
(0, _defineProperty2.default)(this, "updateBlacklistDevicesFlag", checked => {
this.props.room.setBlacklistUnverifiedDevices(checked);
});
(0, _defineProperty2.default)(this, "onJoinRuleChangeError", error => {
_Modal.default.createDialog(_ErrorDialog.default, {
title: (0, _languageHandler._t)("room_settings|security|error_join_rule_change_title"),
description: error.message ?? (0, _languageHandler._t)("room_settings|security|error_join_rule_change_unknown")
});
});
(0, _defineProperty2.default)(this, "onBeforeJoinRuleChange", async joinRule => {
if (this.state.encrypted && joinRule === _matrix.JoinRule.Public) {
const dialog = _Modal.default.createDialog(_QuestionDialog.default, {
title: (0, _languageHandler._t)("room_settings|security|encrypted_room_public_confirm_title"),
description: /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("p", null, " ", (0, _languageHandler._t)("room_settings|security|encrypted_room_public_confirm_description_1", undefined, {
b: sub => /*#__PURE__*/_react.default.createElement("strong", null, sub)
}), " "), /*#__PURE__*/_react.default.createElement("p", null, " ", (0, _languageHandler._t)("room_settings|security|encrypted_room_public_confirm_description_2", undefined, {
a: sub => /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, {
kind: "link_inline",
onClick: () => {
dialog.close();
this.createNewRoom(true, false);
}
}, " ", sub, " ")
}), " "))
});
const {
finished
} = dialog;
const [confirm] = await finished;
if (!confirm) return false;
}
return true;
});
(0, _defineProperty2.default)(this, "toggleAdvancedSection", () => {
this.setState({
showAdvancedSection: !this.state.showAdvancedSection
});
});
const state = this.props.room.currentState;
this.state = {
guestAccess: this.pullContentPropertyFromEvent(state?.getStateEvents(_matrix.EventType.RoomGuestAccess, ""), "guest_access", _matrix.GuestAccess.Forbidden),
history: this.pullContentPropertyFromEvent(state?.getStateEvents(_matrix.EventType.RoomHistoryVisibility, ""), "history_visibility", _matrix.HistoryVisibility.Shared),
hasAliases: false,
// async loaded in componentDidMount
encrypted: context.isRoomEncrypted(this.props.room.roomId),
showAdvancedSection: false
};
}
componentDidMount() {
this.context.on(_matrix.RoomStateEvent.Events, this.onStateEvent);
this.hasAliases().then(hasAliases => this.setState({
hasAliases
}));
}
pullContentPropertyFromEvent(event, key, defaultValue) {
return event?.getContent()[key] || defaultValue;
}
componentWillUnmount() {
this.context.removeListener(_matrix.RoomStateEvent.Events, this.onStateEvent);
}
async hasAliases() {
const cli = this.context;
const response = await cli.getLocalAliases(this.props.room.roomId);
const localAliases = response.aliases;
return Array.isArray(localAliases) && localAliases.length !== 0;
}
renderJoinRule() {
const room = this.props.room;
let aliasWarning;
if (room.getJoinRule() === _matrix.JoinRule.Public && !this.state.hasAliases) {
aliasWarning = /*#__PURE__*/_react.default.createElement("div", {
className: "mx_SecurityRoomSettingsTab_warning"
}, /*#__PURE__*/_react.default.createElement(_warning.Icon, {
width: 15,
height: 15
}), /*#__PURE__*/_react.default.createElement("span", null, (0, _languageHandler._t)("room_settings|security|public_without_alias_warning")));
}
const description = (0, _languageHandler._t)("room_settings|security|join_rule_description", {
roomName: room.name
});
let advanced;
if (room.getJoinRule() === _matrix.JoinRule.Public) {
advanced = /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, {
onClick: this.toggleAdvancedSection,
kind: "link",
className: "mx_SettingsTab_showAdvanced",
"aria-expanded": this.state.showAdvancedSection
}, this.state.showAdvancedSection ? (0, _languageHandler._t)("action|hide_advanced") : (0, _languageHandler._t)("action|show_advanced")), this.state.showAdvancedSection && this.renderAdvanced());
}
return /*#__PURE__*/_react.default.createElement(_SettingsFieldset.default, {
legend: (0, _languageHandler._t)("room_settings|access|title"),
description: description
}, /*#__PURE__*/_react.default.createElement(_JoinRuleSettings.default, {
room: room,
beforeChange: this.onBeforeJoinRuleChange,
onError: this.onJoinRuleChangeError,
closeSettingsFn: this.props.closeSettingsFn,
promptUpgrade: true,
aliasWarning: aliasWarning
}), advanced);
}
renderHistory() {
if (!_SettingsStore.default.getValue(_UIFeature.UIFeature.RoomHistorySettings)) {
return null;
}
const client = this.context;
const history = this.state.history;
const state = this.props.room.currentState;
const canChangeHistory = state?.mayClientSendStateEvent(_matrix.EventType.RoomHistoryVisibility, client);
const options = [{
value: _matrix.HistoryVisibility.Shared,
label: (0, _languageHandler._t)("room_settings|security|history_visibility_shared")
}, {
value: _matrix.HistoryVisibility.Invited,
label: (0, _languageHandler._t)("room_settings|security|history_visibility_invited")
}, {
value: _matrix.HistoryVisibility.Joined,
label: (0, _languageHandler._t)("room_settings|security|history_visibility_joined")
}];
// World readable doesn't make sense for encrypted rooms
if (!this.state.encrypted || history === _matrix.HistoryVisibility.WorldReadable) {
options.unshift({
value: _matrix.HistoryVisibility.WorldReadable,
label: (0, _languageHandler._t)("room_settings|security|history_visibility_world_readable")
});
}
const description = (0, _languageHandler._t)("room_settings|security|history_visibility_warning");
return /*#__PURE__*/_react.default.createElement(_SettingsFieldset.default, {
legend: (0, _languageHandler._t)("room_settings|security|history_visibility_legend"),
description: description
}, /*#__PURE__*/_react.default.createElement(_StyledRadioGroup.default, {
name: "historyVis",
value: history,
onChange: this.onHistoryRadioToggle,
disabled: !canChangeHistory,
definitions: options
}));
}
renderAdvanced() {
const client = this.context;
const guestAccess = this.state.guestAccess;
const state = this.props.room.currentState;
const canSetGuestAccess = state?.mayClientSendStateEvent(_matrix.EventType.RoomGuestAccess, client);
return /*#__PURE__*/_react.default.createElement("div", {
className: "mx_SecurityRoomSettingsTab_advancedSection"
}, /*#__PURE__*/_react.default.createElement(_LabelledToggleSwitch.default, {
value: guestAccess === _matrix.GuestAccess.CanJoin,
onChange: this.onGuestAccessChange,
disabled: !canSetGuestAccess,
label: (0, _languageHandler._t)("room_settings|visibility|guest_access_label")
}), /*#__PURE__*/_react.default.createElement("p", null, (0, _languageHandler._t)("room_settings|security|guest_access_warning")));
}
render() {
const client = this.context;
const room = this.props.room;
const isEncrypted = this.state.encrypted;
const hasEncryptionPermission = room.currentState.mayClientSendStateEvent(_matrix.EventType.RoomEncryption, client);
const isEncryptionForceDisabled = (0, _shouldForceDisableEncryption.shouldForceDisableEncryption)(client);
const canEnableEncryption = !isEncrypted && !isEncryptionForceDisabled && hasEncryptionPermission;
let encryptionSettings;
if (isEncrypted && _SettingsStore.default.canSetValue("blacklistUnverifiedDevices", this.props.room.roomId, _SettingLevel.SettingLevel.ROOM_DEVICE)) {
encryptionSettings = /*#__PURE__*/_react.default.createElement(_SettingsFlag.default, {
name: "blacklistUnverifiedDevices",
level: _SettingLevel.SettingLevel.ROOM_DEVICE,
onChange: this.updateBlacklistDevicesFlag,
roomId: this.props.room.roomId
});
}
const historySection = this.renderHistory();
return /*#__PURE__*/_react.default.createElement(_SettingsTab.default, null, /*#__PURE__*/_react.default.createElement(_SettingsSection.SettingsSection, {
heading: (0, _languageHandler._t)("room_settings|security|title")
}, /*#__PURE__*/_react.default.createElement(_SettingsFieldset.default, {
legend: (0, _languageHandler._t)("settings|security|encryption_section"),
description: isEncryptionForceDisabled && !isEncrypted ? undefined : (0, _languageHandler._t)("room_settings|security|encryption_permanent")
}, /*#__PURE__*/_react.default.createElement(_LabelledToggleSwitch.default, {
value: isEncrypted,
onChange: this.onEncryptionChange,
label: (0, _languageHandler._t)("common|encrypted"),
disabled: !canEnableEncryption
}), isEncryptionForceDisabled && !isEncrypted && /*#__PURE__*/_react.default.createElement(_Caption.Caption, null, (0, _languageHandler._t)("room_settings|security|encryption_forced")), encryptionSettings), this.renderJoinRule(), historySection));
}
}
exports.default = SecurityRoomSettingsTab;
(0, _defineProperty2.default)(SecurityRoomSettingsTab, "contextType", _MatrixClientContext.default);
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfcmVhY3QiLCJfaW50ZXJvcFJlcXVpcmVEZWZhdWx0IiwicmVxdWlyZSIsIl9tYXRyaXgiLCJfbG9nZ2VyIiwiX3dhcm5pbmciLCJfbGFuZ3VhZ2VIYW5kbGVyIiwiX0xhYmVsbGVkVG9nZ2xlU3dpdGNoIiwiX01vZGFsIiwiX1F1ZXN0aW9uRGlhbG9nIiwiX1N0eWxlZFJhZGlvR3JvdXAiLCJfU2V0dGluZ0xldmVsIiwiX1NldHRpbmdzU3RvcmUiLCJfVUlGZWF0dXJlIiwiX0FjY2Vzc2libGVCdXR0b24iLCJfU2V0dGluZ3NGbGFnIiwiX2NyZWF0ZVJvb20iLCJfQ3JlYXRlUm9vbURpYWxvZyIsIl9Kb2luUnVsZVNldHRpbmdzIiwiX0Vycm9yRGlhbG9nIiwiX1NldHRpbmdzRmllbGRzZXQiLCJfRXh0ZXJuYWxMaW5rIiwiX1Bvc3Rob2dUcmFja2VycyIsIl9NYXRyaXhDbGllbnRDb250ZXh0IiwiX1NldHRpbmdzU2VjdGlvbiIsIl9TZXR0aW5nc1RhYiIsIl9TZGtDb25maWciLCJfc2hvdWxkRm9yY2VEaXNhYmxlRW5jcnlwdGlvbiIsIl9DYXB0aW9uIiwiX2NyeXB0byIsIlNlY3VyaXR5Um9vbVNldHRpbmdzVGFiIiwiUmVhY3QiLCJDb21wb25lbnQiLCJjb25zdHJ1Y3RvciIsInByb3BzIiwiY29udGV4dCIsIl9kZWZpbmVQcm9wZXJ0eTIiLCJkZWZhdWx0IiwiZSIsInJlZnJlc2hXaGVuVHlwZXMiLCJFdmVudFR5cGUiLCJSb29tSm9pblJ1bGVzIiwiUm9vbUd1ZXN0QWNjZXNzIiwiUm9vbUhpc3RvcnlWaXNpYmlsaXR5IiwiUm9vbUVuY3J5cHRpb24iLCJpbmNsdWRlcyIsImdldFR5cGUiLCJmb3JjZVVwZGF0ZSIsInJvb20iLCJnZXRKb2luUnVsZSIsIkpvaW5SdWxlIiwiUHVibGljIiwiZGlhbG9nIiwiTW9kYWwiLCJjcmVhdGVEaWFsb2ciLCJRdWVzdGlvbkRpYWxvZyIsInRpdGxlIiwiX3QiLCJkZXNjcmlwdGlvbiIsImNyZWF0ZUVsZW1lbnQiLCJ1bmRlZmluZWQiLCJiIiwic3ViIiwiYSIsImtpbmQiLCJvbkNsaWNrIiwiY2xvc2UiLCJjcmVhdGVOZXdSb29tIiwiZmluaXNoZWQiLCJjb25maXJtIiwiaHJlZiIsIlNka0NvbmZpZyIsImdldCIsIm9uRmluaXNoZWQiLCJzZXRTdGF0ZSIsImVuY3J5cHRlZCIsImJlZm9yZUVuY3J5cHRlZCIsInN0YXRlIiwic2VuZFN0YXRlRXZlbnQiLCJyb29tSWQiLCJhbGdvcml0aG0iLCJNRUdPTE1fRU5DUllQVElPTl9BTEdPUklUSE0iLCJjYXRjaCIsImxvZ2dlciIsImVycm9yIiwiYWxsb3dlZCIsImd1ZXN0QWNjZXNzIiwiR3Vlc3RBY2Nlc3MiLCJDYW5Kb2luIiwiRm9yYmlkZGVuIiwiYmVmb3JlR3Vlc3RBY2Nlc3MiLCJndWVzdF9hY2Nlc3MiLCJkZWZhdWx0UHVibGljIiwiZGVmYXVsdEVuY3J5cHRlZCIsIm1vZGFsIiwiQ3JlYXRlUm9vbURpYWxvZyIsIlBvc3Rob2dUcmFja2VycyIsInRyYWNrSW50ZXJhY3Rpb24iLCJzaG91bGRDcmVhdGUiLCJvcHRzIiwiY3JlYXRlUm9vbSIsImhpc3RvcnkiLCJiZWZvcmVIaXN0b3J5IiwiaGlzdG9yeV92aXNpYmlsaXR5IiwiY2hlY2tlZCIsInNldEJsYWNrbGlzdFVudmVyaWZpZWREZXZpY2VzIiwiRXJyb3JEaWFsb2ciLCJtZXNzYWdlIiwiam9pblJ1bGUiLCJzaG93QWR2YW5jZWRTZWN0aW9uIiwiY3VycmVudFN0YXRlIiwicHVsbENvbnRlbnRQcm9wZXJ0eUZyb21FdmVudCIsImdldFN0YXRlRXZlbnRzIiwiSGlzdG9yeVZpc2liaWxpdHkiLCJTaGFyZWQiLCJoYXNBbGlhc2VzIiwiaXNSb29tRW5jcnlwdGVkIiwiY29tcG9uZW50RGlkTW91bnQiLCJvbiIsIlJvb21TdGF0ZUV2ZW50IiwiRXZlbnRzIiwib25TdGF0ZUV2ZW50IiwidGhlbiIsImV2ZW50Iiwia2V5IiwiZGVmYXVsdFZhbHVlIiwiZ2V0Q29udGVudCIsImNvbXBvbmVudFdpbGxVbm1vdW50IiwicmVtb3ZlTGlzdGVuZXIiLCJjbGkiLCJyZXNwb25zZSIsImdldExvY2FsQWxpYXNlcyIsImxvY2FsQWxpYXNlcyIsImFsaWFzZXMiLCJBcnJheSIsImlzQXJyYXkiLCJsZW5ndGgiLCJyZW5kZXJKb2luUnVsZSIsImFsaWFzV2FybmluZyIsImNsYXNzTmFtZSIsIkljb24iLCJ3aWR0aCIsImhlaWdodCIsInJvb21OYW1lIiwibmFtZSIsImFkdmFuY2VkIiwidG9nZ2xlQWR2YW5jZWRTZWN0aW9uIiwicmVuZGVyQWR2YW5jZWQiLCJsZWdlbmQiLCJiZWZvcmVDaGFuZ2UiLCJvbkJlZm9yZUpvaW5SdWxlQ2hhbmdlIiwib25FcnJvciIsIm9uSm9pblJ1bGVDaGFuZ2VFcnJvciIsImNsb3NlU2V0dGluZ3NGbiIsInByb21wdFVwZ3JhZGUiLCJyZW5kZXJIaXN0b3J5IiwiU2V0dGluZ3NTdG9yZSIsImdldFZhbHVlIiwiVUlGZWF0dXJlIiwiUm9vbUhpc3RvcnlTZXR0aW5ncyIsImNsaWVudCIsImNhbkNoYW5nZUhpc3RvcnkiLCJtYXlDbGllbnRTZW5kU3RhdGVFdmVudCIsIm9wdGlvbnMiLCJ2YWx1ZSIsImxhYmVsIiwiSW52aXRlZCIsIkpvaW5lZCIsIldvcmxkUmVhZGFibGUiLCJ1bnNoaWZ0Iiwib25DaGFuZ2UiLCJvbkhpc3RvcnlSYWRpb1RvZ2dsZSIsImRpc2FibGVkIiwiZGVmaW5pdGlvbnMiLCJjYW5TZXRHdWVzdEFjY2VzcyIsIm9uR3Vlc3RBY2Nlc3NDaGFuZ2UiLCJyZW5kZXIiLCJpc0VuY3J5cHRlZCIsImhhc0VuY3J5cHRpb25QZXJtaXNzaW9uIiwiaXNFbmNyeXB0aW9uRm9yY2VEaXNhYmxlZCIsInNob3VsZEZvcmNlRGlzYWJsZUVuY3J5cHRpb24iLCJjYW5FbmFibGVFbmNyeXB0aW9uIiwiZW5jcnlwdGlvblNldHRpbmdzIiwiY2FuU2V0VmFsdWUiLCJTZXR0aW5nTGV2ZWwiLCJST09NX0RFVklDRSIsImxldmVsIiwidXBkYXRlQmxhY2tsaXN0RGV2aWNlc0ZsYWciLCJoaXN0b3J5U2VjdGlvbiIsIlNldHRpbmdzU2VjdGlvbiIsImhlYWRpbmciLCJvbkVuY3J5cHRpb25DaGFuZ2UiLCJDYXB0aW9uIiwiZXhwb3J0cyIsIk1hdHJpeENsaWVudENvbnRleHQiXSwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvY29tcG9uZW50cy92aWV3cy9zZXR0aW5ncy90YWJzL3Jvb20vU2VjdXJpdHlSb29tU2V0dGluZ3NUYWIudHN4Il0sInNvdXJjZXNDb250ZW50IjpbIi8qXG5Db3B5cmlnaHQgMjAyNCBOZXcgVmVjdG9yIEx0ZC5cbkNvcHlyaWdodCAyMDE5LTIwMjMgVGhlIE1hdHJpeC5vcmcgRm91bmRhdGlvbiBDLkkuQy5cblxuU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFHUEwtMy4wLW9ubHkgT1IgR1BMLTMuMC1vbmx5XG5QbGVhc2Ugc2VlIExJQ0VOU0UgZmlsZXMgaW4gdGhlIHJlcG9zaXRvcnkgcm9vdCBmb3IgZnVsbCBkZXRhaWxzLlxuKi9cblxuaW1wb3J0IFJlYWN0LCB7IFJlYWN0Tm9kZSB9IGZyb20gXCJyZWFjdFwiO1xuaW1wb3J0IHtcbiAgICBHdWVzdEFjY2VzcyxcbiAgICBIaXN0b3J5VmlzaWJpbGl0eSxcbiAgICBKb2luUnVsZSxcbiAgICBNYXRyaXhFdmVudCxcbiAgICBSb29tU3RhdGVFdmVudCxcbiAgICBSb29tLFxuICAgIEV2ZW50VHlwZSxcbn0gZnJvbSBcIm1hdHJpeC1qcy1zZGsvc3JjL21hdHJpeFwiO1xuaW1wb3J0IHsgbG9nZ2VyIH0gZnJvbSBcIm1hdHJpeC1qcy1zZGsvc3JjL2xvZ2dlclwiO1xuXG5pbXBvcnQgeyBJY29uIGFzIFdhcm5pbmdJY29uIH0gZnJvbSBcIi4uLy4uLy4uLy4uLy4uLy4uL3Jlcy9pbWcvd2FybmluZy5zdmdcIjtcbmltcG9ydCB7IF90IH0gZnJvbSBcIi4uLy4uLy4uLy4uLy4uL2xhbmd1YWdlSGFuZGxlclwiO1xuaW1wb3J0IExhYmVsbGVkVG9nZ2xlU3dpdGNoIGZyb20gXCIuLi8uLi8uLi9lbGVtZW50cy9MYWJlbGxlZFRvZ2dsZVN3aXRjaFwiO1xuaW1wb3J0IE1vZGFsIGZyb20gXCIuLi8uLi8uLi8uLi8uLi9Nb2RhbFwiO1xuaW1wb3J0IFF1ZXN0aW9uRGlhbG9nIGZyb20gXCIuLi8uLi8uLi9kaWFsb2dzL1F1ZXN0aW9uRGlhbG9nXCI7XG5pbXBvcnQgU3R5bGVkUmFkaW9Hcm91cCBmcm9tIFwiLi4vLi4vLi4vZWxlbWVudHMvU3R5bGVkUmFkaW9Hcm91cFwiO1xuaW1wb3J0IHsgU2V0dGluZ0xldmVsIH0gZnJvbSBcIi4uLy4uLy4uLy4uLy4uL3NldHRpbmdzL1NldHRpbmdMZXZlbFwiO1xuaW1wb3J0IFNldHRpbmdzU3RvcmUgZnJvbSBcIi4uLy4uLy4uLy4uLy4uL3NldHRpbmdzL1NldHRpbmdzU3RvcmVcIjtcbmltcG9ydCB7IFVJRmVhdHVyZSB9IGZyb20gXCIuLi8uLi8uLi8uLi8uLi9zZXR0aW5ncy9VSUZlYXR1cmVcIjtcbmltcG9ydCBBY2Nlc3NpYmxlQnV0dG9uIGZyb20gXCIuLi8uLi8uLi9lbGVtZW50cy9BY2Nlc3NpYmxlQnV0dG9uXCI7XG5pbXBvcnQgU2V0dGluZ3NGbGFnIGZyb20gXCIuLi8uLi8uLi9lbGVtZW50cy9TZXR0aW5nc0ZsYWdcIjtcbmltcG9ydCBjcmVhdGVSb29tIGZyb20gXCIuLi8uLi8uLi8uLi8uLi9jcmVhdGVSb29tXCI7XG5pbXBvcnQgQ3JlYXRlUm9vbURpYWxvZyBmcm9tIFwiLi4vLi4vLi4vZGlhbG9ncy9DcmVhdGVSb29tRGlhbG9nXCI7XG5pbXBvcnQgSm9pblJ1bGVTZXR0aW5ncyBmcm9tIFwiLi4vLi4vSm9pblJ1bGVTZXR0aW5nc1wiO1xuaW1wb3J0IEVycm9yRGlhbG9nIGZyb20gXCIuLi8uLi8uLi9kaWFsb2dzL0Vycm9yRGlhbG9nXCI7XG5pbXBvcnQgU2V0dGluZ3NGaWVsZHNldCBmcm9tIFwiLi4vLi4vU2V0dGluZ3NGaWVsZHNldFwiO1xuaW1wb3J0IEV4dGVybmFsTGluayBmcm9tIFwiLi4vLi4vLi4vZWxlbWVudHMvRXh0ZXJuYWxMaW5rXCI7XG5pbXBvcnQgUG9zdGhvZ1RyYWNrZXJzIGZyb20gXCIuLi8uLi8uLi8uLi8uLi9Qb3N0aG9nVHJhY2tlcnNcIjtcbmltcG9ydCBNYXRyaXhDbGllbnRDb250ZXh0IGZyb20gXCIuLi8uLi8uLi8uLi8uLi9jb250ZXh0cy9NYXRyaXhDbGllbnRDb250ZXh0XCI7XG5pbXBvcnQgeyBTZXR0aW5nc1NlY3Rpb24gfSBmcm9tIFwiLi4vLi4vc2hhcmVkL1NldHRpbmdzU2VjdGlvblwiO1xuaW1wb3J0IFNldHRpbmdzVGFiIGZyb20gXCIuLi9TZXR0aW5nc1RhYlwiO1xuaW1wb3J0IFNka0NvbmZpZyBmcm9tIFwiLi4vLi4vLi4vLi4vLi4vU2RrQ29uZmlnXCI7XG5pbXBvcnQgeyBzaG91bGRGb3JjZURpc2FibGVFbmNyeXB0aW9uIH0gZnJvbSBcIi4uLy4uLy4uLy4uLy4uL3V0aWxzL2NyeXB0by9zaG91bGRGb3JjZURpc2FibGVFbmNyeXB0aW9uXCI7XG5pbXBvcnQgeyBDYXB0aW9uIH0gZnJvbSBcIi4uLy4uLy4uL3R5cG9ncmFwaHkvQ2FwdGlvblwiO1xuaW1wb3J0IHsgTUVHT0xNX0VOQ1JZUFRJT05fQUxHT1JJVEhNIH0gZnJvbSBcIi4uLy4uLy4uLy4uLy4uL3V0aWxzL2NyeXB0b1wiO1xuXG5pbnRlcmZhY2UgSVByb3BzIHtcbiAgICByb29tOiBSb29tO1xuICAgIGNsb3NlU2V0dGluZ3NGbjogKCkgPT4gdm9pZDtcbn1cblxuaW50ZXJmYWNlIElTdGF0ZSB7XG4gICAgZ3Vlc3RBY2Nlc3M6IEd1ZXN0QWNjZXNzO1xuICAgIGhpc3Rvcnk6IEhpc3RvcnlWaXNpYmlsaXR5O1xuICAgIGhhc0FsaWFzZXM6IGJvb2xlYW47XG4gICAgZW5jcnlwdGVkOiBib29sZWFuO1xuICAgIHNob3dBZHZhbmNlZFNlY3Rpb246IGJvb2xlYW47XG59XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFNlY3VyaXR5Um9vbVNldHRpbmdzVGFiIGV4dGVuZHMgUmVhY3QuQ29tcG9uZW50PElQcm9wcywgSVN0YXRlPiB7XG4gICAgcHVibGljIHN0YXRpYyBjb250ZXh0VHlwZSA9IE1hdHJpeENsaWVudENvbnRleHQ7XG4gICAgcHVibGljIGRlY2xhcmUgY29udGV4dDogUmVhY3QuQ29udGV4dFR5cGU8dHlwZW9mIE1hdHJpeENsaWVudENvbnRleHQ+O1xuXG4gICAgcHVibGljIGNvbnN0cnVjdG9yKHByb3BzOiBJUHJvcHMsIGNvbnRleHQ6IFJlYWN0LkNvbnRleHRUeXBlPHR5cGVvZiBNYXRyaXhDbGllbnRDb250ZXh0Pikge1xuICAgICAgICBzdXBlcihwcm9wcywgY29udGV4dCk7XG5cbiAgICAgICAgY29uc3Qgc3RhdGUgPSB0aGlzLnByb3BzLnJvb20uY3VycmVudFN0YXRlO1xuXG4gICAgICAgIHRoaXMuc3RhdGUgPSB7XG4gICAgICAgICAgICBndWVzdEFjY2VzczogdGhpcy5wdWxsQ29udGVudFByb3BlcnR5RnJvbUV2ZW50PEd1ZXN0QWNjZXNzPihcbiAgICAgICAgICAgICAgICBzdGF0ZT8uZ2V0U3RhdGVFdmVudHMoRXZlbnRUeXBlLlJvb21HdWVzdEFjY2VzcywgXCJcIiksXG4gICAgICAgICAgICAgICAgXCJndWVzdF9hY2Nlc3NcIixcbiAgICAgICAgICAgICAgICBHdWVzdEFjY2Vzcy5Gb3JiaWRkZW4sXG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgaGlzdG9yeTogdGhpcy5wdWxsQ29udGVudFByb3BlcnR5RnJvbUV2ZW50PEhpc3RvcnlWaXNpYmlsaXR5PihcbiAgICAgICAgICAgICAgICBzdGF0ZT8uZ2V0U3RhdGVFdmVudHMoRXZlbnRUeXBlLlJvb21IaXN0b3J5VmlzaWJpbGl0eSwgXCJcIiksXG4gICAgICAgICAgICAgICAgXCJoaXN0b3J5X3Zpc2liaWxpdHlcIixcbiAgICAgICAgICAgICAgICBIaXN0b3J5VmlzaWJpbGl0eS5TaGFyZWQsXG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgaGFzQWxpYXNlczogZmFsc2UsIC8vIGFzeW5jIGxvYWRlZCBpbiBjb21wb25lbnREaWRNb3VudFxuICAgICAgICAgICAgZW5jcnlwdGVkOiBjb250ZXh0LmlzUm9vbUVuY3J5cHRlZCh0aGlzLnByb3BzLnJvb20ucm9vbUlkKSxcbiAgICAgICAgICAgIHNob3dBZHZhbmNlZFNlY3Rpb246IGZhbHNlLFxuICAgICAgICB9O1xuICAgIH1cblxuICAgIHB1YmxpYyBjb21wb25lbnREaWRNb3VudCgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5jb250ZXh0Lm9uKFJvb21TdGF0ZUV2ZW50LkV2ZW50cywgdGhpcy5vblN0YXRlRXZlbnQpO1xuICAgICAgICB0aGlzLmhhc0FsaWFzZXMoKS50aGVuKChoYXNBbGlhc2VzKSA9PiB0aGlzLnNldFN0YXRlKHsgaGFzQWxpYXNlcyB9KSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBwdWxsQ29udGVudFByb3BlcnR5RnJvbUV2ZW50PFQ+KGV2ZW50OiBNYXRyaXhFdmVudCB8IG51bGwgfCB1bmRlZmluZWQsIGtleTogc3RyaW5nLCBkZWZhdWx0VmFsdWU6IFQpOiBUIHtcbiAgICAgICAgcmV0dXJuIGV2ZW50Py5nZXRDb250ZW50KClba2V5XSB8fCBkZWZhdWx0VmFsdWU7XG4gICAgfVxuXG4gICAgcHVibGljIGNvbXBvbmVudFdpbGxVbm1vdW50KCk6IHZvaWQge1xuICAgICAgICB0aGlzLmNvbnRleHQucmVtb3ZlTGlzdGVuZXIoUm9vbVN0YXRlRXZlbnQuRXZlbnRzLCB0aGlzLm9uU3RhdGVFdmVudCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBvblN0YXRlRXZlbnQgPSAoZTogTWF0cml4RXZlbnQpOiB2b2lkID0+IHtcbiAgICAgICAgY29uc3QgcmVmcmVzaFdoZW5UeXBlczogRXZlbnRUeXBlW10gPSBbXG4gICAgICAgICAgICBFdmVudFR5cGUuUm9vbUpvaW5SdWxlcyxcbiAgICAgICAgICAgIEV2ZW50VHlwZS5Sb29tR3Vlc3RBY2Nlc3MsXG4gICAgICAgICAgICBFdmVudFR5cGUuUm9vbUhpc3RvcnlWaXNpYmlsaXR5LFxuICAgICAgICAgICAgRXZlbnRUeXBlLlJvb21FbmNyeXB0aW9uLFxuICAgICAgICBdO1xuICAgICAgICBpZiAocmVmcmVzaFdoZW5UeXBlcy5pbmNsdWRlcyhlLmdldFR5cGUoKSBhcyBFdmVudFR5cGUpKSB0aGlzLmZvcmNlVXBkYXRlKCk7XG4gICAgfTtcblxuICAgIHByaXZhdGUgb25FbmNyeXB0aW9uQ2hhbmdlID0gYXN5bmMgKCk6IFByb21pc2U8dm9pZD4gPT4ge1xuICAgICAgICBpZiAodGhpcy5wcm9wcy5yb29tLmdldEpvaW5SdWxlKCkgPT09IEpvaW5SdWxlLlB1YmxpYykge1xuICAgICAgICAgICAgY29uc3QgZGlhbG9nID0gTW9kYWwuY3JlYXRlRGlhbG9nKFF1ZXN0aW9uRGlhbG9nLCB7XG4gICAgICAgICAgICAgICAgdGl0bGU6IF90KFwicm9vbV9zZXR0aW5nc3xzZWN1cml0eXxlbmFibGVfZW5jcnlwdGlvbl9wdWJsaWNfcm9vbV9jb25maXJtX3RpdGxlXCIpLFxuICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uOiAoXG4gICAgICAgICAgICAgICAgICAgIDxkaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICA8cD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB7XCIgXCJ9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAge190KFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcInJvb21fc2V0dGluZ3N8c2VjdXJpdHl8ZW5hYmxlX2VuY3J5cHRpb25fcHVibGljX3Jvb21fY29uZmlybV9kZXNjcmlwdGlvbl8xXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeyBiOiAoc3ViKSA9PiA8c3Ryb25nPntzdWJ9PC9zdHJvbmc+IH0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKX17XCIgXCJ9XG4gICAgICAgICAgICAgICAgICAgICAgICA8L3A+XG4gICAgICAgICAgICAgICAgICAgICAgICA8cD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB7XCIgXCJ9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAge190KFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcInJvb21fc2V0dGluZ3N8c2VjdXJpdHl8ZW5hYmxlX2VuY3J5cHRpb25fcHVibGljX3Jvb21fY29uZmlybV9kZXNjcmlwdGlvbl8yXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYTogKHN1YikgPT4gKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxBY2Nlc3NpYmxlQnV0dG9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGtpbmQ9XCJsaW5rX2lubGluZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9uQ2xpY2s9eygpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpYWxvZy5jbG9zZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jcmVhdGVOZXdSb29tKGZhbHNlLCB0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHtcIiBcIn1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge3N1Yn17XCIgXCJ9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9BY2Nlc3NpYmxlQnV0dG9uPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICApfXtcIiBcIn1cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvcD5cbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBjb25zdCB7IGZpbmlzaGVkIH0gPSBkaWFsb2c7XG4gICAgICAgICAgICBjb25zdCBbY29uZmlybV0gPSBhd2FpdCBmaW5pc2hlZDtcbiAgICAgICAgICAgIGlmICghY29uZmlybSkgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgTW9kYWwuY3JlYXRlRGlhbG9nKFF1ZXN0aW9uRGlhbG9nLCB7XG4gICAgICAgICAgICB0aXRsZTogX3QoXCJyb29tX3NldHRpbmdzfHNlY3VyaXR5fGVuYWJsZV9lbmNyeXB0aW9uX2NvbmZpcm1fdGl0bGVcIiksXG4gICAgICAgICAgICBkZXNjcmlwdGlvbjogX3QoXG4gICAgICAgICAgICAgICAgXCJyb29tX3NldHRpbmdzfHNlY3VyaXR5fGVuYWJsZV9lbmNyeXB0aW9uX2NvbmZpcm1fZGVzY3JpcHRpb25cIixcbiAgICAgICAgICAgICAgICB7fSxcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIGE6IChzdWIpID0+IDxFeHRlcm5hbExpbmsgaHJlZj17U2RrQ29uZmlnLmdldChcImhlbHBfZW5jcnlwdGlvbl91cmxcIil9PntzdWJ9PC9FeHRlcm5hbExpbms+LFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgb25GaW5pc2hlZDogKGNvbmZpcm0pID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoIWNvbmZpcm0pIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7IGVuY3J5cHRlZDogZmFsc2UgfSk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBjb25zdCBiZWZvcmVFbmNyeXB0ZWQgPSB0aGlzLnN0YXRlLmVuY3J5cHRlZDtcbiAgICAgICAgICAgICAgICB0aGlzLnNldFN0YXRlKHsgZW5jcnlwdGVkOiB0cnVlIH0pO1xuICAgICAgICAgICAgICAgIHRoaXMuY29udGV4dFxuICAgICAgICAgICAgICAgICAgICAuc2VuZFN0YXRlRXZlbnQodGhpcy5wcm9wcy5yb29tLnJvb21JZCwgRXZlbnRUeXBlLlJvb21FbmNyeXB0aW9uLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhbGdvcml0aG06IE1FR09MTV9FTkNSWVBUSU9OX0FMR09SSVRITSxcbiAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgLmNhdGNoKChlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsb2dnZXIuZXJyb3IoZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldFN0YXRlKHsgZW5jcnlwdGVkOiBiZWZvcmVFbmNyeXB0ZWQgfSk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIHByaXZhdGUgb25HdWVzdEFjY2Vzc0NoYW5nZSA9IChhbGxvd2VkOiBib29sZWFuKTogdm9pZCA9PiB7XG4gICAgICAgIGNvbnN0IGd1ZXN0QWNjZXNzID0gYWxsb3dlZCA/IEd1ZXN0QWNjZXNzLkNhbkpvaW4gOiBHdWVzdEFjY2Vzcy5Gb3JiaWRkZW47XG4gICAgICAgIGNvbnN0IGJlZm9yZUd1ZXN0QWNjZXNzID0gdGhpcy5zdGF0ZS5ndWVzdEFjY2VzcztcbiAgICAgICAgaWYgKGJlZm9yZUd1ZXN0QWNjZXNzID09PSBndWVzdEFjY2VzcykgcmV0dXJuO1xuXG4gICAgICAgIHRoaXMuc2V0U3RhdGUoeyBndWVzdEFjY2VzcyB9KTtcblxuICAgICAgICB0aGlzLmNvbnRleHRcbiAgICAgICAgICAgIC5zZW5kU3RhdGVFdmVudChcbiAgICAgICAgICAgICAgICB0aGlzLnByb3BzLnJvb20ucm9vbUlkLFxuICAgICAgICAgICAgICAgIEV2ZW50VHlwZS5Sb29tR3Vlc3RBY2Nlc3MsXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICBndWVzdF9hY2Nlc3M6IGd1ZXN0QWNjZXNzLFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgXCJcIixcbiAgICAgICAgICAgIClcbiAgICAgICAgICAgIC5jYXRjaCgoZSkgPT4ge1xuICAgICAgICAgICAgICAgIGxvZ2dlci5lcnJvcihlKTtcbiAgICAgICAgICAgICAgICB0aGlzLnNldFN0YXRlKHsgZ3Vlc3RBY2Nlc3M6IGJlZm9yZUd1ZXN0QWNjZXNzIH0pO1xuICAgICAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIHByaXZhdGUgY3JlYXRlTmV3Um9vbSA9IGFzeW5jIChkZWZhdWx0UHVibGljOiBib29sZWFuLCBkZWZhdWx0RW5jcnlwdGVkOiBib29sZWFuKTogUHJvbWlzZTxib29sZWFuPiA9PiB7XG4gICAgICAgIGNvbnN0IG1vZGFsID0gTW9kYWwuY3JlYXRlRGlhbG9nKENyZWF0ZVJvb21EaWFsb2csIHsgZGVmYXVsdFB1YmxpYywgZGVmYXVsdEVuY3J5cHRlZCB9KTtcblxuICAgICAgICBQb3N0aG9nVHJhY2tlcnMudHJhY2tJbnRlcmFjdGlvbihcIldlYlJvb21TZXR0aW5nc1NlY3VyaXR5VGFiQ3JlYXRlTmV3Um9vbUJ1dHRvblwiKTtcblxuICAgICAgICBjb25zdCBbc2hvdWxkQ3JlYXRlLCBvcHRzXSA9IGF3YWl0IG1vZGFsLmZpbmlzaGVkO1xuICAgICAgICBpZiAoc2hvdWxkQ3JlYXRlKSB7XG4gICAgICAgICAgICBhd2FpdCBjcmVhdGVSb29tKHRoaXMuY29udGV4dCwgb3B0cyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHNob3VsZENyZWF0ZTtcbiAgICB9O1xuXG4gICAgcHJpdmF0ZSBvbkhpc3RvcnlSYWRpb1RvZ2dsZSA9IChoaXN0b3J5OiBIaXN0b3J5VmlzaWJpbGl0eSk6IHZvaWQgPT4ge1xuICAgICAgICBjb25zdCBiZWZvcmVIaXN0b3J5ID0gdGhpcy5zdGF0ZS5oaXN0b3J5O1xuICAgICAgICBpZiAoYmVmb3JlSGlzdG9yeSA9PT0gaGlzdG9yeSkgcmV0dXJuO1xuXG4gICAgICAgIHRoaXMuc2V0U3RhdGUoeyBoaXN0b3J5OiBoaXN0b3J5IH0pO1xuICAgICAgICB0aGlzLmNvbnRleHRcbiAgICAgICAgICAgIC5zZW5kU3RhdGVFdmVudChcbiAgICAgICAgICAgICAgICB0aGlzLnByb3BzLnJvb20ucm9vbUlkLFxuICAgICAgICAgICAgICAgIEV2ZW50VHlwZS5Sb29tSGlzdG9yeVZpc2liaWxpdHksXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICBoaXN0b3J5X3Zpc2liaWxpdHk6IGhpc3RvcnksXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBcIlwiLFxuICAgICAgICAgICAgKVxuICAgICAgICAgICAgLmNhdGNoKChlKSA9PiB7XG4gICAgICAgICAgICAgICAgbG9nZ2VyLmVycm9yKGUpO1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoeyBoaXN0b3J5OiBiZWZvcmVIaXN0b3J5IH0pO1xuICAgICAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIHByaXZhdGUgdXBkYXRlQmxhY2tsaXN0RGV2aWNlc0ZsYWcgPSAoY2hlY2tlZDogYm9vbGVhbik6IHZvaWQgPT4ge1xuICAgICAgICB0aGlzLnByb3BzLnJvb20uc2V0QmxhY2tsaXN0VW52ZXJpZmllZERldmljZXMoY2hlY2tlZCk7XG4gICAgfTtcblxuICAgIHByaXZhdGUgYXN5bmMgaGFzQWxpYXNlcygpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAgICAgY29uc3QgY2xpID0gdGhpcy5jb250ZXh0O1xuICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGNsaS5nZXRMb2NhbEFsaWFzZXModGhpcy5wcm9wcy5yb29tLnJvb21JZCk7XG4gICAgICAgIGNvbnN0IGxvY2FsQWxpYXNlcyA9IHJlc3BvbnNlLmFsaWFzZXM7XG4gICAgICAgIHJldHVybiBBcnJheS5pc0FycmF5KGxvY2FsQWxpYXNlcykgJiYgbG9jYWxBbGlhc2VzLmxlbmd0aCAhPT0gMDtcbiAgICB9XG5cbiAgICBwcml2YXRlIHJlbmRlckpvaW5SdWxlKCk6IEpTWC5FbGVtZW50IHtcbiAgICAgICAgY29uc3Qgcm9vbSA9IHRoaXMucHJvcHMucm9vbTtcblxuICAgICAgICBsZXQgYWxpYXNXYXJuaW5nOiBKU1guRWxlbWVudCB8IHVuZGVmaW5lZDtcbiAgICAgICAgaWYgKHJvb20uZ2V0Sm9pblJ1bGUoKSA9PT0gSm9pblJ1bGUuUHVibGljICYmICF0aGlzLnN0YXRlLmhhc0FsaWFzZXMpIHtcbiAgICAgICAgICAgIGFsaWFzV2FybmluZyA9IChcbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzTmFtZT1cIm14X1NlY3VyaXR5Um9vbVNldHRpbmdzVGFiX3dhcm5pbmdcIj5cbiAgICAgICAgICAgICAgICAgICAgPFdhcm5pbmdJY29uIHdpZHRoPXsxNX0gaGVpZ2h0PXsxNX0gLz5cbiAgICAgICAgICAgICAgICAgICAgPHNwYW4+e190KFwicm9vbV9zZXR0aW5nc3xzZWN1cml0eXxwdWJsaWNfd2l0aG91dF9hbGlhc193YXJuaW5nXCIpfTwvc3Bhbj5cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgZGVzY3JpcHRpb24gPSBfdChcInJvb21fc2V0dGluZ3N8c2VjdXJpdHl8am9pbl9ydWxlX2Rlc2NyaXB0aW9uXCIsIHtcbiAgICAgICAgICAgIHJvb21OYW1lOiByb29tLm5hbWUsXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGxldCBhZHZhbmNlZDogSlNYLkVsZW1lbnQgfCB1bmRlZmluZWQ7XG4gICAgICAgIGlmIChyb29tLmdldEpvaW5SdWxlKCkgPT09IEpvaW5SdWxlLlB1YmxpYykge1xuICAgICAgICAgICAgYWR2YW5jZWQgPSAoXG4gICAgICAgICAgICAgICAgPGRpdj5cbiAgICAgICAgICAgICAgICAgICAgPEFjY2Vzc2libGVCdXR0b25cbiAgICAgICAgICAgICAgICAgICAgICAgIG9uQ2xpY2s9e3RoaXMudG9nZ2xlQWR2YW5jZWRTZWN0aW9ufVxuICAgICAgICAgICAgICAgICAgICAgICAga2luZD1cImxpbmtcIlxuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3NOYW1lPVwibXhfU2V0dGluZ3NUYWJfc2hvd0FkdmFuY2VkXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIGFyaWEtZXhwYW5kZWQ9e3RoaXMuc3RhdGUuc2hvd0FkdmFuY2VkU2VjdGlvbn1cbiAgICAgICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgICAgICAge3RoaXMuc3RhdGUuc2hvd0FkdmFuY2VkU2VjdGlvbiA/IF90KFwiYWN0aW9ufGhpZGVfYWR2YW5jZWRcIikgOiBfdChcImFjdGlvbnxzaG93X2FkdmFuY2VkXCIpfVxuICAgICAgICAgICAgICAgICAgICA8L0FjY2Vzc2libGVCdXR0b24+XG4gICAgICAgICAgICAgICAgICAgIHt0aGlzLnN0YXRlLnNob3dBZHZhbmNlZFNlY3Rpb24gJiYgdGhpcy5yZW5kZXJBZHZhbmNlZCgpfVxuICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICA8U2V0dGluZ3NGaWVsZHNldCBsZWdlbmQ9e190KFwicm9vbV9zZXR0aW5nc3xhY2Nlc3N8dGl0bGVcIil9IGRlc2NyaXB0aW9uPXtkZXNjcmlwdGlvbn0+XG4gICAgICAgICAgICAgICAgPEpvaW5SdWxlU2V0dGluZ3NcbiAgICAgICAgICAgICAgICAgICAgcm9vbT17cm9vbX1cbiAgICAgICAgICAgICAgICAgICAgYmVmb3JlQ2hhbmdlPXt0aGlzLm9uQmVmb3JlSm9pblJ1bGVDaGFuZ2V9XG4gICAgICAgICAgICAgICAgICAgIG9uRXJyb3I9e3RoaXMub25Kb2luUnVsZUNoYW5nZUVycm9yfVxuICAgICAgICAgICAgICAgICAgICBjbG9zZVNldHRpbmdzRm49e3RoaXMucHJvcHMuY2xvc2VTZXR0aW5nc0ZufVxuICAgICAgICAgICAgICAgICAgICBwcm9tcHRVcGdyYWRlPXt0cnVlfVxuICAgICAgICAgICAgICAgICAgICBhbGlhc1dhcm5pbmc9e2FsaWFzV2FybmluZ31cbiAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICAgIHthZHZhbmNlZH1cbiAgICAgICAgICAgIDwvU2V0dGluZ3NGaWVsZHNldD5cbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIG9uSm9pblJ1bGVDaGFuZ2VFcnJvciA9IChlcnJvcjogRXJyb3IpOiB2b2lkID0+IHtcbiAgICAgICAgTW9kYWwuY3JlYXRlRGlhbG9nKEVycm9yRGlhbG9nLCB7XG4gICAgICAgICAgICB0aXRsZTogX3QoXCJyb29tX3NldHRpbmdzfHNlY3VyaXR5fGVycm9yX2pvaW5fcnVsZV9jaGFuZ2VfdGl0bGVcIiksXG4gICAgICAgICAgICBkZXNjcmlwdGlvbjogZXJyb3IubWVzc2FnZSA/PyBfdChcInJvb21fc2V0dGluZ3N8c2VjdXJpdHl8ZXJyb3Jfam9pbl9ydWxlX2NoYW5nZV91bmtub3duXCIpLFxuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgcHJpdmF0ZSBvbkJlZm9yZUpvaW5SdWxlQ2hhbmdlID0gYXN5bmMgKGpvaW5SdWxlOiBKb2luUnVsZSk6IFByb21pc2U8Ym9vbGVhbj4gPT4ge1xuICAgICAgICBpZiAodGhpcy5zdGF0ZS5lbmNyeXB0ZWQgJiYgam9pblJ1bGUgPT09IEpvaW5SdWxlLlB1YmxpYykge1xuICAgICAgICAgICAgY29uc3QgZGlhbG9nID0gTW9kYWwuY3JlYXRlRGlhbG9nKFF1ZXN0aW9uRGlhbG9nLCB7XG4gICAgICAgICAgICAgICAgdGl0bGU6IF90KFwicm9vbV9zZXR0aW5nc3xzZWN1cml0eXxlbmNyeXB0ZWRfcm9vbV9wdWJsaWNfY29uZmlybV90aXRsZVwiKSxcbiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbjogKFxuICAgICAgICAgICAgICAgICAgICA8ZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgPHA+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAge1wiIFwifVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHtfdChcInJvb21fc2V0dGluZ3N8c2VjdXJpdHl8ZW5jcnlwdGVkX3Jvb21fcHVibGljX2NvbmZpcm1fZGVzY3JpcHRpb25fMVwiLCB1bmRlZmluZWQsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYjogKHN1YikgPT4gPHN0cm9uZz57c3VifTwvc3Ryb25nPixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KX17XCIgXCJ9XG4gICAgICAgICAgICAgICAgICAgICAgICA8L3A+XG4gICAgICAgICAgICAgICAgICAgICAgICA8cD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB7XCIgXCJ9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAge190KFwicm9vbV9zZXR0aW5nc3xzZWN1cml0eXxlbmNyeXB0ZWRfcm9vbV9wdWJsaWNfY29uZmlybV9kZXNjcmlwdGlvbl8yXCIsIHVuZGVmaW5lZCwge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhOiAoc3ViKSA9PiAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8QWNjZXNzaWJsZUJ1dHRvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGtpbmQ9XCJsaW5rX2lubGluZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb25DbGljaz17KCk6IHZvaWQgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWFsb2cuY2xvc2UoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jcmVhdGVOZXdSb29tKHRydWUsIGZhbHNlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9fVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHtcIiBcIn1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7c3VifXtcIiBcIn1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvQWNjZXNzaWJsZUJ1dHRvbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KX17XCIgXCJ9XG4gICAgICAgICAgICAgICAgICAgICAgICA8L3A+XG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgY29uc3QgeyBmaW5pc2hlZCB9ID0gZGlhbG9nO1xuICAgICAgICAgICAgY29uc3QgW2NvbmZpcm1dID0gYXdhaXQgZmluaXNoZWQ7XG4gICAgICAgICAgICBpZiAoIWNvbmZpcm0pIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH07XG5cbiAgICBwcml2YXRlIHJlbmRlckhpc3RvcnkoKTogUmVhY3ROb2RlIHtcbiAgICAgICAgaWYgKCFTZXR0aW5nc1N0b3JlLmdldFZhbHVlKFVJRmVhdHVyZS5Sb29tSGlzdG9yeVNldHRpbmdzKSkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBjbGllbnQgPSB0aGlzLmNvbnRleHQ7XG4gICAgICAgIGNvbnN0IGhpc3RvcnkgPSB0aGlzLnN0YXRlLmhpc3Rvcnk7XG4gICAgICAgIGNvbnN0IHN0YXRlID0gdGhpcy5wcm9wcy5yb29tLmN1cnJlbnRTdGF0ZTtcbiAgICAgICAgY29uc3QgY2FuQ2hhbmdlSGlzdG9yeSA9IHN0YXRlPy5tYXlDbGllbnRTZW5kU3RhdGVFdmVudChFdmVudFR5cGUuUm9vbUhpc3RvcnlWaXNpYmlsaXR5LCBjbGllbnQpO1xuXG4gICAgICAgIGNvbnN0IG9wdGlvbnMgPSBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgdmFsdWU6IEhpc3RvcnlWaXNpYmlsaXR5LlNoYXJlZCxcbiAgICAgICAgICAgICAgICBsYWJlbDogX3QoXCJyb29tX3NldHRpbmdzfHNlY3VyaXR5fGhpc3RvcnlfdmlzaWJpbGl0eV9zaGFyZWRcIiksXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHZhbHVlOiBIaXN0b3J5VmlzaWJpbGl0eS5JbnZpdGVkLFxuICAgICAgICAgICAgICAgIGxhYmVsOiBfdChcInJvb21fc2V0dGluZ3N8c2VjdXJpdHl8aGlzdG9yeV92aXNpYmlsaXR5X2ludml0ZWRcIiksXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHZhbHVlOiBIaXN0b3J5VmlzaWJpbGl0eS5Kb2luZWQsXG4gICAgICAgICAgICAgICAgbGFiZWw6IF90KFwicm9vbV9zZXR0aW5nc3xzZWN1cml0eXxoaXN0b3J5X3Zpc2liaWxpdHlfam9pbmVkXCIpLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgXTtcblxuICAgICAgICAvLyBXb3JsZCByZWFkYWJsZSBkb2Vzbid0IG1ha2Ugc2Vuc2UgZm9yIGVuY3J5cHRlZCByb29tc1xuICAgICAgICBpZiAoIXRoaXMuc3RhdGUuZW5jcnlwdGVkIHx8IGhpc3RvcnkgPT09IEhpc3RvcnlWaXNpYmlsaXR5LldvcmxkUmVhZGFibGUpIHtcbiAgICAgICAgICAgIG9wdGlvbnMudW5zaGlmdCh7XG4gICAgICAgICAgICAgICAgdmFsdWU6IEhpc3RvcnlWaXNpYmlsaXR5LldvcmxkUmVhZGFibGUsXG4gICAgICAgICAgICAgICAgbGFiZWw6IF90KFwicm9vbV9zZXR0aW5nc3xzZWN1cml0eXxoaXN0b3J5X3Zpc2liaWxpdHlfd29ybGRfcmVhZGFibGVcIiksXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGRlc2NyaXB0aW9uID0gX3QoXCJyb29tX3NldHRpbmdzfHNlY3VyaXR5fGhpc3RvcnlfdmlzaWJpbGl0eV93YXJuaW5nXCIpO1xuXG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICA8U2V0dGluZ3NGaWVsZHNldCBsZWdlbmQ9e190KFwicm9vbV9zZXR0aW5nc3xzZWN1cml0eXxoaXN0b3J5X3Zpc2liaWxpdHlfbGVnZW5kXCIpfSBkZXNjcmlwdGlvbj17ZGVzY3JpcHRpb259PlxuICAgICAgICAgICAgICAgIDxTdHlsZWRSYWRpb0dyb3VwXG4gICAgICAgICAgICAgICAgICAgIG5hbWU9XCJoaXN0b3J5VmlzXCJcbiAgICAgICAgICAgICAgICAgICAgdmFsdWU9e2hpc3Rvcnl9XG4gICAgICAgICAgICAgICAgICAgIG9uQ2hhbmdlPXt0aGlzLm9uSGlzdG9yeVJhZGlvVG9nZ2xlfVxuICAgICAgICAgICAgICAgICAgICBkaXNhYmxlZD17IWNhbkNoYW5nZUhpc3Rvcnl9XG4gICAgICAgICAgICAgICAgICAgIGRlZmluaXRpb25zPXtvcHRpb25zfVxuICAgICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICA8L1NldHRpbmdzRmllbGRzZXQ+XG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSB0b2dnbGVBZHZhbmNlZFNlY3Rpb24gPSAoKTogdm9pZCA9PiB7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoeyBzaG93QWR2YW5jZWRTZWN0aW9uOiAhdGhpcy5zdGF0ZS5zaG93QWR2YW5jZWRTZWN0aW9uIH0pO1xuICAgIH07XG5cbiAgICBwcml2YXRlIHJlbmRlckFkdmFuY2VkKCk6IEpTWC5FbGVtZW50IHtcbiAgICAgICAgY29uc3QgY2xpZW50ID0gdGhpcy5jb250ZXh0O1xuICAgICAgICBjb25zdCBndWVzdEFjY2VzcyA9IHRoaXMuc3RhdGUuZ3Vlc3RBY2Nlc3M7XG4gICAgICAgIGNvbnN0IHN0YXRlID0gdGhpcy5wcm9wcy5yb29tLmN1cnJlbnRTdGF0ZTtcbiAgICAgICAgY29uc3QgY2FuU2V0R3Vlc3RBY2Nlc3MgPSBzdGF0ZT8ubWF5Q2xpZW50U2VuZFN0YXRlRXZlbnQoRXZlbnRUeXBlLlJvb21HdWVzdEFjY2VzcywgY2xpZW50KTtcblxuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJteF9TZWN1cml0eVJvb21TZXR0aW5nc1RhYl9hZHZhbmNlZFNlY3Rpb25cIj5cbiAgICAgICAgICAgICAgICA8TGFiZWxsZWRUb2dnbGVTd2l0Y2hcbiAgICAgICAgICAgICAgICAgICAgdmFsdWU9e2d1ZXN0QWNjZXNzID09PSBHdWVzdEFjY2Vzcy5DYW5Kb2lufVxuICAgICAgICAgICAgICAgICAgICBvbkNoYW5nZT17dGhpcy5vbkd1ZXN0QWNjZXNzQ2hhbmdlfVxuICAgICAgICAgICAgICAgICAgICBkaXNhYmxlZD17IWNhblNldEd1ZXN0QWNjZXNzfVxuICAgICAgICAgICAgICAgICAgICBsYWJlbD17X3QoXCJyb29tX3NldHRpbmdzfHZpc2liaWxpdHl8Z3Vlc3RfYWNjZXNzX2xhYmVsXCIpfVxuICAgICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICAgICAgPHA+e190KFwicm9vbV9zZXR0aW5nc3xzZWN1cml0eXxndWVzdF9hY2Nlc3Nfd2FybmluZ1wiKX08L3A+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgcmVuZGVyKCk6IFJlYWN0LlJlYWN0Tm9kZSB7XG4gICAgICAgIGNvbnN0IGNsaWVudCA9IHRoaXMuY29udGV4dDtcbiAgICAgICAgY29uc3Qgcm9vbSA9IHRoaXMucHJvcHMucm9vbTtcbiAgICAgICAgY29uc3QgaXNFbmNyeXB0ZWQgPSB0aGlzLnN0YXRlLmVuY3J5cHRlZDtcbiAgICAgICAgY29uc3QgaGFzRW5jcnlwdGlvblBlcm1pc3Npb24gPSByb29tLmN1cnJlbnRTdGF0ZS5tYXlDbGllbnRTZW5kU3RhdGVFdmVudChFdmVudFR5cGUuUm9vbUVuY3J5cHRpb24sIGNsaWVudCk7XG4gICAgICAgIGNvbnN0IGlzRW5jcnlwdGlvbkZvcmNlRGlzYWJsZWQgPSBzaG91bGRGb3JjZURpc2FibGVFbmNyeXB0aW9uKGNsaWVudCk7XG4gICAgICAgIGNvbnN0IGNhbkVuYWJsZUVuY3J5cHRpb24gPSAhaXNFbmNyeXB0ZWQgJiYgIWlzRW5jcnlwdGlvbkZvcmNlRGlzYWJsZWQgJiYgaGFzRW5jcnlwdGlvblBlcm1pc3Npb247XG5cbiAgICAgICAgbGV0IGVuY3J5cHRpb25TZXR0aW5nczogSlNYLkVsZW1lbnQgfCB1bmRlZmluZWQ7XG4gICAgICAgIGlmIChcbiAgICAgICAgICAgIGlzRW5jcnlwdGVkICYmXG4gICAgICAgICAgICBTZXR0aW5nc1N0b3JlLmNhblNldFZhbHVlKFwiYmxhY2tsaXN0VW52ZXJpZmllZERldmljZXNcIiwgdGhpcy5wcm9wcy5yb29tLnJvb21JZCwgU2V0dGluZ0xldmVsLlJPT01fREVWSUNFKVxuICAgICAgICApIHtcbiAgICAgICAgICAgIGVuY3J5cHRpb25TZXR0aW5ncyA9IChcbiAgICAgICAgICAgICAgICA8U2V0dGluZ3NGbGFnXG4gICAgICAgICAgICAgICAgICAgIG5hbWU9XCJibGFja2xpc3RVbnZlcmlmaWVkRGV2aWNlc1wiXG4gICAgICAgICAgICAgICAgICAgIGxldmVsPXtTZXR0aW5nTGV2ZWwuUk9PTV9ERVZJQ0V9XG4gICAgICAgICAgICAgICAgICAgIG9uQ2hhbmdlPXt0aGlzLnVwZGF0ZUJsYWNrbGlzdERldmljZXNGbGFnfVxuICAgICAgICAgICAgICAgICAgICByb29tSWQ9e3RoaXMucHJvcHMucm9vbS5yb29tSWR9XG4gICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBoaXN0b3J5U2VjdGlvbiA9IHRoaXMucmVuZGVySGlzdG9yeSgpO1xuXG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICA8U2V0dGluZ3NUYWI+XG4gICAgICAgICAgICAgICAgPFNldHRpbmdzU2VjdGlvbiBoZWFkaW5nPXtfdChcInJvb21fc2V0dGluZ3N8c2VjdXJpdHl8dGl0bGVcIil9PlxuICAgICAgICAgICAgICAgICAgICA8U2V0dGluZ3NGaWVsZHNldFxuICAgICAgICAgICAgICAgICAgICAgICAgbGVnZW5kPXtfdChcInNldHRpbmdzfHNlY3VyaXR5fGVuY3J5cHRpb25fc2VjdGlvblwiKX1cbiAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uPXtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc0VuY3J5cHRpb25Gb3JjZURpc2FibGVkICYmICFpc0VuY3J5cHRlZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA/IHVuZGVmaW5lZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA6IF90KFwicm9vbV9zZXR0aW5nc3xzZWN1cml0eXxlbmNyeXB0aW9uX3Blcm1hbmVudFwiKVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgICAgICA8TGFiZWxsZWRUb2dnbGVTd2l0Y2hcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZT17aXNFbmNyeXB0ZWR9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb25DaGFuZ2U9e3RoaXMub25FbmNyeXB0aW9uQ2hhbmdlfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVsPXtfdChcImNvbW1vbnxlbmNyeXB0ZWRcIil9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlzYWJsZWQ9eyFjYW5FbmFibGVFbmNyeXB0aW9ufVxuICAgICAgICAgICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICAgICAgICAgIHtpc0VuY3J5cHRpb25Gb3JjZURpc2FibGVkICYmICFpc0VuY3J5cHRlZCAmJiAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPENhcHRpb24+e190KFwicm9vbV9zZXR0aW5nc3xzZWN1cml0eXxlbmNyeXB0aW9uX2ZvcmNlZFwiKX08L0NhcHRpb24+XG4gICAgICAgICAgICAgICAgICAgICAgICApfVxuICAgICAgICAgICAgICAgICAgICAgICAge2VuY3J5cHRpb25TZXR0aW5nc31cbiAgICAgICAgICAgICAgICAgICAgPC9TZXR0aW5nc0ZpZWxkc2V0PlxuXG4gICAgICAgICAgICAgICAgICAgIHt0aGlzLnJlbmRlckpvaW5SdWxlKCl9XG4gICAgICAgICAgICAgICAgICAgIHtoaXN0b3J5U2VjdGlvbn1cbiAgICAgICAgICAgICAgICA8L1NldHRpbmdzU2VjdGlvbj5cbiAgICAgICAgICAgIDwvU2V0dGluZ3NUYWI+XG4gICAgICAgICk7XG4gICAgfVxufVxuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7OztBQVFBLElBQUFBLE1BQUEsR0FBQUMsc0JBQUEsQ0FBQUMsT0FBQTtBQUNBLElBQUFDLE9BQUEsR0FBQUQsT0FBQTtBQVNBLElBQUFFLE9BQUEsR0FBQUYsT0FBQTtBQUVBLElBQUFHLFFBQUEsR0FBQUgsT0FBQTtBQUNBLElBQUFJLGdCQUFBLEdBQUFKLE9BQUE7QUFDQSxJQUFBSyxxQkFBQSxHQUFBTixzQkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQU0sTUFBQSxHQUFBUCxzQkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQU8sZUFBQSxHQUFBUixzQkFBQSxDQUFBQyxP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