UNPKG

matrix-react-sdk

Version:
350 lines (342 loc) 55.9 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _react = _interopRequireDefault(require("react")); var _logger = require("matrix-js-sdk/src/logger"); var _languageHandler = require("../../../languageHandler"); var _MatrixClientPeg = require("../../../MatrixClientPeg"); var _Modal = _interopRequireDefault(require("../../../Modal")); var _dispatcher = _interopRequireDefault(require("../../../dispatcher/dispatcher")); var _boundThreepids = require("../../../boundThreepids"); var _IdentityAuthClient = _interopRequireDefault(require("../../../IdentityAuthClient")); var _UrlUtils = require("../../../utils/UrlUtils"); var _IdentityServerUtils = require("../../../utils/IdentityServerUtils"); var _promise = require("../../../utils/promise"); var _InlineSpinner = _interopRequireDefault(require("../elements/InlineSpinner")); var _AccessibleButton = _interopRequireDefault(require("../elements/AccessibleButton")); var _Field = _interopRequireDefault(require("../elements/Field")); var _QuestionDialog = _interopRequireDefault(require("../dialogs/QuestionDialog")); var _SettingsFieldset = _interopRequireDefault(require("./SettingsFieldset")); var _SettingsSubsection = require("./shared/SettingsSubsection"); /* Copyright 2024 New Vector Ltd. Copyright 2019-2021 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'll wait up to this long when checking for 3PID bindings on the IS. const REACHABILITY_TIMEOUT = 10000; // ms /** * Check an IS URL is valid, including liveness check * * @param {string} u The url to check * @returns {string} null if url passes all checks, otherwise i18ned error string */ async function checkIdentityServerUrl(u) { const parsedUrl = (0, _UrlUtils.parseUrl)(u); if (parsedUrl.protocol !== "https:") return (0, _languageHandler._t)("identity_server|url_not_https"); // XXX: duplicated logic from js-sdk but it's quite tied up in the validation logic in the // js-sdk so probably as easy to duplicate it than to separate it out so we can reuse it try { const response = await fetch(u + "/_matrix/identity/v2"); if (response.ok) { return null; } else if (response.status < 200 || response.status >= 300) { return (0, _languageHandler._t)("identity_server|error_invalid", { code: response.status }); } else { return (0, _languageHandler._t)("identity_server|error_connection"); } } catch (e) { return (0, _languageHandler._t)("identity_server|error_connection"); } } class SetIdServer extends _react.default.Component { constructor(props) { super(props); (0, _defineProperty2.default)(this, "dispatcherRef", void 0); (0, _defineProperty2.default)(this, "onAction", payload => { // We react to changes in the identity server in the event the user is staring at this form // when changing their identity server on another device. if (payload.action !== "id_server_changed") return; this.setState({ currentClientIdServer: _MatrixClientPeg.MatrixClientPeg.safeGet().getIdentityServerUrl() }); }); (0, _defineProperty2.default)(this, "onIdentityServerChanged", ev => { const u = ev.target.value; this.setState({ idServer: u }); }); (0, _defineProperty2.default)(this, "getTooltip", () => { if (this.state.checking) { return /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement(_InlineSpinner.default, null), (0, _languageHandler._t)("identity_server|checking")); } else if (this.state.error) { return /*#__PURE__*/_react.default.createElement("strong", { className: "warning" }, this.state.error); } else { return null; } }); (0, _defineProperty2.default)(this, "idServerChangeEnabled", () => { return !!this.state.idServer && !this.state.busy; }); (0, _defineProperty2.default)(this, "saveIdServer", fullUrl => { // Account data change will update localstorage, client, etc through dispatcher _MatrixClientPeg.MatrixClientPeg.safeGet().setAccountData("m.identity_server", { base_url: fullUrl }); this.setState({ busy: false, error: undefined, currentClientIdServer: fullUrl, idServer: "" }); }); (0, _defineProperty2.default)(this, "checkIdServer", async e => { e.preventDefault(); const { idServer, currentClientIdServer } = this.state; this.setState({ busy: true, checking: true, error: undefined }); const fullUrl = (0, _UrlUtils.unabbreviateUrl)(idServer); let errStr = await checkIdentityServerUrl(fullUrl); if (!errStr) { try { this.setState({ checking: false }); // clear tooltip // Test the identity server by trying to register with it. This // may result in a terms of service prompt. const authClient = new _IdentityAuthClient.default(fullUrl); await authClient.getAccessToken(); let save = true; // Double check that the identity server even has terms of service. const hasTerms = await (0, _IdentityServerUtils.doesIdentityServerHaveTerms)(_MatrixClientPeg.MatrixClientPeg.safeGet(), fullUrl); if (!hasTerms) { const [confirmed] = await this.showNoTermsWarning(fullUrl); save = !!confirmed; } // Show a general warning, possibly with details about any bound // 3PIDs that would be left behind. if (save && currentClientIdServer && fullUrl !== currentClientIdServer) { const [confirmed] = await this.showServerChangeWarning({ title: (0, _languageHandler._t)("identity_server|change"), unboundMessage: (0, _languageHandler._t)("identity_server|change_prompt", {}, { current: sub => /*#__PURE__*/_react.default.createElement("strong", null, (0, _UrlUtils.abbreviateUrl)(currentClientIdServer)), new: sub => /*#__PURE__*/_react.default.createElement("strong", null, (0, _UrlUtils.abbreviateUrl)(idServer)) }), button: (0, _languageHandler._t)("action|continue") }); save = !!confirmed; } if (save) { this.saveIdServer(fullUrl); } } catch (e) { _logger.logger.error(e); errStr = (0, _languageHandler._t)("identity_server|error_invalid_or_terms"); } } this.setState({ busy: false, checking: false, error: errStr ?? undefined, currentClientIdServer: _MatrixClientPeg.MatrixClientPeg.safeGet().getIdentityServerUrl() }); }); (0, _defineProperty2.default)(this, "onDisconnectClicked", async () => { this.setState({ disconnectBusy: true }); try { const [confirmed] = await this.showServerChangeWarning({ title: (0, _languageHandler._t)("identity_server|disconnect"), unboundMessage: (0, _languageHandler._t)("identity_server|disconnect_server", {}, { idserver: sub => /*#__PURE__*/_react.default.createElement("strong", null, (0, _UrlUtils.abbreviateUrl)(this.state.currentClientIdServer)) }), button: (0, _languageHandler._t)("action|disconnect") }); if (confirmed) { this.disconnectIdServer(); } } finally { this.setState({ disconnectBusy: false }); } }); (0, _defineProperty2.default)(this, "disconnectIdServer", () => { // Account data change will update localstorage, client, etc through dispatcher _MatrixClientPeg.MatrixClientPeg.safeGet().setAccountData("m.identity_server", { base_url: null // clear }); let newFieldVal = ""; if ((0, _IdentityServerUtils.getDefaultIdentityServerUrl)()) { // Prepopulate the client's default so the user at least has some idea of // a valid value they might enter newFieldVal = (0, _UrlUtils.abbreviateUrl)((0, _IdentityServerUtils.getDefaultIdentityServerUrl)()); } this.setState({ busy: false, error: undefined, currentClientIdServer: _MatrixClientPeg.MatrixClientPeg.safeGet().getIdentityServerUrl(), idServer: newFieldVal }); }); let defaultIdServer = ""; if (!_MatrixClientPeg.MatrixClientPeg.safeGet().getIdentityServerUrl() && (0, _IdentityServerUtils.getDefaultIdentityServerUrl)()) { // If no identity server is configured but there's one in the config, prepopulate // the field to help the user. defaultIdServer = (0, _UrlUtils.abbreviateUrl)((0, _IdentityServerUtils.getDefaultIdentityServerUrl)()); } this.state = { defaultIdServer, currentClientIdServer: _MatrixClientPeg.MatrixClientPeg.safeGet().getIdentityServerUrl(), idServer: "", busy: false, disconnectBusy: false, checking: false }; } componentDidMount() { this.dispatcherRef = _dispatcher.default.register(this.onAction); } componentWillUnmount() { if (this.dispatcherRef) _dispatcher.default.unregister(this.dispatcherRef); } showNoTermsWarning(fullUrl) { const { finished } = _Modal.default.createDialog(_QuestionDialog.default, { title: (0, _languageHandler._t)("terms|identity_server_no_terms_title"), description: /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("strong", { className: "warning" }, (0, _languageHandler._t)("identity_server|no_terms")), /*#__PURE__*/_react.default.createElement("span", null, "\xA0", (0, _languageHandler._t)("terms|identity_server_no_terms_description_2"))), button: (0, _languageHandler._t)("action|continue") }); return finished; } async showServerChangeWarning({ title, unboundMessage, button }) { const { currentClientIdServer } = this.state; let threepids = []; let currentServerReachable = true; try { threepids = await (0, _promise.timeout)((0, _boundThreepids.getThreepidsWithBindStatus)(_MatrixClientPeg.MatrixClientPeg.safeGet()), Promise.reject(new Error("Timeout attempting to reach identity server")), REACHABILITY_TIMEOUT); } catch (e) { currentServerReachable = false; _logger.logger.warn(`Unable to reach identity server at ${currentClientIdServer} to check ` + `for 3PIDs during IS change flow`); _logger.logger.warn(e); } const boundThreepids = threepids.filter(tp => tp.bound); let message; let danger = false; const messageElements = { idserver: sub => /*#__PURE__*/_react.default.createElement("strong", null, (0, _UrlUtils.abbreviateUrl)(currentClientIdServer)), b: sub => /*#__PURE__*/_react.default.createElement("strong", null, sub) }; if (!currentServerReachable) { message = /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("p", null, (0, _languageHandler._t)("identity_server|disconnect_offline_warning", {}, messageElements)), /*#__PURE__*/_react.default.createElement("p", null, (0, _languageHandler._t)("identity_server|suggestions")), /*#__PURE__*/_react.default.createElement("ul", null, /*#__PURE__*/_react.default.createElement("li", null, (0, _languageHandler._t)("identity_server|suggestions_1")), /*#__PURE__*/_react.default.createElement("li", null, (0, _languageHandler._t)("identity_server|suggestions_2", {}, { idserver: messageElements.idserver })), /*#__PURE__*/_react.default.createElement("li", null, (0, _languageHandler._t)("identity_server|suggestions_3")))); danger = true; button = (0, _languageHandler._t)("identity_server|disconnect_anyway"); } else if (boundThreepids.length) { message = /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("p", null, (0, _languageHandler._t)("identity_server|disconnect_personal_data_warning_1", {}, messageElements)), /*#__PURE__*/_react.default.createElement("p", null, (0, _languageHandler._t)("identity_server|disconnect_personal_data_warning_2"))); danger = true; button = (0, _languageHandler._t)("identity_server|disconnect_anyway"); } else { message = unboundMessage; } const { finished } = _Modal.default.createDialog(_QuestionDialog.default, { title, description: message, button, cancelButton: (0, _languageHandler._t)("action|go_back"), danger }); return finished; } render() { const idServerUrl = this.state.currentClientIdServer; let sectionTitle; let bodyText; if (idServerUrl) { sectionTitle = (0, _languageHandler._t)("identity_server|url", { server: (0, _UrlUtils.abbreviateUrl)(idServerUrl) }); bodyText = (0, _languageHandler._t)("identity_server|description_connected", {}, { server: sub => /*#__PURE__*/_react.default.createElement("strong", null, (0, _UrlUtils.abbreviateUrl)(idServerUrl)) }); if (this.props.missingTerms) { bodyText = (0, _languageHandler._t)("identity_server|change_server_prompt", {}, { server: sub => /*#__PURE__*/_react.default.createElement("strong", null, (0, _UrlUtils.abbreviateUrl)(idServerUrl)) }); } } else { sectionTitle = (0, _languageHandler._t)("common|identity_server"); bodyText = (0, _languageHandler._t)("identity_server|description_disconnected"); } let discoSection; if (idServerUrl) { let discoButtonContent = (0, _languageHandler._t)("action|disconnect"); let discoBodyText = (0, _languageHandler._t)("identity_server|disconnect_warning"); if (this.props.missingTerms) { discoBodyText = (0, _languageHandler._t)("identity_server|description_optional"); discoButtonContent = (0, _languageHandler._t)("identity_server|do_not_use"); } if (this.state.disconnectBusy) { discoButtonContent = /*#__PURE__*/_react.default.createElement(_InlineSpinner.default, null); } discoSection = /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_SettingsSubsection.SettingsSubsectionText, null, discoBodyText), /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, { onClick: this.onDisconnectClicked, kind: "danger_sm" }, discoButtonContent)); } return /*#__PURE__*/_react.default.createElement(_SettingsFieldset.default, { legend: sectionTitle, description: bodyText }, /*#__PURE__*/_react.default.createElement("form", { className: "mx_SetIdServer", onSubmit: this.checkIdServer }, /*#__PURE__*/_react.default.createElement(_Field.default, { label: (0, _languageHandler._t)("identity_server|url_field_label"), type: "text", autoComplete: "off", placeholder: this.state.defaultIdServer, value: this.state.idServer, onChange: this.onIdentityServerChanged, tooltipContent: this.getTooltip(), tooltipClassName: "mx_SetIdServer_tooltip", disabled: this.state.busy, forceValidity: this.state.error ? false : undefined }), /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, { type: "submit", kind: "primary_sm", onClick: this.checkIdServer, disabled: !this.idServerChangeEnabled() }, (0, _languageHandler._t)("action|change")), discoSection)); } } exports.default = SetIdServer; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfcmVhY3QiLCJfaW50ZXJvcFJlcXVpcmVEZWZhdWx0IiwicmVxdWlyZSIsIl9sb2dnZXIiLCJfbGFuZ3VhZ2VIYW5kbGVyIiwiX01hdHJpeENsaWVudFBlZyIsIl9Nb2RhbCIsIl9kaXNwYXRjaGVyIiwiX2JvdW5kVGhyZWVwaWRzIiwiX0lkZW50aXR5QXV0aENsaWVudCIsIl9VcmxVdGlscyIsIl9JZGVudGl0eVNlcnZlclV0aWxzIiwiX3Byb21pc2UiLCJfSW5saW5lU3Bpbm5lciIsIl9BY2Nlc3NpYmxlQnV0dG9uIiwiX0ZpZWxkIiwiX1F1ZXN0aW9uRGlhbG9nIiwiX1NldHRpbmdzRmllbGRzZXQiLCJfU2V0dGluZ3NTdWJzZWN0aW9uIiwiUkVBQ0hBQklMSVRZX1RJTUVPVVQiLCJjaGVja0lkZW50aXR5U2VydmVyVXJsIiwidSIsInBhcnNlZFVybCIsInBhcnNlVXJsIiwicHJvdG9jb2wiLCJfdCIsInJlc3BvbnNlIiwiZmV0Y2giLCJvayIsInN0YXR1cyIsImNvZGUiLCJlIiwiU2V0SWRTZXJ2ZXIiLCJSZWFjdCIsIkNvbXBvbmVudCIsImNvbnN0cnVjdG9yIiwicHJvcHMiLCJfZGVmaW5lUHJvcGVydHkyIiwiZGVmYXVsdCIsInBheWxvYWQiLCJhY3Rpb24iLCJzZXRTdGF0ZSIsImN1cnJlbnRDbGllbnRJZFNlcnZlciIsIk1hdHJpeENsaWVudFBlZyIsInNhZmVHZXQiLCJnZXRJZGVudGl0eVNlcnZlclVybCIsImV2IiwidGFyZ2V0IiwidmFsdWUiLCJpZFNlcnZlciIsInN0YXRlIiwiY2hlY2tpbmciLCJjcmVhdGVFbGVtZW50IiwiZXJyb3IiLCJjbGFzc05hbWUiLCJidXN5IiwiZnVsbFVybCIsInNldEFjY291bnREYXRhIiwiYmFzZV91cmwiLCJ1bmRlZmluZWQiLCJwcmV2ZW50RGVmYXVsdCIsInVuYWJicmV2aWF0ZVVybCIsImVyclN0ciIsImF1dGhDbGllbnQiLCJJZGVudGl0eUF1dGhDbGllbnQiLCJnZXRBY2Nlc3NUb2tlbiIsInNhdmUiLCJoYXNUZXJtcyIsImRvZXNJZGVudGl0eVNlcnZlckhhdmVUZXJtcyIsImNvbmZpcm1lZCIsInNob3dOb1Rlcm1zV2FybmluZyIsInNob3dTZXJ2ZXJDaGFuZ2VXYXJuaW5nIiwidGl0bGUiLCJ1bmJvdW5kTWVzc2FnZSIsImN1cnJlbnQiLCJzdWIiLCJhYmJyZXZpYXRlVXJsIiwibmV3IiwiYnV0dG9uIiwic2F2ZUlkU2VydmVyIiwibG9nZ2VyIiwiZGlzY29ubmVjdEJ1c3kiLCJpZHNlcnZlciIsImRpc2Nvbm5lY3RJZFNlcnZlciIsIm5ld0ZpZWxkVmFsIiwiZ2V0RGVmYXVsdElkZW50aXR5U2VydmVyVXJsIiwiZGVmYXVsdElkU2VydmVyIiwiY29tcG9uZW50RGlkTW91bnQiLCJkaXNwYXRjaGVyUmVmIiwiZGlzIiwicmVnaXN0ZXIiLCJvbkFjdGlvbiIsImNvbXBvbmVudFdpbGxVbm1vdW50IiwidW5yZWdpc3RlciIsImZpbmlzaGVkIiwiTW9kYWwiLCJjcmVhdGVEaWFsb2ciLCJRdWVzdGlvbkRpYWxvZyIsImRlc2NyaXB0aW9uIiwidGhyZWVwaWRzIiwiY3VycmVudFNlcnZlclJlYWNoYWJsZSIsInRpbWVvdXQiLCJnZXRUaHJlZXBpZHNXaXRoQmluZFN0YXR1cyIsIlByb21pc2UiLCJyZWplY3QiLCJFcnJvciIsIndhcm4iLCJib3VuZFRocmVlcGlkcyIsImZpbHRlciIsInRwIiwiYm91bmQiLCJtZXNzYWdlIiwiZGFuZ2VyIiwibWVzc2FnZUVsZW1lbnRzIiwiYiIsImxlbmd0aCIsImNhbmNlbEJ1dHRvbiIsInJlbmRlciIsImlkU2VydmVyVXJsIiwic2VjdGlvblRpdGxlIiwiYm9keVRleHQiLCJzZXJ2ZXIiLCJtaXNzaW5nVGVybXMiLCJkaXNjb1NlY3Rpb24iLCJkaXNjb0J1dHRvbkNvbnRlbnQiLCJkaXNjb0JvZHlUZXh0IiwiRnJhZ21lbnQiLCJTZXR0aW5nc1N1YnNlY3Rpb25UZXh0Iiwib25DbGljayIsIm9uRGlzY29ubmVjdENsaWNrZWQiLCJraW5kIiwibGVnZW5kIiwib25TdWJtaXQiLCJjaGVja0lkU2VydmVyIiwibGFiZWwiLCJ0eXBlIiwiYXV0b0NvbXBsZXRlIiwicGxhY2Vob2xkZXIiLCJvbkNoYW5nZSIsIm9uSWRlbnRpdHlTZXJ2ZXJDaGFuZ2VkIiwidG9vbHRpcENvbnRlbnQiLCJnZXRUb29sdGlwIiwidG9vbHRpcENsYXNzTmFtZSIsImRpc2FibGVkIiwiZm9yY2VWYWxpZGl0eSIsImlkU2VydmVyQ2hhbmdlRW5hYmxlZCIsImV4cG9ydHMiXSwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvY29tcG9uZW50cy92aWV3cy9zZXR0aW5ncy9TZXRJZFNlcnZlci50c3giXSwic291cmNlc0NvbnRlbnQiOlsiLypcbkNvcHlyaWdodCAyMDI0IE5ldyBWZWN0b3IgTHRkLlxuQ29weXJpZ2h0IDIwMTktMjAyMSBUaGUgTWF0cml4Lm9yZyBGb3VuZGF0aW9uIEMuSS5DLlxuXG5TUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQUdQTC0zLjAtb25seSBPUiBHUEwtMy4wLW9ubHlcblBsZWFzZSBzZWUgTElDRU5TRSBmaWxlcyBpbiB0aGUgcmVwb3NpdG9yeSByb290IGZvciBmdWxsIGRldGFpbHMuXG4qL1xuXG5pbXBvcnQgUmVhY3QsIHsgUmVhY3ROb2RlIH0gZnJvbSBcInJlYWN0XCI7XG5pbXBvcnQgeyBsb2dnZXIgfSBmcm9tIFwibWF0cml4LWpzLXNkay9zcmMvbG9nZ2VyXCI7XG5pbXBvcnQgeyBJVGhyZWVwaWQgfSBmcm9tIFwibWF0cml4LWpzLXNkay9zcmMvbWF0cml4XCI7XG5cbmltcG9ydCB7IF90IH0gZnJvbSBcIi4uLy4uLy4uL2xhbmd1YWdlSGFuZGxlclwiO1xuaW1wb3J0IHsgTWF0cml4Q2xpZW50UGVnIH0gZnJvbSBcIi4uLy4uLy4uL01hdHJpeENsaWVudFBlZ1wiO1xuaW1wb3J0IE1vZGFsIGZyb20gXCIuLi8uLi8uLi9Nb2RhbFwiO1xuaW1wb3J0IGRpcyBmcm9tIFwiLi4vLi4vLi4vZGlzcGF0Y2hlci9kaXNwYXRjaGVyXCI7XG5pbXBvcnQgeyBnZXRUaHJlZXBpZHNXaXRoQmluZFN0YXR1cyB9IGZyb20gXCIuLi8uLi8uLi9ib3VuZFRocmVlcGlkc1wiO1xuaW1wb3J0IElkZW50aXR5QXV0aENsaWVudCBmcm9tIFwiLi4vLi4vLi4vSWRlbnRpdHlBdXRoQ2xpZW50XCI7XG5pbXBvcnQgeyBhYmJyZXZpYXRlVXJsLCBwYXJzZVVybCwgdW5hYmJyZXZpYXRlVXJsIH0gZnJvbSBcIi4uLy4uLy4uL3V0aWxzL1VybFV0aWxzXCI7XG5pbXBvcnQgeyBnZXREZWZhdWx0SWRlbnRpdHlTZXJ2ZXJVcmwsIGRvZXNJZGVudGl0eVNlcnZlckhhdmVUZXJtcyB9IGZyb20gXCIuLi8uLi8uLi91dGlscy9JZGVudGl0eVNlcnZlclV0aWxzXCI7XG5pbXBvcnQgeyB0aW1lb3V0IH0gZnJvbSBcIi4uLy4uLy4uL3V0aWxzL3Byb21pc2VcIjtcbmltcG9ydCB7IEFjdGlvblBheWxvYWQgfSBmcm9tIFwiLi4vLi4vLi4vZGlzcGF0Y2hlci9wYXlsb2Fkc1wiO1xuaW1wb3J0IElubGluZVNwaW5uZXIgZnJvbSBcIi4uL2VsZW1lbnRzL0lubGluZVNwaW5uZXJcIjtcbmltcG9ydCBBY2Nlc3NpYmxlQnV0dG9uIGZyb20gXCIuLi9lbGVtZW50cy9BY2Nlc3NpYmxlQnV0dG9uXCI7XG5pbXBvcnQgRmllbGQgZnJvbSBcIi4uL2VsZW1lbnRzL0ZpZWxkXCI7XG5pbXBvcnQgUXVlc3Rpb25EaWFsb2cgZnJvbSBcIi4uL2RpYWxvZ3MvUXVlc3Rpb25EaWFsb2dcIjtcbmltcG9ydCBTZXR0aW5nc0ZpZWxkc2V0IGZyb20gXCIuL1NldHRpbmdzRmllbGRzZXRcIjtcbmltcG9ydCB7IFNldHRpbmdzU3Vic2VjdGlvblRleHQgfSBmcm9tIFwiLi9zaGFyZWQvU2V0dGluZ3NTdWJzZWN0aW9uXCI7XG5cbi8vIFdlJ2xsIHdhaXQgdXAgdG8gdGhpcyBsb25nIHdoZW4gY2hlY2tpbmcgZm9yIDNQSUQgYmluZGluZ3Mgb24gdGhlIElTLlxuY29uc3QgUkVBQ0hBQklMSVRZX1RJTUVPVVQgPSAxMDAwMDsgLy8gbXNcblxuLyoqXG4gKiBDaGVjayBhbiBJUyBVUkwgaXMgdmFsaWQsIGluY2x1ZGluZyBsaXZlbmVzcyBjaGVja1xuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSB1IFRoZSB1cmwgdG8gY2hlY2tcbiAqIEByZXR1cm5zIHtzdHJpbmd9IG51bGwgaWYgdXJsIHBhc3NlcyBhbGwgY2hlY2tzLCBvdGhlcndpc2UgaTE4bmVkIGVycm9yIHN0cmluZ1xuICovXG5hc3luYyBmdW5jdGlvbiBjaGVja0lkZW50aXR5U2VydmVyVXJsKHU6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nIHwgbnVsbD4ge1xuICAgIGNvbnN0IHBhcnNlZFVybCA9IHBhcnNlVXJsKHUpO1xuXG4gICAgaWYgKHBhcnNlZFVybC5wcm90b2NvbCAhPT0gXCJodHRwczpcIikgcmV0dXJuIF90KFwiaWRlbnRpdHlfc2VydmVyfHVybF9ub3RfaHR0cHNcIik7XG5cbiAgICAvLyBYWFg6IGR1cGxpY2F0ZWQgbG9naWMgZnJvbSBqcy1zZGsgYnV0IGl0J3MgcXVpdGUgdGllZCB1cCBpbiB0aGUgdmFsaWRhdGlvbiBsb2dpYyBpbiB0aGVcbiAgICAvLyBqcy1zZGsgc28gcHJvYmFibHkgYXMgZWFzeSB0byBkdXBsaWNhdGUgaXQgdGhhbiB0byBzZXBhcmF0ZSBpdCBvdXQgc28gd2UgY2FuIHJldXNlIGl0XG4gICAgdHJ5IHtcbiAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaCh1ICsgXCIvX21hdHJpeC9pZGVudGl0eS92MlwiKTtcbiAgICAgICAgaWYgKHJlc3BvbnNlLm9rKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfSBlbHNlIGlmIChyZXNwb25zZS5zdGF0dXMgPCAyMDAgfHwgcmVzcG9uc2Uuc3RhdHVzID49IDMwMCkge1xuICAgICAgICAgICAgcmV0dXJuIF90KFwiaWRlbnRpdHlfc2VydmVyfGVycm9yX2ludmFsaWRcIiwgeyBjb2RlOiByZXNwb25zZS5zdGF0dXMgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gX3QoXCJpZGVudGl0eV9zZXJ2ZXJ8ZXJyb3JfY29ubmVjdGlvblwiKTtcbiAgICAgICAgfVxuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgcmV0dXJuIF90KFwiaWRlbnRpdHlfc2VydmVyfGVycm9yX2Nvbm5lY3Rpb25cIik7XG4gICAgfVxufVxuXG5pbnRlcmZhY2UgSVByb3BzIHtcbiAgICAvLyBXaGV0aGVyIG9yIG5vdCB0aGUgaWRlbnRpdHkgc2VydmVyIGlzIG1pc3NpbmcgdGVybXMuIFRoaXMgYWZmZWN0cyB0aGUgdGV4dFxuICAgIC8vIHNob3duIHRvIHRoZSB1c2VyLlxuICAgIG1pc3NpbmdUZXJtczogYm9vbGVhbjtcbn1cblxuaW50ZXJmYWNlIElTdGF0ZSB7XG4gICAgZGVmYXVsdElkU2VydmVyPzogc3RyaW5nO1xuICAgIGN1cnJlbnRDbGllbnRJZFNlcnZlcj86IHN0cmluZztcbiAgICBpZFNlcnZlcjogc3RyaW5nO1xuICAgIGVycm9yPzogc3RyaW5nO1xuICAgIGJ1c3k6IGJvb2xlYW47XG4gICAgZGlzY29ubmVjdEJ1c3k6IGJvb2xlYW47XG4gICAgY2hlY2tpbmc6IGJvb2xlYW47XG59XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFNldElkU2VydmVyIGV4dGVuZHMgUmVhY3QuQ29tcG9uZW50PElQcm9wcywgSVN0YXRlPiB7XG4gICAgcHJpdmF0ZSBkaXNwYXRjaGVyUmVmPzogc3RyaW5nO1xuXG4gICAgcHVibGljIGNvbnN0cnVjdG9yKHByb3BzOiBJUHJvcHMpIHtcbiAgICAgICAgc3VwZXIocHJvcHMpO1xuXG4gICAgICAgIGxldCBkZWZhdWx0SWRTZXJ2ZXIgPSBcIlwiO1xuICAgICAgICBpZiAoIU1hdHJpeENsaWVudFBlZy5zYWZlR2V0KCkuZ2V0SWRlbnRpdHlTZXJ2ZXJVcmwoKSAmJiBnZXREZWZhdWx0SWRlbnRpdHlTZXJ2ZXJVcmwoKSkge1xuICAgICAgICAgICAgLy8gSWYgbm8gaWRlbnRpdHkgc2VydmVyIGlzIGNvbmZpZ3VyZWQgYnV0IHRoZXJlJ3Mgb25lIGluIHRoZSBjb25maWcsIHByZXBvcHVsYXRlXG4gICAgICAgICAgICAvLyB0aGUgZmllbGQgdG8gaGVscCB0aGUgdXNlci5cbiAgICAgICAgICAgIGRlZmF1bHRJZFNlcnZlciA9IGFiYnJldmlhdGVVcmwoZ2V0RGVmYXVsdElkZW50aXR5U2VydmVyVXJsKCkpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5zdGF0ZSA9IHtcbiAgICAgICAgICAgIGRlZmF1bHRJZFNlcnZlcixcbiAgICAgICAgICAgIGN1cnJlbnRDbGllbnRJZFNlcnZlcjogTWF0cml4Q2xpZW50UGVnLnNhZmVHZXQoKS5nZXRJZGVudGl0eVNlcnZlclVybCgpLFxuICAgICAgICAgICAgaWRTZXJ2ZXI6IFwiXCIsXG4gICAgICAgICAgICBidXN5OiBmYWxzZSxcbiAgICAgICAgICAgIGRpc2Nvbm5lY3RCdXN5OiBmYWxzZSxcbiAgICAgICAgICAgIGNoZWNraW5nOiBmYWxzZSxcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBwdWJsaWMgY29tcG9uZW50RGlkTW91bnQoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZGlzcGF0Y2hlclJlZiA9IGRpcy5yZWdpc3Rlcih0aGlzLm9uQWN0aW9uKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgY29tcG9uZW50V2lsbFVubW91bnQoKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLmRpc3BhdGNoZXJSZWYpIGRpcy51bnJlZ2lzdGVyKHRoaXMuZGlzcGF0Y2hlclJlZik7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBvbkFjdGlvbiA9IChwYXlsb2FkOiBBY3Rpb25QYXlsb2FkKTogdm9pZCA9PiB7XG4gICAgICAgIC8vIFdlIHJlYWN0IHRvIGNoYW5nZXMgaW4gdGhlIGlkZW50aXR5IHNlcnZlciBpbiB0aGUgZXZlbnQgdGhlIHVzZXIgaXMgc3RhcmluZyBhdCB0aGlzIGZvcm1cbiAgICAgICAgLy8gd2hlbiBjaGFuZ2luZyB0aGVpciBpZGVudGl0eSBzZXJ2ZXIgb24gYW5vdGhlciBkZXZpY2UuXG4gICAgICAgIGlmIChwYXlsb2FkLmFjdGlvbiAhPT0gXCJpZF9zZXJ2ZXJfY2hhbmdlZFwiKSByZXR1cm47XG5cbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICBjdXJyZW50Q2xpZW50SWRTZXJ2ZXI6IE1hdHJpeENsaWVudFBlZy5zYWZlR2V0KCkuZ2V0SWRlbnRpdHlTZXJ2ZXJVcmwoKSxcbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIHByaXZhdGUgb25JZGVudGl0eVNlcnZlckNoYW5nZWQgPSAoZXY6IFJlYWN0LkNoYW5nZUV2ZW50PEhUTUxJbnB1dEVsZW1lbnQ+KTogdm9pZCA9PiB7XG4gICAgICAgIGNvbnN0IHUgPSBldi50YXJnZXQudmFsdWU7XG5cbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7IGlkU2VydmVyOiB1IH0pO1xuICAgIH07XG5cbiAgICBwcml2YXRlIGdldFRvb2x0aXAgPSAoKTogUmVhY3ROb2RlID0+IHtcbiAgICAgICAgaWYgKHRoaXMuc3RhdGUuY2hlY2tpbmcpIHtcbiAgICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAgICAgPGRpdj5cbiAgICAgICAgICAgICAgICAgICAgPElubGluZVNwaW5uZXIgLz5cbiAgICAgICAgICAgICAgICAgICAge190KFwiaWRlbnRpdHlfc2VydmVyfGNoZWNraW5nXCIpfVxuICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLnN0YXRlLmVycm9yKSB7XG4gICAgICAgICAgICByZXR1cm4gPHN0cm9uZyBjbGFzc05hbWU9XCJ3YXJuaW5nXCI+e3RoaXMuc3RhdGUuZXJyb3J9PC9zdHJvbmc+O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgcHJpdmF0ZSBpZFNlcnZlckNoYW5nZUVuYWJsZWQgPSAoKTogYm9vbGVhbiA9PiB7XG4gICAgICAgIHJldHVybiAhIXRoaXMuc3RhdGUuaWRTZXJ2ZXIgJiYgIXRoaXMuc3RhdGUuYnVzeTtcbiAgICB9O1xuXG4gICAgcHJpdmF0ZSBzYXZlSWRTZXJ2ZXIgPSAoZnVsbFVybDogc3RyaW5nKTogdm9pZCA9PiB7XG4gICAgICAgIC8vIEFjY291bnQgZGF0YSBjaGFuZ2Ugd2lsbCB1cGRhdGUgbG9jYWxzdG9yYWdlLCBjbGllbnQsIGV0YyB0aHJvdWdoIGRpc3BhdGNoZXJcbiAgICAgICAgTWF0cml4Q2xpZW50UGVnLnNhZmVHZXQoKS5zZXRBY2NvdW50RGF0YShcIm0uaWRlbnRpdHlfc2VydmVyXCIsIHtcbiAgICAgICAgICAgIGJhc2VfdXJsOiBmdWxsVXJsLFxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICBidXN5OiBmYWxzZSxcbiAgICAgICAgICAgIGVycm9yOiB1bmRlZmluZWQsXG4gICAgICAgICAgICBjdXJyZW50Q2xpZW50SWRTZXJ2ZXI6IGZ1bGxVcmwsXG4gICAgICAgICAgICBpZFNlcnZlcjogXCJcIixcbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIHByaXZhdGUgY2hlY2tJZFNlcnZlciA9IGFzeW5jIChlOiBSZWFjdC5TeW50aGV0aWNFdmVudCk6IFByb21pc2U8dm9pZD4gPT4ge1xuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIGNvbnN0IHsgaWRTZXJ2ZXIsIGN1cnJlbnRDbGllbnRJZFNlcnZlciB9ID0gdGhpcy5zdGF0ZTtcblxuICAgICAgICB0aGlzLnNldFN0YXRlKHsgYnVzeTogdHJ1ZSwgY2hlY2tpbmc6IHRydWUsIGVycm9yOiB1bmRlZmluZWQgfSk7XG5cbiAgICAgICAgY29uc3QgZnVsbFVybCA9IHVuYWJicmV2aWF0ZVVybChpZFNlcnZlcik7XG5cbiAgICAgICAgbGV0IGVyclN0ciA9IGF3YWl0IGNoZWNrSWRlbnRpdHlTZXJ2ZXJVcmwoZnVsbFVybCk7XG4gICAgICAgIGlmICghZXJyU3RyKSB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoeyBjaGVja2luZzogZmFsc2UgfSk7IC8vIGNsZWFyIHRvb2x0aXBcblxuICAgICAgICAgICAgICAgIC8vIFRlc3QgdGhlIGlkZW50aXR5IHNlcnZlciBieSB0cnlpbmcgdG8gcmVnaXN0ZXIgd2l0aCBpdC4gVGhpc1xuICAgICAgICAgICAgICAgIC8vIG1heSByZXN1bHQgaW4gYSB0ZXJtcyBvZiBzZXJ2aWNlIHByb21wdC5cbiAgICAgICAgICAgICAgICBjb25zdCBhdXRoQ2xpZW50ID0gbmV3IElkZW50aXR5QXV0aENsaWVudChmdWxsVXJsKTtcbiAgICAgICAgICAgICAgICBhd2FpdCBhdXRoQ2xpZW50LmdldEFjY2Vzc1Rva2VuKCk7XG5cbiAgICAgICAgICAgICAgICBsZXQgc2F2ZSA9IHRydWU7XG5cbiAgICAgICAgICAgICAgICAvLyBEb3VibGUgY2hlY2sgdGhhdCB0aGUgaWRlbnRpdHkgc2VydmVyIGV2ZW4gaGFzIHRlcm1zIG9mIHNlcnZpY2UuXG4gICAgICAgICAgICAgICAgY29uc3QgaGFzVGVybXMgPSBhd2FpdCBkb2VzSWRlbnRpdHlTZXJ2ZXJIYXZlVGVybXMoTWF0cml4Q2xpZW50UGVnLnNhZmVHZXQoKSwgZnVsbFVybCk7XG4gICAgICAgICAgICAgICAgaWYgKCFoYXNUZXJtcykge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBbY29uZmlybWVkXSA9IGF3YWl0IHRoaXMuc2hvd05vVGVybXNXYXJuaW5nKGZ1bGxVcmwpO1xuICAgICAgICAgICAgICAgICAgICBzYXZlID0gISFjb25maXJtZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gU2hvdyBhIGdlbmVyYWwgd2FybmluZywgcG9zc2libHkgd2l0aCBkZXRhaWxzIGFib3V0IGFueSBib3VuZFxuICAgICAgICAgICAgICAgIC8vIDNQSURzIHRoYXQgd291bGQgYmUgbGVmdCBiZWhpbmQuXG4gICAgICAgICAgICAgICAgaWYgKHNhdmUgJiYgY3VycmVudENsaWVudElkU2VydmVyICYmIGZ1bGxVcmwgIT09IGN1cnJlbnRDbGllbnRJZFNlcnZlcikge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBbY29uZmlybWVkXSA9IGF3YWl0IHRoaXMuc2hvd1NlcnZlckNoYW5nZVdhcm5pbmcoe1xuICAgICAgICAgICAgICAgICAgICAgICAgdGl0bGU6IF90KFwiaWRlbnRpdHlfc2VydmVyfGNoYW5nZVwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHVuYm91bmRNZXNzYWdlOiBfdChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImlkZW50aXR5X3NlcnZlcnxjaGFuZ2VfcHJvbXB0XCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAge30sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50OiAoc3ViKSA9PiA8c3Ryb25nPnthYmJyZXZpYXRlVXJsKGN1cnJlbnRDbGllbnRJZFNlcnZlcil9PC9zdHJvbmc+LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXc6IChzdWIpID0+IDxzdHJvbmc+e2FiYnJldmlhdGVVcmwoaWRTZXJ2ZXIpfTwvc3Ryb25nPixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGJ1dHRvbjogX3QoXCJhY3Rpb258Y29udGludWVcIiksXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICBzYXZlID0gISFjb25maXJtZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKHNhdmUpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zYXZlSWRTZXJ2ZXIoZnVsbFVybCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIGxvZ2dlci5lcnJvcihlKTtcbiAgICAgICAgICAgICAgICBlcnJTdHIgPSBfdChcImlkZW50aXR5X3NlcnZlcnxlcnJvcl9pbnZhbGlkX29yX3Rlcm1zXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgYnVzeTogZmFsc2UsXG4gICAgICAgICAgICBjaGVja2luZzogZmFsc2UsXG4gICAgICAgICAgICBlcnJvcjogZXJyU3RyID8/IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIGN1cnJlbnRDbGllbnRJZFNlcnZlcjogTWF0cml4Q2xpZW50UGVnLnNhZmVHZXQoKS5nZXRJZGVudGl0eVNlcnZlclVybCgpLFxuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgcHJpdmF0ZSBzaG93Tm9UZXJtc1dhcm5pbmcoZnVsbFVybDogc3RyaW5nKTogUHJvbWlzZTxbb2s/OiBib29sZWFuXT4ge1xuICAgICAgICBjb25zdCB7IGZpbmlzaGVkIH0gPSBNb2RhbC5jcmVhdGVEaWFsb2coUXVlc3Rpb25EaWFsb2csIHtcbiAgICAgICAgICAgIHRpdGxlOiBfdChcInRlcm1zfGlkZW50aXR5X3NlcnZlcl9ub190ZXJtc190aXRsZVwiKSxcbiAgICAgICAgICAgIGRlc2NyaXB0aW9uOiAoXG4gICAgICAgICAgICAgICAgPGRpdj5cbiAgICAgICAgICAgICAgICAgICAgPHN0cm9uZyBjbGFzc05hbWU9XCJ3YXJuaW5nXCI+e190KFwiaWRlbnRpdHlfc2VydmVyfG5vX3Rlcm1zXCIpfTwvc3Ryb25nPlxuICAgICAgICAgICAgICAgICAgICA8c3Bhbj4mbmJzcDt7X3QoXCJ0ZXJtc3xpZGVudGl0eV9zZXJ2ZXJfbm9fdGVybXNfZGVzY3JpcHRpb25fMlwiKX08L3NwYW4+XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgYnV0dG9uOiBfdChcImFjdGlvbnxjb250aW51ZVwiKSxcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBmaW5pc2hlZDtcbiAgICB9XG5cbiAgICBwcml2YXRlIG9uRGlzY29ubmVjdENsaWNrZWQgPSBhc3luYyAoKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoeyBkaXNjb25uZWN0QnVzeTogdHJ1ZSB9KTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IFtjb25maXJtZWRdID0gYXdhaXQgdGhpcy5zaG93U2VydmVyQ2hhbmdlV2FybmluZyh7XG4gICAgICAgICAgICAgICAgdGl0bGU6IF90KFwiaWRlbnRpdHlfc2VydmVyfGRpc2Nvbm5lY3RcIiksXG4gICAgICAgICAgICAgICAgdW5ib3VuZE1lc3NhZ2U6IF90KFxuICAgICAgICAgICAgICAgICAgICBcImlkZW50aXR5X3NlcnZlcnxkaXNjb25uZWN0X3NlcnZlclwiLFxuICAgICAgICAgICAgICAgICAgICB7fSxcbiAgICAgICAgICAgICAgICAgICAgeyBpZHNlcnZlcjogKHN1YikgPT4gPHN0cm9uZz57YWJicmV2aWF0ZVVybCh0aGlzLnN0YXRlLmN1cnJlbnRDbGllbnRJZFNlcnZlcil9PC9zdHJvbmc+IH0sXG4gICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICBidXR0b246IF90KFwiYWN0aW9ufGRpc2Nvbm5lY3RcIiksXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGlmIChjb25maXJtZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmRpc2Nvbm5lY3RJZFNlcnZlcigpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGZpbmFsbHkge1xuICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7IGRpc2Nvbm5lY3RCdXN5OiBmYWxzZSB9KTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBwcml2YXRlIGFzeW5jIHNob3dTZXJ2ZXJDaGFuZ2VXYXJuaW5nKHtcbiAgICAgICAgdGl0bGUsXG4gICAgICAgIHVuYm91bmRNZXNzYWdlLFxuICAgICAgICBidXR0b24sXG4gICAgfToge1xuICAgICAgICB0aXRsZTogc3RyaW5nO1xuICAgICAgICB1bmJvdW5kTWVzc2FnZTogUmVhY3ROb2RlO1xuICAgICAgICBidXR0b246IHN0cmluZztcbiAgICB9KTogUHJvbWlzZTxbb2s/OiBib29sZWFuXT4ge1xuICAgICAgICBjb25zdCB7IGN1cnJlbnRDbGllbnRJZFNlcnZlciB9ID0gdGhpcy5zdGF0ZTtcblxuICAgICAgICBsZXQgdGhyZWVwaWRzOiBJVGhyZWVwaWRbXSA9IFtdO1xuICAgICAgICBsZXQgY3VycmVudFNlcnZlclJlYWNoYWJsZSA9IHRydWU7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICB0aHJlZXBpZHMgPSBhd2FpdCB0aW1lb3V0KFxuICAgICAgICAgICAgICAgIGdldFRocmVlcGlkc1dpdGhCaW5kU3RhdHVzKE1hdHJpeENsaWVudFBlZy5zYWZlR2V0KCkpLFxuICAgICAgICAgICAgICAgIFByb21pc2UucmVqZWN0KG5ldyBFcnJvcihcIlRpbWVvdXQgYXR0ZW1wdGluZyB0byByZWFjaCBpZGVudGl0eSBzZXJ2ZXJcIikpLFxuICAgICAgICAgICAgICAgIFJFQUNIQUJJTElUWV9USU1FT1VULFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgY3VycmVudFNlcnZlclJlYWNoYWJsZSA9IGZhbHNlO1xuICAgICAgICAgICAgbG9nZ2VyLndhcm4oXG4gICAgICAgICAgICAgICAgYFVuYWJsZSB0byByZWFjaCBpZGVudGl0eSBzZXJ2ZXIgYXQgJHtjdXJyZW50Q2xpZW50SWRTZXJ2ZXJ9IHRvIGNoZWNrIGAgK1xuICAgICAgICAgICAgICAgICAgICBgZm9yIDNQSURzIGR1cmluZyBJUyBjaGFuZ2UgZmxvd2AsXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgbG9nZ2VyLndhcm4oZSk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgYm91bmRUaHJlZXBpZHMgPSB0aHJlZXBpZHMuZmlsdGVyKCh0cCkgPT4gdHAuYm91bmQpO1xuICAgICAgICBsZXQgbWVzc2FnZTtcbiAgICAgICAgbGV0IGRhbmdlciA9IGZhbHNlO1xuICAgICAgICBjb25zdCBtZXNzYWdlRWxlbWVudHMgPSB7XG4gICAgICAgICAgICBpZHNlcnZlcjogKHN1Yjogc3RyaW5nKSA9PiA8c3Ryb25nPnthYmJyZXZpYXRlVXJsKGN1cnJlbnRDbGllbnRJZFNlcnZlcil9PC9zdHJvbmc+LFxuICAgICAgICAgICAgYjogKHN1Yjogc3RyaW5nKSA9PiA8c3Ryb25nPntzdWJ9PC9zdHJvbmc+LFxuICAgICAgICB9O1xuICAgICAgICBpZiAoIWN1cnJlbnRTZXJ2ZXJSZWFjaGFibGUpIHtcbiAgICAgICAgICAgIG1lc3NhZ2UgPSAoXG4gICAgICAgICAgICAgICAgPGRpdj5cbiAgICAgICAgICAgICAgICAgICAgPHA+e190KFwiaWRlbnRpdHlfc2VydmVyfGRpc2Nvbm5lY3Rfb2ZmbGluZV93YXJuaW5nXCIsIHt9LCBtZXNzYWdlRWxlbWVudHMpfTwvcD5cbiAgICAgICAgICAgICAgICAgICAgPHA+e190KFwiaWRlbnRpdHlfc2VydmVyfHN1Z2dlc3Rpb25zXCIpfTwvcD5cbiAgICAgICAgICAgICAgICAgICAgPHVsPlxuICAgICAgICAgICAgICAgICAgICAgICAgPGxpPntfdChcImlkZW50aXR5X3NlcnZlcnxzdWdnZXN0aW9uc18xXCIpfTwvbGk+XG4gICAgICAgICAgICAgICAgICAgICAgICA8bGk+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAge190KFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImlkZW50aXR5X3NlcnZlcnxzdWdnZXN0aW9uc18yXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHt9LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZHNlcnZlcjogbWVzc2FnZUVsZW1lbnRzLmlkc2VydmVyLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICl9XG4gICAgICAgICAgICAgICAgICAgICAgICA8L2xpPlxuICAgICAgICAgICAgICAgICAgICAgICAgPGxpPntfdChcImlkZW50aXR5X3NlcnZlcnxzdWdnZXN0aW9uc18zXCIpfTwvbGk+XG4gICAgICAgICAgICAgICAgICAgIDwvdWw+XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgZGFuZ2VyID0gdHJ1ZTtcbiAgICAgICAgICAgIGJ1dHRvbiA9IF90KFwiaWRlbnRpdHlfc2VydmVyfGRpc2Nvbm5lY3RfYW55d2F5XCIpO1xuICAgICAgICB9IGVsc2UgaWYgKGJvdW5kVGhyZWVwaWRzLmxlbmd0aCkge1xuICAgICAgICAgICAgbWVzc2FnZSA9IChcbiAgICAgICAgICAgICAgICA8ZGl2PlxuICAgICAgICAgICAgICAgICAgICA8cD57X3QoXCJpZGVudGl0eV9zZXJ2ZXJ8ZGlzY29ubmVjdF9wZXJzb25hbF9kYXRhX3dhcm5pbmdfMVwiLCB7fSwgbWVzc2FnZUVsZW1lbnRzKX08L3A+XG4gICAgICAgICAgICAgICAgICAgIDxwPntfdChcImlkZW50aXR5X3NlcnZlcnxkaXNjb25uZWN0X3BlcnNvbmFsX2RhdGFfd2FybmluZ18yXCIpfTwvcD5cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBkYW5nZXIgPSB0cnVlO1xuICAgICAgICAgICAgYnV0dG9uID0gX3QoXCJpZGVudGl0eV9zZXJ2ZXJ8ZGlzY29ubmVjdF9hbnl3YXlcIik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBtZXNzYWdlID0gdW5ib3VuZE1lc3NhZ2U7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCB7IGZpbmlzaGVkIH0gPSBNb2RhbC5jcmVhdGVEaWFsb2coUXVlc3Rpb25EaWFsb2csIHtcbiAgICAgICAgICAgIHRpdGxlLFxuICAgICAgICAgICAgZGVzY3JpcHRpb246IG1lc3NhZ2UsXG4gICAgICAgICAgICBidXR0b24sXG4gICAgICAgICAgICBjYW5jZWxCdXR0b246IF90KFwiYWN0aW9ufGdvX2JhY2tcIiksXG4gICAgICAgICAgICBkYW5nZXIsXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gZmluaXNoZWQ7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBkaXNjb25uZWN0SWRTZXJ2ZXIgPSAoKTogdm9pZCA9PiB7XG4gICAgICAgIC8vIEFjY291bnQgZGF0YSBjaGFuZ2Ugd2lsbCB1cGRhdGUgbG9jYWxzdG9yYWdlLCBjbGllbnQsIGV0YyB0aHJvdWdoIGRpc3BhdGNoZXJcbiAgICAgICAgTWF0cml4Q2xpZW50UGVnLnNhZmVHZXQoKS5zZXRBY2NvdW50RGF0YShcIm0uaWRlbnRpdHlfc2VydmVyXCIsIHtcbiAgICAgICAgICAgIGJhc2VfdXJsOiBudWxsLCAvLyBjbGVhclxuICAgICAgICB9KTtcblxuICAgICAgICBsZXQgbmV3RmllbGRWYWwgPSBcIlwiO1xuICAgICAgICBpZiAoZ2V0RGVmYXVsdElkZW50aXR5U2VydmVyVXJsKCkpIHtcbiAgICAgICAgICAgIC8vIFByZXBvcHVsYXRlIHRoZSBjbGllbnQncyBkZWZhdWx0IHNvIHRoZSB1c2VyIGF0IGxlYXN0IGhhcyBzb21lIGlkZWEgb2ZcbiAgICAgICAgICAgIC8vIGEgdmFsaWQgdmFsdWUgdGhleSBtaWdodCBlbnRlclxuICAgICAgICAgICAgbmV3RmllbGRWYWwgPSBhYmJyZXZpYXRlVXJsKGdldERlZmF1bHRJZGVudGl0eVNlcnZlclVybCgpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgYnVzeTogZmFsc2UsXG4gICAgICAgICAgICBlcnJvcjogdW5kZWZpbmVkLFxuICAgICAgICAgICAgY3VycmVudENsaWVudElkU2VydmVyOiBNYXRyaXhDbGllbnRQZWcuc2FmZUdldCgpLmdldElkZW50aXR5U2VydmVyVXJsKCksXG4gICAgICAgICAgICBpZFNlcnZlcjogbmV3RmllbGRWYWwsXG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICBwdWJsaWMgcmVuZGVyKCk6IFJlYWN0LlJlYWN0Tm9kZSB7XG4gICAgICAgIGNvbnN0IGlkU2VydmVyVXJsID0gdGhpcy5zdGF0ZS5jdXJyZW50Q2xpZW50SWRTZXJ2ZXI7XG4gICAgICAgIGxldCBzZWN0aW9uVGl0bGU7XG4gICAgICAgIGxldCBib2R5VGV4dDtcbiAgICAgICAgaWYgKGlkU2VydmVyVXJsKSB7XG4gICAgICAgICAgICBzZWN0aW9uVGl0bGUgPSBfdChcImlkZW50aXR5X3NlcnZlcnx1cmxcIiwgeyBzZXJ2ZXI6IGFiYnJldmlhdGVVcmwoaWRTZXJ2ZXJVcmwpIH0pO1xuICAgICAgICAgICAgYm9keVRleHQgPSBfdChcbiAgICAgICAgICAgICAgICBcImlkZW50aXR5X3NlcnZlcnxkZXNjcmlwdGlvbl9jb25uZWN0ZWRcIixcbiAgICAgICAgICAgICAgICB7fSxcbiAgICAgICAgICAgICAgICB7IHNlcnZlcjogKHN1YikgPT4gPHN0cm9uZz57YWJicmV2aWF0ZVVybChpZFNlcnZlclVybCl9PC9zdHJvbmc+IH0sXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgaWYgKHRoaXMucHJvcHMubWlzc2luZ1Rlcm1zKSB7XG4gICAgICAgICAgICAgICAgYm9keVRleHQgPSBfdChcbiAgICAgICAgICAgICAgICAgICAgXCJpZGVudGl0eV9zZXJ2ZXJ8Y2hhbmdlX3NlcnZlcl9wcm9tcHRcIixcbiAgICAgICAgICAgICAgICAgICAge30sXG4gICAgICAgICAgICAgICAgICAgIHsgc2VydmVyOiAoc3ViKSA9PiA8c3Ryb25nPnthYmJyZXZpYXRlVXJsKGlkU2VydmVyVXJsKX08L3N0cm9uZz4gfSxcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc2VjdGlvblRpdGxlID0gX3QoXCJjb21tb258aWRlbnRpdHlfc2VydmVyXCIpO1xuICAgICAgICAgICAgYm9keVRleHQgPSBfdChcImlkZW50aXR5X3NlcnZlcnxkZXNjcmlwdGlvbl9kaXNjb25uZWN0ZWRcIik7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgZGlzY29TZWN0aW9uO1xuICAgICAgICBpZiAoaWRTZXJ2ZXJVcmwpIHtcbiAgICAgICAgICAgIGxldCBkaXNjb0J1dHRvbkNvbnRlbnQ6IFJlYWN0LlJlYWN0Tm9kZSA9IF90KFwiYWN0aW9ufGRpc2Nvbm5lY3RcIik7XG4gICAgICAgICAgICBsZXQgZGlzY29Cb2R5VGV4dCA9IF90KFwiaWRlbnRpdHlfc2VydmVyfGRpc2Nvbm5lY3Rfd2FybmluZ1wiKTtcbiAgICAgICAgICAgIGlmICh0aGlzLnByb3BzLm1pc3NpbmdUZXJtcykge1xuICAgICAgICAgICAgICAgIGRpc2NvQm9keVRleHQgPSBfdChcImlkZW50aXR5X3NlcnZlcnxkZXNjcmlwdGlvbl9vcHRpb25hbFwiKTtcbiAgICAgICAgICAgICAgICBkaXNjb0J1dHRvbkNvbnRlbnQgPSBfdChcImlkZW50aXR5X3NlcnZlcnxkb19ub3RfdXNlXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuc3RhdGUuZGlzY29ubmVjdEJ1c3kpIHtcbiAgICAgICAgICAgICAgICBkaXNjb0J1dHRvbkNvbnRlbnQgPSA8SW5saW5lU3Bpbm5lciAvPjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGRpc2NvU2VjdGlvbiA9IChcbiAgICAgICAgICAgICAgICA8PlxuICAgICAgICAgICAgICAgICAgICA8U2V0dGluZ3NTdWJzZWN0aW9uVGV4dD57ZGlzY29Cb2R5VGV4dH08L1NldHRpbmdzU3Vic2VjdGlvblRleHQ+XG4gICAgICAgICAgICAgICAgICAgIDxBY2Nlc3NpYmxlQnV0dG9uIG9uQ2xpY2s9e3RoaXMub25EaXNjb25uZWN0Q2xpY2tlZH0ga2luZD1cImRhbmdlcl9zbVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAge2Rpc2NvQnV0dG9uQ29udGVudH1cbiAgICAgICAgICAgICAgICAgICAgPC9BY2Nlc3NpYmxlQnV0dG9uPlxuICAgICAgICAgICAgICAgIDwvPlxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICA8U2V0dGluZ3NGaWVsZHNldCBsZWdlbmQ9e3NlY3Rpb25UaXRsZX0gZGVzY3JpcHRpb249e2JvZHlUZXh0fT5cbiAgICAgICAgICAgICAgICA8Zm9ybSBjbGFzc05hbWU9XCJteF9TZXRJZFNlcnZlclwiIG9uU3VibWl0PXt0aGlzLmNoZWNrSWRTZXJ2ZXJ9PlxuICAgICAgICAgICAgICAgICAgICA8RmllbGRcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVsPXtfdChcImlkZW50aXR5X3NlcnZlcnx1cmxfZmllbGRfbGFiZWxcIil9XG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlPVwidGV4dFwiXG4gICAgICAgICAgICAgICAgICAgICAgICBhdXRvQ29tcGxldGU9XCJvZmZcIlxuICAgICAgICAgICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI9e3RoaXMuc3RhdGUuZGVmYXVsdElkU2VydmVyfVxuICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU9e3RoaXMuc3RhdGUuaWRTZXJ2ZXJ9XG4gICAgICAgICAgICAgICAgICAgICAgICBvbkNoYW5nZT17dGhpcy5vbklkZW50aXR5U2VydmVyQ2hhbmdlZH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHRvb2x0aXBDb250ZW50PXt0aGlzLmdldFRvb2x0aXAoKX1cbiAgICAgICAgICAgICAgICAgICAgICAgIHRvb2x0aXBDbGFzc05hbWU9XCJteF9TZXRJZFNlcnZlcl90b29sdGlwXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpc2FibGVkPXt0aGlzLnN0YXRlLmJ1c3l9XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3JjZVZhbGlkaXR5PXt0aGlzLnN0YXRlLmVycm9yID8gZmFsc2UgOiB1bmRlZmluZWR9XG4gICAgICAgICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICAgICAgICAgIDxBY2Nlc3NpYmxlQnV0dG9uXG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlPVwic3VibWl0XCJcbiAgICAgICAgICAgICAgICAgICAgICAgIGtpbmQ9XCJwcmltYXJ5X3NtXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIG9uQ2xpY2s9e3RoaXMuY2hlY2tJZFNlcnZlcn1cbiAgICAgICAgICAgICAgICAgICAgICAgIGRpc2FibGVkPXshdGhpcy5pZFNlcnZlckNoYW5nZUVuYWJsZWQoKX1cbiAgICAgICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgICAgICAge190KFwiYWN0aW9ufGNoYW5nZVwiKX1cbiAgICAgICAgICAgICAgICAgICAgPC9BY2Nlc3NpYmxlQnV0dG9uPlxuICAgICAgICAgICAgICAgICAgICB7ZGlzY29TZWN0aW9ufVxuICAgICAgICAgICAgICAgIDwvZm9ybT5cbiAgICAgICAgICAgIDwvU2V0dGluZ3NGaWVsZHNldD5cbiAgICAgICAgKTtcbiAgICB9XG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7O0FBUUEsSUFBQUEsTUFBQSxHQUFBQyxzQkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQUMsT0FBQSxHQUFBRCxPQUFBO0FBR0EsSUFBQUUsZ0JBQUEsR0FBQUYsT0FBQTtBQUNBLElBQUFHLGdCQUFBLEdBQUFILE9BQUE7QUFDQSxJQUFBSSxNQUFBLEdBQUFMLHNCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBSyxXQUFBLEdBQUFOLHNCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBTSxlQUFBLEdBQUFOLE9BQUE7QUFDQSxJQUFBTyxtQkFBQSxHQUFBUixzQkFBQSxDQUFBQyxPQUFBO0FBQ0Es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