UNPKG

matrix-react-sdk

Version:
323 lines (316 loc) 46.6 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 _Field = _interopRequireDefault(require("../elements/Field")); var _MatrixClientPeg = require("../../../MatrixClientPeg"); var _AccessibleButton = _interopRequireDefault(require("../elements/AccessibleButton")); var _Spinner = _interopRequireDefault(require("../elements/Spinner")); var _Validation = _interopRequireDefault(require("../elements/Validation")); var _languageHandler = require("../../../languageHandler"); var _Modal = _interopRequireDefault(require("../../../Modal")); var _PassphraseField = _interopRequireDefault(require("../auth/PassphraseField")); var _RegistrationForm = require("../auth/RegistrationForm"); var _SetEmailDialog = _interopRequireDefault(require("../dialogs/SetEmailDialog")); /* Copyright 2018-2024 New Vector Ltd. Copyright 2015, 2016 OpenMarket Ltd SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ const FIELD_OLD_PASSWORD = "field_old_password"; const FIELD_NEW_PASSWORD = "field_new_password"; const FIELD_NEW_PASSWORD_CONFIRM = "field_new_password_confirm"; var Phase = /*#__PURE__*/function (Phase) { Phase["Edit"] = "edit"; Phase["Uploading"] = "uploading"; Phase["Error"] = "error"; return Phase; }(Phase || {}); class ChangePassword extends _react.default.Component { constructor(props) { super(props); (0, _defineProperty2.default)(this, FIELD_OLD_PASSWORD, null); (0, _defineProperty2.default)(this, FIELD_NEW_PASSWORD, null); (0, _defineProperty2.default)(this, FIELD_NEW_PASSWORD_CONFIRM, null); (0, _defineProperty2.default)(this, "onChangeOldPassword", ev => { this.setState({ oldPassword: ev.target.value }); }); (0, _defineProperty2.default)(this, "onOldPasswordValidate", async fieldState => { const result = await this.validateOldPasswordRules(fieldState); this.markFieldValid(FIELD_OLD_PASSWORD, result.valid); return result; }); (0, _defineProperty2.default)(this, "validateOldPasswordRules", (0, _Validation.default)({ rules: [{ key: "required", test: ({ value, allowEmpty }) => allowEmpty || !!value, invalid: () => (0, _languageHandler._t)("auth|change_password_empty") }] })); (0, _defineProperty2.default)(this, "onChangeNewPassword", ev => { this.setState({ newPassword: ev.target.value }); }); (0, _defineProperty2.default)(this, "onNewPasswordValidate", result => { this.markFieldValid(FIELD_NEW_PASSWORD, result.valid); }); (0, _defineProperty2.default)(this, "onChangeNewPasswordConfirm", ev => { this.setState({ newPasswordConfirm: ev.target.value }); }); (0, _defineProperty2.default)(this, "onNewPasswordConfirmValidate", async fieldState => { const result = await this.validatePasswordConfirmRules(fieldState); this.markFieldValid(FIELD_NEW_PASSWORD_CONFIRM, result.valid); return result; }); (0, _defineProperty2.default)(this, "validatePasswordConfirmRules", (0, _Validation.default)({ rules: [{ key: "required", test: ({ value, allowEmpty }) => allowEmpty || !!value, invalid: () => (0, _languageHandler._t)("auth|change_password_confirm_label") }, { key: "match", test({ value }) { return !value || value === this.state.newPassword; }, invalid: () => (0, _languageHandler._t)("auth|change_password_confirm_invalid") }] })); (0, _defineProperty2.default)(this, "onClickChange", async ev => { ev.preventDefault(); const allFieldsValid = await this.verifyFieldsBeforeSubmit(); if (!allFieldsValid) { return; } const oldPassword = this.state.oldPassword; const newPassword = this.state.newPassword; const confirmPassword = this.state.newPasswordConfirm; try { // TODO: We can remove this check (but should add some Playwright tests to // sanity check this flow). This logic is redundant with the input field // validation we do and `verifyFieldsBeforeSubmit()` above. See // https://github.com/matrix-org/matrix-react-sdk/pull/10615#discussion_r1167364214 this.checkPassword(oldPassword, newPassword, confirmPassword); return this.onChangePassword(oldPassword, newPassword); } catch (err) { if (err instanceof Error) { this.props.onError(err); } else { this.props.onError(new _languageHandler.UserFriendlyError("auth|change_password_error", { error: String(err), cause: undefined })); } } }); this.state = { fieldValid: {}, phase: Phase.Edit, oldPassword: "", newPassword: "", newPasswordConfirm: "" }; } async onChangePassword(oldPassword, newPassword) { const cli = _MatrixClientPeg.MatrixClientPeg.safeGet(); this.changePassword(cli, oldPassword, newPassword); } changePassword(cli, oldPassword, newPassword) { const authDict = { type: "m.login.password", identifier: { type: "m.id.user", user: cli.credentials.userId }, password: oldPassword }; this.setState({ phase: Phase.Uploading }); cli.setPassword(authDict, newPassword, false).then(() => { if (this.props.shouldAskForEmail) { return this.optionallySetEmail().then(confirmed => { this.props.onFinished({ didSetEmail: confirmed }); }); } else { this.props.onFinished({}); } }, err => { if (err instanceof Error) { this.props.onError(err); } else { this.props.onError(new _languageHandler.UserFriendlyError("auth|change_password_error", { error: String(err), cause: undefined })); } }).finally(() => { this.setState({ phase: Phase.Edit, oldPassword: "", newPassword: "", newPasswordConfirm: "" }); }); } /** * Checks the `newPass` and throws an error if it is unacceptable. * @param oldPass The old password * @param newPass The new password that the user is trying to be set * @param confirmPass The confirmation password where the user types the `newPass` * again for confirmation and should match the `newPass` before we accept their new * password. */ checkPassword(oldPass, newPass, confirmPass) { if (newPass !== confirmPass) { throw new _languageHandler.UserFriendlyError("auth|change_password_mismatch"); } else if (!newPass || newPass.length === 0) { throw new _languageHandler.UserFriendlyError("auth|change_password_empty"); } } optionallySetEmail() { // Ask for an email otherwise the user has no way to reset their password const modal = _Modal.default.createDialog(_SetEmailDialog.default, { title: (0, _languageHandler._t)("auth|set_email_prompt") }); return modal.finished.then(([confirmed]) => !!confirmed); } markFieldValid(fieldID, valid) { const { fieldValid } = this.state; fieldValid[fieldID] = valid; this.setState({ fieldValid }); } async verifyFieldsBeforeSubmit() { // Blur the active element if any, so we first run its blur validation, // which is less strict than the pass we're about to do below for all fields. const activeElement = document.activeElement; if (activeElement) { activeElement.blur(); } const fieldIDsInDisplayOrder = [FIELD_OLD_PASSWORD, FIELD_NEW_PASSWORD, FIELD_NEW_PASSWORD_CONFIRM]; // Run all fields with stricter validation that no longer allows empty // values for required fields. for (const fieldID of fieldIDsInDisplayOrder) { const field = this[fieldID]; if (!field) { continue; } // We must wait for these validations to finish before queueing // up the setState below so our setState goes in the queue after // all the setStates from these validate calls (that's how we // know they've finished). await field.validate({ allowEmpty: false }); } // Validation and state updates are async, so we need to wait for them to complete // first. Queue a `setState` callback and wait for it to resolve. await new Promise(resolve => this.setState({}, resolve)); if (this.allFieldsValid()) { return true; } const invalidField = this.findFirstInvalidField(fieldIDsInDisplayOrder); if (!invalidField) { return true; } // Focus the first invalid field and show feedback in the stricter mode // that no longer allows empty values for required fields. invalidField.focus(); invalidField.validate({ allowEmpty: false, focused: true }); return false; } allFieldsValid() { return Object.values(this.state.fieldValid).every(Boolean); } findFirstInvalidField(fieldIDs) { for (const fieldID of fieldIDs) { if (!this.state.fieldValid[fieldID] && this[fieldID]) { return this[fieldID]; } } return null; } render() { const rowClassName = this.props.rowClassName; const buttonClassName = this.props.buttonClassName; switch (this.state.phase) { case Phase.Edit: return /*#__PURE__*/_react.default.createElement("form", { className: this.props.className, onSubmit: this.onClickChange }, /*#__PURE__*/_react.default.createElement("div", { className: rowClassName }, /*#__PURE__*/_react.default.createElement(_Field.default, { ref: field => this[FIELD_OLD_PASSWORD] = field, type: "password", label: (0, _languageHandler._t)("auth|change_password_current_label"), value: this.state.oldPassword, onChange: this.onChangeOldPassword, onValidate: this.onOldPasswordValidate })), /*#__PURE__*/_react.default.createElement("div", { className: rowClassName }, /*#__PURE__*/_react.default.createElement(_PassphraseField.default, { fieldRef: field => this[FIELD_NEW_PASSWORD] = field, type: "password", label: (0, _languageHandler._td)("auth|change_password_new_label"), minScore: _RegistrationForm.PASSWORD_MIN_SCORE, value: this.state.newPassword, autoFocus: this.props.autoFocusNewPasswordInput, onChange: this.onChangeNewPassword, onValidate: this.onNewPasswordValidate, autoComplete: "new-password" })), /*#__PURE__*/_react.default.createElement("div", { className: rowClassName }, /*#__PURE__*/_react.default.createElement(_Field.default, { ref: field => this[FIELD_NEW_PASSWORD_CONFIRM] = field, type: "password", label: (0, _languageHandler._t)("auth|change_password_confirm_label"), value: this.state.newPasswordConfirm, onChange: this.onChangeNewPasswordConfirm, onValidate: this.onNewPasswordConfirmValidate, autoComplete: "new-password" })), /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, { className: buttonClassName, kind: this.props.buttonKind, onClick: this.onClickChange }, this.props.buttonLabel || (0, _languageHandler._t)("auth|change_password_action"))); case Phase.Uploading: return /*#__PURE__*/_react.default.createElement("div", { className: "mx_Dialog_content" }, /*#__PURE__*/_react.default.createElement(_Spinner.default, null)); } } } exports.default = ChangePassword; (0, _defineProperty2.default)(ChangePassword, "defaultProps", { onFinished() {}, onError() {}, confirm: true }); //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfcmVhY3QiLCJfaW50ZXJvcFJlcXVpcmVEZWZhdWx0IiwicmVxdWlyZSIsIl9GaWVsZCIsIl9NYXRyaXhDbGllbnRQZWciLCJfQWNjZXNzaWJsZUJ1dHRvbiIsIl9TcGlubmVyIiwiX1ZhbGlkYXRpb24iLCJfbGFuZ3VhZ2VIYW5kbGVyIiwiX01vZGFsIiwiX1Bhc3NwaHJhc2VGaWVsZCIsIl9SZWdpc3RyYXRpb25Gb3JtIiwiX1NldEVtYWlsRGlhbG9nIiwiRklFTERfT0xEX1BBU1NXT1JEIiwiRklFTERfTkVXX1BBU1NXT1JEIiwiRklFTERfTkVXX1BBU1NXT1JEX0NPTkZJUk0iLCJQaGFzZSIsIkNoYW5nZVBhc3N3b3JkIiwiUmVhY3QiLCJDb21wb25lbnQiLCJjb25zdHJ1Y3RvciIsInByb3BzIiwiX2RlZmluZVByb3BlcnR5MiIsImRlZmF1bHQiLCJldiIsInNldFN0YXRlIiwib2xkUGFzc3dvcmQiLCJ0YXJnZXQiLCJ2YWx1ZSIsImZpZWxkU3RhdGUiLCJyZXN1bHQiLCJ2YWxpZGF0ZU9sZFBhc3N3b3JkUnVsZXMiLCJtYXJrRmllbGRWYWxpZCIsInZhbGlkIiwid2l0aFZhbGlkYXRpb24iLCJydWxlcyIsImtleSIsInRlc3QiLCJhbGxvd0VtcHR5IiwiaW52YWxpZCIsIl90IiwibmV3UGFzc3dvcmQiLCJuZXdQYXNzd29yZENvbmZpcm0iLCJ2YWxpZGF0ZVBhc3N3b3JkQ29uZmlybVJ1bGVzIiwic3RhdGUiLCJwcmV2ZW50RGVmYXVsdCIsImFsbEZpZWxkc1ZhbGlkIiwidmVyaWZ5RmllbGRzQmVmb3JlU3VibWl0IiwiY29uZmlybVBhc3N3b3JkIiwiY2hlY2tQYXNzd29yZCIsIm9uQ2hhbmdlUGFzc3dvcmQiLCJlcnIiLCJFcnJvciIsIm9uRXJyb3IiLCJVc2VyRnJpZW5kbHlFcnJvciIsImVycm9yIiwiU3RyaW5nIiwiY2F1c2UiLCJ1bmRlZmluZWQiLCJmaWVsZFZhbGlkIiwicGhhc2UiLCJFZGl0IiwiY2xpIiwiTWF0cml4Q2xpZW50UGVnIiwic2FmZUdldCIsImNoYW5nZVBhc3N3b3JkIiwiYXV0aERpY3QiLCJ0eXBlIiwiaWRlbnRpZmllciIsInVzZXIiLCJjcmVkZW50aWFscyIsInVzZXJJZCIsInBhc3N3b3JkIiwiVXBsb2FkaW5nIiwic2V0UGFzc3dvcmQiLCJ0aGVuIiwic2hvdWxkQXNrRm9yRW1haWwiLCJvcHRpb25hbGx5U2V0RW1haWwiLCJjb25maXJtZWQiLCJvbkZpbmlzaGVkIiwiZGlkU2V0RW1haWwiLCJmaW5hbGx5Iiwib2xkUGFzcyIsIm5ld1Bhc3MiLCJjb25maXJtUGFzcyIsImxlbmd0aCIsIm1vZGFsIiwiTW9kYWwiLCJjcmVhdGVEaWFsb2ciLCJTZXRFbWFpbERpYWxvZyIsInRpdGxlIiwiZmluaXNoZWQiLCJmaWVsZElEIiwiYWN0aXZlRWxlbWVudCIsImRvY3VtZW50IiwiYmx1ciIsImZpZWxkSURzSW5EaXNwbGF5T3JkZXIiLCJmaWVsZCIsInZhbGlkYXRlIiwiUHJvbWlzZSIsInJlc29sdmUiLCJpbnZhbGlkRmllbGQiLCJmaW5kRmlyc3RJbnZhbGlkRmllbGQiLCJmb2N1cyIsImZvY3VzZWQiLCJPYmplY3QiLCJ2YWx1ZXMiLCJldmVyeSIsIkJvb2xlYW4iLCJmaWVsZElEcyIsInJlbmRlciIsInJvd0NsYXNzTmFtZSIsImJ1dHRvbkNsYXNzTmFtZSIsImNyZWF0ZUVsZW1lbnQiLCJjbGFzc05hbWUiLCJvblN1Ym1pdCIsIm9uQ2xpY2tDaGFuZ2UiLCJyZWYiLCJsYWJlbCIsIm9uQ2hhbmdlIiwib25DaGFuZ2VPbGRQYXNzd29yZCIsIm9uVmFsaWRhdGUiLCJvbk9sZFBhc3N3b3JkVmFsaWRhdGUiLCJmaWVsZFJlZiIsIl90ZCIsIm1pblNjb3JlIiwiUEFTU1dPUkRfTUlOX1NDT1JFIiwiYXV0b0ZvY3VzIiwiYXV0b0ZvY3VzTmV3UGFzc3dvcmRJbnB1dCIsIm9uQ2hhbmdlTmV3UGFzc3dvcmQiLCJvbk5ld1Bhc3N3b3JkVmFsaWRhdGUiLCJhdXRvQ29tcGxldGUiLCJvbkNoYW5nZU5ld1Bhc3N3b3JkQ29uZmlybSIsIm9uTmV3UGFzc3dvcmRDb25maXJtVmFsaWRhdGUiLCJraW5kIiwiYnV0dG9uS2luZCIsIm9uQ2xpY2siLCJidXR0b25MYWJlbCIsImV4cG9ydHMiLCJjb25maXJtIl0sInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2NvbXBvbmVudHMvdmlld3Mvc2V0dGluZ3MvQ2hhbmdlUGFzc3dvcmQudHN4Il0sInNvdXJjZXNDb250ZW50IjpbIi8qXG5Db3B5cmlnaHQgMjAxOC0yMDI0IE5ldyBWZWN0b3IgTHRkLlxuQ29weXJpZ2h0IDIwMTUsIDIwMTYgT3Blbk1hcmtldCBMdGRcblxuU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFHUEwtMy4wLW9ubHkgT1IgR1BMLTMuMC1vbmx5XG5QbGVhc2Ugc2VlIExJQ0VOU0UgZmlsZXMgaW4gdGhlIHJlcG9zaXRvcnkgcm9vdCBmb3IgZnVsbCBkZXRhaWxzLlxuKi9cblxuaW1wb3J0IFJlYWN0IGZyb20gXCJyZWFjdFwiO1xuaW1wb3J0IHsgTWF0cml4Q2xpZW50IH0gZnJvbSBcIm1hdHJpeC1qcy1zZGsvc3JjL21hdHJpeFwiO1xuXG5pbXBvcnQgRmllbGQgZnJvbSBcIi4uL2VsZW1lbnRzL0ZpZWxkXCI7XG5pbXBvcnQgeyBNYXRyaXhDbGllbnRQZWcgfSBmcm9tIFwiLi4vLi4vLi4vTWF0cml4Q2xpZW50UGVnXCI7XG5pbXBvcnQgQWNjZXNzaWJsZUJ1dHRvbiwgeyBBY2Nlc3NpYmxlQnV0dG9uS2luZCB9IGZyb20gXCIuLi9lbGVtZW50cy9BY2Nlc3NpYmxlQnV0dG9uXCI7XG5pbXBvcnQgU3Bpbm5lciBmcm9tIFwiLi4vZWxlbWVudHMvU3Bpbm5lclwiO1xuaW1wb3J0IHdpdGhWYWxpZGF0aW9uLCB7IElGaWVsZFN0YXRlLCBJVmFsaWRhdGlvblJlc3VsdCB9IGZyb20gXCIuLi9lbGVtZW50cy9WYWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBVc2VyRnJpZW5kbHlFcnJvciwgX3QsIF90ZCB9IGZyb20gXCIuLi8uLi8uLi9sYW5ndWFnZUhhbmRsZXJcIjtcbmltcG9ydCBNb2RhbCBmcm9tIFwiLi4vLi4vLi4vTW9kYWxcIjtcbmltcG9ydCBQYXNzcGhyYXNlRmllbGQgZnJvbSBcIi4uL2F1dGgvUGFzc3BocmFzZUZpZWxkXCI7XG5pbXBvcnQgeyBQQVNTV09SRF9NSU5fU0NPUkUgfSBmcm9tIFwiLi4vYXV0aC9SZWdpc3RyYXRpb25Gb3JtXCI7XG5pbXBvcnQgU2V0RW1haWxEaWFsb2cgZnJvbSBcIi4uL2RpYWxvZ3MvU2V0RW1haWxEaWFsb2dcIjtcblxuY29uc3QgRklFTERfT0xEX1BBU1NXT1JEID0gXCJmaWVsZF9vbGRfcGFzc3dvcmRcIjtcbmNvbnN0IEZJRUxEX05FV19QQVNTV09SRCA9IFwiZmllbGRfbmV3X3Bhc3N3b3JkXCI7XG5jb25zdCBGSUVMRF9ORVdfUEFTU1dPUkRfQ09ORklSTSA9IFwiZmllbGRfbmV3X3Bhc3N3b3JkX2NvbmZpcm1cIjtcbnR5cGUgRmllbGRUeXBlID0gdHlwZW9mIEZJRUxEX09MRF9QQVNTV09SRCB8IHR5cGVvZiBGSUVMRF9ORVdfUEFTU1dPUkQgfCB0eXBlb2YgRklFTERfTkVXX1BBU1NXT1JEX0NPTkZJUk07XG5cbmVudW0gUGhhc2Uge1xuICAgIEVkaXQgPSBcImVkaXRcIixcbiAgICBVcGxvYWRpbmcgPSBcInVwbG9hZGluZ1wiLFxuICAgIEVycm9yID0gXCJlcnJvclwiLFxufVxuXG5pbnRlcmZhY2UgSVByb3BzIHtcbiAgICBvbkZpbmlzaGVkOiAob3V0Y29tZTogeyBkaWRTZXRFbWFpbD86IGJvb2xlYW4gfSkgPT4gdm9pZDtcbiAgICBvbkVycm9yOiAoZXJyb3I6IEVycm9yKSA9PiB2b2lkO1xuICAgIHJvd0NsYXNzTmFtZT86IHN0cmluZztcbiAgICBidXR0b25DbGFzc05hbWU/OiBzdHJpbmc7XG4gICAgYnV0dG9uS2luZD86IEFjY2Vzc2libGVCdXR0b25LaW5kO1xuICAgIGJ1dHRvbkxhYmVsPzogc3RyaW5nO1xuICAgIGNvbmZpcm0/OiBib29sZWFuO1xuICAgIC8vIFdoZXRoZXIgdG8gYXV0b0ZvY3VzIHRoZSBuZXcgcGFzc3dvcmQgaW5wdXRcbiAgICBhdXRvRm9jdXNOZXdQYXNzd29yZElucHV0PzogYm9vbGVhbjtcbiAgICBjbGFzc05hbWU/OiBzdHJpbmc7XG4gICAgc2hvdWxkQXNrRm9yRW1haWw/OiBib29sZWFuO1xufVxuXG5pbnRlcmZhY2UgSVN0YXRlIHtcbiAgICBmaWVsZFZhbGlkOiBQYXJ0aWFsPFJlY29yZDxGaWVsZFR5cGUsIGJvb2xlYW4+PjtcbiAgICBwaGFzZTogUGhhc2U7XG4gICAgb2xkUGFzc3dvcmQ6IHN0cmluZztcbiAgICBuZXdQYXNzd29yZDogc3RyaW5nO1xuICAgIG5ld1Bhc3N3b3JkQ29uZmlybTogc3RyaW5nO1xufVxuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBDaGFuZ2VQYXNzd29yZCBleHRlbmRzIFJlYWN0LkNvbXBvbmVudDxJUHJvcHMsIElTdGF0ZT4ge1xuICAgIHByaXZhdGUgW0ZJRUxEX09MRF9QQVNTV09SRF06IEZpZWxkIHwgbnVsbCA9IG51bGw7XG4gICAgcHJpdmF0ZSBbRklFTERfTkVXX1BBU1NXT1JEXTogRmllbGQgfCBudWxsID0gbnVsbDtcbiAgICBwcml2YXRlIFtGSUVMRF9ORVdfUEFTU1dPUkRfQ09ORklSTV06IEZpZWxkIHwgbnVsbCA9IG51bGw7XG5cbiAgICBwdWJsaWMgc3RhdGljIGRlZmF1bHRQcm9wczogUGFydGlhbDxJUHJvcHM+ID0ge1xuICAgICAgICBvbkZpbmlzaGVkKCkge30sXG4gICAgICAgIG9uRXJyb3IoKSB7fSxcblxuICAgICAgICBjb25maXJtOiB0cnVlLFxuICAgIH07XG5cbiAgICBwdWJsaWMgY29uc3RydWN0b3IocHJvcHM6IElQcm9wcykge1xuICAgICAgICBzdXBlcihwcm9wcyk7XG5cbiAgICAgICAgdGhpcy5zdGF0ZSA9IHtcbiAgICAgICAgICAgIGZpZWxkVmFsaWQ6IHt9LFxuICAgICAgICAgICAgcGhhc2U6IFBoYXNlLkVkaXQsXG4gICAgICAgICAgICBvbGRQYXNzd29yZDogXCJcIixcbiAgICAgICAgICAgIG5ld1Bhc3N3b3JkOiBcIlwiLFxuICAgICAgICAgICAgbmV3UGFzc3dvcmRDb25maXJtOiBcIlwiLFxuICAgICAgICB9O1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgb25DaGFuZ2VQYXNzd29yZChvbGRQYXNzd29yZDogc3RyaW5nLCBuZXdQYXNzd29yZDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGNvbnN0IGNsaSA9IE1hdHJpeENsaWVudFBlZy5zYWZlR2V0KCk7XG5cbiAgICAgICAgdGhpcy5jaGFuZ2VQYXNzd29yZChjbGksIG9sZFBhc3N3b3JkLCBuZXdQYXNzd29yZCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBjaGFuZ2VQYXNzd29yZChjbGk6IE1hdHJpeENsaWVudCwgb2xkUGFzc3dvcmQ6IHN0cmluZywgbmV3UGFzc3dvcmQ6IHN0cmluZyk6IHZvaWQge1xuICAgICAgICBjb25zdCBhdXRoRGljdCA9IHtcbiAgICAgICAgICAgIHR5cGU6IFwibS5sb2dpbi5wYXNzd29yZFwiLFxuICAgICAgICAgICAgaWRlbnRpZmllcjoge1xuICAgICAgICAgICAgICAgIHR5cGU6IFwibS5pZC51c2VyXCIsXG4gICAgICAgICAgICAgICAgdXNlcjogY2xpLmNyZWRlbnRpYWxzLnVzZXJJZCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBwYXNzd29yZDogb2xkUGFzc3dvcmQsXG4gICAgICAgIH07XG5cbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICBwaGFzZTogUGhhc2UuVXBsb2FkaW5nLFxuICAgICAgICB9KTtcblxuICAgICAgICBjbGkuc2V0UGFzc3dvcmQoYXV0aERpY3QsIG5ld1Bhc3N3b3JkLCBmYWxzZSlcbiAgICAgICAgICAgIC50aGVuKFxuICAgICAgICAgICAgICAgICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMucHJvcHMuc2hvdWxkQXNrRm9yRW1haWwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLm9wdGlvbmFsbHlTZXRFbWFpbCgpLnRoZW4oKGNvbmZpcm1lZCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucHJvcHMub25GaW5pc2hlZCh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZFNldEVtYWlsOiBjb25maXJtZWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucHJvcHMub25GaW5pc2hlZCh7fSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIChlcnIpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVyciBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnByb3BzLm9uRXJyb3IoZXJyKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucHJvcHMub25FcnJvcihcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXcgVXNlckZyaWVuZGx5RXJyb3IoXCJhdXRofGNoYW5nZV9wYXNzd29yZF9lcnJvclwiLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yOiBTdHJpbmcoZXJyKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2F1c2U6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgKVxuICAgICAgICAgICAgLmZpbmFsbHkoKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgICAgICAgICBwaGFzZTogUGhhc2UuRWRpdCxcbiAgICAgICAgICAgICAgICAgICAgb2xkUGFzc3dvcmQ6IFwiXCIsXG4gICAgICAgICAgICAgICAgICAgIG5ld1Bhc3N3b3JkOiBcIlwiLFxuICAgICAgICAgICAgICAgICAgICBuZXdQYXNzd29yZENvbmZpcm06IFwiXCIsXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgdGhlIGBuZXdQYXNzYCBhbmQgdGhyb3dzIGFuIGVycm9yIGlmIGl0IGlzIHVuYWNjZXB0YWJsZS5cbiAgICAgKiBAcGFyYW0gb2xkUGFzcyBUaGUgb2xkIHBhc3N3b3JkXG4gICAgICogQHBhcmFtIG5ld1Bhc3MgVGhlIG5ldyBwYXNzd29yZCB0aGF0IHRoZSB1c2VyIGlzIHRyeWluZyB0byBiZSBzZXRcbiAgICAgKiBAcGFyYW0gY29uZmlybVBhc3MgVGhlIGNvbmZpcm1hdGlvbiBwYXNzd29yZCB3aGVyZSB0aGUgdXNlciB0eXBlcyB0aGUgYG5ld1Bhc3NgXG4gICAgICogYWdhaW4gZm9yIGNvbmZpcm1hdGlvbiBhbmQgc2hvdWxkIG1hdGNoIHRoZSBgbmV3UGFzc2AgYmVmb3JlIHdlIGFjY2VwdCB0aGVpciBuZXdcbiAgICAgKiBwYXNzd29yZC5cbiAgICAgKi9cbiAgICBwcml2YXRlIGNoZWNrUGFzc3dvcmQob2xkUGFzczogc3RyaW5nLCBuZXdQYXNzOiBzdHJpbmcsIGNvbmZpcm1QYXNzOiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgaWYgKG5ld1Bhc3MgIT09IGNvbmZpcm1QYXNzKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVXNlckZyaWVuZGx5RXJyb3IoXCJhdXRofGNoYW5nZV9wYXNzd29yZF9taXNtYXRjaFwiKTtcbiAgICAgICAgfSBlbHNlIGlmICghbmV3UGFzcyB8fCBuZXdQYXNzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFVzZXJGcmllbmRseUVycm9yKFwiYXV0aHxjaGFuZ2VfcGFzc3dvcmRfZW1wdHlcIik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIG9wdGlvbmFsbHlTZXRFbWFpbCgpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAgICAgLy8gQXNrIGZvciBhbiBlbWFpbCBvdGhlcndpc2UgdGhlIHVzZXIgaGFzIG5vIHdheSB0byByZXNldCB0aGVpciBwYXNzd29yZFxuICAgICAgICBjb25zdCBtb2RhbCA9IE1vZGFsLmNyZWF0ZURpYWxvZyhTZXRFbWFpbERpYWxvZywge1xuICAgICAgICAgICAgdGl0bGU6IF90KFwiYXV0aHxzZXRfZW1haWxfcHJvbXB0XCIpLFxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIG1vZGFsLmZpbmlzaGVkLnRoZW4oKFtjb25maXJtZWRdKSA9PiAhIWNvbmZpcm1lZCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBtYXJrRmllbGRWYWxpZChmaWVsZElEOiBGaWVsZFR5cGUsIHZhbGlkPzogYm9vbGVhbik6IHZvaWQge1xuICAgICAgICBjb25zdCB7IGZpZWxkVmFsaWQgfSA9IHRoaXMuc3RhdGU7XG4gICAgICAgIGZpZWxkVmFsaWRbZmllbGRJRF0gPSB2YWxpZDtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICBmaWVsZFZhbGlkLFxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIG9uQ2hhbmdlT2xkUGFzc3dvcmQgPSAoZXY6IFJlYWN0LkNoYW5nZUV2ZW50PEhUTUxJbnB1dEVsZW1lbnQ+KTogdm9pZCA9PiB7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgb2xkUGFzc3dvcmQ6IGV2LnRhcmdldC52YWx1ZSxcbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIHByaXZhdGUgb25PbGRQYXNzd29yZFZhbGlkYXRlID0gYXN5bmMgKGZpZWxkU3RhdGU6IElGaWVsZFN0YXRlKTogUHJvbWlzZTxJVmFsaWRhdGlvblJlc3VsdD4gPT4ge1xuICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLnZhbGlkYXRlT2xkUGFzc3dvcmRSdWxlcyhmaWVsZFN0YXRlKTtcbiAgICAgICAgdGhpcy5tYXJrRmllbGRWYWxpZChGSUVMRF9PTERfUEFTU1dPUkQsIHJlc3VsdC52YWxpZCk7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfTtcblxuICAgIHByaXZhdGUgdmFsaWRhdGVPbGRQYXNzd29yZFJ1bGVzID0gd2l0aFZhbGlkYXRpb24oe1xuICAgICAgICBydWxlczogW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIGtleTogXCJyZXF1aXJlZFwiLFxuICAgICAgICAgICAgICAgIHRlc3Q6ICh7IHZhbHVlLCBhbGxvd0VtcHR5IH0pID0+IGFsbG93RW1wdHkgfHwgISF2YWx1ZSxcbiAgICAgICAgICAgICAgICBpbnZhbGlkOiAoKSA9PiBfdChcImF1dGh8Y2hhbmdlX3Bhc3N3b3JkX2VtcHR5XCIpLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICB9KTtcblxuICAgIHByaXZhdGUgb25DaGFuZ2VOZXdQYXNzd29yZCA9IChldjogUmVhY3QuQ2hhbmdlRXZlbnQ8SFRNTElucHV0RWxlbWVudD4pOiB2b2lkID0+IHtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICBuZXdQYXNzd29yZDogZXYudGFyZ2V0LnZhbHVlLFxuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgcHJpdmF0ZSBvbk5ld1Bhc3N3b3JkVmFsaWRhdGUgPSAocmVzdWx0OiBJVmFsaWRhdGlvblJlc3VsdCk6IHZvaWQgPT4ge1xuICAgICAgICB0aGlzLm1hcmtGaWVsZFZhbGlkKEZJRUxEX05FV19QQVNTV09SRCwgcmVzdWx0LnZhbGlkKTtcbiAgICB9O1xuXG4gICAgcHJpdmF0ZSBvbkNoYW5nZU5ld1Bhc3N3b3JkQ29uZmlybSA9IChldjogUmVhY3QuQ2hhbmdlRXZlbnQ8SFRNTElucHV0RWxlbWVudD4pOiB2b2lkID0+IHtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICBuZXdQYXNzd29yZENvbmZpcm06IGV2LnRhcmdldC52YWx1ZSxcbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIHByaXZhdGUgb25OZXdQYXNzd29yZENvbmZpcm1WYWxpZGF0ZSA9IGFzeW5jIChmaWVsZFN0YXRlOiBJRmllbGRTdGF0ZSk6IFByb21pc2U8SVZhbGlkYXRpb25SZXN1bHQ+ID0+IHtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdGhpcy52YWxpZGF0ZVBhc3N3b3JkQ29uZmlybVJ1bGVzKGZpZWxkU3RhdGUpO1xuICAgICAgICB0aGlzLm1hcmtGaWVsZFZhbGlkKEZJRUxEX05FV19QQVNTV09SRF9DT05GSVJNLCByZXN1bHQudmFsaWQpO1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH07XG5cbiAgICBwcml2YXRlIHZhbGlkYXRlUGFzc3dvcmRDb25maXJtUnVsZXMgPSB3aXRoVmFsaWRhdGlvbjx0aGlzPih7XG4gICAgICAgIHJ1bGVzOiBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAga2V5OiBcInJlcXVpcmVkXCIsXG4gICAgICAgICAgICAgICAgdGVzdDogKHsgdmFsdWUsIGFsbG93RW1wdHkgfSkgPT4gYWxsb3dFbXB0eSB8fCAhIXZhbHVlLFxuICAgICAgICAgICAgICAgIGludmFsaWQ6ICgpID0+IF90KFwiYXV0aHxjaGFuZ2VfcGFzc3dvcmRfY29uZmlybV9sYWJlbFwiKSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAga2V5OiBcIm1hdGNoXCIsXG4gICAgICAgICAgICAgICAgdGVzdCh7IHZhbHVlIH0pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICF2YWx1ZSB8fCB2YWx1ZSA9PT0gdGhpcy5zdGF0ZS5uZXdQYXNzd29yZDtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGludmFsaWQ6ICgpID0+IF90KFwiYXV0aHxjaGFuZ2VfcGFzc3dvcmRfY29uZmlybV9pbnZhbGlkXCIpLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICB9KTtcblxuICAgIHByaXZhdGUgb25DbGlja0NoYW5nZSA9IGFzeW5jIChldjogUmVhY3QuTW91c2VFdmVudCB8IFJlYWN0LkZvcm1FdmVudCk6IFByb21pc2U8dm9pZD4gPT4ge1xuICAgICAgICBldi5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgICAgIGNvbnN0IGFsbEZpZWxkc1ZhbGlkID0gYXdhaXQgdGhpcy52ZXJpZnlGaWVsZHNCZWZvcmVTdWJtaXQoKTtcbiAgICAgICAgaWYgKCFhbGxGaWVsZHNWYWxpZCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3Qgb2xkUGFzc3dvcmQgPSB0aGlzLnN0YXRlLm9sZFBhc3N3b3JkO1xuICAgICAgICBjb25zdCBuZXdQYXNzd29yZCA9IHRoaXMuc3RhdGUubmV3UGFzc3dvcmQ7XG4gICAgICAgIGNvbnN0IGNvbmZpcm1QYXNzd29yZCA9IHRoaXMuc3RhdGUubmV3UGFzc3dvcmRDb25maXJtO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgLy8gVE9ETzogV2UgY2FuIHJlbW92ZSB0aGlzIGNoZWNrIChidXQgc2hvdWxkIGFkZCBzb21lIFBsYXl3cmlnaHQgdGVzdHMgdG9cbiAgICAgICAgICAgIC8vIHNhbml0eSBjaGVjayB0aGlzIGZsb3cpLiBUaGlzIGxvZ2ljIGlzIHJlZHVuZGFudCB3aXRoIHRoZSBpbnB1dCBmaWVsZFxuICAgICAgICAgICAgLy8gdmFsaWRhdGlvbiB3ZSBkbyBhbmQgYHZlcmlmeUZpZWxkc0JlZm9yZVN1Ym1pdCgpYCBhYm92ZS4gU2VlXG4gICAgICAgICAgICAvLyBodHRwczovL2dpdGh1Yi5jb20vbWF0cml4LW9yZy9tYXRyaXgtcmVhY3Qtc2RrL3B1bGwvMTA2MTUjZGlzY3Vzc2lvbl9yMTE2NzM2NDIxNFxuICAgICAgICAgICAgdGhpcy5jaGVja1Bhc3N3b3JkKG9sZFBhc3N3b3JkLCBuZXdQYXNzd29yZCwgY29uZmlybVBhc3N3b3JkKTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm9uQ2hhbmdlUGFzc3dvcmQob2xkUGFzc3dvcmQsIG5ld1Bhc3N3b3JkKTtcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICBpZiAoZXJyIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnByb3BzLm9uRXJyb3IoZXJyKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5wcm9wcy5vbkVycm9yKFxuICAgICAgICAgICAgICAgICAgICBuZXcgVXNlckZyaWVuZGx5RXJyb3IoXCJhdXRofGNoYW5nZV9wYXNzd29yZF9lcnJvclwiLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvcjogU3RyaW5nKGVyciksXG4gICAgICAgICAgICAgICAgICAgICAgICBjYXVzZTogdW5kZWZpbmVkLFxuICAgICAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcblxuICAgIHByaXZhdGUgYXN5bmMgdmVyaWZ5RmllbGRzQmVmb3JlU3VibWl0KCk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgICAgICAvLyBCbHVyIHRoZSBhY3RpdmUgZWxlbWVudCBpZiBhbnksIHNvIHdlIGZpcnN0IHJ1biBpdHMgYmx1ciB2YWxpZGF0aW9uLFxuICAgICAgICAvLyB3aGljaCBpcyBsZXNzIHN0cmljdCB0aGFuIHRoZSBwYXNzIHdlJ3JlIGFib3V0IHRvIGRvIGJlbG93IGZvciBhbGwgZmllbGRzLlxuICAgICAgICBjb25zdCBhY3RpdmVFbGVtZW50ID0gZG9jdW1lbnQuYWN0aXZlRWxlbWVudCBhcyBIVE1MRWxlbWVudDtcbiAgICAgICAgaWYgKGFjdGl2ZUVsZW1lbnQpIHtcbiAgICAgICAgICAgIGFjdGl2ZUVsZW1lbnQuYmx1cigpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgZmllbGRJRHNJbkRpc3BsYXlPcmRlcjogRmllbGRUeXBlW10gPSBbXG4gICAgICAgICAgICBGSUVMRF9PTERfUEFTU1dPUkQsXG4gICAgICAgICAgICBGSUVMRF9ORVdfUEFTU1dPUkQsXG4gICAgICAgICAgICBGSUVMRF9ORVdfUEFTU1dPUkRfQ09ORklSTSxcbiAgICAgICAgXTtcblxuICAgICAgICAvLyBSdW4gYWxsIGZpZWxkcyB3aXRoIHN0cmljdGVyIHZhbGlkYXRpb24gdGhhdCBubyBsb25nZXIgYWxsb3dzIGVtcHR5XG4gICAgICAgIC8vIHZhbHVlcyBmb3IgcmVxdWlyZWQgZmllbGRzLlxuICAgICAgICBmb3IgKGNvbnN0IGZpZWxkSUQgb2YgZmllbGRJRHNJbkRpc3BsYXlPcmRlcikge1xuICAgICAgICAgICAgY29uc3QgZmllbGQgPSB0aGlzW2ZpZWxkSURdO1xuICAgICAgICAgICAgaWYgKCFmaWVsZCkge1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gV2UgbXVzdCB3YWl0IGZvciB0aGVzZSB2YWxpZGF0aW9ucyB0byBmaW5pc2ggYmVmb3JlIHF1ZXVlaW5nXG4gICAgICAgICAgICAvLyB1cCB0aGUgc2V0U3RhdGUgYmVsb3cgc28gb3VyIHNldFN0YXRlIGdvZXMgaW4gdGhlIHF1ZXVlIGFmdGVyXG4gICAgICAgICAgICAvLyBhbGwgdGhlIHNldFN0YXRlcyBmcm9tIHRoZXNlIHZhbGlkYXRlIGNhbGxzICh0aGF0J3MgaG93IHdlXG4gICAgICAgICAgICAvLyBrbm93IHRoZXkndmUgZmluaXNoZWQpLlxuICAgICAgICAgICAgYXdhaXQgZmllbGQudmFsaWRhdGUoeyBhbGxvd0VtcHR5OiBmYWxzZSB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFZhbGlkYXRpb24gYW5kIHN0YXRlIHVwZGF0ZXMgYXJlIGFzeW5jLCBzbyB3ZSBuZWVkIHRvIHdhaXQgZm9yIHRoZW0gdG8gY29tcGxldGVcbiAgICAgICAgLy8gZmlyc3QuIFF1ZXVlIGEgYHNldFN0YXRlYCBjYWxsYmFjayBhbmQgd2FpdCBmb3IgaXQgdG8gcmVzb2x2ZS5cbiAgICAgICAgYXdhaXQgbmV3IFByb21pc2U8dm9pZD4oKHJlc29sdmUpID0+IHRoaXMuc2V0U3RhdGUoe30sIHJlc29sdmUpKTtcblxuICAgICAgICBpZiAodGhpcy5hbGxGaWVsZHNWYWxpZCgpKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGludmFsaWRGaWVsZCA9IHRoaXMuZmluZEZpcnN0SW52YWxpZEZpZWxkKGZpZWxkSURzSW5EaXNwbGF5T3JkZXIpO1xuXG4gICAgICAgIGlmICghaW52YWxpZEZpZWxkKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEZvY3VzIHRoZSBmaXJzdCBpbnZhbGlkIGZpZWxkIGFuZCBzaG93IGZlZWRiYWNrIGluIHRoZSBzdHJpY3RlciBtb2RlXG4gICAgICAgIC8vIHRoYXQgbm8gbG9uZ2VyIGFsbG93cyBlbXB0eSB2YWx1ZXMgZm9yIHJlcXVpcmVkIGZpZWxkcy5cbiAgICAgICAgaW52YWxpZEZpZWxkLmZvY3VzKCk7XG4gICAgICAgIGludmFsaWRGaWVsZC52YWxpZGF0ZSh7IGFsbG93RW1wdHk6IGZhbHNlLCBmb2N1c2VkOiB0cnVlIH0pO1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhbGxGaWVsZHNWYWxpZCgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIE9iamVjdC52YWx1ZXModGhpcy5zdGF0ZS5maWVsZFZhbGlkKS5ldmVyeShCb29sZWFuKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGZpbmRGaXJzdEludmFsaWRGaWVsZChmaWVsZElEczogRmllbGRUeXBlW10pOiBGaWVsZCB8IG51bGwge1xuICAgICAgICBmb3IgKGNvbnN0IGZpZWxkSUQgb2YgZmllbGRJRHMpIHtcbiAgICAgICAgICAgIGlmICghdGhpcy5zdGF0ZS5maWVsZFZhbGlkW2ZpZWxkSURdICYmIHRoaXNbZmllbGRJRF0pIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpc1tmaWVsZElEXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICBwdWJsaWMgcmVuZGVyKCk6IFJlYWN0LlJlYWN0Tm9kZSB7XG4gICAgICAgIGNvbnN0IHJvd0NsYXNzTmFtZSA9IHRoaXMucHJvcHMucm93Q2xhc3NOYW1lO1xuICAgICAgICBjb25zdCBidXR0b25DbGFzc05hbWUgPSB0aGlzLnByb3BzLmJ1dHRvbkNsYXNzTmFtZTtcblxuICAgICAgICBzd2l0Y2ggKHRoaXMuc3RhdGUucGhhc2UpIHtcbiAgICAgICAgICAgIGNhc2UgUGhhc2UuRWRpdDpcbiAgICAgICAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgICAgICAgICA8Zm9ybSBjbGFzc05hbWU9e3RoaXMucHJvcHMuY2xhc3NOYW1lfSBvblN1Ym1pdD17dGhpcy5vbkNsaWNrQ2hhbmdlfT5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3NOYW1lPXtyb3dDbGFzc05hbWV9PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxGaWVsZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWY9eyhmaWVsZCkgPT4gKHRoaXNbRklFTERfT0xEX1BBU1NXT1JEXSA9IGZpZWxkKX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZT1cInBhc3N3b3JkXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWw9e190KFwiYXV0aHxjaGFuZ2VfcGFzc3dvcmRfY3VycmVudF9sYWJlbFwiKX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU9e3RoaXMuc3RhdGUub2xkUGFzc3dvcmR9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9uQ2hhbmdlPXt0aGlzLm9uQ2hhbmdlT2xkUGFzc3dvcmR9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9uVmFsaWRhdGU9e3RoaXMub25PbGRQYXNzd29yZFZhbGlkYXRlfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3NOYW1lPXtyb3dDbGFzc05hbWV9PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxQYXNzcGhyYXNlRmllbGRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmllbGRSZWY9eyhmaWVsZCkgPT4gKHRoaXNbRklFTERfTkVXX1BBU1NXT1JEXSA9IGZpZWxkKX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZT1cInBhc3N3b3JkXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWw9e190ZChcImF1dGh8Y2hhbmdlX3Bhc3N3b3JkX25ld19sYWJlbFwiKX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluU2NvcmU9e1BBU1NXT1JEX01JTl9TQ09SRX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU9e3RoaXMuc3RhdGUubmV3UGFzc3dvcmR9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF1dG9Gb2N1cz17dGhpcy5wcm9wcy5hdXRvRm9jdXNOZXdQYXNzd29yZElucHV0fVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbkNoYW5nZT17dGhpcy5vbkNoYW5nZU5ld1Bhc3N3b3JkfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvblZhbGlkYXRlPXt0aGlzLm9uTmV3UGFzc3dvcmRWYWxpZGF0ZX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXV0b0NvbXBsZXRlPVwibmV3LXBhc3N3b3JkXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzTmFtZT17cm93Q2xhc3NOYW1lfT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8RmllbGRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVmPXsoZmllbGQpID0+ICh0aGlzW0ZJRUxEX05FV19QQVNTV09SRF9DT05GSVJNXSA9IGZpZWxkKX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZT1cInBhc3N3b3JkXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWw9e190KFwiYXV0aHxjaGFuZ2VfcGFzc3dvcmRfY29uZmlybV9sYWJlbFwiKX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU9e3RoaXMuc3RhdGUubmV3UGFzc3dvcmRDb25maXJtfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbkNoYW5nZT17dGhpcy5vbkNoYW5nZU5ld1Bhc3N3b3JkQ29uZmlybX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb25WYWxpZGF0ZT17dGhpcy5vbk5ld1Bhc3N3b3JkQ29uZmlybVZhbGlkYXRlfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdXRvQ29tcGxldGU9XCJuZXctcGFzc3dvcmRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxBY2Nlc3NpYmxlQnV0dG9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3NOYW1lPXtidXR0b25DbGFzc05hbWV9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAga2luZD17dGhpcy5wcm9wcy5idXR0b25LaW5kfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9uQ2xpY2s9e3RoaXMub25DbGlja0NoYW5nZX1cbiAgICAgICAgICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB7dGhpcy5wcm9wcy5idXR0b25MYWJlbCB8fCBfdChcImF1dGh8Y2hhbmdlX3Bhc3N3b3JkX2FjdGlvblwiKX1cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvQWNjZXNzaWJsZUJ1dHRvbj5cbiAgICAgICAgICAgICAgICAgICAgPC9mb3JtPlxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICBjYXNlIFBoYXNlLlVwbG9hZGluZzpcbiAgICAgICAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzTmFtZT1cIm14X0RpYWxvZ19jb250ZW50XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8U3Bpbm5lciAvPlxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgfVxufVxuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7OztBQVFBLElBQUFBLE1BQUEsR0FBQUMsc0JBQUEsQ0FBQUMsT0FBQTtBQUdBLElBQUFDLE1BQUEsR0FBQUYsc0JBQUEsQ0FBQUMsT0FBQTtBQUNBLElBQUFFLGdCQUFBLEdBQUFGLE9BQUE7QUFDQSxJQUFBRyxpQkFBQSxHQUFBSixzQkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQUksUUFBQSxHQUFBTCxzQkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQUssV0FBQSxHQUFBTixzQkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQU0sZ0JBQUEsR0FBQU4sT0FBQTtBQUNBLElBQUFPLE1BQUEsR0FBQVIsc0JBQUEsQ0FBQUMsT0FBQTtB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