UNPKG

matrix-react-sdk

Version:
316 lines (312 loc) 56 kB
"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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