matrix-react-sdk
Version:
SDK for matrix.org using React
321 lines (312 loc) • 55.1 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = exports.IgnoredUser = void 0;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _react = _interopRequireDefault(require("react"));
var _utils = require("matrix-js-sdk/src/utils");
var _matrix = require("matrix-js-sdk/src/matrix");
var _types = require("matrix-js-sdk/src/types");
var _logger = require("matrix-js-sdk/src/logger");
var _languageHandler = require("../../../../../languageHandler");
var _MatrixClientPeg = require("../../../../../MatrixClientPeg");
var _AccessibleButton = _interopRequireDefault(require("../../../elements/AccessibleButton"));
var _dispatcher = _interopRequireDefault(require("../../../../../dispatcher/dispatcher"));
var _SettingLevel = require("../../../../../settings/SettingLevel");
var _SecureBackupPanel = _interopRequireDefault(require("../../SecureBackupPanel"));
var _SettingsStore = _interopRequireDefault(require("../../../../../settings/SettingsStore"));
var _UIFeature = require("../../../../../settings/UIFeature");
var _CryptographyPanel = _interopRequireDefault(require("../../CryptographyPanel"));
var _SettingsFlag = _interopRequireDefault(require("../../../elements/SettingsFlag"));
var _CrossSigningPanel = _interopRequireDefault(require("../../CrossSigningPanel"));
var _EventIndexPanel = _interopRequireDefault(require("../../EventIndexPanel"));
var _InlineSpinner = _interopRequireDefault(require("../../../elements/InlineSpinner"));
var _PosthogAnalytics = require("../../../../../PosthogAnalytics");
var _AnalyticsLearnMoreDialog = require("../../../dialogs/AnalyticsLearnMoreDialog");
var _rooms = require("../../../../../utils/rooms");
var _SettingsTab = _interopRequireDefault(require("../SettingsTab"));
var _SettingsSection = require("../../shared/SettingsSection");
var _SettingsSubsection = _interopRequireWildcard(require("../../shared/SettingsSubsection"));
var _useOwnDevices = require("../../devices/useOwnDevices");
var _DiscoverySettings = _interopRequireDefault(require("../../discovery/DiscoverySettings"));
var _SetIntegrationManager = _interopRequireDefault(require("../../SetIntegrationManager"));
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 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.
*/
const DehydratedDeviceStatus = () => {
const {
dehydratedDeviceId
} = (0, _useOwnDevices.useOwnDevices)();
if (dehydratedDeviceId) {
return /*#__PURE__*/_react.default.createElement("div", {
className: "mx_SettingsSubsection_content"
}, /*#__PURE__*/_react.default.createElement("div", {
className: "mx_SettingsFlag_label"
}, (0, _languageHandler._t)("settings|security|dehydrated_device_enabled")), /*#__PURE__*/_react.default.createElement("div", {
className: "mx_SettingsSubsection_text"
}, (0, _languageHandler._t)("settings|security|dehydrated_device_description")));
} else {
return null;
}
};
class IgnoredUser extends _react.default.Component {
constructor(...args) {
super(...args);
(0, _defineProperty2.default)(this, "onUnignoreClicked", () => {
this.props.onUnignored(this.props.userId);
});
}
render() {
const id = `mx_SecurityUserSettingsTab_ignoredUser_${this.props.userId}`;
return /*#__PURE__*/_react.default.createElement("div", {
className: "mx_SecurityUserSettingsTab_ignoredUser"
}, /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, {
onClick: this.onUnignoreClicked,
kind: "primary_sm",
"aria-describedby": id,
disabled: this.props.inProgress
}, (0, _languageHandler._t)("action|unignore")), /*#__PURE__*/_react.default.createElement("span", {
id: id
}, this.props.userId));
}
}
exports.IgnoredUser = IgnoredUser;
class SecurityUserSettingsTab extends _react.default.Component {
constructor(props) {
super(props);
// Get rooms we're invited to
(0, _defineProperty2.default)(this, "dispatcherRef", void 0);
(0, _defineProperty2.default)(this, "onAction", ({
action
}) => {
if (action === "ignore_state_changed") {
const ignoredUserIds = _MatrixClientPeg.MatrixClientPeg.safeGet().getIgnoredUsers();
const newWaitingUnignored = this.state.waitingUnignored.filter(e => ignoredUserIds.includes(e));
this.setState({
ignoredUserIds,
waitingUnignored: newWaitingUnignored
});
}
});
(0, _defineProperty2.default)(this, "onMyMembership", (room, membership) => {
if (room.isSpaceRoom()) {
return;
}
if (membership === _types.KnownMembership.Invite) {
this.addInvitedRoom(room);
} else if (this.state.invitedRoomIds.has(room.roomId)) {
// The user isn't invited anymore
this.removeInvitedRoom(room.roomId);
}
});
(0, _defineProperty2.default)(this, "addInvitedRoom", room => {
this.setState(({
invitedRoomIds
}) => ({
invitedRoomIds: new Set(invitedRoomIds).add(room.roomId)
}));
});
(0, _defineProperty2.default)(this, "removeInvitedRoom", roomId => {
this.setState(({
invitedRoomIds
}) => {
const newInvitedRoomIds = new Set(invitedRoomIds);
newInvitedRoomIds.delete(roomId);
return {
invitedRoomIds: newInvitedRoomIds
};
});
});
(0, _defineProperty2.default)(this, "onUserUnignored", async userId => {
const {
ignoredUserIds,
waitingUnignored
} = this.state;
const currentlyIgnoredUserIds = ignoredUserIds.filter(e => !waitingUnignored.includes(e));
const index = currentlyIgnoredUserIds.indexOf(userId);
if (index !== -1) {
currentlyIgnoredUserIds.splice(index, 1);
this.setState(({
waitingUnignored
}) => ({
waitingUnignored: [...waitingUnignored, userId]
}));
_MatrixClientPeg.MatrixClientPeg.safeGet().setIgnoredUsers(currentlyIgnoredUserIds);
}
});
(0, _defineProperty2.default)(this, "getInvitedRooms", () => {
return _MatrixClientPeg.MatrixClientPeg.safeGet().getRooms().filter(r => {
return r.hasMembershipState(_MatrixClientPeg.MatrixClientPeg.safeGet().getUserId(), _types.KnownMembership.Invite);
});
});
(0, _defineProperty2.default)(this, "manageInvites", async accept => {
this.setState({
managingInvites: true
});
// iterate with a normal for loop in order to retry on action failure
const invitedRoomIdsValues = Array.from(this.state.invitedRoomIds);
// Execute all acceptances/rejections sequentially
const cli = _MatrixClientPeg.MatrixClientPeg.safeGet();
const action = accept ? cli.joinRoom.bind(cli) : cli.leave.bind(cli);
for (let i = 0; i < invitedRoomIdsValues.length; i++) {
const roomId = invitedRoomIdsValues[i];
// Accept/reject invite
await action(roomId).then(() => {
// No error, update invited rooms button
this.removeInvitedRoom(roomId);
}, async e => {
// Action failure
if (e.errcode === "M_LIMIT_EXCEEDED") {
// Add a delay between each invite change in order to avoid rate
// limiting by the server.
await (0, _utils.sleep)(e.retry_after_ms || 2500);
// Redo last action
i--;
} else {
// Print out error with joining/leaving room
_logger.logger.warn(e);
}
});
}
this.setState({
managingInvites: false
});
});
(0, _defineProperty2.default)(this, "onAcceptAllInvitesClicked", () => {
this.manageInvites(true);
});
(0, _defineProperty2.default)(this, "onRejectAllInvitesClicked", () => {
this.manageInvites(false);
});
const _invitedRoomIds = new Set(this.getInvitedRooms().map(room => room.roomId));
this.state = {
ignoredUserIds: _MatrixClientPeg.MatrixClientPeg.safeGet().getIgnoredUsers(),
waitingUnignored: [],
managingInvites: false,
invitedRoomIds: _invitedRoomIds
};
}
componentDidMount() {
this.dispatcherRef = _dispatcher.default.register(this.onAction);
_MatrixClientPeg.MatrixClientPeg.safeGet().on(_matrix.RoomEvent.MyMembership, this.onMyMembership);
_MatrixClientPeg.MatrixClientPeg.safeGet().getVersions().then(versions => this.setState({
versions
}));
}
componentWillUnmount() {
if (this.dispatcherRef) _dispatcher.default.unregister(this.dispatcherRef);
_MatrixClientPeg.MatrixClientPeg.safeGet().removeListener(_matrix.RoomEvent.MyMembership, this.onMyMembership);
}
renderIgnoredUsers() {
const {
waitingUnignored,
ignoredUserIds
} = this.state;
const userIds = !ignoredUserIds?.length ? (0, _languageHandler._t)("settings|security|ignore_users_empty") : ignoredUserIds.map(u => {
return /*#__PURE__*/_react.default.createElement(IgnoredUser, {
userId: u,
onUnignored: this.onUserUnignored,
key: u,
inProgress: waitingUnignored.includes(u)
});
});
return /*#__PURE__*/_react.default.createElement(_SettingsSubsection.default, {
heading: (0, _languageHandler._t)("settings|security|ignore_users_section")
}, /*#__PURE__*/_react.default.createElement(_SettingsSubsection.SettingsSubsectionText, null, userIds));
}
renderManageInvites() {
const {
invitedRoomIds
} = this.state;
if (invitedRoomIds.size === 0) {
return null;
}
return /*#__PURE__*/_react.default.createElement(_SettingsSubsection.default, {
heading: (0, _languageHandler._t)("settings|security|bulk_options_section")
}, /*#__PURE__*/_react.default.createElement("div", {
className: "mx_SecurityUserSettingsTab_bulkOptions"
}, /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, {
onClick: this.onAcceptAllInvitesClicked,
kind: "primary_outline",
disabled: this.state.managingInvites
}, (0, _languageHandler._t)("settings|security|bulk_options_accept_all_invites", {
invitedRooms: invitedRoomIds.size
})), /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, {
onClick: this.onRejectAllInvitesClicked,
kind: "danger_outline",
disabled: this.state.managingInvites
}, (0, _languageHandler._t)("settings|security|bulk_options_reject_all_invites", {
invitedRooms: invitedRoomIds.size
})), this.state.managingInvites ? /*#__PURE__*/_react.default.createElement(_InlineSpinner.default, null) : /*#__PURE__*/_react.default.createElement("div", null)));
}
render() {
const secureBackup = /*#__PURE__*/_react.default.createElement(_SettingsSubsection.default, {
heading: (0, _languageHandler._t)("common|secure_backup")
}, /*#__PURE__*/_react.default.createElement(_SecureBackupPanel.default, null), /*#__PURE__*/_react.default.createElement(DehydratedDeviceStatus, null));
const eventIndex = /*#__PURE__*/_react.default.createElement(_SettingsSubsection.default, {
heading: (0, _languageHandler._t)("settings|security|message_search_section")
}, /*#__PURE__*/_react.default.createElement(_EventIndexPanel.default, null));
// XXX: There's no such panel in the current cross-signing designs, but
// it's useful to have for testing the feature. If there's no interest
// in having advanced details here once all flows are implemented, we
// can remove this.
const crossSigning = /*#__PURE__*/_react.default.createElement(_SettingsSubsection.default, {
heading: (0, _languageHandler._t)("common|cross_signing")
}, /*#__PURE__*/_react.default.createElement(_CrossSigningPanel.default, null));
let warning;
if (!(0, _rooms.privateShouldBeEncrypted)(_MatrixClientPeg.MatrixClientPeg.safeGet())) {
warning = /*#__PURE__*/_react.default.createElement("div", {
className: "mx_SecurityUserSettingsTab_warning"
}, (0, _languageHandler._t)("settings|security|e2ee_default_disabled_warning"));
}
let privacySection;
if (_PosthogAnalytics.PosthogAnalytics.instance.isEnabled()) {
const onClickAnalyticsLearnMore = () => {
(0, _AnalyticsLearnMoreDialog.showDialog)({
primaryButton: (0, _languageHandler._t)("action|ok"),
hasCancel: false
});
};
privacySection = /*#__PURE__*/_react.default.createElement(_SettingsSection.SettingsSection, {
heading: (0, _languageHandler._t)("common|privacy")
}, /*#__PURE__*/_react.default.createElement(_DiscoverySettings.default, null), /*#__PURE__*/_react.default.createElement(_SettingsSubsection.default, {
heading: (0, _languageHandler._t)("common|analytics"),
description: (0, _languageHandler._t)("settings|security|analytics_description")
}, /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, {
kind: "link",
onClick: onClickAnalyticsLearnMore
}, (0, _languageHandler._t)("action|learn_more")), _PosthogAnalytics.PosthogAnalytics.instance.isEnabled() && /*#__PURE__*/_react.default.createElement(_SettingsFlag.default, {
name: "pseudonymousAnalyticsOptIn",
level: _SettingLevel.SettingLevel.ACCOUNT
})), /*#__PURE__*/_react.default.createElement(_SettingsSubsection.default, {
heading: (0, _languageHandler._t)("settings|sessions|title")
}, /*#__PURE__*/_react.default.createElement(_SettingsFlag.default, {
name: "deviceClientInformationOptIn",
level: _SettingLevel.SettingLevel.ACCOUNT
})));
}
let advancedSection;
if (_SettingsStore.default.getValue(_UIFeature.UIFeature.AdvancedSettings)) {
const ignoreUsersPanel = this.renderIgnoredUsers();
const invitesPanel = this.renderManageInvites();
// only show the section if there's something to show
if (ignoreUsersPanel || invitesPanel) {
advancedSection = /*#__PURE__*/_react.default.createElement(_SettingsSection.SettingsSection, {
heading: (0, _languageHandler._t)("common|advanced")
}, ignoreUsersPanel, invitesPanel);
}
}
return /*#__PURE__*/_react.default.createElement(_SettingsTab.default, null, warning, /*#__PURE__*/_react.default.createElement(_SetIntegrationManager.default, null), /*#__PURE__*/_react.default.createElement(_SettingsSection.SettingsSection, {
heading: (0, _languageHandler._t)("settings|security|encryption_section")
}, secureBackup, eventIndex, crossSigning, /*#__PURE__*/_react.default.createElement(_CryptographyPanel.default, null)), privacySection, advancedSection);
}
}
exports.default = SecurityUserSettingsTab;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfcmVhY3QiLCJfaW50ZXJvcFJlcXVpcmVEZWZhdWx0IiwicmVxdWlyZSIsIl91dGlscyIsIl9tYXRyaXgiLCJfdHlwZXMiLCJfbG9nZ2VyIiwiX2xhbmd1YWdlSGFuZGxlciIsIl9NYXRyaXhDbGllbnRQZWciLCJfQWNjZXNzaWJsZUJ1dHRvbiIsIl9kaXNwYXRjaGVyIiwiX1NldHRpbmdMZXZlbCIsIl9TZWN1cmVCYWNrdXBQYW5lbCIsIl9TZXR0aW5nc1N0b3JlIiwiX1VJRmVhdHVyZSIsIl9DcnlwdG9ncmFwaHlQYW5lbCIsIl9TZXR0aW5nc0ZsYWciLCJfQ3Jvc3NTaWduaW5nUGFuZWwiLCJfRXZlbnRJbmRleFBhbmVsIiwiX0lubGluZVNwaW5uZXIiLCJfUG9zdGhvZ0FuYWx5dGljcyIsIl9BbmFseXRpY3NMZWFybk1vcmVEaWFsb2ciLCJfcm9vbXMiLCJfU2V0dGluZ3NUYWIiLCJfU2V0dGluZ3NTZWN0aW9uIiwiX1NldHRpbmdzU3Vic2VjdGlvbiIsIl9pbnRlcm9wUmVxdWlyZVdpbGRjYXJkIiwiX3VzZU93bkRldmljZXMiLCJfRGlzY292ZXJ5U2V0dGluZ3MiLCJfU2V0SW50ZWdyYXRpb25NYW5hZ2VyIiwiX2dldFJlcXVpcmVXaWxkY2FyZENhY2hlIiwiZSIsIldlYWtNYXAiLCJyIiwidCIsIl9fZXNNb2R1bGUiLCJkZWZhdWx0IiwiaGFzIiwiZ2V0IiwibiIsIl9fcHJvdG9fXyIsImEiLCJPYmplY3QiLCJkZWZpbmVQcm9wZXJ0eSIsImdldE93blByb3BlcnR5RGVzY3JpcHRvciIsInUiLCJoYXNPd25Qcm9wZXJ0eSIsImNhbGwiLCJpIiwic2V0IiwiRGVoeWRyYXRlZERldmljZVN0YXR1cyIsImRlaHlkcmF0ZWREZXZpY2VJZCIsInVzZU93bkRldmljZXMiLCJjcmVhdGVFbGVtZW50IiwiY2xhc3NOYW1lIiwiX3QiLCJJZ25vcmVkVXNlciIsIlJlYWN0IiwiQ29tcG9uZW50IiwiY29uc3RydWN0b3IiLCJhcmdzIiwiX2RlZmluZVByb3BlcnR5MiIsInByb3BzIiwib25Vbmlnbm9yZWQiLCJ1c2VySWQiLCJyZW5kZXIiLCJpZCIsIm9uQ2xpY2siLCJvblVuaWdub3JlQ2xpY2tlZCIsImtpbmQiLCJkaXNhYmxlZCIsImluUHJvZ3Jlc3MiLCJleHBvcnRzIiwiU2VjdXJpdHlVc2VyU2V0dGluZ3NUYWIiLCJhY3Rpb24iLCJpZ25vcmVkVXNlcklkcyIsIk1hdHJpeENsaWVudFBlZyIsInNhZmVHZXQiLCJnZXRJZ25vcmVkVXNlcnMiLCJuZXdXYWl0aW5nVW5pZ25vcmVkIiwic3RhdGUiLCJ3YWl0aW5nVW5pZ25vcmVkIiwiZmlsdGVyIiwiaW5jbHVkZXMiLCJzZXRTdGF0ZSIsInJvb20iLCJtZW1iZXJzaGlwIiwiaXNTcGFjZVJvb20iLCJLbm93bk1lbWJlcnNoaXAiLCJJbnZpdGUiLCJhZGRJbnZpdGVkUm9vbSIsImludml0ZWRSb29tSWRzIiwicm9vbUlkIiwicmVtb3ZlSW52aXRlZFJvb20iLCJTZXQiLCJhZGQiLCJuZXdJbnZpdGVkUm9vbUlkcyIsImRlbGV0ZSIsImN1cnJlbnRseUlnbm9yZWRVc2VySWRzIiwiaW5kZXgiLCJpbmRleE9mIiwic3BsaWNlIiwic2V0SWdub3JlZFVzZXJzIiwiZ2V0Um9vbXMiLCJoYXNNZW1iZXJzaGlwU3RhdGUiLCJnZXRVc2VySWQiLCJhY2NlcHQiLCJtYW5hZ2luZ0ludml0ZXMiLCJpbnZpdGVkUm9vbUlkc1ZhbHVlcyIsIkFycmF5IiwiZnJvbSIsImNsaSIsImpvaW5Sb29tIiwiYmluZCIsImxlYXZlIiwibGVuZ3RoIiwidGhlbiIsImVycmNvZGUiLCJzbGVlcCIsInJldHJ5X2FmdGVyX21zIiwibG9nZ2VyIiwid2FybiIsIm1hbmFnZUludml0ZXMiLCJnZXRJbnZpdGVkUm9vbXMiLCJtYXAiLCJjb21wb25lbnREaWRNb3VudCIsImRpc3BhdGNoZXJSZWYiLCJkaXMiLCJyZWdpc3RlciIsIm9uQWN0aW9uIiwib24iLCJSb29tRXZlbnQiLCJNeU1lbWJlcnNoaXAiLCJvbk15TWVtYmVyc2hpcCIsImdldFZlcnNpb25zIiwidmVyc2lvbnMiLCJjb21wb25lbnRXaWxsVW5tb3VudCIsInVucmVnaXN0ZXIiLCJyZW1vdmVMaXN0ZW5lciIsInJlbmRlcklnbm9yZWRVc2VycyIsInVzZXJJZHMiLCJvblVzZXJVbmlnbm9yZWQiLCJrZXkiLCJoZWFkaW5nIiwiU2V0dGluZ3NTdWJzZWN0aW9uVGV4dCIsInJlbmRlck1hbmFnZUludml0ZXMiLCJzaXplIiwib25BY2NlcHRBbGxJbnZpdGVzQ2xpY2tlZCIsImludml0ZWRSb29tcyIsIm9uUmVqZWN0QWxsSW52aXRlc0NsaWNrZWQiLCJzZWN1cmVCYWNrdXAiLCJldmVudEluZGV4IiwiY3Jvc3NTaWduaW5nIiwid2FybmluZyIsInByaXZhdGVTaG91bGRCZUVuY3J5cHRlZCIsInByaXZhY3lTZWN0aW9uIiwiUG9zdGhvZ0FuYWx5dGljcyIsImluc3RhbmNlIiwiaXNFbmFibGVkIiwib25DbGlja0FuYWx5dGljc0xlYXJuTW9yZSIsInNob3dBbmFseXRpY3NMZWFybk1vcmVEaWFsb2ciLCJwcmltYXJ5QnV0dG9uIiwiaGFzQ2FuY2VsIiwiU2V0dGluZ3NTZWN0aW9uIiwiZGVzY3JpcHRpb24iLCJuYW1lIiwibGV2ZWwiLCJTZXR0aW5nTGV2ZWwiLCJBQ0NPVU5UIiwiYWR2YW5jZWRTZWN0aW9uIiwiU2V0dGluZ3NTdG9yZSIsImdldFZhbHVlIiwiVUlGZWF0dXJlIiwiQWR2YW5jZWRTZXR0aW5ncyIsImlnbm9yZVVzZXJzUGFuZWwiLCJpbnZpdGVzUGFuZWwiXSwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvY29tcG9uZW50cy92aWV3cy9zZXR0aW5ncy90YWJzL3VzZXIvU2VjdXJpdHlVc2VyU2V0dGluZ3NUYWIudHN4Il0sInNvdXJjZXNDb250ZW50IjpbIi8qXG5Db3B5cmlnaHQgMjAyNCBOZXcgVmVjdG9yIEx0ZC5cbkNvcHlyaWdodCAyMDE5LTIwMjMgVGhlIE1hdHJpeC5vcmcgRm91bmRhdGlvbiBDLkkuQy5cblxuU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFHUEwtMy4wLW9ubHkgT1IgR1BMLTMuMC1vbmx5XG5QbGVhc2Ugc2VlIExJQ0VOU0UgZmlsZXMgaW4gdGhlIHJlcG9zaXRvcnkgcm9vdCBmb3IgZnVsbCBkZXRhaWxzLlxuKi9cblxuaW1wb3J0IFJlYWN0LCB7IFJlYWN0Tm9kZSB9IGZyb20gXCJyZWFjdFwiO1xuaW1wb3J0IHsgc2xlZXAgfSBmcm9tIFwibWF0cml4LWpzLXNkay9zcmMvdXRpbHNcIjtcbmltcG9ydCB7IFJvb20sIFJvb21FdmVudCB9IGZyb20gXCJtYXRyaXgtanMtc2RrL3NyYy9tYXRyaXhcIjtcbmltcG9ydCB7IEtub3duTWVtYmVyc2hpcCwgTWVtYmVyc2hpcCB9IGZyb20gXCJtYXRyaXgtanMtc2RrL3NyYy90eXBlc1wiO1xuaW1wb3J0IHsgbG9nZ2VyIH0gZnJvbSBcIm1hdHJpeC1qcy1zZGsvc3JjL2xvZ2dlclwiO1xuXG5pbXBvcnQgeyBfdCB9IGZyb20gXCIuLi8uLi8uLi8uLi8uLi9sYW5ndWFnZUhhbmRsZXJcIjtcbmltcG9ydCB7IE1hdHJpeENsaWVudFBlZyB9IGZyb20gXCIuLi8uLi8uLi8uLi8uLi9NYXRyaXhDbGllbnRQZWdcIjtcbmltcG9ydCBBY2Nlc3NpYmxlQnV0dG9uIGZyb20gXCIuLi8uLi8uLi9lbGVtZW50cy9BY2Nlc3NpYmxlQnV0dG9uXCI7XG5pbXBvcnQgZGlzIGZyb20gXCIuLi8uLi8uLi8uLi8uLi9kaXNwYXRjaGVyL2Rpc3BhdGNoZXJcIjtcbmltcG9ydCB7IFNldHRpbmdMZXZlbCB9IGZyb20gXCIuLi8uLi8uLi8uLi8uLi9zZXR0aW5ncy9TZXR0aW5nTGV2ZWxcIjtcbmltcG9ydCBTZWN1cmVCYWNrdXBQYW5lbCBmcm9tIFwiLi4vLi4vU2VjdXJlQmFja3VwUGFuZWxcIjtcbmltcG9ydCBTZXR0aW5nc1N0b3JlIGZyb20gXCIuLi8uLi8uLi8uLi8uLi9zZXR0aW5ncy9TZXR0aW5nc1N0b3JlXCI7XG5pbXBvcnQgeyBVSUZlYXR1cmUgfSBmcm9tIFwiLi4vLi4vLi4vLi4vLi4vc2V0dGluZ3MvVUlGZWF0dXJlXCI7XG5pbXBvcnQgeyBBY3Rpb25QYXlsb2FkIH0gZnJvbSBcIi4uLy4uLy4uLy4uLy4uL2Rpc3BhdGNoZXIvcGF5bG9hZHNcIjtcbmltcG9ydCBDcnlwdG9ncmFwaHlQYW5lbCBmcm9tIFwiLi4vLi4vQ3J5cHRvZ3JhcGh5UGFuZWxcIjtcbmltcG9ydCBTZXR0aW5nc0ZsYWcgZnJvbSBcIi4uLy4uLy4uL2VsZW1lbnRzL1NldHRpbmdzRmxhZ1wiO1xuaW1wb3J0IENyb3NzU2lnbmluZ1BhbmVsIGZyb20gXCIuLi8uLi9Dcm9zc1NpZ25pbmdQYW5lbFwiO1xuaW1wb3J0IEV2ZW50SW5kZXhQYW5lbCBmcm9tIFwiLi4vLi4vRXZlbnRJbmRleFBhbmVsXCI7XG5pbXBvcnQgSW5saW5lU3Bpbm5lciBmcm9tIFwiLi4vLi4vLi4vZWxlbWVudHMvSW5saW5lU3Bpbm5lclwiO1xuaW1wb3J0IHsgUG9zdGhvZ0FuYWx5dGljcyB9IGZyb20gXCIuLi8uLi8uLi8uLi8uLi9Qb3N0aG9nQW5hbHl0aWNzXCI7XG5pbXBvcnQgeyBzaG93RGlhbG9nIGFzIHNob3dBbmFseXRpY3NMZWFybk1vcmVEaWFsb2cgfSBmcm9tIFwiLi4vLi4vLi4vZGlhbG9ncy9BbmFseXRpY3NMZWFybk1vcmVEaWFsb2dcIjtcbmltcG9ydCB7IHByaXZhdGVTaG91bGRCZUVuY3J5cHRlZCB9IGZyb20gXCIuLi8uLi8uLi8uLi8uLi91dGlscy9yb29tc1wiO1xuaW1wb3J0IHR5cGUgeyBJU2VydmVyVmVyc2lvbnMgfSBmcm9tIFwibWF0cml4LWpzLXNkay9zcmMvbWF0cml4XCI7XG5pbXBvcnQgU2V0dGluZ3NUYWIgZnJvbSBcIi4uL1NldHRpbmdzVGFiXCI7XG5pbXBvcnQgeyBTZXR0aW5nc1NlY3Rpb24gfSBmcm9tIFwiLi4vLi4vc2hhcmVkL1NldHRpbmdzU2VjdGlvblwiO1xuaW1wb3J0IFNldHRpbmdzU3Vic2VjdGlvbiwgeyBTZXR0aW5nc1N1YnNlY3Rpb25UZXh0IH0gZnJvbSBcIi4uLy4uL3NoYXJlZC9TZXR0aW5nc1N1YnNlY3Rpb25cIjtcbmltcG9ydCB7IHVzZU93bkRldmljZXMgfSBmcm9tIFwiLi4vLi4vZGV2aWNlcy91c2VPd25EZXZpY2VzXCI7XG5pbXBvcnQgRGlzY292ZXJ5U2V0dGluZ3MgZnJvbSBcIi4uLy4uL2Rpc2NvdmVyeS9EaXNjb3ZlcnlTZXR0aW5nc1wiO1xuaW1wb3J0IFNldEludGVncmF0aW9uTWFuYWdlciBmcm9tIFwiLi4vLi4vU2V0SW50ZWdyYXRpb25NYW5hZ2VyXCI7XG5cbmludGVyZmFjZSBJSWdub3JlZFVzZXJQcm9wcyB7XG4gICAgdXNlcklkOiBzdHJpbmc7XG4gICAgb25Vbmlnbm9yZWQ6ICh1c2VySWQ6IHN0cmluZykgPT4gdm9pZDtcbiAgICBpblByb2dyZXNzOiBib29sZWFuO1xufVxuXG5jb25zdCBEZWh5ZHJhdGVkRGV2aWNlU3RhdHVzOiBSZWFjdC5GQyA9ICgpID0+IHtcbiAgICBjb25zdCB7IGRlaHlkcmF0ZWREZXZpY2VJZCB9ID0gdXNlT3duRGV2aWNlcygpO1xuXG4gICAgaWYgKGRlaHlkcmF0ZWREZXZpY2VJZCkge1xuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJteF9TZXR0aW5nc1N1YnNlY3Rpb25fY29udGVudFwiPlxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3NOYW1lPVwibXhfU2V0dGluZ3NGbGFnX2xhYmVsXCI+e190KFwic2V0dGluZ3N8c2VjdXJpdHl8ZGVoeWRyYXRlZF9kZXZpY2VfZW5hYmxlZFwiKX08L2Rpdj5cbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzTmFtZT1cIm14X1NldHRpbmdzU3Vic2VjdGlvbl90ZXh0XCI+XG4gICAgICAgICAgICAgICAgICAgIHtfdChcInNldHRpbmdzfHNlY3VyaXR5fGRlaHlkcmF0ZWRfZGV2aWNlX2Rlc2NyaXB0aW9uXCIpfVxuICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxufTtcblxuZXhwb3J0IGNsYXNzIElnbm9yZWRVc2VyIGV4dGVuZHMgUmVhY3QuQ29tcG9uZW50PElJZ25vcmVkVXNlclByb3BzPiB7XG4gICAgcHJpdmF0ZSBvblVuaWdub3JlQ2xpY2tlZCA9ICgpOiB2b2lkID0+IHtcbiAgICAgICAgdGhpcy5wcm9wcy5vblVuaWdub3JlZCh0aGlzLnByb3BzLnVzZXJJZCk7XG4gICAgfTtcblxuICAgIHB1YmxpYyByZW5kZXIoKTogUmVhY3QuUmVhY3ROb2RlIHtcbiAgICAgICAgY29uc3QgaWQgPSBgbXhfU2VjdXJpdHlVc2VyU2V0dGluZ3NUYWJfaWdub3JlZFVzZXJfJHt0aGlzLnByb3BzLnVzZXJJZH1gO1xuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJteF9TZWN1cml0eVVzZXJTZXR0aW5nc1RhYl9pZ25vcmVkVXNlclwiPlxuICAgICAgICAgICAgICAgIDxBY2Nlc3NpYmxlQnV0dG9uXG4gICAgICAgICAgICAgICAgICAgIG9uQ2xpY2s9e3RoaXMub25Vbmlnbm9yZUNsaWNrZWR9XG4gICAgICAgICAgICAgICAgICAgIGtpbmQ9XCJwcmltYXJ5X3NtXCJcbiAgICAgICAgICAgICAgICAgICAgYXJpYS1kZXNjcmliZWRieT17aWR9XG4gICAgICAgICAgICAgICAgICAgIGRpc2FibGVkPXt0aGlzLnByb3BzLmluUHJvZ3Jlc3N9XG4gICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgICB7X3QoXCJhY3Rpb258dW5pZ25vcmVcIil9XG4gICAgICAgICAgICAgICAgPC9BY2Nlc3NpYmxlQnV0dG9uPlxuICAgICAgICAgICAgICAgIDxzcGFuIGlkPXtpZH0+e3RoaXMucHJvcHMudXNlcklkfTwvc3Bhbj5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICApO1xuICAgIH1cbn1cblxuaW50ZXJmYWNlIElQcm9wcyB7XG4gICAgY2xvc2VTZXR0aW5nc0ZuOiAoKSA9PiB2b2lkO1xufVxuXG5pbnRlcmZhY2UgSVN0YXRlIHtcbiAgICBpZ25vcmVkVXNlcklkczogc3RyaW5nW107XG4gICAgd2FpdGluZ1VuaWdub3JlZDogc3RyaW5nW107XG4gICAgbWFuYWdpbmdJbnZpdGVzOiBib29sZWFuO1xuICAgIGludml0ZWRSb29tSWRzOiBTZXQ8c3RyaW5nPjtcbiAgICB2ZXJzaW9ucz86IElTZXJ2ZXJWZXJzaW9ucztcbn1cblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgU2VjdXJpdHlVc2VyU2V0dGluZ3NUYWIgZXh0ZW5kcyBSZWFjdC5Db21wb25lbnQ8SVByb3BzLCBJU3RhdGU+IHtcbiAgICBwcml2YXRlIGRpc3BhdGNoZXJSZWY/OiBzdHJpbmc7XG5cbiAgICBwdWJsaWMgY29uc3RydWN0b3IocHJvcHM6IElQcm9wcykge1xuICAgICAgICBzdXBlcihwcm9wcyk7XG5cbiAgICAgICAgLy8gR2V0IHJvb21zIHdlJ3JlIGludml0ZWQgdG9cbiAgICAgICAgY29uc3QgaW52aXRlZFJvb21JZHMgPSBuZXcgU2V0KHRoaXMuZ2V0SW52aXRlZFJvb21zKCkubWFwKChyb29tKSA9PiByb29tLnJvb21JZCkpO1xuXG4gICAgICAgIHRoaXMuc3RhdGUgPSB7XG4gICAgICAgICAgICBpZ25vcmVkVXNlcklkczogTWF0cml4Q2xpZW50UGVnLnNhZmVHZXQoKS5nZXRJZ25vcmVkVXNlcnMoKSxcbiAgICAgICAgICAgIHdhaXRpbmdVbmlnbm9yZWQ6IFtdLFxuICAgICAgICAgICAgbWFuYWdpbmdJbnZpdGVzOiBmYWxzZSxcbiAgICAgICAgICAgIGludml0ZWRSb29tSWRzLFxuICAgICAgICB9O1xuICAgIH1cblxuICAgIHByaXZhdGUgb25BY3Rpb24gPSAoeyBhY3Rpb24gfTogQWN0aW9uUGF5bG9hZCk6IHZvaWQgPT4ge1xuICAgICAgICBpZiAoYWN0aW9uID09PSBcImlnbm9yZV9zdGF0ZV9jaGFuZ2VkXCIpIHtcbiAgICAgICAgICAgIGNvbnN0IGlnbm9yZWRVc2VySWRzID0gTWF0cml4Q2xpZW50UGVnLnNhZmVHZXQoKS5nZXRJZ25vcmVkVXNlcnMoKTtcbiAgICAgICAgICAgIGNvbnN0IG5ld1dhaXRpbmdVbmlnbm9yZWQgPSB0aGlzLnN0YXRlLndhaXRpbmdVbmlnbm9yZWQuZmlsdGVyKChlKSA9PiBpZ25vcmVkVXNlcklkcy5pbmNsdWRlcyhlKSk7XG4gICAgICAgICAgICB0aGlzLnNldFN0YXRlKHsgaWdub3JlZFVzZXJJZHMsIHdhaXRpbmdVbmlnbm9yZWQ6IG5ld1dhaXRpbmdVbmlnbm9yZWQgfSk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgcHVibGljIGNvbXBvbmVudERpZE1vdW50KCk6IHZvaWQge1xuICAgICAgICB0aGlzLmRpc3BhdGNoZXJSZWYgPSBkaXMucmVnaXN0ZXIodGhpcy5vbkFjdGlvbik7XG4gICAgICAgIE1hdHJpeENsaWVudFBlZy5zYWZlR2V0KCkub24oUm9vbUV2ZW50Lk15TWVtYmVyc2hpcCwgdGhpcy5vbk15TWVtYmVyc2hpcCk7XG4gICAgICAgIE1hdHJpeENsaWVudFBlZy5zYWZlR2V0KClcbiAgICAgICAgICAgIC5nZXRWZXJzaW9ucygpXG4gICAgICAgICAgICAudGhlbigodmVyc2lvbnMpID0+IHRoaXMuc2V0U3RhdGUoeyB2ZXJzaW9ucyB9KSk7XG4gICAgfVxuXG4gICAgcHVibGljIGNvbXBvbmVudFdpbGxVbm1vdW50KCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy5kaXNwYXRjaGVyUmVmKSBkaXMudW5yZWdpc3Rlcih0aGlzLmRpc3BhdGNoZXJSZWYpO1xuICAgICAgICBNYXRyaXhDbGllbnRQZWcuc2FmZUdldCgpLnJlbW92ZUxpc3RlbmVyKFJvb21FdmVudC5NeU1lbWJlcnNoaXAsIHRoaXMub25NeU1lbWJlcnNoaXApO1xuICAgIH1cblxuICAgIHByaXZhdGUgb25NeU1lbWJlcnNoaXAgPSAocm9vbTogUm9vbSwgbWVtYmVyc2hpcDogTWVtYmVyc2hpcCk6IHZvaWQgPT4ge1xuICAgICAgICBpZiAocm9vbS5pc1NwYWNlUm9vbSgpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAobWVtYmVyc2hpcCA9PT0gS25vd25NZW1iZXJzaGlwLkludml0ZSkge1xuICAgICAgICAgICAgdGhpcy5hZGRJbnZpdGVkUm9vbShyb29tKTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLnN0YXRlLmludml0ZWRSb29tSWRzLmhhcyhyb29tLnJvb21JZCkpIHtcbiAgICAgICAgICAgIC8vIFRoZSB1c2VyIGlzbid0IGludml0ZWQgYW55bW9yZVxuICAgICAgICAgICAgdGhpcy5yZW1vdmVJbnZpdGVkUm9vbShyb29tLnJvb21JZCk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgcHJpdmF0ZSBhZGRJbnZpdGVkUm9vbSA9IChyb29tOiBSb29tKTogdm9pZCA9PiB7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoKHsgaW52aXRlZFJvb21JZHMgfSkgPT4gKHtcbiAgICAgICAgICAgIGludml0ZWRSb29tSWRzOiBuZXcgU2V0KGludml0ZWRSb29tSWRzKS5hZGQocm9vbS5yb29tSWQpLFxuICAgICAgICB9KSk7XG4gICAgfTtcblxuICAgIHByaXZhdGUgcmVtb3ZlSW52aXRlZFJvb20gPSAocm9vbUlkOiBzdHJpbmcpOiB2b2lkID0+IHtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSgoeyBpbnZpdGVkUm9vbUlkcyB9KSA9PiB7XG4gICAgICAgICAgICBjb25zdCBuZXdJbnZpdGVkUm9vbUlkcyA9IG5ldyBTZXQoaW52aXRlZFJvb21JZHMpO1xuICAgICAgICAgICAgbmV3SW52aXRlZFJvb21JZHMuZGVsZXRlKHJvb21JZCk7XG5cbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgaW52aXRlZFJvb21JZHM6IG5ld0ludml0ZWRSb29tSWRzLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIHByaXZhdGUgb25Vc2VyVW5pZ25vcmVkID0gYXN5bmMgKHVzZXJJZDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gICAgICAgIGNvbnN0IHsgaWdub3JlZFVzZXJJZHMsIHdhaXRpbmdVbmlnbm9yZWQgfSA9IHRoaXMuc3RhdGU7XG4gICAgICAgIGNvbnN0IGN1cnJlbnRseUlnbm9yZWRVc2VySWRzID0gaWdub3JlZFVzZXJJZHMuZmlsdGVyKChlKSA9PiAhd2FpdGluZ1VuaWdub3JlZC5pbmNsdWRlcyhlKSk7XG5cbiAgICAgICAgY29uc3QgaW5kZXggPSBjdXJyZW50bHlJZ25vcmVkVXNlcklkcy5pbmRleE9mKHVzZXJJZCk7XG4gICAgICAgIGlmIChpbmRleCAhPT0gLTEpIHtcbiAgICAgICAgICAgIGN1cnJlbnRseUlnbm9yZWRVc2VySWRzLnNwbGljZShpbmRleCwgMSk7XG4gICAgICAgICAgICB0aGlzLnNldFN0YXRlKCh7IHdhaXRpbmdVbmlnbm9yZWQgfSkgPT4gKHsgd2FpdGluZ1VuaWdub3JlZDogWy4uLndhaXRpbmdVbmlnbm9yZWQsIHVzZXJJZF0gfSkpO1xuICAgICAgICAgICAgTWF0cml4Q2xpZW50UGVnLnNhZmVHZXQoKS5zZXRJZ25vcmVkVXNlcnMoY3VycmVudGx5SWdub3JlZFVzZXJJZHMpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIHByaXZhdGUgZ2V0SW52aXRlZFJvb21zID0gKCk6IFJvb21bXSA9PiB7XG4gICAgICAgIHJldHVybiBNYXRyaXhDbGllbnRQZWcuc2FmZUdldCgpXG4gICAgICAgICAgICAuZ2V0Um9vbXMoKVxuICAgICAgICAgICAgLmZpbHRlcigocikgPT4ge1xuICAgICAgICAgICAgICAgIHJldHVybiByLmhhc01lbWJlcnNoaXBTdGF0ZShNYXRyaXhDbGllbnRQZWcuc2FmZUdldCgpLmdldFVzZXJJZCgpISwgS25vd25NZW1iZXJzaGlwLkludml0ZSk7XG4gICAgICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgcHJpdmF0ZSBtYW5hZ2VJbnZpdGVzID0gYXN5bmMgKGFjY2VwdDogYm9vbGVhbik6IFByb21pc2U8dm9pZD4gPT4ge1xuICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgIG1hbmFnaW5nSW52aXRlczogdHJ1ZSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gaXRlcmF0ZSB3aXRoIGEgbm9ybWFsIGZvciBsb29wIGluIG9yZGVyIHRvIHJldHJ5IG9uIGFjdGlvbiBmYWlsdXJlXG4gICAgICAgIGNvbnN0IGludml0ZWRSb29tSWRzVmFsdWVzID0gQXJyYXkuZnJvbSh0aGlzLnN0YXRlLmludml0ZWRSb29tSWRzKTtcblxuICAgICAgICAvLyBFeGVjdXRlIGFsbCBhY2NlcHRhbmNlcy9yZWplY3Rpb25zIHNlcXVlbnRpYWxseVxuICAgICAgICBjb25zdCBjbGkgPSBNYXRyaXhDbGllbnRQZWcuc2FmZUdldCgpO1xuICAgICAgICBjb25zdCBhY3Rpb24gPSBhY2NlcHQgPyBjbGkuam9pblJvb20uYmluZChjbGkpIDogY2xpLmxlYXZlLmJpbmQoY2xpKTtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBpbnZpdGVkUm9vbUlkc1ZhbHVlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgY29uc3Qgcm9vbUlkID0gaW52aXRlZFJvb21JZHNWYWx1ZXNbaV07XG5cbiAgICAgICAgICAgIC8vIEFjY2VwdC9yZWplY3QgaW52aXRlXG4gICAgICAgICAgICBhd2FpdCBhY3Rpb24ocm9vbUlkKS50aGVuKFxuICAgICAgICAgICAgICAgICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgLy8gTm8gZXJyb3IsIHVwZGF0ZSBpbnZpdGVkIHJvb21zIGJ1dHRvblxuICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbW92ZUludml0ZWRSb29tKHJvb21JZCk7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBhc3luYyAoZSk6IFByb21pc2U8dm9pZD4gPT4ge1xuICAgICAgICAgICAgICAgICAgICAvLyBBY3Rpb24gZmFpbHVyZVxuICAgICAgICAgICAgICAgICAgICBpZiAoZS5lcnJjb2RlID09PSBcIk1fTElNSVRfRVhDRUVERURcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gQWRkIGEgZGVsYXkgYmV0d2VlbiBlYWNoIGludml0ZSBjaGFuZ2UgaW4gb3JkZXIgdG8gYXZvaWQgcmF0ZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gbGltaXRpbmcgYnkgdGhlIHNlcnZlci5cbiAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IHNsZWVwKGUucmV0cnlfYWZ0ZXJfbXMgfHwgMjUwMCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFJlZG8gbGFzdCBhY3Rpb25cbiAgICAgICAgICAgICAgICAgICAgICAgIGktLTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFByaW50IG91dCBlcnJvciB3aXRoIGpvaW5pbmcvbGVhdmluZyByb29tXG4gICAgICAgICAgICAgICAgICAgICAgICBsb2dnZXIud2FybihlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICBtYW5hZ2luZ0ludml0ZXM6IGZhbHNlLFxuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgcHJpdmF0ZSBvbkFjY2VwdEFsbEludml0ZXNDbGlja2VkID0gKCk6IHZvaWQgPT4ge1xuICAgICAgICB0aGlzLm1hbmFnZUludml0ZXModHJ1ZSk7XG4gICAgfTtcblxuICAgIHByaXZhdGUgb25SZWplY3RBbGxJbnZpdGVzQ2xpY2tlZCA9ICgpOiB2b2lkID0+IHtcbiAgICAgICAgdGhpcy5tYW5hZ2VJbnZpdGVzKGZhbHNlKTtcbiAgICB9O1xuXG4gICAgcHJpdmF0ZSByZW5kZXJJZ25vcmVkVXNlcnMoKTogSlNYLkVsZW1lbnQge1xuICAgICAgICBjb25zdCB7IHdhaXRpbmdVbmlnbm9yZWQsIGlnbm9yZWRVc2VySWRzIH0gPSB0aGlzLnN0YXRlO1xuXG4gICAgICAgIGNvbnN0IHVzZXJJZHMgPSAhaWdub3JlZFVzZXJJZHM/Lmxlbmd0aFxuICAgICAgICAgICAgPyBfdChcInNldHRpbmdzfHNlY3VyaXR5fGlnbm9yZV91c2Vyc19lbXB0eVwiKVxuICAgICAgICAgICAgOiBpZ25vcmVkVXNlcklkcy5tYXAoKHUpID0+IHtcbiAgICAgICAgICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAgICAgICAgICAgPElnbm9yZWRVc2VyXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHVzZXJJZD17dX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgb25Vbmlnbm9yZWQ9e3RoaXMub25Vc2VyVW5pZ25vcmVkfVxuICAgICAgICAgICAgICAgICAgICAgICAgICBrZXk9e3V9XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGluUHJvZ3Jlc3M9e3dhaXRpbmdVbmlnbm9yZWQuaW5jbHVkZXModSl9XG4gICAgICAgICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICA8U2V0dGluZ3NTdWJzZWN0aW9uIGhlYWRpbmc9e190KFwic2V0dGluZ3N8c2VjdXJpdHl8aWdub3JlX3VzZXJzX3NlY3Rpb25cIil9PlxuICAgICAgICAgICAgICAgIDxTZXR0aW5nc1N1YnNlY3Rpb25UZXh0Pnt1c2VySWRzfTwvU2V0dGluZ3NTdWJzZWN0aW9uVGV4dD5cbiAgICAgICAgICAgIDwvU2V0dGluZ3NTdWJzZWN0aW9uPlxuICAgICAgICApO1xuICAgIH1cblxuICAgIHByaXZhdGUgcmVuZGVyTWFuYWdlSW52aXRlcygpOiBSZWFjdE5vZGUge1xuICAgICAgICBjb25zdCB7IGludml0ZWRSb29tSWRzIH0gPSB0aGlzLnN0YXRlO1xuXG4gICAgICAgIGlmIChpbnZpdGVkUm9vbUlkcy5zaXplID09PSAwKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICA8U2V0dGluZ3NTdWJzZWN0aW9uIGhlYWRpbmc9e190KFwic2V0dGluZ3N8c2VjdXJpdHl8YnVsa19vcHRpb25zX3NlY3Rpb25cIil9PlxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3NOYW1lPVwibXhfU2VjdXJpdHlVc2VyU2V0dGluZ3NUYWJfYnVsa09wdGlvbnNcIj5cbiAgICAgICAgICAgICAgICAgICAgPEFjY2Vzc2libGVCdXR0b25cbiAgICAgICAgICAgICAgICAgICAgICAgIG9uQ2xpY2s9e3RoaXMub25BY2NlcHRBbGxJbnZpdGVzQ2xpY2tlZH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGtpbmQ9XCJwcmltYXJ5X291dGxpbmVcIlxuICAgICAgICAgICAgICAgICAgICAgICAgZGlzYWJsZWQ9e3RoaXMuc3RhdGUubWFuYWdpbmdJbnZpdGVzfVxuICAgICAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgICAgICB7X3QoXCJzZXR0aW5nc3xzZWN1cml0eXxidWxrX29wdGlvbnNfYWNjZXB0X2FsbF9pbnZpdGVzXCIsIHsgaW52aXRlZFJvb21zOiBpbnZpdGVkUm9vbUlkcy5zaXplIH0pfVxuICAgICAgICAgICAgICAgICAgICA8L0FjY2Vzc2libGVCdXR0b24+XG4gICAgICAgICAgICAgICAgICAgIDxBY2Nlc3NpYmxlQnV0dG9uXG4gICAgICAgICAgICAgICAgICAgICAgICBvbkNsaWNrPXt0aGlzLm9uUmVqZWN0QWxsSW52aXRlc0NsaWNrZWR9XG4gICAgICAgICAgICAgICAgICAgICAgICBraW5kPVwiZGFuZ2VyX291dGxpbmVcIlxuICAgICAgICAgICAgICAgICAgICAgICAgZGlzYWJsZWQ9e3RoaXMuc3RhdGUubWFuYWdpbmdJbnZpdGVzfVxuICAgICAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgICAgICB7X3QoXCJzZXR0aW5nc3xzZWN1cml0eXxidWxrX29wdGlvbnNfcmVqZWN0X2FsbF9pbnZpdGVzXCIsIHsgaW52aXRlZFJvb21zOiBpbnZpdGVkUm9vbUlkcy5zaXplIH0pfVxuICAgICAgICAgICAgICAgICAgICA8L0FjY2Vzc2libGVCdXR0b24+XG4gICAgICAgICAgICAgICAgICAgIHt0aGlzLnN0YXRlLm1hbmFnaW5nSW52aXRlcyA/IDxJbmxpbmVTcGlubmVyIC8+IDogPGRpdiAvPn1cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDwvU2V0dGluZ3NTdWJzZWN0aW9uPlxuICAgICAgICApO1xuICAgIH1cblxuICAgIHB1YmxpYyByZW5kZXIoKTogUmVhY3QuUmVhY3ROb2RlIHtcbiAgICAgICAgY29uc3Qgc2VjdXJlQmFja3VwID0gKFxuICAgICAgICAgICAgPFNldHRpbmdzU3Vic2VjdGlvbiBoZWFkaW5nPXtfdChcImNvbW1vbnxzZWN1cmVfYmFja3VwXCIpfT5cbiAgICAgICAgICAgICAgICA8U2VjdXJlQmFja3VwUGFuZWwgLz5cbiAgICAgICAgICAgICAgICA8RGVoeWRyYXRlZERldmljZVN0YXR1cyAvPlxuICAgICAgICAgICAgPC9TZXR0aW5nc1N1YnNlY3Rpb24+XG4gICAgICAgICk7XG5cbiAgICAgICAgY29uc3QgZXZlbnRJbmRleCA9IChcbiAgICAgICAgICAgIDxTZXR0aW5nc1N1YnNlY3Rpb24gaGVhZGluZz17X3QoXCJzZXR0aW5nc3xzZWN1cml0eXxtZXNzYWdlX3NlYXJjaF9zZWN0aW9uXCIpfT5cbiAgICAgICAgICAgICAgICA8RXZlbnRJbmRleFBhbmVsIC8+XG4gICAgICAgICAgICA8L1NldHRpbmdzU3Vic2VjdGlvbj5cbiAgICAgICAgKTtcblxuICAgICAgICAvLyBYWFg6IFRoZXJlJ3Mgbm8gc3VjaCBwYW5lbCBpbiB0aGUgY3VycmVudCBjcm9zcy1zaWduaW5nIGRlc2lnbnMsIGJ1dFxuICAgICAgICAvLyBpdCdzIHVzZWZ1bCB0byBoYXZlIGZvciB0ZXN0aW5nIHRoZSBmZWF0dXJlLiBJZiB0aGVyZSdzIG5vIGludGVyZXN0XG4gICAgICAgIC8vIGluIGhhdmluZyBhZHZhbmNlZCBkZXRhaWxzIGhlcmUgb25jZSBhbGwgZmxvd3MgYXJlIGltcGxlbWVudGVkLCB3ZVxuICAgICAgICAvLyBjYW4gcmVtb3ZlIHRoaXMuXG4gICAgICAgIGNvbnN0IGNyb3NzU2lnbmluZyA9IChcbiAgICAgICAgICAgIDxTZXR0aW5nc1N1YnNlY3Rpb24gaGVhZGluZz17X3QoXCJjb21tb258Y3Jvc3Nfc2lnbmluZ1wiKX0+XG4gICAgICAgICAgICAgICAgPENyb3NzU2lnbmluZ1BhbmVsIC8+XG4gICAgICAgICAgICA8L1NldHRpbmdzU3Vic2VjdGlvbj5cbiAgICAgICAgKTtcblxuICAgICAgICBsZXQgd2FybmluZztcbiAgICAgICAgaWYgKCFwcml2YXRlU2hvdWxkQmVFbmNyeXB0ZWQoTWF0cml4Q2xpZW50UGVnLnNhZmVHZXQoKSkpIHtcbiAgICAgICAgICAgIHdhcm5pbmcgPSAoXG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJteF9TZWN1cml0eVVzZXJTZXR0aW5nc1RhYl93YXJuaW5nXCI+XG4gICAgICAgICAgICAgICAgICAgIHtfdChcInNldHRpbmdzfHNlY3VyaXR5fGUyZWVfZGVmYXVsdF9kaXNhYmxlZF93YXJuaW5nXCIpfVxuICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBwcml2YWN5U2VjdGlvbjtcbiAgICAgICAgaWYgKFBvc3Rob2dBbmFseXRpY3MuaW5zdGFuY2UuaXNFbmFibGVkKCkpIHtcbiAgICAgICAgICAgIGNvbnN0IG9uQ2xpY2tBbmFseXRpY3NMZWFybk1vcmUgPSAoKTogdm9pZCA9PiB7XG4gICAgICAgICAgICAgICAgc2hvd0FuYWx5dGljc0xlYXJuTW9yZURpYWxvZyh7XG4gICAgICAgICAgICAgICAgICAgIHByaW1hcnlCdXR0b246IF90KFwiYWN0aW9ufG9rXCIpLFxuICAgICAgICAgICAgICAgICAgICBoYXNDYW5jZWw6IGZhbHNlLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHByaXZhY3lTZWN0aW9uID0gKFxuICAgICAgICAgICAgICAgIDxTZXR0aW5nc1NlY3Rpb24gaGVhZGluZz17X3QoXCJjb21tb258cHJpdmFjeVwiKX0+XG4gICAgICAgICAgICAgICAgICAgIDxEaXNjb3ZlcnlTZXR0aW5ncyAvPlxuICAgICAgICAgICAgICAgICAgICA8U2V0dGluZ3NTdWJzZWN0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICBoZWFkaW5nPXtfdChcImNvbW1vbnxhbmFseXRpY3NcIil9XG4gICAgICAgICAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbj17X3QoXCJzZXR0aW5nc3xzZWN1cml0eXxhbmFseXRpY3NfZGVzY3JpcHRpb25cIil9XG4gICAgICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxBY2Nlc3NpYmxlQnV0dG9uIGtpbmQ9XCJsaW5rXCIgb25DbGljaz17b25DbGlja0FuYWx5dGljc0xlYXJuTW9yZX0+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAge190KFwiYWN0aW9ufGxlYXJuX21vcmVcIil9XG4gICAgICAgICAgICAgICAgICAgICAgICA8L0FjY2Vzc2libGVCdXR0b24+XG4gICAgICAgICAgICAgICAgICAgICAgICB7UG9zdGhvZ0FuYWx5dGljcy5pbnN0YW5jZS5pc0VuYWJsZWQoKSAmJiAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPFNldHRpbmdzRmxhZyBuYW1lPVwicHNldWRvbnltb3VzQW5hbHl0aWNzT3B0SW5cIiBsZXZlbD17U2V0dGluZ0xldmVsLkFDQ09VTlR9IC8+XG4gICAgICAgICAgICAgICAgICAgICAgICApfVxuICAgICAgICAgICAgICAgICAgICA8L1NldHRpbmdzU3Vic2VjdGlvbj5cbiAgICAgICAgICAgICAgICAgICAgPFNldHRpbmdzU3Vic2VjdGlvbiBoZWFkaW5nPXtfdChcInNldHRpbmdzfHNlc3Npb25zfHRpdGxlXCIpfT5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxTZXR0aW5nc0ZsYWcgbmFtZT1cImRldmljZUNsaWVudEluZm9ybWF0aW9uT3B0SW5cIiBsZXZlbD17U2V0dGluZ0xldmVsLkFDQ09VTlR9IC8+XG4gICAgICAgICAgICAgICAgICAgIDwvU2V0dGluZ3NTdWJzZWN0aW9uPlxuICAgICAgICAgICAgICAgIDwvU2V0dGluZ3NTZWN0aW9uPlxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBhZHZhbmNlZFNlY3Rpb247XG4gICAgICAgIGlmIChTZXR0aW5nc1N0b3JlLmdldFZhbHVlKFVJRmVhdHVyZS5BZHZhbmNlZFNldHRpbmdzKSkge1xuICAgICAgICAgICAgY29uc3QgaWdub3JlVXNlcnNQYW5lbCA9IHRoaXMucmVuZGVySWdub3JlZFVzZXJzKCk7XG4gICAgICAgICAgICBjb25zdCBpbnZpdGVzUGFuZWwgPSB0aGlzLnJlbmRlck1hbmFnZUludml0ZXMoKTtcbiAgICAgICAgICAgIC8vIG9ubHkgc2hvdyB0aGUgc2VjdGlvbiBpZiB0aGVyZSdzIHNvbWV0aGluZyB0byBzaG93XG4gICAgICAgICAgICBpZiAoaWdub3JlVXNlcnNQYW5lbCB8fCBpbnZpdGVzUGFuZWwpIHtcbiAgICAgICAgICAgICAgICBhZHZhbmNlZFNlY3Rpb24gPSAoXG4gICAgICAgICAgICAgICAgICAgIDxTZXR0aW5nc1NlY3Rpb24gaGVhZGluZz17X3QoXCJjb21tb258YWR2YW5jZWRcIil9PlxuICAgICAgICAgICAgICAgICAgICAgICAge2lnbm9yZVVzZXJzUGFuZWx9XG4gICAgICAgICAgICAgICAgICAgICAgICB7aW52aXRlc1BhbmVsfVxuICAgICAgICAgICAgICAgICAgICA8L1NldHRpbmdzU2VjdGlvbj5cbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIDxTZXR0aW5nc1RhYj5cbiAgICAgICAgICAgICAgICB7d2FybmluZ31cbiAgICAgICAgICAgICAgICA8U2V0SW50ZWdyYXRpb25NYW5hZ2VyIC8+XG4gICAgICAgICAgICAgICAgPFNldHRpbmdzU2VjdGlvbiBoZWFkaW5nPXtfdChcInNldHRpbmdzfHNlY3VyaXR5fGVuY3J5cHRpb25fc2VjdGlvblwiKX0+XG4gICAgICAgICAgICAgICAgICAgIHtzZWN1cmVCYWNrdXB9XG4gICAgICAgICAgICAgICAgICAgIHtldmVudEluZGV4fVxuICAgICAgICAgICAgICAgICAgICB7Y3Jvc3NTaWduaW5nfVxuICAgICAgICAgICAgICAgICAgICA8Q3J5cHRvZ3JhcGh5UGFuZWwgLz5cbiAgICAgICAgICAgICAgICA8L1NldHRpbmdzU2VjdGlvbj5cbiAgICAgICAgICAgICAgICB7cHJpdmFjeVNlY3Rpb259XG4gICAgICAgICAgICAgICAge2FkdmFuY2VkU2VjdGlvbn1cbiAgICAgICAgICAgIDwvU2V0dGluZ3NUYWI+XG4gICAgICAgICk7XG4gICAgfVxufVxuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7OztBQVFBLElBQUFBLE1BQUEsR0FBQUMsc0JBQUEsQ0FBQUMsT0FBQTtBQUNBLElBQUFDLE1BQUEsR0FBQUQsT0FBQTtBQUNBLElBQUFFLE9BQUEsR0FBQUYsT0FBQTtBQUNBLElBQUFHLE1BQUEsR0FBQUgsT0FBQTtBQUNBLElBQUFJLE9BQUEsR0FBQUosT0FBQTtBQUVBLElBQUFLLGdCQUFBLEdBQUFMLE9BQUE7QUFDQSxJQUFBTSxnQkFBQSxHQUFBTixPQUFBO0FBQ0EsSUFBQU8saUJBQUEsR0FBQVIsc0JBQUEsQ0FBQUMsT0FBQTtBQUNBLElBQUFRLFdBQUEsR0FBQVQsc0JBQUEsQ0FBQUMsT0FBQTtBQUNBLElBQUFTLGFBQUEsR0FBQVQsT0FBQTtBQUNBLElBQUFVLGtCQUFBLEdBQUFYLHNC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