matrix-react-sdk
Version:
SDK for matrix.org using React
344 lines (338 loc) • 48.7 kB
JavaScript
"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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