UNPKG

matrix-react-sdk

Version:
344 lines (338 loc) 48.7 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = exports.LoginWithQRFailureReason = void 0; var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _react = _interopRequireDefault(require("react")); var _rendezvous = require("matrix-js-sdk/src/rendezvous"); var _logger = require("matrix-js-sdk/src/logger"); var _matrix = require("matrix-js-sdk/src/matrix"); var _LoginWithQRTypes = require("./LoginWithQR-types"); var _LoginWithQRFlow = _interopRequireDefault(require("./LoginWithQRFlow")); var _UserInteractiveAuth = require("../../../utils/UserInteractiveAuth"); var _languageHandler = require("../../../languageHandler"); /* 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. */ let LoginWithQRFailureReason = exports.LoginWithQRFailureReason = /*#__PURE__*/function (LoginWithQRFailureReason) { LoginWithQRFailureReason["RateLimited"] = "rate_limited"; LoginWithQRFailureReason["CheckCodeMismatch"] = "check_code_mismatch"; return LoginWithQRFailureReason; }({}); // n.b MSC3886/MSC3903/MSC3906 that this is based on are now closed. // However, we want to keep this implementation around for some time. // TODO: define an end-of-life date for this implementation. /** * A component that allows sign in and E2EE set up with a QR code. * * It implements `login.reciprocate` capabilities and showing QR codes. * * This uses the unstable feature of MSC3906: https://github.com/matrix-org/matrix-spec-proposals/pull/3906 */ class LoginWithQR extends _react.default.Component { constructor(props) { super(props); (0, _defineProperty2.default)(this, "finished", false); (0, _defineProperty2.default)(this, "generateAndShowCode", async () => { let rendezvous; try { const fallbackRzServer = this.props.client?.getClientWellKnown()?.["io.element.rendezvous"]?.server; if (this.props.legacy) { const transport = new _rendezvous.MSC3886SimpleHttpRendezvousTransport({ onFailure: this.onFailure, client: this.props.client, fallbackRzServer }); const channel = new _rendezvous.MSC3903ECDHv2RendezvousChannel(transport, undefined, this.onFailure); rendezvous = new _rendezvous.MSC3906Rendezvous(channel, this.props.client, this.onFailure); } else { const transport = new _rendezvous.MSC4108RendezvousSession({ onFailure: this.onFailure, client: this.props.client, fallbackRzServer }); await transport.send(""); const channel = new _rendezvous.MSC4108SecureChannel(transport, undefined, this.onFailure); rendezvous = new _rendezvous.MSC4108SignInWithQR(channel, false, this.props.client, this.onFailure); } await rendezvous.generateCode(); this.setState({ phase: _LoginWithQRTypes.Phase.ShowingQR, rendezvous, failureReason: undefined }); } catch (e) { _logger.logger.error("Error whilst generating QR code", e); this.setState({ phase: _LoginWithQRTypes.Phase.Error, failureReason: _rendezvous.ClientRendezvousFailureReason.HomeserverLacksSupport }); return; } try { if (rendezvous instanceof _rendezvous.MSC3906Rendezvous) { const confirmationDigits = await rendezvous.startAfterShowingCode(); this.setState({ phase: _LoginWithQRTypes.Phase.LegacyConnected, confirmationDigits }); } else if (this.ourIntent === _rendezvous.RendezvousIntent.RECIPROCATE_LOGIN_ON_EXISTING_DEVICE) { // MSC4108-Flow: NewScanned await rendezvous.negotiateProtocols(); const { verificationUri } = await rendezvous.deviceAuthorizationGrant(); this.setState({ phase: _LoginWithQRTypes.Phase.OutOfBandConfirmation, verificationUri }); } // we ask the user to confirm that the channel is secure } catch (e) { _logger.logger.error("Error whilst approving login", e); if (rendezvous instanceof _rendezvous.MSC3906Rendezvous) { // only set to error phase if it hasn't already been set by onFailure or similar if (this.state.phase !== _LoginWithQRTypes.Phase.Error) { this.setState({ phase: _LoginWithQRTypes.Phase.Error, failureReason: _rendezvous.LegacyRendezvousFailureReason.Unknown }); } } else { await rendezvous?.cancel(e instanceof _rendezvous.RendezvousError ? e.code : _rendezvous.ClientRendezvousFailureReason.Unknown); } } }); (0, _defineProperty2.default)(this, "approveLogin", async checkCode => { if (!(this.state.rendezvous instanceof _rendezvous.MSC4108SignInWithQR)) { this.setState({ phase: _LoginWithQRTypes.Phase.Error, failureReason: _rendezvous.ClientRendezvousFailureReason.Unknown }); throw new Error("Rendezvous not found"); } if (!this.state.lastScannedCode && this.state.rendezvous?.checkCode !== checkCode) { this.setState({ failureReason: LoginWithQRFailureReason.CheckCodeMismatch }); return; } try { if (this.ourIntent === _rendezvous.RendezvousIntent.RECIPROCATE_LOGIN_ON_EXISTING_DEVICE) { // MSC4108-Flow: NewScanned this.setState({ phase: _LoginWithQRTypes.Phase.Loading }); if (this.state.verificationUri) { window.open(this.state.verificationUri, "_blank"); } this.setState({ phase: _LoginWithQRTypes.Phase.WaitingForDevice }); // send secrets await this.state.rendezvous.shareSecrets(); // done this.onFinished(true); } else { this.setState({ phase: _LoginWithQRTypes.Phase.Error, failureReason: _rendezvous.ClientRendezvousFailureReason.Unknown }); throw new Error("New device flows around OIDC are not yet implemented"); } } catch (e) { _logger.logger.error("Error whilst approving sign in", e); this.setState({ phase: _LoginWithQRTypes.Phase.Error, failureReason: e instanceof _rendezvous.RendezvousError ? e.code : _rendezvous.ClientRendezvousFailureReason.Unknown }); } }); (0, _defineProperty2.default)(this, "onFailure", reason => { if (this.state.phase === _LoginWithQRTypes.Phase.Error) return; // Already in failed state _logger.logger.info(`Rendezvous failed: ${reason}`); this.setState({ phase: _LoginWithQRTypes.Phase.Error, failureReason: reason }); }); (0, _defineProperty2.default)(this, "onClick", async (type, checkCode) => { switch (type) { case _LoginWithQRTypes.Click.Cancel: if (this.state.rendezvous instanceof _rendezvous.MSC3906Rendezvous) { await this.state.rendezvous?.cancel(_rendezvous.LegacyRendezvousFailureReason.UserCancelled); } else { await this.state.rendezvous?.cancel(_rendezvous.MSC4108FailureReason.UserCancelled); } this.reset(); this.onFinished(false); break; case _LoginWithQRTypes.Click.Approve: await (this.props.legacy ? this.legacyApproveLogin() : this.approveLogin(checkCode)); break; case _LoginWithQRTypes.Click.Decline: await this.state.rendezvous?.declineLoginOnExistingDevice(); this.reset(); this.onFinished(false); break; case _LoginWithQRTypes.Click.Back: if (this.state.rendezvous instanceof _rendezvous.MSC3906Rendezvous) { await this.state.rendezvous?.cancel(_rendezvous.LegacyRendezvousFailureReason.UserCancelled); } else { await this.state.rendezvous?.cancel(_rendezvous.MSC4108FailureReason.UserCancelled); } this.onFinished(false); break; case _LoginWithQRTypes.Click.ShowQr: await this.updateMode(_LoginWithQRTypes.Mode.Show); break; } }); this.state = { phase: _LoginWithQRTypes.Phase.Loading }; } get ourIntent() { return _rendezvous.RendezvousIntent.RECIPROCATE_LOGIN_ON_EXISTING_DEVICE; } componentDidMount() { this.updateMode(this.props.mode).then(() => {}); } componentDidUpdate(prevProps) { if (prevProps.mode !== this.props.mode) { this.updateMode(this.props.mode).then(() => {}); } } async updateMode(mode) { this.setState({ phase: _LoginWithQRTypes.Phase.Loading }); if (this.state.rendezvous) { const rendezvous = this.state.rendezvous; rendezvous.onFailure = undefined; if (rendezvous instanceof _rendezvous.MSC3906Rendezvous) { await rendezvous.cancel(_rendezvous.LegacyRendezvousFailureReason.UserCancelled); } this.setState({ rendezvous: undefined }); } if (mode === _LoginWithQRTypes.Mode.Show) { await this.generateAndShowCode(); } } componentWillUnmount() { if (this.state.rendezvous && !this.finished) { // eslint-disable-next-line react/no-direct-mutation-state this.state.rendezvous.onFailure = undefined; // calling cancel will call close() as well to clean up the resources if (this.state.rendezvous instanceof _rendezvous.MSC3906Rendezvous) { this.state.rendezvous.cancel(_rendezvous.LegacyRendezvousFailureReason.UserCancelled); } else { this.state.rendezvous.cancel(_rendezvous.MSC4108FailureReason.UserCancelled); } } } async legacyApproveLogin() { if (!(this.state.rendezvous instanceof _rendezvous.MSC3906Rendezvous)) { throw new Error("Rendezvous not found"); } if (!this.props.client) { throw new Error("No client to approve login with"); } this.setState({ phase: _LoginWithQRTypes.Phase.Loading }); try { _logger.logger.info("Requesting login token"); const { login_token: loginToken } = await (0, _UserInteractiveAuth.wrapRequestWithDialog)(this.props.client.requestLoginToken, { matrixClient: this.props.client, title: (0, _languageHandler._t)("auth|qr_code_login|sign_in_new_device") })(); this.setState({ phase: _LoginWithQRTypes.Phase.WaitingForDevice }); const newDeviceId = await this.state.rendezvous.approveLoginOnExistingDevice(loginToken); if (!newDeviceId) { // user denied return; } if (!this.props.client.getCrypto()) { // no E2EE to set up this.onFinished(true); return; } this.setState({ phase: _LoginWithQRTypes.Phase.Verifying }); await this.state.rendezvous.verifyNewDeviceOnExistingDevice(); // clean up our state: try { await this.state.rendezvous.close(); } finally { this.setState({ rendezvous: undefined }); } this.onFinished(true); } catch (e) { _logger.logger.error("Error whilst approving sign in", e); if (e instanceof _matrix.HTTPError && e.httpStatus === 429) { // 429: rate limit this.setState({ phase: _LoginWithQRTypes.Phase.Error, failureReason: LoginWithQRFailureReason.RateLimited }); return; } this.setState({ phase: _LoginWithQRTypes.Phase.Error, failureReason: _rendezvous.ClientRendezvousFailureReason.Unknown }); } } onFinished(success) { this.finished = true; this.props.onFinished(success); } reset() { this.setState({ rendezvous: undefined, confirmationDigits: undefined, verificationUri: undefined, failureReason: undefined, userCode: undefined, checkCode: undefined, lastScannedCode: undefined, mediaPermissionError: false }); } render() { if (this.state.rendezvous instanceof _rendezvous.MSC3906Rendezvous) { return /*#__PURE__*/_react.default.createElement(_LoginWithQRFlow.default, { onClick: this.onClick, phase: this.state.phase, code: this.state.phase === _LoginWithQRTypes.Phase.ShowingQR ? this.state.rendezvous?.code : undefined, confirmationDigits: this.state.phase === _LoginWithQRTypes.Phase.LegacyConnected ? this.state.confirmationDigits : undefined, failureReason: this.state.failureReason }); } return /*#__PURE__*/_react.default.createElement(_LoginWithQRFlow.default, { onClick: this.onClick, phase: this.state.phase, code: this.state.phase === _LoginWithQRTypes.Phase.ShowingQR ? this.state.rendezvous?.code : undefined, failureReason: this.state.failureReason, userCode: this.state.userCode, checkCode: this.state.checkCode }); } } exports.default = LoginWithQR; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfcmVhY3QiLCJfaW50ZXJvcFJlcXVpcmVEZWZhdWx0IiwicmVxdWlyZSIsIl9yZW5kZXp2b3VzIiwiX2xvZ2dlciIsIl9tYXRyaXgiLCJfTG9naW5XaXRoUVJUeXBlcyIsIl9Mb2dpbldpdGhRUkZsb3ciLCJfVXNlckludGVyYWN0aXZlQXV0aCIsIl9sYW5ndWFnZUhhbmRsZXIiLCJMb2dpbldpdGhRUkZhaWx1cmVSZWFzb24iLCJleHBvcnRzIiwiTG9naW5XaXRoUVIiLCJSZWFjdCIsIkNvbXBvbmVudCIsImNvbnN0cnVjdG9yIiwicHJvcHMiLCJfZGVmaW5lUHJvcGVydHkyIiwiZGVmYXVsdCIsInJlbmRlenZvdXMiLCJmYWxsYmFja1J6U2VydmVyIiwiY2xpZW50IiwiZ2V0Q2xpZW50V2VsbEtub3duIiwic2VydmVyIiwibGVnYWN5IiwidHJhbnNwb3J0IiwiTVNDMzg4NlNpbXBsZUh0dHBSZW5kZXp2b3VzVHJhbnNwb3J0Iiwib25GYWlsdXJlIiwiY2hhbm5lbCIsIk1TQzM5MDNFQ0RIdjJSZW5kZXp2b3VzQ2hhbm5lbCIsInVuZGVmaW5lZCIsIk1TQzM5MDZSZW5kZXp2b3VzIiwiTVNDNDEwOFJlbmRlenZvdXNTZXNzaW9uIiwic2VuZCIsIk1TQzQxMDhTZWN1cmVDaGFubmVsIiwiTVNDNDEwOFNpZ25JbldpdGhRUiIsImdlbmVyYXRlQ29kZSIsInNldFN0YXRlIiwicGhhc2UiLCJQaGFzZSIsIlNob3dpbmdRUiIsImZhaWx1cmVSZWFzb24iLCJlIiwibG9nZ2VyIiwiZXJyb3IiLCJFcnJvciIsIkNsaWVudFJlbmRlenZvdXNGYWlsdXJlUmVhc29uIiwiSG9tZXNlcnZlckxhY2tzU3VwcG9ydCIsImNvbmZpcm1hdGlvbkRpZ2l0cyIsInN0YXJ0QWZ0ZXJTaG93aW5nQ29kZSIsIkxlZ2FjeUNvbm5lY3RlZCIsIm91ckludGVudCIsIlJlbmRlenZvdXNJbnRlbnQiLCJSRUNJUFJPQ0FURV9MT0dJTl9PTl9FWElTVElOR19ERVZJQ0UiLCJuZWdvdGlhdGVQcm90b2NvbHMiLCJ2ZXJpZmljYXRpb25VcmkiLCJkZXZpY2VBdXRob3JpemF0aW9uR3JhbnQiLCJPdXRPZkJhbmRDb25maXJtYXRpb24iLCJzdGF0ZSIsIkxlZ2FjeVJlbmRlenZvdXNGYWlsdXJlUmVhc29uIiwiVW5rbm93biIsImNhbmNlbCIsIlJlbmRlenZvdXNFcnJvciIsImNvZGUiLCJjaGVja0NvZGUiLCJsYXN0U2Nhbm5lZENvZGUiLCJDaGVja0NvZGVNaXNtYXRjaCIsIkxvYWRpbmciLCJ3aW5kb3ciLCJvcGVuIiwiV2FpdGluZ0ZvckRldmljZSIsInNoYXJlU2VjcmV0cyIsIm9uRmluaXNoZWQiLCJyZWFzb24iLCJpbmZvIiwidHlwZSIsIkNsaWNrIiwiQ2FuY2VsIiwiVXNlckNhbmNlbGxlZCIsIk1TQzQxMDhGYWlsdXJlUmVhc29uIiwicmVzZXQiLCJBcHByb3ZlIiwibGVnYWN5QXBwcm92ZUxvZ2luIiwiYXBwcm92ZUxvZ2luIiwiRGVjbGluZSIsImRlY2xpbmVMb2dpbk9uRXhpc3RpbmdEZXZpY2UiLCJCYWNrIiwiU2hvd1FyIiwidXBkYXRlTW9kZSIsIk1vZGUiLCJTaG93IiwiY29tcG9uZW50RGlkTW91bnQiLCJtb2RlIiwidGhlbiIsImNvbXBvbmVudERpZFVwZGF0ZSIsInByZXZQcm9wcyIsImdlbmVyYXRlQW5kU2hvd0NvZGUiLCJjb21wb25lbnRXaWxsVW5tb3VudCIsImZpbmlzaGVkIiwibG9naW5fdG9rZW4iLCJsb2dpblRva2VuIiwid3JhcFJlcXVlc3RXaXRoRGlhbG9nIiwicmVxdWVzdExvZ2luVG9rZW4iLCJtYXRyaXhDbGllbnQiLCJ0aXRsZSIsIl90IiwibmV3RGV2aWNlSWQiLCJhcHByb3ZlTG9naW5PbkV4aXN0aW5nRGV2aWNlIiwiZ2V0Q3J5cHRvIiwiVmVyaWZ5aW5nIiwidmVyaWZ5TmV3RGV2aWNlT25FeGlzdGluZ0RldmljZSIsImNsb3NlIiwiSFRUUEVycm9yIiwiaHR0cFN0YXR1cyIsIlJhdGVMaW1pdGVkIiwic3VjY2VzcyIsInVzZXJDb2RlIiwibWVkaWFQZXJtaXNzaW9uRXJyb3IiLCJyZW5kZXIiLCJjcmVhdGVFbGVtZW50Iiwib25DbGljayJdLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9jb21wb25lbnRzL3ZpZXdzL2F1dGgvTG9naW5XaXRoUVIudHN4Il0sInNvdXJjZXNDb250ZW50IjpbIi8qXG5Db3B5cmlnaHQgMjAyNCBOZXcgVmVjdG9yIEx0ZC5cbkNvcHlyaWdodCAyMDIyIFRoZSBNYXRyaXgub3JnIEZvdW5kYXRpb24gQy5JLkMuXG5cblNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBR1BMLTMuMC1vbmx5IE9SIEdQTC0zLjAtb25seVxuUGxlYXNlIHNlZSBMSUNFTlNFIGZpbGVzIGluIHRoZSByZXBvc2l0b3J5IHJvb3QgZm9yIGZ1bGwgZGV0YWlscy5cbiovXG5cbmltcG9ydCBSZWFjdCBmcm9tIFwicmVhY3RcIjtcbmltcG9ydCB7XG4gICAgQ2xpZW50UmVuZGV6dm91c0ZhaWx1cmVSZWFzb24sXG4gICAgTGVnYWN5UmVuZGV6dm91c0ZhaWx1cmVSZWFzb24sXG4gICAgTVNDMzg4NlNpbXBsZUh0dHBSZW5kZXp2b3VzVHJhbnNwb3J0LFxuICAgIE1TQzM5MDNFQ0RIUGF5bG9hZCxcbiAgICBNU0MzOTAzRUNESHYyUmVuZGV6dm91c0NoYW5uZWwsXG4gICAgTVNDMzkwNlJlbmRlenZvdXMsXG4gICAgTVNDNDEwOEZhaWx1cmVSZWFzb24sXG4gICAgTVNDNDEwOFJlbmRlenZvdXNTZXNzaW9uLFxuICAgIE1TQzQxMDhTZWN1cmVDaGFubmVsLFxuICAgIE1TQzQxMDhTaWduSW5XaXRoUVIsXG4gICAgUmVuZGV6dm91c0Vycm9yLFxuICAgIFJlbmRlenZvdXNGYWlsdXJlUmVhc29uLFxuICAgIFJlbmRlenZvdXNJbnRlbnQsXG59IGZyb20gXCJtYXRyaXgtanMtc2RrL3NyYy9yZW5kZXp2b3VzXCI7XG5pbXBvcnQgeyBsb2dnZXIgfSBmcm9tIFwibWF0cml4LWpzLXNkay9zcmMvbG9nZ2VyXCI7XG5pbXBvcnQgeyBIVFRQRXJyb3IsIE1hdHJpeENsaWVudCB9IGZyb20gXCJtYXRyaXgtanMtc2RrL3NyYy9tYXRyaXhcIjtcblxuaW1wb3J0IHsgQ2xpY2ssIE1vZGUsIFBoYXNlIH0gZnJvbSBcIi4vTG9naW5XaXRoUVItdHlwZXNcIjtcbmltcG9ydCBMb2dpbldpdGhRUkZsb3cgZnJvbSBcIi4vTG9naW5XaXRoUVJGbG93XCI7XG5pbXBvcnQgeyB3cmFwUmVxdWVzdFdpdGhEaWFsb2cgfSBmcm9tIFwiLi4vLi4vLi4vdXRpbHMvVXNlckludGVyYWN0aXZlQXV0aFwiO1xuaW1wb3J0IHsgX3QgfSBmcm9tIFwiLi4vLi4vLi4vbGFuZ3VhZ2VIYW5kbGVyXCI7XG5cbmludGVyZmFjZSBJUHJvcHMge1xuICAgIGNsaWVudDogTWF0cml4Q2xpZW50O1xuICAgIG1vZGU6IE1vZGU7XG4gICAgbGVnYWN5OiBib29sZWFuO1xuICAgIG9uRmluaXNoZWQoLi4uYXJnczogYW55KTogdm9pZDtcbn1cblxuaW50ZXJmYWNlIElTdGF0ZSB7XG4gICAgcGhhc2U6IFBoYXNlO1xuICAgIHJlbmRlenZvdXM/OiBNU0MzOTA2UmVuZGV6dm91cyB8IE1TQzQxMDhTaWduSW5XaXRoUVI7XG4gICAgbWVkaWFQZXJtaXNzaW9uRXJyb3I/OiBib29sZWFuO1xuXG4gICAgLy8gTVNDMzkwNlxuICAgIGNvbmZpcm1hdGlvbkRpZ2l0cz86IHN0cmluZztcblxuICAgIC8vIE1TQzQxMDhcbiAgICB2ZXJpZmljYXRpb25Vcmk/OiBzdHJpbmc7XG4gICAgdXNlckNvZGU/OiBzdHJpbmc7XG4gICAgY2hlY2tDb2RlPzogc3RyaW5nO1xuICAgIGZhaWx1cmVSZWFzb24/OiBGYWlsdXJlUmVhc29uO1xuICAgIGxhc3RTY2FubmVkQ29kZT86IEJ1ZmZlcjtcbn1cblxuZXhwb3J0IGVudW0gTG9naW5XaXRoUVJGYWlsdXJlUmVhc29uIHtcbiAgICAvKipcbiAgICAgKiBAZGVwcmVjYXRlZCB0aGUgTVNDMzkwNiBpbXBsZW1lbnRhdGlvbiBpcyBkZXByZWNhdGVkIGluIGZhdm91ciBvZiBNU0M0MTA4LlxuICAgICAqL1xuICAgIFJhdGVMaW1pdGVkID0gXCJyYXRlX2xpbWl0ZWRcIixcbiAgICBDaGVja0NvZGVNaXNtYXRjaCA9IFwiY2hlY2tfY29kZV9taXNtYXRjaFwiLFxufVxuXG5leHBvcnQgdHlwZSBGYWlsdXJlUmVhc29uID0gUmVuZGV6dm91c0ZhaWx1cmVSZWFzb24gfCBMb2dpbldpdGhRUkZhaWx1cmVSZWFzb247XG5cbi8vIG4uYiBNU0MzODg2L01TQzM5MDMvTVNDMzkwNiB0aGF0IHRoaXMgaXMgYmFzZWQgb24gYXJlIG5vdyBjbG9zZWQuXG4vLyBIb3dldmVyLCB3ZSB3YW50IHRvIGtlZXAgdGhpcyBpbXBsZW1lbnRhdGlvbiBhcm91bmQgZm9yIHNvbWUgdGltZS5cbi8vIFRPRE86IGRlZmluZSBhbiBlbmQtb2YtbGlmZSBkYXRlIGZvciB0aGlzIGltcGxlbWVudGF0aW9uLlxuXG4vKipcbiAqIEEgY29tcG9uZW50IHRoYXQgYWxsb3dzIHNpZ24gaW4gYW5kIEUyRUUgc2V0IHVwIHdpdGggYSBRUiBjb2RlLlxuICpcbiAqIEl0IGltcGxlbWVudHMgYGxvZ2luLnJlY2lwcm9jYXRlYCBjYXBhYmlsaXRpZXMgYW5kIHNob3dpbmcgUVIgY29kZXMuXG4gKlxuICogVGhpcyB1c2VzIHRoZSB1bnN0YWJsZSBmZWF0dXJlIG9mIE1TQzM5MDY6IGh0dHBzOi8vZ2l0aHViLmNvbS9tYXRyaXgtb3JnL21hdHJpeC1zcGVjLXByb3Bvc2Fscy9wdWxsLzM5MDZcbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgTG9naW5XaXRoUVIgZXh0ZW5kcyBSZWFjdC5Db21wb25lbnQ8SVByb3BzLCBJU3RhdGU+IHtcbiAgICBwcml2YXRlIGZpbmlzaGVkID0gZmFsc2U7XG5cbiAgICBwdWJsaWMgY29uc3RydWN0b3IocHJvcHM6IElQcm9wcykge1xuICAgICAgICBzdXBlcihwcm9wcyk7XG5cbiAgICAgICAgdGhpcy5zdGF0ZSA9IHtcbiAgICAgICAgICAgIHBoYXNlOiBQaGFzZS5Mb2FkaW5nLFxuICAgICAgICB9O1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0IG91ckludGVudCgpOiBSZW5kZXp2b3VzSW50ZW50IHtcbiAgICAgICAgcmV0dXJuIFJlbmRlenZvdXNJbnRlbnQuUkVDSVBST0NBVEVfTE9HSU5fT05fRVhJU1RJTkdfREVWSUNFO1xuICAgIH1cblxuICAgIHB1YmxpYyBjb21wb25lbnREaWRNb3VudCgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy51cGRhdGVNb2RlKHRoaXMucHJvcHMubW9kZSkudGhlbigoKSA9PiB7fSk7XG4gICAgfVxuXG4gICAgcHVibGljIGNvbXBvbmVudERpZFVwZGF0ZShwcmV2UHJvcHM6IFJlYWRvbmx5PElQcm9wcz4pOiB2b2lkIHtcbiAgICAgICAgaWYgKHByZXZQcm9wcy5tb2RlICE9PSB0aGlzLnByb3BzLm1vZGUpIHtcbiAgICAgICAgICAgIHRoaXMudXBkYXRlTW9kZSh0aGlzLnByb3BzLm1vZGUpLnRoZW4oKCkgPT4ge30pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyB1cGRhdGVNb2RlKG1vZGU6IE1vZGUpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7IHBoYXNlOiBQaGFzZS5Mb2FkaW5nIH0pO1xuICAgICAgICBpZiAodGhpcy5zdGF0ZS5yZW5kZXp2b3VzKSB7XG4gICAgICAgICAgICBjb25zdCByZW5kZXp2b3VzID0gdGhpcy5zdGF0ZS5yZW5kZXp2b3VzO1xuICAgICAgICAgICAgcmVuZGV6dm91cy5vbkZhaWx1cmUgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICBpZiAocmVuZGV6dm91cyBpbnN0YW5jZW9mIE1TQzM5MDZSZW5kZXp2b3VzKSB7XG4gICAgICAgICAgICAgICAgYXdhaXQgcmVuZGV6dm91cy5jYW5jZWwoTGVnYWN5UmVuZGV6dm91c0ZhaWx1cmVSZWFzb24uVXNlckNhbmNlbGxlZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLnNldFN0YXRlKHsgcmVuZGV6dm91czogdW5kZWZpbmVkIH0pO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtb2RlID09PSBNb2RlLlNob3cpIHtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuZ2VuZXJhdGVBbmRTaG93Q29kZSgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHVibGljIGNvbXBvbmVudFdpbGxVbm1vdW50KCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy5zdGF0ZS5yZW5kZXp2b3VzICYmICF0aGlzLmZpbmlzaGVkKSB7XG4gICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgcmVhY3Qvbm8tZGlyZWN0LW11dGF0aW9uLXN0YXRlXG4gICAgICAgICAgICB0aGlzLnN0YXRlLnJlbmRlenZvdXMub25GYWlsdXJlID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgLy8gY2FsbGluZyBjYW5jZWwgd2lsbCBjYWxsIGNsb3NlKCkgYXMgd2VsbCB0byBjbGVhbiB1cCB0aGUgcmVzb3VyY2VzXG4gICAgICAgICAgICBpZiAodGhpcy5zdGF0ZS5yZW5kZXp2b3VzIGluc3RhbmNlb2YgTVNDMzkwNlJlbmRlenZvdXMpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnN0YXRlLnJlbmRlenZvdXMuY2FuY2VsKExlZ2FjeVJlbmRlenZvdXNGYWlsdXJlUmVhc29uLlVzZXJDYW5jZWxsZWQpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLnN0YXRlLnJlbmRlenZvdXMuY2FuY2VsKE1TQzQxMDhGYWlsdXJlUmVhc29uLlVzZXJDYW5jZWxsZWQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBsZWdhY3lBcHByb3ZlTG9naW4oKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGlmICghKHRoaXMuc3RhdGUucmVuZGV6dm91cyBpbnN0YW5jZW9mIE1TQzM5MDZSZW5kZXp2b3VzKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiUmVuZGV6dm91cyBub3QgZm91bmRcIik7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0aGlzLnByb3BzLmNsaWVudCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTm8gY2xpZW50IHRvIGFwcHJvdmUgbG9naW4gd2l0aFwiKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnNldFN0YXRlKHsgcGhhc2U6IFBoYXNlLkxvYWRpbmcgfSk7XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGxvZ2dlci5pbmZvKFwiUmVxdWVzdGluZyBsb2dpbiB0b2tlblwiKTtcblxuICAgICAgICAgICAgY29uc3QgeyBsb2dpbl90b2tlbjogbG9naW5Ub2tlbiB9ID0gYXdhaXQgd3JhcFJlcXVlc3RXaXRoRGlhbG9nKHRoaXMucHJvcHMuY2xpZW50LnJlcXVlc3RMb2dpblRva2VuLCB7XG4gICAgICAgICAgICAgICAgbWF0cml4Q2xpZW50OiB0aGlzLnByb3BzLmNsaWVudCxcbiAgICAgICAgICAgICAgICB0aXRsZTogX3QoXCJhdXRofHFyX2NvZGVfbG9naW58c2lnbl9pbl9uZXdfZGV2aWNlXCIpLFxuICAgICAgICAgICAgfSkoKTtcblxuICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7IHBoYXNlOiBQaGFzZS5XYWl0aW5nRm9yRGV2aWNlIH0pO1xuXG4gICAgICAgICAgICBjb25zdCBuZXdEZXZpY2VJZCA9IGF3YWl0IHRoaXMuc3RhdGUucmVuZGV6dm91cy5hcHByb3ZlTG9naW5PbkV4aXN0aW5nRGV2aWNlKGxvZ2luVG9rZW4pO1xuICAgICAgICAgICAgaWYgKCFuZXdEZXZpY2VJZCkge1xuICAgICAgICAgICAgICAgIC8vIHVzZXIgZGVuaWVkXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCF0aGlzLnByb3BzLmNsaWVudC5nZXRDcnlwdG8oKSkge1xuICAgICAgICAgICAgICAgIC8vIG5vIEUyRUUgdG8gc2V0IHVwXG4gICAgICAgICAgICAgICAgdGhpcy5vbkZpbmlzaGVkKHRydWUpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoeyBwaGFzZTogUGhhc2UuVmVyaWZ5aW5nIH0pO1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5zdGF0ZS5yZW5kZXp2b3VzLnZlcmlmeU5ld0RldmljZU9uRXhpc3RpbmdEZXZpY2UoKTtcbiAgICAgICAgICAgIC8vIGNsZWFuIHVwIG91ciBzdGF0ZTpcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5zdGF0ZS5yZW5kZXp2b3VzLmNsb3NlKCk7XG4gICAgICAgICAgICB9IGZpbmFsbHkge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoeyByZW5kZXp2b3VzOiB1bmRlZmluZWQgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLm9uRmluaXNoZWQodHJ1ZSk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIGxvZ2dlci5lcnJvcihcIkVycm9yIHdoaWxzdCBhcHByb3Zpbmcgc2lnbiBpblwiLCBlKTtcbiAgICAgICAgICAgIGlmIChlIGluc3RhbmNlb2YgSFRUUEVycm9yICYmIGUuaHR0cFN0YXR1cyA9PT0gNDI5KSB7XG4gICAgICAgICAgICAgICAgLy8gNDI5OiByYXRlIGxpbWl0XG4gICAgICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7IHBoYXNlOiBQaGFzZS5FcnJvciwgZmFpbHVyZVJlYXNvbjogTG9naW5XaXRoUVJGYWlsdXJlUmVhc29uLlJhdGVMaW1pdGVkIH0pO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoeyBwaGFzZTogUGhhc2UuRXJyb3IsIGZhaWx1cmVSZWFzb246IENsaWVudFJlbmRlenZvdXNGYWlsdXJlUmVhc29uLlVua25vd24gfSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIG9uRmluaXNoZWQoc3VjY2VzczogYm9vbGVhbik6IHZvaWQge1xuICAgICAgICB0aGlzLmZpbmlzaGVkID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5wcm9wcy5vbkZpbmlzaGVkKHN1Y2Nlc3MpO1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2VuZXJhdGVBbmRTaG93Q29kZSA9IGFzeW5jICgpOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgICAgICAgbGV0IHJlbmRlenZvdXM6IE1TQzQxMDhTaWduSW5XaXRoUVIgfCBNU0MzOTA2UmVuZGV6dm91cztcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IGZhbGxiYWNrUnpTZXJ2ZXIgPSB0aGlzLnByb3BzLmNsaWVudD8uZ2V0Q2xpZW50V2VsbEtub3duKCk/LltcImlvLmVsZW1lbnQucmVuZGV6dm91c1wiXT8uc2VydmVyO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5wcm9wcy5sZWdhY3kpIHtcbiAgICAgICAgICAgICAgICBjb25zdCB0cmFuc3BvcnQgPSBuZXcgTVNDMzg4NlNpbXBsZUh0dHBSZW5kZXp2b3VzVHJhbnNwb3J0PE1TQzM5MDNFQ0RIUGF5bG9hZD4oe1xuICAgICAgICAgICAgICAgICAgICBvbkZhaWx1cmU6IHRoaXMub25GYWlsdXJlLFxuICAgICAgICAgICAgICAgICAgICBjbGllbnQ6IHRoaXMucHJvcHMuY2xpZW50LFxuICAgICAgICAgICAgICAgICAgICBmYWxsYmFja1J6U2VydmVyLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGNvbnN0IGNoYW5uZWwgPSBuZXcgTVNDMzkwM0VDREh2MlJlbmRlenZvdXNDaGFubmVsKHRyYW5zcG9ydCwgdW5kZWZpbmVkLCB0aGlzLm9uRmFpbHVyZSk7XG4gICAgICAgICAgICAgICAgcmVuZGV6dm91cyA9IG5ldyBNU0MzOTA2UmVuZGV6dm91cyhjaGFubmVsLCB0aGlzLnByb3BzLmNsaWVudCwgdGhpcy5vbkZhaWx1cmUpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zdCB0cmFuc3BvcnQgPSBuZXcgTVNDNDEwOFJlbmRlenZvdXNTZXNzaW9uKHtcbiAgICAgICAgICAgICAgICAgICAgb25GYWlsdXJlOiB0aGlzLm9uRmFpbHVyZSxcbiAgICAgICAgICAgICAgICAgICAgY2xpZW50OiB0aGlzLnByb3BzLmNsaWVudCxcbiAgICAgICAgICAgICAgICAgICAgZmFsbGJhY2tSelNlcnZlcixcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBhd2FpdCB0cmFuc3BvcnQuc2VuZChcIlwiKTtcbiAgICAgICAgICAgICAgICBjb25zdCBjaGFubmVsID0gbmV3IE1TQzQxMDhTZWN1cmVDaGFubmVsKHRyYW5zcG9ydCwgdW5kZWZpbmVkLCB0aGlzLm9uRmFpbHVyZSk7XG4gICAgICAgICAgICAgICAgcmVuZGV6dm91cyA9IG5ldyBNU0M0MTA4U2lnbkluV2l0aFFSKGNoYW5uZWwsIGZhbHNlLCB0aGlzLnByb3BzLmNsaWVudCwgdGhpcy5vbkZhaWx1cmUpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBhd2FpdCByZW5kZXp2b3VzLmdlbmVyYXRlQ29kZSgpO1xuICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICAgICAgcGhhc2U6IFBoYXNlLlNob3dpbmdRUixcbiAgICAgICAgICAgICAgICByZW5kZXp2b3VzLFxuICAgICAgICAgICAgICAgIGZhaWx1cmVSZWFzb246IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICBsb2dnZXIuZXJyb3IoXCJFcnJvciB3aGlsc3QgZ2VuZXJhdGluZyBRUiBjb2RlXCIsIGUpO1xuICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7IHBoYXNlOiBQaGFzZS5FcnJvciwgZmFpbHVyZVJlYXNvbjogQ2xpZW50UmVuZGV6dm91c0ZhaWx1cmVSZWFzb24uSG9tZXNlcnZlckxhY2tzU3VwcG9ydCB9KTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBpZiAocmVuZGV6dm91cyBpbnN0YW5jZW9mIE1TQzM5MDZSZW5kZXp2b3VzKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgY29uZmlybWF0aW9uRGlnaXRzID0gYXdhaXQgcmVuZGV6dm91cy5zdGFydEFmdGVyU2hvd2luZ0NvZGUoKTtcbiAgICAgICAgICAgICAgICB0aGlzLnNldFN0YXRlKHsgcGhhc2U6IFBoYXNlLkxlZ2FjeUNvbm5lY3RlZCwgY29uZmlybWF0aW9uRGlnaXRzIH0pO1xuICAgICAgICAgICAgfSBlbHNlIGlmICh0aGlzLm91ckludGVudCA9PT0gUmVuZGV6dm91c0ludGVudC5SRUNJUFJPQ0FURV9MT0dJTl9PTl9FWElTVElOR19ERVZJQ0UpIHtcbiAgICAgICAgICAgICAgICAvLyBNU0M0MTA4LUZsb3c6IE5ld1NjYW5uZWRcbiAgICAgICAgICAgICAgICBhd2FpdCByZW5kZXp2b3VzLm5lZ290aWF0ZVByb3RvY29scygpO1xuICAgICAgICAgICAgICAgIGNvbnN0IHsgdmVyaWZpY2F0aW9uVXJpIH0gPSBhd2FpdCByZW5kZXp2b3VzLmRldmljZUF1dGhvcml6YXRpb25HcmFudCgpO1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgICAgICAgICBwaGFzZTogUGhhc2UuT3V0T2ZCYW5kQ29uZmlybWF0aW9uLFxuICAgICAgICAgICAgICAgICAgICB2ZXJpZmljYXRpb25VcmksXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIHdlIGFzayB0aGUgdXNlciB0byBjb25maXJtIHRoYXQgdGhlIGNoYW5uZWwgaXMgc2VjdXJlXG4gICAgICAgIH0gY2F0Y2ggKGU6IFJlbmRlenZvdXNFcnJvciB8IHVua25vd24pIHtcbiAgICAgICAgICAgIGxvZ2dlci5lcnJvcihcIkVycm9yIHdoaWxzdCBhcHByb3ZpbmcgbG9naW5cIiwgZSk7XG4gICAgICAgICAgICBpZiAocmVuZGV6dm91cyBpbnN0YW5jZW9mIE1TQzM5MDZSZW5kZXp2b3VzKSB7XG4gICAgICAgICAgICAgICAgLy8gb25seSBzZXQgdG8gZXJyb3IgcGhhc2UgaWYgaXQgaGFzbid0IGFscmVhZHkgYmVlbiBzZXQgYnkgb25GYWlsdXJlIG9yIHNpbWlsYXJcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zdGF0ZS5waGFzZSAhPT0gUGhhc2UuRXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7IHBoYXNlOiBQaGFzZS5FcnJvciwgZmFpbHVyZVJlYXNvbjogTGVnYWN5UmVuZGV6dm91c0ZhaWx1cmVSZWFzb24uVW5rbm93biB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGF3YWl0IHJlbmRlenZvdXM/LmNhbmNlbChcbiAgICAgICAgICAgICAgICAgICAgZSBpbnN0YW5jZW9mIFJlbmRlenZvdXNFcnJvclxuICAgICAgICAgICAgICAgICAgICAgICAgPyAoZS5jb2RlIGFzIE1TQzQxMDhGYWlsdXJlUmVhc29uKVxuICAgICAgICAgICAgICAgICAgICAgICAgOiBDbGllbnRSZW5kZXp2b3VzRmFpbHVyZVJlYXNvbi5Vbmtub3duLFxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgcHJpdmF0ZSBhcHByb3ZlTG9naW4gPSBhc3luYyAoY2hlY2tDb2RlOiBzdHJpbmcgfCB1bmRlZmluZWQpOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgICAgICAgaWYgKCEodGhpcy5zdGF0ZS5yZW5kZXp2b3VzIGluc3RhbmNlb2YgTVNDNDEwOFNpZ25JbldpdGhRUikpIHtcbiAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoeyBwaGFzZTogUGhhc2UuRXJyb3IsIGZhaWx1cmVSZWFzb246IENsaWVudFJlbmRlenZvdXNGYWlsdXJlUmVhc29uLlVua25vd24gfSk7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJSZW5kZXp2b3VzIG5vdCBmb3VuZFwiKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghdGhpcy5zdGF0ZS5sYXN0U2Nhbm5lZENvZGUgJiYgdGhpcy5zdGF0ZS5yZW5kZXp2b3VzPy5jaGVja0NvZGUgIT09IGNoZWNrQ29kZSkge1xuICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7IGZhaWx1cmVSZWFzb246IExvZ2luV2l0aFFSRmFpbHVyZVJlYXNvbi5DaGVja0NvZGVNaXNtYXRjaCB9KTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBpZiAodGhpcy5vdXJJbnRlbnQgPT09IFJlbmRlenZvdXNJbnRlbnQuUkVDSVBST0NBVEVfTE9HSU5fT05fRVhJU1RJTkdfREVWSUNFKSB7XG4gICAgICAgICAgICAgICAgLy8gTVNDNDEwOC1GbG93OiBOZXdTY2FubmVkXG4gICAgICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7IHBoYXNlOiBQaGFzZS5Mb2FkaW5nIH0pO1xuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc3RhdGUudmVyaWZpY2F0aW9uVXJpKSB7XG4gICAgICAgICAgICAgICAgICAgIHdpbmRvdy5vcGVuKHRoaXMuc3RhdGUudmVyaWZpY2F0aW9uVXJpLCBcIl9ibGFua1wiKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLnNldFN0YXRlKHsgcGhhc2U6IFBoYXNlLldhaXRpbmdGb3JEZXZpY2UgfSk7XG5cbiAgICAgICAgICAgICAgICAvLyBzZW5kIHNlY3JldHNcbiAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLnN0YXRlLnJlbmRlenZvdXMuc2hhcmVTZWNyZXRzKCk7XG5cbiAgICAgICAgICAgICAgICAvLyBkb25lXG4gICAgICAgICAgICAgICAgdGhpcy5vbkZpbmlzaGVkKHRydWUpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldFN0YXRlKHsgcGhhc2U6IFBoYXNlLkVycm9yLCBmYWlsdXJlUmVhc29uOiBDbGllbnRSZW5kZXp2b3VzRmFpbHVyZVJlYXNvbi5Vbmtub3duIH0pO1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIk5ldyBkZXZpY2UgZmxvd3MgYXJvdW5kIE9JREMgYXJlIG5vdCB5ZXQgaW1wbGVtZW50ZWRcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gY2F0Y2ggKGU6IFJlbmRlenZvdXNFcnJvciB8IHVua25vd24pIHtcbiAgICAgICAgICAgIGxvZ2dlci5lcnJvcihcIkVycm9yIHdoaWxzdCBhcHByb3Zpbmcgc2lnbiBpblwiLCBlKTtcbiAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgICAgIHBoYXNlOiBQaGFzZS5FcnJvcixcbiAgICAgICAgICAgICAgICBmYWlsdXJlUmVhc29uOiBlIGluc3RhbmNlb2YgUmVuZGV6dm91c0Vycm9yID8gZS5jb2RlIDogQ2xpZW50UmVuZGV6dm91c0ZhaWx1cmVSZWFzb24uVW5rbm93bixcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIHByaXZhdGUgb25GYWlsdXJlID0gKHJlYXNvbjogUmVuZGV6dm91c0ZhaWx1cmVSZWFzb24pOiB2b2lkID0+IHtcbiAgICAgICAgaWYgKHRoaXMuc3RhdGUucGhhc2UgPT09IFBoYXNlLkVycm9yKSByZXR1cm47IC8vIEFscmVhZHkgaW4gZmFpbGVkIHN0YXRlXG4gICAgICAgIGxvZ2dlci5pbmZvKGBSZW5kZXp2b3VzIGZhaWxlZDogJHtyZWFzb259YCk7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoeyBwaGFzZTogUGhhc2UuRXJyb3IsIGZhaWx1cmVSZWFzb246IHJlYXNvbiB9KTtcbiAgICB9O1xuXG4gICAgcHVibGljIHJlc2V0KCk6IHZvaWQge1xuICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgIHJlbmRlenZvdXM6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIGNvbmZpcm1hdGlvbkRpZ2l0czogdW5kZWZpbmVkLFxuICAgICAgICAgICAgdmVyaWZpY2F0aW9uVXJpOiB1bmRlZmluZWQsXG4gICAgICAgICAgICBmYWlsdXJlUmVhc29uOiB1bmRlZmluZWQsXG4gICAgICAgICAgICB1c2VyQ29kZTogdW5kZWZpbmVkLFxuICAgICAgICAgICAgY2hlY2tDb2RlOiB1bmRlZmluZWQsXG4gICAgICAgICAgICBsYXN0U2Nhbm5lZENvZGU6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIG1lZGlhUGVybWlzc2lvbkVycm9yOiBmYWxzZSxcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBvbkNsaWNrID0gYXN5bmMgKHR5cGU6IENsaWNrLCBjaGVja0NvZGU/OiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgICAgICAgc3dpdGNoICh0eXBlKSB7XG4gICAgICAgICAgICBjYXNlIENsaWNrLkNhbmNlbDpcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zdGF0ZS5yZW5kZXp2b3VzIGluc3RhbmNlb2YgTVNDMzkwNlJlbmRlenZvdXMpIHtcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5zdGF0ZS5yZW5kZXp2b3VzPy5jYW5jZWwoTGVnYWN5UmVuZGV6dm91c0ZhaWx1cmVSZWFzb24uVXNlckNhbmNlbGxlZCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5zdGF0ZS5yZW5kZXp2b3VzPy5jYW5jZWwoTVNDNDEwOEZhaWx1cmVSZWFzb24uVXNlckNhbmNlbGxlZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMucmVzZXQoKTtcbiAgICAgICAgICAgICAgICB0aGlzLm9uRmluaXNoZWQoZmFsc2UpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBDbGljay5BcHByb3ZlOlxuICAgICAgICAgICAgICAgIGF3YWl0ICh0aGlzLnByb3BzLmxlZ2FjeSA/IHRoaXMubGVnYWN5QXBwcm92ZUxvZ2luKCkgOiB0aGlzLmFwcHJvdmVMb2dpbihjaGVja0NvZGUpKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgQ2xpY2suRGVjbGluZTpcbiAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLnN0YXRlLnJlbmRlenZvdXM/LmRlY2xpbmVMb2dpbk9uRXhpc3RpbmdEZXZpY2UoKTtcbiAgICAgICAgICAgICAgICB0aGlzLnJlc2V0KCk7XG4gICAgICAgICAgICAgICAgdGhpcy5vbkZpbmlzaGVkKGZhbHNlKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgQ2xpY2suQmFjazpcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zdGF0ZS5yZW5kZXp2b3VzIGluc3RhbmNlb2YgTVNDMzkwNlJlbmRlenZvdXMpIHtcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5zdGF0ZS5yZW5kZXp2b3VzPy5jYW5jZWwoTGVnYWN5UmVuZGV6dm91c0ZhaWx1cmVSZWFzb24uVXNlckNhbmNlbGxlZCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5zdGF0ZS5yZW5kZXp2b3VzPy5jYW5jZWwoTVNDNDEwOEZhaWx1cmVSZWFzb24uVXNlckNhbmNlbGxlZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMub25GaW5pc2hlZChmYWxzZSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIENsaWNrLlNob3dRcjpcbiAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLnVwZGF0ZU1vZGUoTW9kZS5TaG93KTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBwdWJsaWMgcmVuZGVyKCk6IFJlYWN0LlJlYWN0Tm9kZSB7XG4gICAgICAgIGlmICh0aGlzLnN0YXRlLnJlbmRlenZvdXMgaW5zdGFuY2VvZiBNU0MzOTA2UmVuZGV6dm91cykge1xuICAgICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgICAgICA8TG9naW5XaXRoUVJGbG93XG4gICAgICAgICAgICAgICAgICAgIG9uQ2xpY2s9e3RoaXMub25DbGlja31cbiAgICAgICAgICAgICAgICAgICAgcGhhc2U9e3RoaXMuc3RhdGUucGhhc2V9XG4gICAgICAgICAgICAgICAgICAgIGNvZGU9e3RoaXMuc3RhdGUucGhhc2UgPT09IFBoYXNlLlNob3dpbmdRUiA/IHRoaXMuc3RhdGUucmVuZGV6dm91cz8uY29kZSA6IHVuZGVmaW5lZH1cbiAgICAgICAgICAgICAgICAgICAgY29uZmlybWF0aW9uRGlnaXRzPXtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdGUucGhhc2UgPT09IFBoYXNlLkxlZ2FjeUNvbm5lY3RlZCA/IHRoaXMuc3RhdGUuY29uZmlybWF0aW9uRGlnaXRzIDogdW5kZWZpbmVkXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZmFpbHVyZVJlYXNvbj17dGhpcy5zdGF0ZS5mYWlsdXJlUmVhc29ufVxuICAgICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIDxMb2dpbldpdGhRUkZsb3dcbiAgICAgICAgICAgICAgICBvbkNsaWNrPXt0aGlzLm9uQ2xpY2t9XG4gICAgICAgICAgICAgICAgcGhhc2U9e3RoaXMuc3RhdGUucGhhc2V9XG4gICAgICAgICAgICAgICAgY29kZT17dGhpcy5zdGF0ZS5waGFzZSA9PT0gUGhhc2UuU2hvd2luZ1FSID8gdGhpcy5zdGF0ZS5yZW5kZXp2b3VzPy5jb2RlIDogdW5kZWZpbmVkfVxuICAgICAgICAgICAgICAgIGZhaWx1cmVSZWFzb249e3RoaXMuc3RhdGUuZmFpbHVyZVJlYXNvbn1cbiAgICAgICAgICAgICAgICB1c2VyQ29kZT17dGhpcy5zdGF0ZS51c2VyQ29kZX1cbiAgICAgICAgICAgICAgICBjaGVja0NvZGU9e3RoaXMuc3RhdGUuY2hlY2tDb2RlfVxuICAgICAgICAgICAgLz5cbiAgICAgICAgKTtcbiAgICB9XG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7O0FBUUEsSUFBQUEsTUFBQSxHQUFBQyxzQkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQUMsV0FBQSxHQUFBRCxPQUFBO0FBZUEsSUFBQUUsT0FBQSxHQUFBRixPQUFBO0FBQ0EsSUFBQUcsT0FBQSxHQUFBSCxPQUFBO0FBRUEsSUFBQUksaUJBQUEsR0FBQUosT0FBQTtBQUNBLElBQUFLLGdCQUFBLEdBQUFOLHNCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBTSxvQkFBQSxHQUFBTixPQUFBO0FBQ0EsSUFBQU8sZ0JBQUEsR0FBQVAsT0FBQTtBQTlCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQU5BLElBdURZUSx3QkFBd0IsR0FBQUMsT0FBQSxDQUFBRCx3QkFBQSwwQkFBeEJBLHdCQUF3QjtFQUF4QkEsd0JBQXdCO0VBQXhCQSx3QkFBd0I7RUFBQSxPQUF4QkEsd0JBQXdCO0FBQUE7QUFVcEM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ2UsTUFBTUUsV0FBVyxTQUFTQyxjQUFLLENBQUNDLFNBQVMsQ0FBaUI7RUFHOURDLFdBQVdBLENBQUNDLEtBQWEsRUFBRTtJQUM5QixLQUFLLENBQUNBLEtBQUssQ0FBQztJQUFDLElBQUFDLGdCQUFBLENBQUFDLE9BQUEsb0JBSEUsS0FBSztJQUFBLElBQUFELGdCQUFBLENBQUFDLE9BQUEsK0JBMEdNLFlBQTJCO01BQ3JELElBQUlDLFVBQW1EO01BQ3ZE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