matrix-react-sdk
Version:
SDK for matrix.org using React
316 lines (312 loc) • 56 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
var _react = _interopRequireWildcard(require("react"));
var _matrix = require("matrix-js-sdk/src/matrix");
var _logger = require("matrix-js-sdk/src/logger");
var _languageHandler = require("../../../../../languageHandler");
var _Modal = _interopRequireDefault(require("../../../../../Modal"));
var _SettingsSubsection = _interopRequireDefault(require("../../shared/SettingsSubsection"));
var _SetupEncryptionDialog = _interopRequireDefault(require("../../../dialogs/security/SetupEncryptionDialog"));
var _VerificationRequestDialog = _interopRequireDefault(require("../../../dialogs/VerificationRequestDialog"));
var _LogoutDialog = _interopRequireDefault(require("../../../dialogs/LogoutDialog"));
var _useOwnDevices = require("../../devices/useOwnDevices");
var _FilteredDeviceList = require("../../devices/FilteredDeviceList");
var _CurrentDeviceSection = _interopRequireDefault(require("../../devices/CurrentDeviceSection"));
var _SecurityRecommendations = _interopRequireDefault(require("../../devices/SecurityRecommendations"));
var _deleteDevices = require("../../devices/deleteDevices");
var _SettingsTab = _interopRequireDefault(require("../SettingsTab"));
var _LoginWithQRSection = _interopRequireDefault(require("../../devices/LoginWithQRSection"));
var _LoginWithQRTypes = require("../../../auth/LoginWithQR-types");
var _useAsyncMemo = require("../../../../../hooks/useAsyncMemo");
var _QuestionDialog = _interopRequireDefault(require("../../../dialogs/QuestionDialog"));
var _OtherSessionsSectionHeading = require("../../devices/OtherSessionsSectionHeading");
var _SettingsSection = require("../../shared/SettingsSection");
var _OidcLogoutDialog = require("../../../dialogs/oidc/OidcLogoutDialog");
var _SDKContext = require("../../../../../contexts/SDKContext");
var _Spinner = _interopRequireDefault(require("../../../elements/Spinner"));
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
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 2022 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.
*/
// We import `LoginWithQR` asynchronously to avoid importing the entire Rust Crypto WASM into the main bundle.
const LoginWithQR = /*#__PURE__*/(0, _react.lazy)(() => Promise.resolve().then(() => _interopRequireWildcard(require("../../../auth/LoginWithQR"))));
const confirmSignOut = async sessionsToSignOutCount => {
const {
finished
} = _Modal.default.createDialog(_QuestionDialog.default, {
title: (0, _languageHandler._t)("action|sign_out"),
description: /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("p", null, (0, _languageHandler._t)("settings|sessions|sign_out_confirm_description", {
count: sessionsToSignOutCount
}))),
cancelButton: (0, _languageHandler._t)("action|cancel"),
button: (0, _languageHandler._t)("action|sign_out")
});
const [confirmed] = await finished;
return !!confirmed;
};
const confirmDelegatedAuthSignOut = async (delegatedAuthAccountUrl, deviceId) => {
const {
finished
} = _Modal.default.createDialog(_OidcLogoutDialog.OidcLogoutDialog, {
deviceId,
delegatedAuthAccountUrl
});
const [confirmed] = await finished;
return !!confirmed;
};
const useSignOut = (matrixClient, onSignoutResolvedCallback, delegatedAuthAccountUrl) => {
const [signingOutDeviceIds, setSigningOutDeviceIds] = (0, _react.useState)([]);
const onSignOutCurrentDevice = () => {
_Modal.default.createDialog(_LogoutDialog.default, {},
// props,
undefined,
// className
false,
// isPriority
true // isStatic
);
};
const onSignOutOtherDevices = async deviceIds => {
if (!deviceIds.length) {
return;
}
// we can only sign out exactly one OIDC-aware device at a time
// we should not encounter this
if (delegatedAuthAccountUrl && deviceIds.length !== 1) {
_logger.logger.warn("Unexpectedly tried to sign out multiple OIDC-aware devices.");
return;
}
// delegated auth logout flow confirms and signs out together
// so only confirm if we are NOT doing a delegated auth sign out
if (!delegatedAuthAccountUrl) {
const userConfirmedSignout = await confirmSignOut(deviceIds.length);
if (!userConfirmedSignout) {
return;
}
}
try {
setSigningOutDeviceIds([...signingOutDeviceIds, ...deviceIds]);
const onSignOutFinished = async success => {
if (success) {
await onSignoutResolvedCallback();
}
setSigningOutDeviceIds(signingOutDeviceIds.filter(deviceId => !deviceIds.includes(deviceId)));
};
if (delegatedAuthAccountUrl) {
const [deviceId] = deviceIds;
try {
setSigningOutDeviceIds([...signingOutDeviceIds, deviceId]);
const success = await confirmDelegatedAuthSignOut(delegatedAuthAccountUrl, deviceId);
await onSignOutFinished(success);
} catch (error) {
_logger.logger.error("Error deleting OIDC-aware sessions", error);
}
} else {
await (0, _deleteDevices.deleteDevicesWithInteractiveAuth)(matrixClient, deviceIds, onSignOutFinished);
}
} catch (error) {
_logger.logger.error("Error deleting sessions", error);
setSigningOutDeviceIds(signingOutDeviceIds.filter(deviceId => !deviceIds.includes(deviceId)));
}
};
return {
onSignOutCurrentDevice,
onSignOutOtherDevices,
signingOutDeviceIds
};
};
const SessionManagerTab = ({
showMsc4108QrCode
}) => {
const {
devices,
dehydratedDeviceId,
pushers,
localNotificationSettings,
currentDeviceId,
isLoadingDeviceList,
requestDeviceVerification,
refreshDevices,
saveDeviceName,
setPushNotifications,
supportsMSC3881
} = (0, _useOwnDevices.useOwnDevices)();
const [filter, setFilter] = (0, _react.useState)();
const [expandedDeviceIds, setExpandedDeviceIds] = (0, _react.useState)([]);
const [selectedDeviceIds, setSelectedDeviceIds] = (0, _react.useState)([]);
const filteredDeviceListRef = (0, _react.useRef)(null);
const scrollIntoViewTimeoutRef = (0, _react.useRef)();
const sdkContext = (0, _react.useContext)(_SDKContext.SDKContext);
const matrixClient = sdkContext.client;
/**
* If we have a delegated auth account management URL, all sessions but the current session need to be managed in the
* delegated auth provider.
* See https://github.com/matrix-org/matrix-spec-proposals/pull/3824
*/
const delegatedAuthAccountUrl = (0, _useAsyncMemo.useAsyncMemo)(async () => {
await sdkContext.oidcClientStore.readyPromise; // wait for the store to be ready
return sdkContext.oidcClientStore.accountManagementEndpoint;
}, [sdkContext.oidcClientStore]);
const disableMultipleSignout = !!delegatedAuthAccountUrl;
const userId = matrixClient?.getUserId();
const currentUserMember = userId && matrixClient?.getUser(userId) || undefined;
const clientVersions = (0, _useAsyncMemo.useAsyncMemo)(() => matrixClient.getVersions(), [matrixClient]);
const capabilities = (0, _useAsyncMemo.useAsyncMemo)(async () => matrixClient?.getCapabilities(), [matrixClient]);
const wellKnown = (0, _react.useMemo)(() => matrixClient?.getClientWellKnown(), [matrixClient]);
const oidcClientConfig = (0, _useAsyncMemo.useAsyncMemo)(async () => {
try {
const authIssuer = await matrixClient?.getAuthIssuer();
if (authIssuer) {
return (0, _matrix.discoverAndValidateOIDCIssuerWellKnown)(authIssuer.issuer);
}
} catch (e) {
_logger.logger.error("Failed to discover OIDC metadata", e);
}
}, [matrixClient]);
const isCrossSigningReady = (0, _useAsyncMemo.useAsyncMemo)(async () => matrixClient.getCrypto()?.isCrossSigningReady() ?? false, [matrixClient]);
const onDeviceExpandToggle = deviceId => {
if (expandedDeviceIds.includes(deviceId)) {
setExpandedDeviceIds(expandedDeviceIds.filter(id => id !== deviceId));
} else {
setExpandedDeviceIds([...expandedDeviceIds, deviceId]);
}
};
const onGoToFilteredList = filter => {
setFilter(filter);
clearTimeout(scrollIntoViewTimeoutRef.current);
// wait a tick for the filtered section to rerender with different height
scrollIntoViewTimeoutRef.current = window.setTimeout(() => filteredDeviceListRef.current?.scrollIntoView({
// align element to top of scrollbox
block: "start",
inline: "nearest",
behavior: "smooth"
}));
};
const {
[currentDeviceId]: currentDevice
} = devices,
otherDevices = (0, _objectWithoutProperties2.default)(devices, [currentDeviceId].map(_toPropertyKey));
if (dehydratedDeviceId && otherDevices[dehydratedDeviceId]?.isVerified) {
delete otherDevices[dehydratedDeviceId];
}
const otherSessionsCount = Object.keys(otherDevices).length;
const shouldShowOtherSessions = otherSessionsCount > 0;
const onVerifyCurrentDevice = () => {
_Modal.default.createDialog(_SetupEncryptionDialog.default, {
onFinished: refreshDevices
});
};
const onTriggerDeviceVerification = (0, _react.useCallback)(deviceId => {
if (!requestDeviceVerification) {
return;
}
const verificationRequestPromise = requestDeviceVerification(deviceId);
_Modal.default.createDialog(_VerificationRequestDialog.default, {
verificationRequestPromise,
member: currentUserMember,
onFinished: async () => {
const request = await verificationRequestPromise;
request.cancel();
await refreshDevices();
}
});
}, [requestDeviceVerification, refreshDevices, currentUserMember]);
const onSignoutResolvedCallback = async () => {
await refreshDevices();
setSelectedDeviceIds([]);
};
const {
onSignOutCurrentDevice,
onSignOutOtherDevices,
signingOutDeviceIds
} = useSignOut(matrixClient, onSignoutResolvedCallback, delegatedAuthAccountUrl);
(0, _react.useEffect)(() => () => {
clearTimeout(scrollIntoViewTimeoutRef.current);
}, [scrollIntoViewTimeoutRef]);
// clear selection when filter changes
(0, _react.useEffect)(() => {
setSelectedDeviceIds([]);
}, [filter, setSelectedDeviceIds]);
const signOutAllOtherSessions = shouldShowOtherSessions && !disableMultipleSignout ? () => {
onSignOutOtherDevices(Object.keys(otherDevices));
} : undefined;
const [signInWithQrMode, setSignInWithQrMode] = (0, _react.useState)(showMsc4108QrCode ? _LoginWithQRTypes.Mode.Show : null);
const onQrFinish = (0, _react.useCallback)(() => {
setSignInWithQrMode(null);
}, [setSignInWithQrMode]);
const onShowQrClicked = (0, _react.useCallback)(() => {
setSignInWithQrMode(_LoginWithQRTypes.Mode.Show);
}, [setSignInWithQrMode]);
if (signInWithQrMode) {
return /*#__PURE__*/_react.default.createElement(_react.Suspense, {
fallback: /*#__PURE__*/_react.default.createElement(_Spinner.default, null)
}, /*#__PURE__*/_react.default.createElement(LoginWithQR, {
mode: signInWithQrMode,
onFinished: onQrFinish,
client: matrixClient,
legacy: !oidcClientConfig && !showMsc4108QrCode
}));
}
return /*#__PURE__*/_react.default.createElement(_SettingsTab.default, null, /*#__PURE__*/_react.default.createElement(_SettingsSection.SettingsSection, null, /*#__PURE__*/_react.default.createElement(_LoginWithQRSection.default, {
onShowQr: onShowQrClicked,
versions: clientVersions,
capabilities: capabilities,
wellKnown: wellKnown,
oidcClientConfig: oidcClientConfig,
isCrossSigningReady: isCrossSigningReady
}), /*#__PURE__*/_react.default.createElement(_SecurityRecommendations.default, {
devices: devices,
goToFilteredList: onGoToFilteredList,
currentDeviceId: currentDeviceId
}), /*#__PURE__*/_react.default.createElement(_CurrentDeviceSection.default, {
device: currentDevice,
localNotificationSettings: localNotificationSettings.get(currentDeviceId),
setPushNotifications: setPushNotifications,
isSigningOut: signingOutDeviceIds.includes(currentDeviceId),
isLoading: isLoadingDeviceList,
saveDeviceName: deviceName => saveDeviceName(currentDeviceId, deviceName),
onVerifyCurrentDevice: onVerifyCurrentDevice,
onSignOutCurrentDevice: onSignOutCurrentDevice,
signOutAllOtherSessions: signOutAllOtherSessions,
otherSessionsCount: otherSessionsCount
}), shouldShowOtherSessions && /*#__PURE__*/_react.default.createElement(_SettingsSubsection.default, {
heading: /*#__PURE__*/_react.default.createElement(_OtherSessionsSectionHeading.OtherSessionsSectionHeading, {
otherSessionsCount: otherSessionsCount,
signOutAllOtherSessions: signOutAllOtherSessions,
disabled: !!signingOutDeviceIds.length
}),
description: (0, _languageHandler._t)("settings|sessions|best_security_note"),
"data-testid": "other-sessions-section",
stretchContent: true
}, /*#__PURE__*/_react.default.createElement(_FilteredDeviceList.FilteredDeviceList, {
devices: otherDevices,
pushers: pushers,
localNotificationSettings: localNotificationSettings,
filter: filter,
expandedDeviceIds: expandedDeviceIds,
signingOutDeviceIds: signingOutDeviceIds,
selectedDeviceIds: selectedDeviceIds,
setSelectedDeviceIds: setSelectedDeviceIds,
onFilterChange: setFilter,
onDeviceExpandToggle: onDeviceExpandToggle,
onRequestDeviceVerification: requestDeviceVerification ? onTriggerDeviceVerification : undefined,
onSignOutDevices: onSignOutOtherDevices,
saveDeviceName: saveDeviceName,
setPushNotifications: setPushNotifications,
ref: filteredDeviceListRef,
supportsMSC3881: supportsMSC3881,
disableMultipleSignout: disableMultipleSignout
}))));
};
var _default = exports.default = SessionManagerTab;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfcmVhY3QiLCJfaW50ZXJvcFJlcXVpcmVXaWxkY2FyZCIsInJlcXVpcmUiLCJfbWF0cml4IiwiX2xvZ2dlciIsIl9sYW5ndWFnZUhhbmRsZXIiLCJfTW9kYWwiLCJfaW50ZXJvcFJlcXVpcmVEZWZhdWx0IiwiX1NldHRpbmdzU3Vic2VjdGlvbiIsIl9TZXR1cEVuY3J5cHRpb25EaWFsb2ciLCJfVmVyaWZpY2F0aW9uUmVxdWVzdERpYWxvZyIsIl9Mb2dvdXREaWFsb2ciLCJfdXNlT3duRGV2aWNlcyIsIl9GaWx0ZXJlZERldmljZUxpc3QiLCJfQ3VycmVudERldmljZVNlY3Rpb24iLCJfU2VjdXJpdHlSZWNvbW1lbmRhdGlvbnMiLCJfZGVsZXRlRGV2aWNlcyIsIl9TZXR0aW5nc1RhYiIsIl9Mb2dpbldpdGhRUlNlY3Rpb24iLCJfTG9naW5XaXRoUVJUeXBlcyIsIl91c2VBc3luY01lbW8iLCJfUXVlc3Rpb25EaWFsb2ciLCJfT3RoZXJTZXNzaW9uc1NlY3Rpb25IZWFkaW5nIiwiX1NldHRpbmdzU2VjdGlvbiIsIl9PaWRjTG9nb3V0RGlhbG9nIiwiX1NES0NvbnRleHQiLCJfU3Bpbm5lciIsIl90b1Byb3BlcnR5S2V5IiwidCIsImkiLCJfdG9QcmltaXRpdmUiLCJyIiwiZSIsIlN5bWJvbCIsInRvUHJpbWl0aXZlIiwiY2FsbCIsIlR5cGVFcnJvciIsIlN0cmluZyIsIk51bWJlciIsIl9nZXRSZXF1aXJlV2lsZGNhcmRDYWNoZSIsIldlYWtNYXAiLCJfX2VzTW9kdWxlIiwiZGVmYXVsdCIsImhhcyIsImdldCIsIm4iLCJfX3Byb3RvX18iLCJhIiwiT2JqZWN0IiwiZGVmaW5lUHJvcGVydHkiLCJnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IiLCJ1IiwiaGFzT3duUHJvcGVydHkiLCJzZXQiLCJMb2dpbldpdGhRUiIsImxhenkiLCJQcm9taXNlIiwicmVzb2x2ZSIsInRoZW4iLCJjb25maXJtU2lnbk91dCIsInNlc3Npb25zVG9TaWduT3V0Q291bnQiLCJmaW5pc2hlZCIsIk1vZGFsIiwiY3JlYXRlRGlhbG9nIiwiUXVlc3Rpb25EaWFsb2ciLCJ0aXRsZSIsIl90IiwiZGVzY3JpcHRpb24iLCJjcmVhdGVFbGVtZW50IiwiY291bnQiLCJjYW5jZWxCdXR0b24iLCJidXR0b24iLCJjb25maXJtZWQiLCJjb25maXJtRGVsZWdhdGVkQXV0aFNpZ25PdXQiLCJkZWxlZ2F0ZWRBdXRoQWNjb3VudFVybCIsImRldmljZUlkIiwiT2lkY0xvZ291dERpYWxvZyIsInVzZVNpZ25PdXQiLCJtYXRyaXhDbGllbnQiLCJvblNpZ25vdXRSZXNvbHZlZENhbGxiYWNrIiwic2lnbmluZ091dERldmljZUlkcyIsInNldFNpZ25pbmdPdXREZXZpY2VJZHMiLCJ1c2VTdGF0ZSIsIm9uU2lnbk91dEN1cnJlbnREZXZpY2UiLCJMb2dvdXREaWFsb2ciLCJ1bmRlZmluZWQiLCJvblNpZ25PdXRPdGhlckRldmljZXMiLCJkZXZpY2VJZHMiLCJsZW5ndGgiLCJsb2dnZXIiLCJ3YXJuIiwidXNlckNvbmZpcm1lZFNpZ25vdXQiLCJvblNpZ25PdXRGaW5pc2hlZCIsInN1Y2Nlc3MiLCJmaWx0ZXIiLCJpbmNsdWRlcyIsImVycm9yIiwiZGVsZXRlRGV2aWNlc1dpdGhJbnRlcmFjdGl2ZUF1dGgiLCJTZXNzaW9uTWFuYWdlclRhYiIsInNob3dNc2M0MTA4UXJDb2RlIiwiZGV2aWNlcyIsImRlaHlkcmF0ZWREZXZpY2VJZCIsInB1c2hlcnMiLCJsb2NhbE5vdGlmaWNhdGlvblNldHRpbmdzIiwiY3VycmVudERldmljZUlkIiwiaXNMb2FkaW5nRGV2aWNlTGlzdCIsInJlcXVlc3REZXZpY2VWZXJpZmljYXRpb24iLCJyZWZyZXNoRGV2aWNlcyIsInNhdmVEZXZpY2VOYW1lIiwic2V0UHVzaE5vdGlmaWNhdGlvbnMiLCJzdXBwb3J0c01TQzM4ODEiLCJ1c2VPd25EZXZpY2VzIiwic2V0RmlsdGVyIiwiZXhwYW5kZWREZXZpY2VJZHMiLCJzZXRFeHBhbmRlZERldmljZUlkcyIsInNlbGVjdGVkRGV2aWNlSWRzIiwic2V0U2VsZWN0ZWREZXZpY2VJZHMiLCJmaWx0ZXJlZERldmljZUxpc3RSZWYiLCJ1c2VSZWYiLCJzY3JvbGxJbnRvVmlld1RpbWVvdXRSZWYiLCJzZGtDb250ZXh0IiwidXNlQ29udGV4dCIsIlNES0NvbnRleHQiLCJjbGllbnQiLCJ1c2VBc3luY01lbW8iLCJvaWRjQ2xpZW50U3RvcmUiLCJyZWFkeVByb21pc2UiLCJhY2NvdW50TWFuYWdlbWVudEVuZHBvaW50IiwiZGlzYWJsZU11bHRpcGxlU2lnbm91dCIsInVzZXJJZCIsImdldFVzZXJJZCIsImN1cnJlbnRVc2VyTWVtYmVyIiwiZ2V0VXNlciIsImNsaWVudFZlcnNpb25zIiwiZ2V0VmVyc2lvbnMiLCJjYXBhYmlsaXRpZXMiLCJnZXRDYXBhYmlsaXRpZXMiLCJ3ZWxsS25vd24iLCJ1c2VNZW1vIiwiZ2V0Q2xpZW50V2VsbEtub3duIiwib2lkY0NsaWVudENvbmZpZyIsImF1dGhJc3N1ZXIiLCJnZXRBdXRoSXNzdWVyIiwiZGlzY292ZXJBbmRWYWxpZGF0ZU9JRENJc3N1ZXJXZWxsS25vd24iLCJpc3N1ZXIiLCJpc0Nyb3NzU2lnbmluZ1JlYWR5IiwiZ2V0Q3J5cHRvIiwib25EZXZpY2VFeHBhbmRUb2dnbGUiLCJpZCIsIm9uR29Ub0ZpbHRlcmVkTGlzdCIsImNsZWFyVGltZW91dCIsImN1cnJlbnQiLCJ3aW5kb3ciLCJzZXRUaW1lb3V0Iiwic2Nyb2xsSW50b1ZpZXciLCJibG9jayIsImlubGluZSIsImJlaGF2aW9yIiwiY3VycmVudERldmljZSIsIm90aGVyRGV2aWNlcyIsIl9vYmplY3RXaXRob3V0UHJvcGVydGllczIiLCJtYXAiLCJpc1ZlcmlmaWVkIiwib3RoZXJTZXNzaW9uc0NvdW50Iiwia2V5cyIsInNob3VsZFNob3dPdGhlclNlc3Npb25zIiwib25WZXJpZnlDdXJyZW50RGV2aWNlIiwiU2V0dXBFbmNyeXB0aW9uRGlhbG9nIiwib25GaW5pc2hlZCIsIm9uVHJpZ2dlckRldmljZVZlcmlmaWNhdGlvbiIsInVzZUNhbGxiYWNrIiwidmVyaWZpY2F0aW9uUmVxdWVzdFByb21pc2UiLCJWZXJpZmljYXRpb25SZXF1ZXN0RGlhbG9nIiwibWVtYmVyIiwicmVxdWVzdCIsImNhbmNlbCIsInVzZUVmZmVjdCIsInNpZ25PdXRBbGxPdGhlclNlc3Npb25zIiwic2lnbkluV2l0aFFyTW9kZSIsInNldFNpZ25JbldpdGhRck1vZGUiLCJNb2RlIiwiU2hvdyIsIm9uUXJGaW5pc2giLCJvblNob3dRckNsaWNrZWQiLCJTdXNwZW5zZSIsImZhbGxiYWNrIiwibW9kZSIsImxlZ2FjeSIsIlNldHRpbmdzU2VjdGlvbiIsIm9uU2hvd1FyIiwidmVyc2lvbnMiLCJnb1RvRmlsdGVyZWRMaXN0IiwiZGV2aWNlIiwiaXNTaWduaW5nT3V0IiwiaXNMb2FkaW5nIiwiZGV2aWNlTmFtZSIsImhlYWRpbmciLCJPdGhlclNlc3Npb25zU2VjdGlvbkhlYWRpbmciLCJkaXNhYmxlZCIsInN0cmV0Y2hDb250ZW50IiwiRmlsdGVyZWREZXZpY2VMaXN0Iiwib25GaWx0ZXJDaGFuZ2UiLCJvblJlcXVlc3REZXZpY2VWZXJpZmljYXRpb24iLCJvblNpZ25PdXREZXZpY2VzIiwicmVmIiwiX2RlZmF1bHQiLCJleHBvcnRzIl0sInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2NvbXBvbmVudHMvdmlld3Mvc2V0dGluZ3MvdGFicy91c2VyL1Nlc3Npb25NYW5hZ2VyVGFiLnRzeCJdLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuQ29weXJpZ2h0IDIwMjQgTmV3IFZlY3RvciBMdGQuXG5Db3B5cmlnaHQgMjAyMiBUaGUgTWF0cml4Lm9yZyBGb3VuZGF0aW9uIEMuSS5DLlxuXG5TUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQUdQTC0zLjAtb25seSBPUiBHUEwtMy4wLW9ubHlcblBsZWFzZSBzZWUgTElDRU5TRSBmaWxlcyBpbiB0aGUgcmVwb3NpdG9yeSByb290IGZvciBmdWxsIGRldGFpbHMuXG4qL1xuXG5pbXBvcnQgUmVhY3QsIHsgbGF6eSwgU3VzcGVuc2UsIHVzZUNhbGxiYWNrLCB1c2VDb250ZXh0LCB1c2VFZmZlY3QsIHVzZU1lbW8sIHVzZVJlZiwgdXNlU3RhdGUgfSBmcm9tIFwicmVhY3RcIjtcbmltcG9ydCB7IGRpc2NvdmVyQW5kVmFsaWRhdGVPSURDSXNzdWVyV2VsbEtub3duLCBNYXRyaXhDbGllbnQgfSBmcm9tIFwibWF0cml4LWpzLXNkay9zcmMvbWF0cml4XCI7XG5pbXBvcnQgeyBsb2dnZXIgfSBmcm9tIFwibWF0cml4LWpzLXNkay9zcmMvbG9nZ2VyXCI7XG5cbmltcG9ydCB7IF90IH0gZnJvbSBcIi4uLy4uLy4uLy4uLy4uL2xhbmd1YWdlSGFuZGxlclwiO1xuaW1wb3J0IE1vZGFsIGZyb20gXCIuLi8uLi8uLi8uLi8uLi9Nb2RhbFwiO1xuaW1wb3J0IFNldHRpbmdzU3Vic2VjdGlvbiBmcm9tIFwiLi4vLi4vc2hhcmVkL1NldHRpbmdzU3Vic2VjdGlvblwiO1xuaW1wb3J0IFNldHVwRW5jcnlwdGlvbkRpYWxvZyBmcm9tIFwiLi4vLi4vLi4vZGlhbG9ncy9zZWN1cml0eS9TZXR1cEVuY3J5cHRpb25EaWFsb2dcIjtcbmltcG9ydCBWZXJpZmljYXRpb25SZXF1ZXN0RGlhbG9nIGZyb20gXCIuLi8uLi8uLi9kaWFsb2dzL1ZlcmlmaWNhdGlvblJlcXVlc3REaWFsb2dcIjtcbmltcG9ydCBMb2dvdXREaWFsb2cgZnJvbSBcIi4uLy4uLy4uL2RpYWxvZ3MvTG9nb3V0RGlhbG9nXCI7XG5pbXBvcnQgeyB1c2VPd25EZXZpY2VzIH0gZnJvbSBcIi4uLy4uL2RldmljZXMvdXNlT3duRGV2aWNlc1wiO1xuaW1wb3J0IHsgRmlsdGVyZWREZXZpY2VMaXN0IH0gZnJvbSBcIi4uLy4uL2RldmljZXMvRmlsdGVyZWREZXZpY2VMaXN0XCI7XG5pbXBvcnQgQ3VycmVudERldmljZVNlY3Rpb24gZnJvbSBcIi4uLy4uL2RldmljZXMvQ3VycmVudERldmljZVNlY3Rpb25cIjtcbmltcG9ydCBTZWN1cml0eVJlY29tbWVuZGF0aW9ucyBmcm9tIFwiLi4vLi4vZGV2aWNlcy9TZWN1cml0eVJlY29tbWVuZGF0aW9uc1wiO1xuaW1wb3J0IHsgRXh0ZW5kZWREZXZpY2UgfSBmcm9tIFwiLi4vLi4vZGV2aWNlcy90eXBlc1wiO1xuaW1wb3J0IHsgZGVsZXRlRGV2aWNlc1dpdGhJbnRlcmFjdGl2ZUF1dGggfSBmcm9tIFwiLi4vLi4vZGV2aWNlcy9kZWxldGVEZXZpY2VzXCI7XG5pbXBvcnQgU2V0dGluZ3NUYWIgZnJvbSBcIi4uL1NldHRpbmdzVGFiXCI7XG5pbXBvcnQgTG9naW5XaXRoUVJTZWN0aW9uIGZyb20gXCIuLi8uLi9kZXZpY2VzL0xvZ2luV2l0aFFSU2VjdGlvblwiO1xuaW1wb3J0IHsgTW9kZSB9IGZyb20gXCIuLi8uLi8uLi9hdXRoL0xvZ2luV2l0aFFSLXR5cGVzXCI7XG5pbXBvcnQgeyB1c2VBc3luY01lbW8gfSBmcm9tIFwiLi4vLi4vLi4vLi4vLi4vaG9va3MvdXNlQXN5bmNNZW1vXCI7XG5pbXBvcnQgUXVlc3Rpb25EaWFsb2cgZnJvbSBcIi4uLy4uLy4uL2RpYWxvZ3MvUXVlc3Rpb25EaWFsb2dcIjtcbmltcG9ydCB7IEZpbHRlclZhcmlhdGlvbiB9IGZyb20gXCIuLi8uLi9kZXZpY2VzL2ZpbHRlclwiO1xuaW1wb3J0IHsgT3RoZXJTZXNzaW9uc1NlY3Rpb25IZWFkaW5nIH0gZnJvbSBcIi4uLy4uL2RldmljZXMvT3RoZXJTZXNzaW9uc1NlY3Rpb25IZWFkaW5nXCI7XG5pbXBvcnQgeyBTZXR0aW5nc1NlY3Rpb24gfSBmcm9tIFwiLi4vLi4vc2hhcmVkL1NldHRpbmdzU2VjdGlvblwiO1xuaW1wb3J0IHsgT2lkY0xvZ291dERpYWxvZyB9IGZyb20gXCIuLi8uLi8uLi9kaWFsb2dzL29pZGMvT2lkY0xvZ291dERpYWxvZ1wiO1xuaW1wb3J0IHsgU0RLQ29udGV4dCB9IGZyb20gXCIuLi8uLi8uLi8uLi8uLi9jb250ZXh0cy9TREtDb250ZXh0XCI7XG5pbXBvcnQgU3Bpbm5lciBmcm9tIFwiLi4vLi4vLi4vZWxlbWVudHMvU3Bpbm5lclwiO1xuXG4vLyBXZSBpbXBvcnQgYExvZ2luV2l0aFFSYCBhc3luY2hyb25vdXNseSB0byBhdm9pZCBpbXBvcnRpbmcgdGhlIGVudGlyZSBSdXN0IENyeXB0byBXQVNNIGludG8gdGhlIG1haW4gYnVuZGxlLlxuY29uc3QgTG9naW5XaXRoUVIgPSBsYXp5KCgpID0+IGltcG9ydChcIi4uLy4uLy4uL2F1dGgvTG9naW5XaXRoUVJcIikpO1xuXG5jb25zdCBjb25maXJtU2lnbk91dCA9IGFzeW5jIChzZXNzaW9uc1RvU2lnbk91dENvdW50OiBudW1iZXIpOiBQcm9taXNlPGJvb2xlYW4+ID0+IHtcbiAgICBjb25zdCB7IGZpbmlzaGVkIH0gPSBNb2RhbC5jcmVhdGVEaWFsb2coUXVlc3Rpb25EaWFsb2csIHtcbiAgICAgICAgdGl0bGU6IF90KFwiYWN0aW9ufHNpZ25fb3V0XCIpLFxuICAgICAgICBkZXNjcmlwdGlvbjogKFxuICAgICAgICAgICAgPGRpdj5cbiAgICAgICAgICAgICAgICA8cD5cbiAgICAgICAgICAgICAgICAgICAge190KFwic2V0dGluZ3N8c2Vzc2lvbnN8c2lnbl9vdXRfY29uZmlybV9kZXNjcmlwdGlvblwiLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb3VudDogc2Vzc2lvbnNUb1NpZ25PdXRDb3VudCxcbiAgICAgICAgICAgICAgICAgICAgfSl9XG4gICAgICAgICAgICAgICAgPC9wPlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICksXG4gICAgICAgIGNhbmNlbEJ1dHRvbjogX3QoXCJhY3Rpb258Y2FuY2VsXCIpLFxuICAgICAgICBidXR0b246IF90KFwiYWN0aW9ufHNpZ25fb3V0XCIpLFxuICAgIH0pO1xuICAgIGNvbnN0IFtjb25maXJtZWRdID0gYXdhaXQgZmluaXNoZWQ7XG5cbiAgICByZXR1cm4gISFjb25maXJtZWQ7XG59O1xuXG5jb25zdCBjb25maXJtRGVsZWdhdGVkQXV0aFNpZ25PdXQgPSBhc3luYyAoZGVsZWdhdGVkQXV0aEFjY291bnRVcmw6IHN0cmluZywgZGV2aWNlSWQ6IHN0cmluZyk6IFByb21pc2U8Ym9vbGVhbj4gPT4ge1xuICAgIGNvbnN0IHsgZmluaXNoZWQgfSA9IE1vZGFsLmNyZWF0ZURpYWxvZyhPaWRjTG9nb3V0RGlhbG9nLCB7XG4gICAgICAgIGRldmljZUlkLFxuICAgICAgICBkZWxlZ2F0ZWRBdXRoQWNjb3VudFVybCxcbiAgICB9KTtcbiAgICBjb25zdCBbY29uZmlybWVkXSA9IGF3YWl0IGZpbmlzaGVkO1xuXG4gICAgcmV0dXJuICEhY29uZmlybWVkO1xufTtcblxuY29uc3QgdXNlU2lnbk91dCA9IChcbiAgICBtYXRyaXhDbGllbnQ6IE1hdHJpeENsaWVudCxcbiAgICBvblNpZ25vdXRSZXNvbHZlZENhbGxiYWNrOiAoKSA9PiBQcm9taXNlPHZvaWQ+LFxuICAgIGRlbGVnYXRlZEF1dGhBY2NvdW50VXJsPzogc3RyaW5nLFxuKToge1xuICAgIG9uU2lnbk91dEN1cnJlbnREZXZpY2U6ICgpID0+IHZvaWQ7XG4gICAgb25TaWduT3V0T3RoZXJEZXZpY2VzOiAoZGV2aWNlSWRzOiBFeHRlbmRlZERldmljZVtcImRldmljZV9pZFwiXVtdKSA9PiBQcm9taXNlPHZvaWQ+O1xuICAgIHNpZ25pbmdPdXREZXZpY2VJZHM6IEV4dGVuZGVkRGV2aWNlW1wiZGV2aWNlX2lkXCJdW107XG59ID0+IHtcbiAgICBjb25zdCBbc2lnbmluZ091dERldmljZUlkcywgc2V0U2lnbmluZ091dERldmljZUlkc10gPSB1c2VTdGF0ZTxFeHRlbmRlZERldmljZVtcImRldmljZV9pZFwiXVtdPihbXSk7XG5cbiAgICBjb25zdCBvblNpZ25PdXRDdXJyZW50RGV2aWNlID0gKCk6IHZvaWQgPT4ge1xuICAgICAgICBNb2RhbC5jcmVhdGVEaWFsb2coXG4gICAgICAgICAgICBMb2dvdXREaWFsb2csXG4gICAgICAgICAgICB7fSwgLy8gcHJvcHMsXG4gICAgICAgICAgICB1bmRlZmluZWQsIC8vIGNsYXNzTmFtZVxuICAgICAgICAgICAgZmFsc2UsIC8vIGlzUHJpb3JpdHlcbiAgICAgICAgICAgIHRydWUsIC8vIGlzU3RhdGljXG4gICAgICAgICk7XG4gICAgfTtcblxuICAgIGNvbnN0IG9uU2lnbk91dE90aGVyRGV2aWNlcyA9IGFzeW5jIChkZXZpY2VJZHM6IEV4dGVuZGVkRGV2aWNlW1wiZGV2aWNlX2lkXCJdW10pOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgICAgICAgaWYgKCFkZXZpY2VJZHMubGVuZ3RoKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgLy8gd2UgY2FuIG9ubHkgc2lnbiBvdXQgZXhhY3RseSBvbmUgT0lEQy1hd2FyZSBkZXZpY2UgYXQgYSB0aW1lXG4gICAgICAgIC8vIHdlIHNob3VsZCBub3QgZW5jb3VudGVyIHRoaXNcbiAgICAgICAgaWYgKGRlbGVnYXRlZEF1dGhBY2NvdW50VXJsICYmIGRldmljZUlkcy5sZW5ndGggIT09IDEpIHtcbiAgICAgICAgICAgIGxvZ2dlci53YXJuKFwiVW5leHBlY3RlZGx5IHRyaWVkIHRvIHNpZ24gb3V0IG11bHRpcGxlIE9JREMtYXdhcmUgZGV2aWNlcy5cIik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyBkZWxlZ2F0ZWQgYXV0aCBsb2dvdXQgZmxvdyBjb25maXJtcyBhbmQgc2lnbnMgb3V0IHRvZ2V0aGVyXG4gICAgICAgIC8vIHNvIG9ubHkgY29uZmlybSBpZiB3ZSBhcmUgTk9UIGRvaW5nIGEgZGVsZWdhdGVkIGF1dGggc2lnbiBvdXRcbiAgICAgICAgaWYgKCFkZWxlZ2F0ZWRBdXRoQWNjb3VudFVybCkge1xuICAgICAgICAgICAgY29uc3QgdXNlckNvbmZpcm1lZFNpZ25vdXQgPSBhd2FpdCBjb25maXJtU2lnbk91dChkZXZpY2VJZHMubGVuZ3RoKTtcbiAgICAgICAgICAgIGlmICghdXNlckNvbmZpcm1lZFNpZ25vdXQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgc2V0U2lnbmluZ091dERldmljZUlkcyhbLi4uc2lnbmluZ091dERldmljZUlkcywgLi4uZGV2aWNlSWRzXSk7XG5cbiAgICAgICAgICAgIGNvbnN0IG9uU2lnbk91dEZpbmlzaGVkID0gYXN5bmMgKHN1Y2Nlc3M6IGJvb2xlYW4pOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoc3VjY2Vzcykge1xuICAgICAgICAgICAgICAgICAgICBhd2FpdCBvblNpZ25vdXRSZXNvbHZlZENhbGxiYWNrKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHNldFNpZ25pbmdPdXREZXZpY2VJZHMoc2lnbmluZ091dERldmljZUlkcy5maWx0ZXIoKGRldmljZUlkKSA9PiAhZGV2aWNlSWRzLmluY2x1ZGVzKGRldmljZUlkKSkpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgaWYgKGRlbGVnYXRlZEF1dGhBY2NvdW50VXJsKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgW2RldmljZUlkXSA9IGRldmljZUlkcztcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICBzZXRTaWduaW5nT3V0RGV2aWNlSWRzKFsuLi5zaWduaW5nT3V0RGV2aWNlSWRzLCBkZXZpY2VJZF0pO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBzdWNjZXNzID0gYXdhaXQgY29uZmlybURlbGVnYXRlZEF1dGhTaWduT3V0KGRlbGVnYXRlZEF1dGhBY2NvdW50VXJsLCBkZXZpY2VJZCk7XG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IG9uU2lnbk91dEZpbmlzaGVkKHN1Y2Nlc3MpO1xuICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIGxvZ2dlci5lcnJvcihcIkVycm9yIGRlbGV0aW5nIE9JREMtYXdhcmUgc2Vzc2lvbnNcIiwgZXJyb3IpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgYXdhaXQgZGVsZXRlRGV2aWNlc1dpdGhJbnRlcmFjdGl2ZUF1dGgobWF0cml4Q2xpZW50LCBkZXZpY2VJZHMsIG9uU2lnbk91dEZpbmlzaGVkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgIGxvZ2dlci5lcnJvcihcIkVycm9yIGRlbGV0aW5nIHNlc3Npb25zXCIsIGVycm9yKTtcbiAgICAgICAgICAgIHNldFNpZ25pbmdPdXREZXZpY2VJZHMoc2lnbmluZ091dERldmljZUlkcy5maWx0ZXIoKGRldmljZUlkKSA9PiAhZGV2aWNlSWRzLmluY2x1ZGVzKGRldmljZUlkKSkpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIHJldHVybiB7XG4gICAgICAgIG9uU2lnbk91dEN1cnJlbnREZXZpY2UsXG4gICAgICAgIG9uU2lnbk91dE90aGVyRGV2aWNlcyxcbiAgICAgICAgc2lnbmluZ091dERldmljZUlkcyxcbiAgICB9O1xufTtcblxuY29uc3QgU2Vzc2lvbk1hbmFnZXJUYWI6IFJlYWN0LkZDPHtcbiAgICBzaG93TXNjNDEwOFFyQ29kZT86IGJvb2xlYW47XG59PiA9ICh7IHNob3dNc2M0MTA4UXJDb2RlIH0pID0+IHtcbiAgICBjb25zdCB7XG4gICAgICAgIGRldmljZXMsXG4gICAgICAgIGRlaHlkcmF0ZWREZXZpY2VJZCxcbiAgICAgICAgcHVzaGVycyxcbiAgICAgICAgbG9jYWxOb3RpZmljYXRpb25TZXR0aW5ncyxcbiAgICAgICAgY3VycmVudERldmljZUlkLFxuICAgICAgICBpc0xvYWRpbmdEZXZpY2VMaXN0LFxuICAgICAgICByZXF1ZXN0RGV2aWNlVmVyaWZpY2F0aW9uLFxuICAgICAgICByZWZyZXNoRGV2aWNlcyxcbiAgICAgICAgc2F2ZURldmljZU5hbWUsXG4gICAgICAgIHNldFB1c2hOb3RpZmljYXRpb25zLFxuICAgICAgICBzdXBwb3J0c01TQzM4ODEsXG4gICAgfSA9IHVzZU93bkRldmljZXMoKTtcbiAgICBjb25zdCBbZmlsdGVyLCBzZXRGaWx0ZXJdID0gdXNlU3RhdGU8RmlsdGVyVmFyaWF0aW9uPigpO1xuICAgIGNvbnN0IFtleHBhbmRlZERldmljZUlkcywgc2V0RXhwYW5kZWREZXZpY2VJZHNdID0gdXNlU3RhdGU8RXh0ZW5kZWREZXZpY2VbXCJkZXZpY2VfaWRcIl1bXT4oW10pO1xuICAgIGNvbnN0IFtzZWxlY3RlZERldmljZUlkcywgc2V0U2VsZWN0ZWREZXZpY2VJZHNdID0gdXNlU3RhdGU8RXh0ZW5kZWREZXZpY2VbXCJkZXZpY2VfaWRcIl1bXT4oW10pO1xuICAgIGNvbnN0IGZpbHRlcmVkRGV2aWNlTGlzdFJlZiA9IHVzZVJlZjxIVE1MRGl2RWxlbWVudD4obnVsbCk7XG4gICAgY29uc3Qgc2Nyb2xsSW50b1ZpZXdUaW1lb3V0UmVmID0gdXNlUmVmPG51bWJlcj4oKTtcblxuICAgIGNvbnN0IHNka0NvbnRleHQgPSB1c2VDb250ZXh0KFNES0NvbnRleHQpO1xuICAgIGNvbnN0IG1hdHJpeENsaWVudCA9IHNka0NvbnRleHQuY2xpZW50ITtcbiAgICAvKipcbiAgICAgKiBJZiB3ZSBoYXZlIGEgZGVsZWdhdGVkIGF1dGggYWNjb3VudCBtYW5hZ2VtZW50IFVSTCwgYWxsIHNlc3Npb25zIGJ1dCB0aGUgY3VycmVudCBzZXNzaW9uIG5lZWQgdG8gYmUgbWFuYWdlZCBpbiB0aGVcbiAgICAgKiBkZWxlZ2F0ZWQgYXV0aCBwcm92aWRlci5cbiAgICAgKiBTZWUgaHR0cHM6Ly9naXRodWIuY29tL21hdHJpeC1vcmcvbWF0cml4LXNwZWMtcHJvcG9zYWxzL3B1bGwvMzgyNFxuICAgICAqL1xuICAgIGNvbnN0IGRlbGVnYXRlZEF1dGhBY2NvdW50VXJsID0gdXNlQXN5bmNNZW1vKGFzeW5jICgpID0+IHtcbiAgICAgICAgYXdhaXQgc2RrQ29udGV4dC5vaWRjQ2xpZW50U3RvcmUucmVhZHlQcm9taXNlOyAvLyB3YWl0IGZvciB0aGUgc3RvcmUgdG8gYmUgcmVhZHlcbiAgICAgICAgcmV0dXJuIHNka0NvbnRleHQub2lkY0NsaWVudFN0b3JlLmFjY291bnRNYW5hZ2VtZW50RW5kcG9pbnQ7XG4gICAgfSwgW3Nka0NvbnRleHQub2lkY0NsaWVudFN0b3JlXSk7XG4gICAgY29uc3QgZGlzYWJsZU11bHRpcGxlU2lnbm91dCA9ICEhZGVsZWdhdGVkQXV0aEFjY291bnRVcmw7XG5cbiAgICBjb25zdCB1c2VySWQgPSBtYXRyaXhDbGllbnQ/LmdldFVzZXJJZCgpO1xuICAgIGNvbnN0IGN1cnJlbnRVc2VyTWVtYmVyID0gKHVzZXJJZCAmJiBtYXRyaXhDbGllbnQ/LmdldFVzZXIodXNlcklkKSkgfHwgdW5kZWZpbmVkO1xuICAgIGNvbnN0IGNsaWVudFZlcnNpb25zID0gdXNlQXN5bmNNZW1vKCgpID0+IG1hdHJpeENsaWVudC5nZXRWZXJzaW9ucygpLCBbbWF0cml4Q2xpZW50XSk7XG4gICAgY29uc3QgY2FwYWJpbGl0aWVzID0gdXNlQXN5bmNNZW1vKGFzeW5jICgpID0+IG1hdHJpeENsaWVudD8uZ2V0Q2FwYWJpbGl0aWVzKCksIFttYXRyaXhDbGllbnRdKTtcbiAgICBjb25zdCB3ZWxsS25vd24gPSB1c2VNZW1vKCgpID0+IG1hdHJpeENsaWVudD8uZ2V0Q2xpZW50V2VsbEtub3duKCksIFttYXRyaXhDbGllbnRdKTtcbiAgICBjb25zdCBvaWRjQ2xpZW50Q29uZmlnID0gdXNlQXN5bmNNZW1vKGFzeW5jICgpID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IGF1dGhJc3N1ZXIgPSBhd2FpdCBtYXRyaXhDbGllbnQ/LmdldEF1dGhJc3N1ZXIoKTtcbiAgICAgICAgICAgIGlmIChhdXRoSXNzdWVyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGRpc2NvdmVyQW5kVmFsaWRhdGVPSURDSXNzdWVyV2VsbEtub3duKGF1dGhJc3N1ZXIuaXNzdWVyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgbG9nZ2VyLmVycm9yKFwiRmFpbGVkIHRvIGRpc2NvdmVyIE9JREMgbWV0YWRhdGFcIiwgZSk7XG4gICAgICAgIH1cbiAgICB9LCBbbWF0cml4Q2xpZW50XSk7XG4gICAgY29uc3QgaXNDcm9zc1NpZ25pbmdSZWFkeSA9IHVzZUFzeW5jTWVtbyhcbiAgICAgICAgYXN5bmMgKCkgPT4gbWF0cml4Q2xpZW50LmdldENyeXB0bygpPy5pc0Nyb3NzU2lnbmluZ1JlYWR5KCkgPz8gZmFsc2UsXG4gICAgICAgIFttYXRyaXhDbGllbnRdLFxuICAgICk7XG5cbiAgICBjb25zdCBvbkRldmljZUV4cGFuZFRvZ2dsZSA9IChkZXZpY2VJZDogRXh0ZW5kZWREZXZpY2VbXCJkZXZpY2VfaWRcIl0pOiB2b2lkID0+IHtcbiAgICAgICAgaWYgKGV4cGFuZGVkRGV2aWNlSWRzLmluY2x1ZGVzKGRldmljZUlkKSkge1xuICAgICAgICAgICAgc2V0RXhwYW5kZWREZXZpY2VJZHMoZXhwYW5kZWREZXZpY2VJZHMuZmlsdGVyKChpZCkgPT4gaWQgIT09IGRldmljZUlkKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzZXRFeHBhbmRlZERldmljZUlkcyhbLi4uZXhwYW5kZWREZXZpY2VJZHMsIGRldmljZUlkXSk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgY29uc3Qgb25Hb1RvRmlsdGVyZWRMaXN0ID0gKGZpbHRlcjogRmlsdGVyVmFyaWF0aW9uKTogdm9pZCA9PiB7XG4gICAgICAgIHNldEZpbHRlcihmaWx0ZXIpO1xuICAgICAgICBjbGVhclRpbWVvdXQoc2Nyb2xsSW50b1ZpZXdUaW1lb3V0UmVmLmN1cnJlbnQpO1xuICAgICAgICAvLyB3YWl0IGEgdGljayBmb3IgdGhlIGZpbHRlcmVkIHNlY3Rpb24gdG8gcmVyZW5kZXIgd2l0aCBkaWZmZXJlbnQgaGVpZ2h0XG4gICAgICAgIHNjcm9sbEludG9WaWV3VGltZW91dFJlZi5jdXJyZW50ID0gd2luZG93LnNldFRpbWVvdXQoKCkgPT5cbiAgICAgICAgICAgIGZpbHRlcmVkRGV2aWNlTGlzdFJlZi5jdXJyZW50Py5zY3JvbGxJbnRvVmlldyh7XG4gICAgICAgICAgICAgICAgLy8gYWxpZ24gZWxlbWVudCB0byB0b3Agb2Ygc2Nyb2xsYm94XG4gICAgICAgICAgICAgICAgYmxvY2s6IFwic3RhcnRcIixcbiAgICAgICAgICAgICAgICBpbmxpbmU6IFwibmVhcmVzdFwiLFxuICAgICAgICAgICAgICAgIGJlaGF2aW9yOiBcInNtb290aFwiLFxuICAgICAgICAgICAgfSksXG4gICAgICAgICk7XG4gICAgfTtcblxuICAgIGNvbnN0IHsgW2N1cnJlbnREZXZpY2VJZF06IGN1cnJlbnREZXZpY2UsIC4uLm90aGVyRGV2aWNlcyB9ID0gZGV2aWNlcztcbiAgICBpZiAoZGVoeWRyYXRlZERldmljZUlkICYmIG90aGVyRGV2aWNlc1tkZWh5ZHJhdGVkRGV2aWNlSWRdPy5pc1ZlcmlmaWVkKSB7XG4gICAgICAgIGRlbGV0ZSBvdGhlckRldmljZXNbZGVoeWRyYXRlZERldmljZUlkXTtcbiAgICB9XG4gICAgY29uc3Qgb3RoZXJTZXNzaW9uc0NvdW50ID0gT2JqZWN0LmtleXMob3RoZXJEZXZpY2VzKS5sZW5ndGg7XG4gICAgY29uc3Qgc2hvdWxkU2hvd090aGVyU2Vzc2lvbnMgPSBvdGhlclNlc3Npb25zQ291bnQgPiAwO1xuXG4gICAgY29uc3Qgb25WZXJpZnlDdXJyZW50RGV2aWNlID0gKCk6IHZvaWQgPT4ge1xuICAgICAgICBNb2RhbC5jcmVhdGVEaWFsb2coU2V0dXBFbmNyeXB0aW9uRGlhbG9nLCB7IG9uRmluaXNoZWQ6IHJlZnJlc2hEZXZpY2VzIH0pO1xuICAgIH07XG5cbiAgICBjb25zdCBvblRyaWdnZXJEZXZpY2VWZXJpZmljYXRpb24gPSB1c2VDYWxsYmFjayhcbiAgICAgICAgKGRldmljZUlkOiBFeHRlbmRlZERldmljZVtcImRldmljZV9pZFwiXSkgPT4ge1xuICAgICAgICAgICAgaWYgKCFyZXF1ZXN0RGV2aWNlVmVyaWZpY2F0aW9uKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgdmVyaWZpY2F0aW9uUmVxdWVzdFByb21pc2UgPSByZXF1ZXN0RGV2aWNlVmVyaWZpY2F0aW9uKGRldmljZUlkKTtcbiAgICAgICAgICAgIE1vZGFsLmNyZWF0ZURpYWxvZyhWZXJpZmljYXRpb25SZXF1ZXN0RGlhbG9nLCB7XG4gICAgICAgICAgICAgICAgdmVyaWZpY2F0aW9uUmVxdWVzdFByb21pc2UsXG4gICAgICAgICAgICAgICAgbWVtYmVyOiBjdXJyZW50VXNlck1lbWJlcixcbiAgICAgICAgICAgICAgICBvbkZpbmlzaGVkOiBhc3luYyAoKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlcXVlc3QgPSBhd2FpdCB2ZXJpZmljYXRpb25SZXF1ZXN0UHJvbWlzZTtcbiAgICAgICAgICAgICAgICAgICAgcmVxdWVzdC5jYW5jZWwoKTtcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgcmVmcmVzaERldmljZXMoKTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0sXG4gICAgICAgIFtyZXF1ZXN0RGV2aWNlVmVyaWZpY2F0aW9uLCByZWZyZXNoRGV2aWNlcywgY3VycmVudFVzZXJNZW1iZXJdLFxuICAgICk7XG5cbiAgICBjb25zdCBvblNpZ25vdXRSZXNvbHZlZENhbGxiYWNrID0gYXN5bmMgKCk6IFByb21pc2U8dm9pZD4gPT4ge1xuICAgICAgICBhd2FpdCByZWZyZXNoRGV2aWNlcygpO1xuICAgICAgICBzZXRTZWxlY3RlZERldmljZUlkcyhbXSk7XG4gICAgfTtcbiAgICBjb25zdCB7IG9uU2lnbk91dEN1cnJlbnREZXZpY2UsIG9uU2lnbk91dE90aGVyRGV2aWNlcywgc2lnbmluZ091dERldmljZUlkcyB9ID0gdXNlU2lnbk91dChcbiAgICAgICAgbWF0cml4Q2xpZW50LFxuICAgICAgICBvblNpZ25vdXRSZXNvbHZlZENhbGxiYWNrLFxuICAgICAgICBkZWxlZ2F0ZWRBdXRoQWNjb3VudFVybCxcbiAgICApO1xuXG4gICAgdXNlRWZmZWN0KFxuICAgICAgICAoKSA9PiAoKSA9PiB7XG4gICAgICAgICAgICBjbGVhclRpbWVvdXQoc2Nyb2xsSW50b1ZpZXdUaW1lb3V0UmVmLmN1cnJlbnQpO1xuICAgICAgICB9LFxuICAgICAgICBbc2Nyb2xsSW50b1ZpZXdUaW1lb3V0UmVmXSxcbiAgICApO1xuXG4gICAgLy8gY2xlYXIgc2VsZWN0aW9uIHdoZW4gZmlsdGVyIGNoYW5nZXNcbiAgICB1c2VFZmZlY3QoKCkgPT4ge1xuICAgICAgICBzZXRTZWxlY3RlZERldmljZUlkcyhbXSk7XG4gICAgfSwgW2ZpbHRlciwgc2V0U2VsZWN0ZWREZXZpY2VJZHNdKTtcblxuICAgIGNvbnN0IHNpZ25PdXRBbGxPdGhlclNlc3Npb25zID1cbiAgICAgICAgc2hvdWxkU2hvd090aGVyU2Vzc2lvbnMgJiYgIWRpc2FibGVNdWx0aXBsZVNpZ25vdXRcbiAgICAgICAgICAgID8gKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgb25TaWduT3V0T3RoZXJEZXZpY2VzKE9iamVjdC5rZXlzKG90aGVyRGV2aWNlcykpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICA6IHVuZGVmaW5lZDtcblxuICAgIGNvbnN0IFtzaWduSW5XaXRoUXJNb2RlLCBzZXRTaWduSW5XaXRoUXJNb2RlXSA9IHVzZVN0YXRlPE1vZGUgfCBudWxsPihzaG93TXNjNDEwOFFyQ29kZSA/IE1vZGUuU2hvdyA6IG51bGwpO1xuXG4gICAgY29uc3Qgb25RckZpbmlzaCA9IHVzZUNhbGxiYWNrKCgpID0+IHtcbiAgICAgICAgc2V0U2lnbkluV2l0aFFyTW9kZShudWxsKTtcbiAgICB9LCBbc2V0U2lnbkluV2l0aFFyTW9kZV0pO1xuXG4gICAgY29uc3Qgb25TaG93UXJDbGlja2VkID0gdXNlQ2FsbGJhY2soKCkgPT4ge1xuICAgICAgICBzZXRTaWduSW5XaXRoUXJNb2RlKE1vZGUuU2hvdyk7XG4gICAgfSwgW3NldFNpZ25JbldpdGhRck1vZGVdKTtcblxuICAgIGlmIChzaWduSW5XaXRoUXJNb2RlKSB7XG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICA8U3VzcGVuc2UgZmFsbGJhY2s9ezxTcGlubmVyIC8+fT5cbiAgICAgICAgICAgICAgICA8TG9naW5XaXRoUVJcbiAgICAgICAgICAgICAgICAgICAgbW9kZT17c2lnbkluV2l0aFFyTW9kZX1cbiAgICAgICAgICAgICAgICAgICAgb25GaW5pc2hlZD17b25RckZpbmlzaH1cbiAgICAgICAgICAgICAgICAgICAgY2xpZW50PXttYXRyaXhDbGllbnR9XG4gICAgICAgICAgICAgICAgICAgIGxlZ2FjeT17IW9pZGNDbGllbnRDb25maWcgJiYgIXNob3dNc2M0MTA4UXJDb2RlfVxuICAgICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICA8L1N1c3BlbnNlPlxuICAgICAgICApO1xuICAgIH1cblxuICAgIHJldHVybiAoXG4gICAgICAgIDxTZXR0aW5nc1RhYj5cbiAgICAgICAgICAgIDxTZXR0aW5nc1NlY3Rpb24+XG4gICAgICAgICAgICAgICAgPExvZ2luV2l0aFFSU2VjdGlvblxuICAgICAgICAgICAgICAgICAgICBvblNob3dRcj17b25TaG93UXJDbGlja2VkfVxuICAgICAgICAgICAgICAgICAgICB2ZXJzaW9ucz17Y2xpZW50VmVyc2lvbnN9XG4gICAgICAgICAgICAgICAgICAgIGNhcGFiaWxpdGllcz17Y2FwYWJpbGl0aWVzfVxuICAgICAgICAgICAgICAgICAgICB3ZWxsS25vd249e3dlbGxLbm93bn1cbiAgICAgICAgICAgICAgICAgICAgb2lkY0NsaWVudENvbmZpZz17b2lkY0NsaWVudENvbmZpZ31cbiAgICAgICAgICAgICAgICAgICAgaXNDcm9zc1NpZ25pbmdSZWFkeT17aXNDcm9zc1NpZ25pbmdSZWFkeX1cbiAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICAgIDxTZWN1cml0eVJlY29tbWVuZGF0aW9uc1xuICAgICAgICAgICAgICAgICAgICBkZXZpY2VzPXtkZXZpY2VzfVxuICAgICAgICAgICAgICAgICAgICBnb1RvRmlsdGVyZWRMaXN0PXtvbkdvVG9GaWx0ZXJlZExpc3R9XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnREZXZpY2VJZD17Y3VycmVudERldmljZUlkfVxuICAgICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICAgICAgPEN1cnJlbnREZXZpY2VTZWN0aW9uXG4gICAgICAgICAgICAgICAgICAgIGRldmljZT17Y3VycmVudERldmljZX1cbiAgICAgICAgICAgICAgICAgICAgbG9jYWxOb3RpZmljYXRpb25TZXR0aW5ncz17bG9jYWxOb3RpZmljYXRpb25TZXR0aW5ncy5nZXQoY3VycmVudERldmljZUlkKX1cbiAgICAgICAgICAgICAgICAgICAgc2V0UHVzaE5vdGlmaWNhdGlvbnM9e3NldFB1c2hOb3RpZmljYXRpb25zfVxuICAgICAgICAgICAgICAgICAgICBpc1NpZ25pbmdPdXQ9e3NpZ25pbmdPdXREZXZpY2VJZHMuaW5jbHVkZXMoY3VycmVudERldmljZUlkKX1cbiAgICAgICAgICAgICAgICAgICAgaXNMb2FkaW5nPXtpc0xvYWRpbmdEZXZpY2VMaXN0fVxuICAgICAgICAgICAgICAgICAgICBzYXZlRGV2aWNlTmFtZT17KGRldmljZU5hbWUpID0+IHNhdmVEZXZpY2VOYW1lKGN1cnJlbnREZXZpY2VJZCwgZGV2aWNlTmFtZSl9XG4gICAgICAgICAgICAgICAgICAgIG9uVmVyaWZ5Q3VycmVudERldmljZT17b25WZXJpZnlDdXJyZW50RGV2aWNlfVxuICAgICAgICAgICAgICAgICAgICBvblNpZ25PdXRDdXJyZW50RGV2aWNlPXtvblNpZ25PdXRDdXJyZW50RGV2aWNlfVxuICAgICAgICAgICAgICAgICAgICBzaWduT3V0QWxsT3RoZXJTZXNzaW9ucz17c2lnbk91dEFsbE90aGVyU2Vzc2lvbnN9XG4gICAgICAgICAgICAgICAgICAgIG90aGVyU2Vzc2lvbnNDb3VudD17b3RoZXJTZXNzaW9uc0NvdW50fVxuICAgICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICAgICAge3Nob3VsZFNob3dPdGhlclNlc3Npb25zICYmIChcbiAgICAgICAgICAgICAgICAgICAgPFNldHRpbmdzU3Vic2VjdGlvblxuICAgICAgICAgICAgICAgICAgICAgICAgaGVhZGluZz17XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPE90aGVyU2Vzc2lvbnNTZWN0aW9uSGVhZGluZ1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdGhlclNlc3Npb25zQ291bnQ9e290aGVyU2Vzc2lvbnNDb3VudH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2lnbk91dEFsbE90aGVyU2Vzc2lvbnM9e3NpZ25PdXRBbGxPdGhlclNlc3Npb25zfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXNhYmxlZD17ISFzaWduaW5nT3V0RGV2aWNlSWRzLmxlbmd0aH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZGVzY3JpcHRpb249e190KFwic2V0dGluZ3N8c2Vzc2lvbnN8YmVzdF9zZWN1cml0eV9ub3RlXCIpfVxuICAgICAgICAgICAgICAgICAgICAgICAgZGF0YS10ZXN0aWQ9XCJvdGhlci1zZXNzaW9ucy1zZWN0aW9uXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0cmV0Y2hDb250ZW50XG4gICAgICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxGaWx0ZXJlZERldmljZUxpc3RcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXZpY2VzPXtvdGhlckRldmljZXN9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHVzaGVycz17cHVzaGVyc31cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2NhbE5vdGlmaWNhdGlvblNldHRpbmdzPXtsb2NhbE5vdGlmaWNhdGlvblNldHRpbmdzfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlcj17ZmlsdGVyfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4cGFuZGVkRGV2aWNlSWRzPXtleHBhbmRlZERldmljZUlkc31cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaWduaW5nT3V0RGV2aWNlSWRzPXtzaWduaW5nT3V0RGV2aWNlSWRzfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGVjdGVkRGV2aWNlSWRzPXtzZWxlY3RlZERldmljZUlkc31cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXRTZWxlY3RlZERldmljZUlkcz17c2V0U2VsZWN0ZWREZXZpY2VJZHN9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb25GaWx0ZXJDaGFuZ2U9e3NldEZpbHRlcn1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbkRldmljZUV4cGFuZFRvZ2dsZT17b25EZXZpY2VFeHBhbmRUb2dnbGV9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb25SZXF1ZXN0RGV2aWNlVmVyaWZpY2F0aW9uPXtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVxdWVzdERldmljZVZlcmlmaWNhdGlvbiA/IG9uVHJpZ2dlckRldmljZVZlcmlmaWNhdGlvbiA6IHVuZGVmaW5lZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvblNpZ25PdXREZXZpY2VzPXtvblNpZ25PdXRPdGhlckRldmljZXN9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2F2ZURldmljZU5hbWU9e3NhdmVEZXZpY2VOYW1lfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNldFB1c2hOb3RpZmljYXRpb25zPXtzZXRQdXNoTm90aWZpY2F0aW9uc31cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWY9e2ZpbHRlcmVkRGV2aWNlTGlzdFJlZn1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdXBwb3J0c01TQzM4ODE9e3N1cHBvcnRzTVNDMzg4MX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXNhYmxlTXVsdGlwbGVTaWdub3V0PXtkaXNhYmxlTXVsdGlwbGVTaWdub3V0fVxuICAgICAgICAgICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICAgICAgPC9TZXR0aW5nc1N1YnNlY3Rpb24+XG4gICAgICAgICAgICAgICAgKX1cbiAgICAgICAgICAgIDwvU2V0dGluZ3NTZWN0aW9uPlxuICAgICAgICA8L1NldHRpbmdzVGFiPlxuICAgICk7XG59O1xuXG5leHBvcnQgZGVmYXVsdCBTZXNzaW9uTWFuYWdlclRhYjtcbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7QUFRQSxJQUFBQSxNQUFBLEdBQUFDLHVCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBQyxPQUFBLEdBQUFELE9BQUE7QUFDQSxJQUFBRSxPQUFBLEdBQUFGLE9BQUE7QUFFQSxJQUFBRyxnQkFBQSxHQUFBSCxPQUFBO0FBQ0EsSUFBQUksTUFBQSxHQUFBQyxzQkFBQSxDQUFBTCxPQUFBO0FBQ0EsSUFBQU0sbUJBQUEsR0FBQUQsc0JBQUEsQ0FBQUwsT0FBQTtBQUNBLElBQUFPLHNCQUFBLEdBQUFGLHNCQUFBLENBQUFMLE9BQUE7QUFDQSxJQUFBUSwwQkFBQSxHQUFBSCxzQkFBQSxDQUFBTCxPQUFBO0FBQ0EsSUFBQVMsYUFBQSxHQUFBSixzQkFBQSxDQUFBTCxPQUFBO0FBQ0EsSUFBQVUsY0FBQSxHQUFBVixPQUFBO0FBQ0EsSUFBQVcsbUJBQUEsR0FBQVgsT0FBQTtBQUNBLElBQUFZLHFCQUFBLEdBQUFQLHNCQUFBLENBQUFMLE9BQUE7QUFDQSxJQUFBYSx3QkFBQSxHQUFBUixzQkFBQSxDQUFB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