matrix-react-sdk
Version:
SDK for matrix.org using React
386 lines (380 loc) • 56.5 kB
JavaScript
"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 _classnames = _interopRequireDefault(require("classnames"));
var _languageHandler = require("../../../languageHandler");
var _SdkConfig = _interopRequireDefault(require("../../../SdkConfig"));
var _AccessibleButton = _interopRequireDefault(require("../elements/AccessibleButton"));
var _Validation = _interopRequireDefault(require("../elements/Validation"));
var _Field = _interopRequireDefault(require("../elements/Field"));
var _CountryDropdown = _interopRequireDefault(require("./CountryDropdown"));
var _EmailField = _interopRequireDefault(require("./EmailField"));
let _LoginField$Email, _LoginField$Phone, _LoginField$MatrixId, _LoginField$Password;
/*
Copyright 2024 New Vector Ltd.
Copyright 2015, 2016 , 2017, 2019 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.
*/
// For validating phone numbers without country codes
const PHONE_NUMBER_REGEX = /^[0-9()\-\s]*$/;
var LoginField = /*#__PURE__*/function (LoginField) {
LoginField["Email"] = "login_field_email";
LoginField["MatrixId"] = "login_field_mxid";
LoginField["Phone"] = "login_field_phone";
LoginField["Password"] = "login_field_password";
return LoginField;
}(LoginField || {});
/*
* A pure UI component which displays a username/password form.
* The email/username/phone fields are fully-controlled, the password field is not.
*/
_LoginField$Email = LoginField.Email;
_LoginField$Phone = LoginField.Phone;
_LoginField$MatrixId = LoginField.MatrixId;
_LoginField$Password = LoginField.Password;
class PasswordLogin extends _react.default.PureComponent {
constructor(props) {
super(props);
(0, _defineProperty2.default)(this, _LoginField$Email, null);
(0, _defineProperty2.default)(this, _LoginField$Phone, null);
(0, _defineProperty2.default)(this, _LoginField$MatrixId, null);
(0, _defineProperty2.default)(this, _LoginField$Password, null);
(0, _defineProperty2.default)(this, "onForgotPasswordClick", ev => {
ev.preventDefault();
ev.stopPropagation();
this.props.onForgotPasswordClick?.();
});
(0, _defineProperty2.default)(this, "onSubmitForm", async ev => {
ev.preventDefault();
const allFieldsValid = await this.verifyFieldsBeforeSubmit();
if (!allFieldsValid) {
return;
}
switch (this.state.loginType) {
case LoginField.Email:
case LoginField.MatrixId:
this.props.onSubmit(this.props.username, undefined, undefined, this.state.password);
break;
case LoginField.Phone:
this.props.onSubmit(undefined, this.props.phoneCountry, this.props.phoneNumber, this.state.password);
break;
}
});
(0, _defineProperty2.default)(this, "onUsernameChanged", ev => {
this.props.onUsernameChanged?.(ev.target.value);
});
(0, _defineProperty2.default)(this, "onUsernameBlur", ev => {
this.props.onUsernameBlur?.(ev.target.value);
});
(0, _defineProperty2.default)(this, "onLoginTypeChange", ev => {
const loginType = ev.target.value;
this.setState({
loginType
});
this.props.onUsernameChanged?.(""); // Reset because email and username use the same state
});
(0, _defineProperty2.default)(this, "onPhoneCountryChanged", country => {
this.props.onPhoneCountryChanged?.(country.iso2);
});
(0, _defineProperty2.default)(this, "onPhoneNumberChanged", ev => {
this.props.onPhoneNumberChanged?.(ev.target.value);
});
(0, _defineProperty2.default)(this, "onPasswordChanged", ev => {
this.setState({
password: ev.target.value
});
});
(0, _defineProperty2.default)(this, "validateUsernameRules", (0, _Validation.default)({
rules: [{
key: "required",
test({
value,
allowEmpty
}) {
return allowEmpty || !!value;
},
invalid: () => (0, _languageHandler._t)("auth|username_field_required_invalid")
}]
}));
(0, _defineProperty2.default)(this, "onUsernameValidate", async fieldState => {
const result = await this.validateUsernameRules(fieldState);
this.markFieldValid(LoginField.MatrixId, result.valid);
return result;
});
(0, _defineProperty2.default)(this, "onEmailValidate", result => {
this.markFieldValid(LoginField.Email, result.valid);
});
(0, _defineProperty2.default)(this, "validatePhoneNumberRules", (0, _Validation.default)({
rules: [{
key: "required",
test({
value,
allowEmpty
}) {
return allowEmpty || !!value;
},
invalid: () => (0, _languageHandler._t)("auth|msisdn_field_required_invalid")
}, {
key: "number",
test: ({
value
}) => !value || PHONE_NUMBER_REGEX.test(value),
invalid: () => (0, _languageHandler._t)("auth|msisdn_field_number_invalid")
}]
}));
(0, _defineProperty2.default)(this, "onPhoneNumberValidate", async fieldState => {
const result = await this.validatePhoneNumberRules(fieldState);
this.markFieldValid(LoginField.Password, result.valid);
return result;
});
(0, _defineProperty2.default)(this, "validatePasswordRules", (0, _Validation.default)({
rules: [{
key: "required",
test({
value,
allowEmpty
}) {
return allowEmpty || !!value;
},
invalid: () => (0, _languageHandler._t)("auth|password_field_label")
}]
}));
(0, _defineProperty2.default)(this, "onPasswordValidate", async fieldState => {
const result = await this.validatePasswordRules(fieldState);
this.markFieldValid(LoginField.Password, result.valid);
return result;
});
this.state = {
// Field error codes by field ID
fieldValid: {},
loginType: LoginField.MatrixId,
password: ""
};
}
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 = [this.state.loginType, LoginField.Password];
// 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;
}
markFieldValid(fieldID, valid) {
const {
fieldValid
} = this.state;
fieldValid[fieldID] = valid;
this.setState({
fieldValid
});
}
renderLoginField(loginType, autoFocus) {
const classes = {
error: false
};
switch (loginType) {
case LoginField.Email:
classes.error = this.props.loginIncorrect && !this.props.username;
return /*#__PURE__*/_react.default.createElement(_EmailField.default, {
id: "mx_LoginForm_email",
className: (0, _classnames.default)(classes),
name: "username" // make it a little easier for browser's remember-password
,
autoComplete: "email",
type: "email",
key: "email_input",
placeholder: "joe@example.com",
value: this.props.username,
onChange: this.onUsernameChanged,
onBlur: this.onUsernameBlur,
disabled: this.props.busy,
autoFocus: autoFocus,
onValidate: this.onEmailValidate,
fieldRef: field => {
this[LoginField.Email] = field;
}
});
case LoginField.MatrixId:
classes.error = this.props.loginIncorrect && !this.props.username;
return /*#__PURE__*/_react.default.createElement(_Field.default, {
id: "mx_LoginForm_username",
className: (0, _classnames.default)(classes),
name: "username" // make it a little easier for browser's remember-password
,
autoComplete: "username",
key: "username_input",
type: "text",
label: (0, _languageHandler._t)("common|username"),
placeholder: (0, _languageHandler._t)("common|username"),
value: this.props.username,
onChange: this.onUsernameChanged,
onBlur: this.onUsernameBlur,
disabled: this.props.busy,
autoFocus: autoFocus,
onValidate: this.onUsernameValidate,
ref: field => {
this[LoginField.MatrixId] = field;
}
});
case LoginField.Phone:
{
classes.error = this.props.loginIncorrect && !this.props.phoneNumber;
const phoneCountry = /*#__PURE__*/_react.default.createElement(_CountryDropdown.default, {
value: this.props.phoneCountry,
isSmall: true,
showPrefix: true,
onOptionChange: this.onPhoneCountryChanged
});
return /*#__PURE__*/_react.default.createElement(_Field.default, {
id: "mx_LoginForm_phone",
className: (0, _classnames.default)(classes),
name: "phoneNumber",
autoComplete: "tel-national",
key: "phone_input",
type: "text",
label: (0, _languageHandler._t)("auth|msisdn_field_label"),
value: this.props.phoneNumber,
prefixComponent: phoneCountry,
onChange: this.onPhoneNumberChanged,
disabled: this.props.busy,
autoFocus: autoFocus,
onValidate: this.onPhoneNumberValidate,
ref: field => {
this[LoginField.Password] = field;
}
});
}
}
}
isLoginEmpty() {
switch (this.state.loginType) {
case LoginField.Email:
case LoginField.MatrixId:
return !this.props.username;
case LoginField.Phone:
return !this.props.phoneCountry || !this.props.phoneNumber;
}
}
render() {
let forgotPasswordJsx;
if (this.props.onForgotPasswordClick) {
forgotPasswordJsx = /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, {
className: "mx_Login_forgot",
disabled: this.props.busy,
kind: "link",
onClick: this.onForgotPasswordClick
}, (0, _languageHandler._t)("auth|reset_password_button"));
}
const pwFieldClass = (0, _classnames.default)({
error: this.props.loginIncorrect && !this.isLoginEmpty() // only error password if error isn't top field
});
// If login is empty, autoFocus login, otherwise autoFocus password.
// this is for when auto server discovery remounts us when the user tries to tab from username to password
const autoFocusPassword = !this.isLoginEmpty();
const loginField = this.renderLoginField(this.state.loginType, !autoFocusPassword);
let loginType;
if (!_SdkConfig.default.get().disable_3pid_login) {
loginType = /*#__PURE__*/_react.default.createElement("div", {
className: "mx_Login_type_container"
}, /*#__PURE__*/_react.default.createElement("label", {
className: "mx_Login_type_label"
}, (0, _languageHandler._t)("auth|identifier_label")), /*#__PURE__*/_react.default.createElement(_Field.default, {
element: "select",
value: this.state.loginType,
onChange: this.onLoginTypeChange,
disabled: this.props.busy
}, /*#__PURE__*/_react.default.createElement("option", {
key: LoginField.MatrixId,
value: LoginField.MatrixId
}, (0, _languageHandler._t)("common|username")), /*#__PURE__*/_react.default.createElement("option", {
key: LoginField.Email,
value: LoginField.Email
}, (0, _languageHandler._t)("common|email_address")), /*#__PURE__*/_react.default.createElement("option", {
key: LoginField.Password,
value: LoginField.Password
}, (0, _languageHandler._t)("auth|msisdn_field_label"))));
}
return /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("form", {
onSubmit: this.onSubmitForm
}, loginType, loginField, /*#__PURE__*/_react.default.createElement(_Field.default, {
id: "mx_LoginForm_password",
className: pwFieldClass,
autoComplete: "current-password",
type: "password",
name: "password",
label: (0, _languageHandler._t)("common|password"),
value: this.state.password,
onChange: this.onPasswordChanged,
disabled: this.props.busy,
autoFocus: autoFocusPassword,
onValidate: this.onPasswordValidate,
ref: field => this[LoginField.Password] = field
}), forgotPasswordJsx, !this.props.busy && /*#__PURE__*/_react.default.createElement("input", {
className: "mx_Login_submit",
type: "submit",
value: (0, _languageHandler._t)("action|sign_in"),
disabled: this.props.disableSubmit
})));
}
}
exports.default = PasswordLogin;
(0, _defineProperty2.default)(PasswordLogin, "defaultProps", {
onUsernameChanged: function () {},
onUsernameBlur: function () {},
onPhoneCountryChanged: function () {},
onPhoneNumberChanged: function () {},
loginIncorrect: false,
disableSubmit: false
});
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfcmVhY3QiLCJfaW50ZXJvcFJlcXVpcmVEZWZhdWx0IiwicmVxdWlyZSIsIl9jbGFzc25hbWVzIiwiX2xhbmd1YWdlSGFuZGxlciIsIl9TZGtDb25maWciLCJfQWNjZXNzaWJsZUJ1dHRvbiIsIl9WYWxpZGF0aW9uIiwiX0ZpZWxkIiwiX0NvdW50cnlEcm9wZG93biIsIl9FbWFpbEZpZWxkIiwiX0xvZ2luRmllbGQkRW1haWwiLCJfTG9naW5GaWVsZCRQaG9uZSIsIl9Mb2dpbkZpZWxkJE1hdHJpeElkIiwiX0xvZ2luRmllbGQkUGFzc3dvcmQiLCJQSE9ORV9OVU1CRVJfUkVHRVgiLCJMb2dpbkZpZWxkIiwiRW1haWwiLCJQaG9uZSIsIk1hdHJpeElkIiwiUGFzc3dvcmQiLCJQYXNzd29yZExvZ2luIiwiUmVhY3QiLCJQdXJlQ29tcG9uZW50IiwiY29uc3RydWN0b3IiLCJwcm9wcyIsIl9kZWZpbmVQcm9wZXJ0eTIiLCJkZWZhdWx0IiwiZXYiLCJwcmV2ZW50RGVmYXVsdCIsInN0b3BQcm9wYWdhdGlvbiIsIm9uRm9yZ290UGFzc3dvcmRDbGljayIsImFsbEZpZWxkc1ZhbGlkIiwidmVyaWZ5RmllbGRzQmVmb3JlU3VibWl0Iiwic3RhdGUiLCJsb2dpblR5cGUiLCJvblN1Ym1pdCIsInVzZXJuYW1lIiwidW5kZWZpbmVkIiwicGFzc3dvcmQiLCJwaG9uZUNvdW50cnkiLCJwaG9uZU51bWJlciIsIm9uVXNlcm5hbWVDaGFuZ2VkIiwidGFyZ2V0IiwidmFsdWUiLCJvblVzZXJuYW1lQmx1ciIsInNldFN0YXRlIiwiY291bnRyeSIsIm9uUGhvbmVDb3VudHJ5Q2hhbmdlZCIsImlzbzIiLCJvblBob25lTnVtYmVyQ2hhbmdlZCIsIndpdGhWYWxpZGF0aW9uIiwicnVsZXMiLCJrZXkiLCJ0ZXN0IiwiYWxsb3dFbXB0eSIsImludmFsaWQiLCJfdCIsImZpZWxkU3RhdGUiLCJyZXN1bHQiLCJ2YWxpZGF0ZVVzZXJuYW1lUnVsZXMiLCJtYXJrRmllbGRWYWxpZCIsInZhbGlkIiwidmFsaWRhdGVQaG9uZU51bWJlclJ1bGVzIiwidmFsaWRhdGVQYXNzd29yZFJ1bGVzIiwiZmllbGRWYWxpZCIsImFjdGl2ZUVsZW1lbnQiLCJkb2N1bWVudCIsImJsdXIiLCJmaWVsZElEc0luRGlzcGxheU9yZGVyIiwiZmllbGRJRCIsImZpZWxkIiwidmFsaWRhdGUiLCJQcm9taXNlIiwicmVzb2x2ZSIsImludmFsaWRGaWVsZCIsImZpbmRGaXJzdEludmFsaWRGaWVsZCIsImZvY3VzIiwiZm9jdXNlZCIsIk9iamVjdCIsInZhbHVlcyIsImV2ZXJ5IiwiQm9vbGVhbiIsImZpZWxkSURzIiwicmVuZGVyTG9naW5GaWVsZCIsImF1dG9Gb2N1cyIsImNsYXNzZXMiLCJlcnJvciIsImxvZ2luSW5jb3JyZWN0IiwiY3JlYXRlRWxlbWVudCIsImlkIiwiY2xhc3NOYW1lIiwiY2xhc3NOYW1lcyIsIm5hbWUiLCJhdXRvQ29tcGxldGUiLCJ0eXBlIiwicGxhY2Vob2xkZXIiLCJvbkNoYW5nZSIsIm9uQmx1ciIsImRpc2FibGVkIiwiYnVzeSIsIm9uVmFsaWRhdGUiLCJvbkVtYWlsVmFsaWRhdGUiLCJmaWVsZFJlZiIsImxhYmVsIiwib25Vc2VybmFtZVZhbGlkYXRlIiwicmVmIiwiaXNTbWFsbCIsInNob3dQcmVmaXgiLCJvbk9wdGlvbkNoYW5nZSIsInByZWZpeENvbXBvbmVudCIsIm9uUGhvbmVOdW1iZXJWYWxpZGF0ZSIsImlzTG9naW5FbXB0eSIsInJlbmRlciIsImZvcmdvdFBhc3N3b3JkSnN4Iiwia2luZCIsIm9uQ2xpY2siLCJwd0ZpZWxkQ2xhc3MiLCJhdXRvRm9jdXNQYXNzd29yZCIsImxvZ2luRmllbGQiLCJTZGtDb25maWciLCJnZXQiLCJkaXNhYmxlXzNwaWRfbG9naW4iLCJlbGVtZW50Iiwib25Mb2dpblR5cGVDaGFuZ2UiLCJvblN1Ym1pdEZvcm0iLCJvblBhc3N3b3JkQ2hhbmdlZCIsIm9uUGFzc3dvcmRWYWxpZGF0ZSIsImRpc2FibGVTdWJtaXQiLCJleHBvcnRzIl0sInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2NvbXBvbmVudHMvdmlld3MvYXV0aC9QYXNzd29yZExvZ2luLnRzeCJdLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuQ29weXJpZ2h0IDIwMjQgTmV3IFZlY3RvciBMdGQuXG5Db3B5cmlnaHQgMjAxNSwgMjAxNiAsIDIwMTcsIDIwMTkgVGhlIE1hdHJpeC5vcmcgRm91bmRhdGlvbiBDLkkuQy5cblxuU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFHUEwtMy4wLW9ubHkgT1IgR1BMLTMuMC1vbmx5XG5QbGVhc2Ugc2VlIExJQ0VOU0UgZmlsZXMgaW4gdGhlIHJlcG9zaXRvcnkgcm9vdCBmb3IgZnVsbCBkZXRhaWxzLlxuKi9cblxuaW1wb3J0IFJlYWN0LCB7IFN5bnRoZXRpY0V2ZW50IH0gZnJvbSBcInJlYWN0XCI7XG5pbXBvcnQgY2xhc3NOYW1lcyBmcm9tIFwiY2xhc3NuYW1lc1wiO1xuXG5pbXBvcnQgeyBfdCB9IGZyb20gXCIuLi8uLi8uLi9sYW5ndWFnZUhhbmRsZXJcIjtcbmltcG9ydCBTZGtDb25maWcgZnJvbSBcIi4uLy4uLy4uL1Nka0NvbmZpZ1wiO1xuaW1wb3J0IHsgVmFsaWRhdGVkU2VydmVyQ29uZmlnIH0gZnJvbSBcIi4uLy4uLy4uL3V0aWxzL1ZhbGlkYXRlZFNlcnZlckNvbmZpZ1wiO1xuaW1wb3J0IEFjY2Vzc2libGVCdXR0b24sIHsgQnV0dG9uRXZlbnQgfSBmcm9tIFwiLi4vZWxlbWVudHMvQWNjZXNzaWJsZUJ1dHRvblwiO1xuaW1wb3J0IHdpdGhWYWxpZGF0aW9uLCB7IElGaWVsZFN0YXRlLCBJVmFsaWRhdGlvblJlc3VsdCB9IGZyb20gXCIuLi9lbGVtZW50cy9WYWxpZGF0aW9uXCI7XG5pbXBvcnQgRmllbGQgZnJvbSBcIi4uL2VsZW1lbnRzL0ZpZWxkXCI7XG5pbXBvcnQgQ291bnRyeURyb3Bkb3duIGZyb20gXCIuL0NvdW50cnlEcm9wZG93blwiO1xuaW1wb3J0IEVtYWlsRmllbGQgZnJvbSBcIi4vRW1haWxGaWVsZFwiO1xuaW1wb3J0IHsgUGhvbmVOdW1iZXJDb3VudHJ5RGVmaW5pdGlvbiB9IGZyb20gXCIuLi8uLi8uLi9waG9uZW51bWJlclwiO1xuXG4vLyBGb3IgdmFsaWRhdGluZyBwaG9uZSBudW1iZXJzIHdpdGhvdXQgY291bnRyeSBjb2Rlc1xuY29uc3QgUEhPTkVfTlVNQkVSX1JFR0VYID0gL15bMC05KClcXC1cXHNdKiQvO1xuXG5pbnRlcmZhY2UgSVByb3BzIHtcbiAgICB1c2VybmFtZTogc3RyaW5nOyAvLyBhbHNvIHVzZWQgZm9yIGVtYWlsIGFkZHJlc3NcbiAgICBwaG9uZUNvdW50cnk6IHN0cmluZztcbiAgICBwaG9uZU51bWJlcjogc3RyaW5nO1xuXG4gICAgc2VydmVyQ29uZmlnOiBWYWxpZGF0ZWRTZXJ2ZXJDb25maWc7XG4gICAgbG9naW5JbmNvcnJlY3Q6IGJvb2xlYW47XG4gICAgZGlzYWJsZVN1Ym1pdD86IGJvb2xlYW47XG4gICAgYnVzeT86IGJvb2xlYW47XG5cbiAgICBvblN1Ym1pdCh1c2VybmFtZTogc3RyaW5nLCBwaG9uZUNvdW50cnk6IHZvaWQsIHBob25lTnVtYmVyOiB2b2lkLCBwYXNzd29yZDogc3RyaW5nKTogdm9pZDtcbiAgICBvblN1Ym1pdCh1c2VybmFtZTogdm9pZCwgcGhvbmVDb3VudHJ5OiBzdHJpbmcsIHBob25lTnVtYmVyOiBzdHJpbmcsIHBhc3N3b3JkOiBzdHJpbmcpOiB2b2lkO1xuICAgIG9uVXNlcm5hbWVDaGFuZ2VkPyh1c2VybmFtZTogc3RyaW5nKTogdm9pZDtcbiAgICBvblVzZXJuYW1lQmx1cj8odXNlcm5hbWU6IHN0cmluZyk6IHZvaWQ7XG4gICAgb25QaG9uZUNvdW50cnlDaGFuZ2VkPyhwaG9uZUNvdW50cnk6IHN0cmluZyk6IHZvaWQ7XG4gICAgb25QaG9uZU51bWJlckNoYW5nZWQ/KHBob25lTnVtYmVyOiBzdHJpbmcpOiB2b2lkO1xuICAgIG9uRm9yZ290UGFzc3dvcmRDbGljaz8oKTogdm9pZDtcbn1cblxuaW50ZXJmYWNlIElTdGF0ZSB7XG4gICAgZmllbGRWYWxpZDogUGFydGlhbDxSZWNvcmQ8TG9naW5GaWVsZCwgYm9vbGVhbj4+O1xuICAgIGxvZ2luVHlwZTogTG9naW5GaWVsZC5FbWFpbCB8IExvZ2luRmllbGQuTWF0cml4SWQgfCBMb2dpbkZpZWxkLlBob25lO1xuICAgIHBhc3N3b3JkOiBzdHJpbmc7XG59XG5cbmNvbnN0IGVudW0gTG9naW5GaWVsZCB7XG4gICAgRW1haWwgPSBcImxvZ2luX2ZpZWxkX2VtYWlsXCIsXG4gICAgTWF0cml4SWQgPSBcImxvZ2luX2ZpZWxkX214aWRcIixcbiAgICBQaG9uZSA9IFwibG9naW5fZmllbGRfcGhvbmVcIixcbiAgICBQYXNzd29yZCA9IFwibG9naW5fZmllbGRfcGFzc3dvcmRcIixcbn1cblxuLypcbiAqIEEgcHVyZSBVSSBjb21wb25lbnQgd2hpY2ggZGlzcGxheXMgYSB1c2VybmFtZS9wYXNzd29yZCBmb3JtLlxuICogVGhlIGVtYWlsL3VzZXJuYW1lL3Bob25lIGZpZWxkcyBhcmUgZnVsbHktY29udHJvbGxlZCwgdGhlIHBhc3N3b3JkIGZpZWxkIGlzIG5vdC5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgUGFzc3dvcmRMb2dpbiBleHRlbmRzIFJlYWN0LlB1cmVDb21wb25lbnQ8SVByb3BzLCBJU3RhdGU+IHtcbiAgICBwcml2YXRlIFtMb2dpbkZpZWxkLkVtYWlsXTogRmllbGQgfCBudWxsID0gbnVsbDtcbiAgICBwcml2YXRlIFtMb2dpbkZpZWxkLlBob25lXTogRmllbGQgfCBudWxsID0gbnVsbDtcbiAgICBwcml2YXRlIFtMb2dpbkZpZWxkLk1hdHJpeElkXTogRmllbGQgfCBudWxsID0gbnVsbDtcbiAgICBwcml2YXRlIFtMb2dpbkZpZWxkLlBhc3N3b3JkXTogRmllbGQgfCBudWxsID0gbnVsbDtcblxuICAgIHB1YmxpYyBzdGF0aWMgZGVmYXVsdFByb3BzID0ge1xuICAgICAgICBvblVzZXJuYW1lQ2hhbmdlZDogZnVuY3Rpb24gKCkge30sXG4gICAgICAgIG9uVXNlcm5hbWVCbHVyOiBmdW5jdGlvbiAoKSB7fSxcbiAgICAgICAgb25QaG9uZUNvdW50cnlDaGFuZ2VkOiBmdW5jdGlvbiAoKSB7fSxcbiAgICAgICAgb25QaG9uZU51bWJlckNoYW5nZWQ6IGZ1bmN0aW9uICgpIHt9LFxuICAgICAgICBsb2dpbkluY29ycmVjdDogZmFsc2UsXG4gICAgICAgIGRpc2FibGVTdWJtaXQ6IGZhbHNlLFxuICAgIH07XG5cbiAgICBwdWJsaWMgY29uc3RydWN0b3IocHJvcHM6IElQcm9wcykge1xuICAgICAgICBzdXBlcihwcm9wcyk7XG4gICAgICAgIHRoaXMuc3RhdGUgPSB7XG4gICAgICAgICAgICAvLyBGaWVsZCBlcnJvciBjb2RlcyBieSBmaWVsZCBJRFxuICAgICAgICAgICAgZmllbGRWYWxpZDoge30sXG4gICAgICAgICAgICBsb2dpblR5cGU6IExvZ2luRmllbGQuTWF0cml4SWQsXG4gICAgICAgICAgICBwYXNzd29yZDogXCJcIixcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBwcml2YXRlIG9uRm9yZ290UGFzc3dvcmRDbGljayA9IChldjogQnV0dG9uRXZlbnQpOiB2b2lkID0+IHtcbiAgICAgICAgZXYucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgZXYuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgIHRoaXMucHJvcHMub25Gb3Jnb3RQYXNzd29yZENsaWNrPy4oKTtcbiAgICB9O1xuXG4gICAgcHJpdmF0ZSBvblN1Ym1pdEZvcm0gPSBhc3luYyAoZXY6IFN5bnRoZXRpY0V2ZW50KTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gICAgICAgIGV2LnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICAgICAgY29uc3QgYWxsRmllbGRzVmFsaWQgPSBhd2FpdCB0aGlzLnZlcmlmeUZpZWxkc0JlZm9yZVN1Ym1pdCgpO1xuICAgICAgICBpZiAoIWFsbEZpZWxkc1ZhbGlkKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBzd2l0Y2ggKHRoaXMuc3RhdGUubG9naW5UeXBlKSB7XG4gICAgICAgICAgICBjYXNlIExvZ2luRmllbGQuRW1haWw6XG4gICAgICAgICAgICBjYXNlIExvZ2luRmllbGQuTWF0cml4SWQ6XG4gICAgICAgICAgICAgICAgdGhpcy5wcm9wcy5vblN1Ym1pdCh0aGlzLnByb3BzLnVzZXJuYW1lLCB1bmRlZmluZWQsIHVuZGVmaW5lZCwgdGhpcy5zdGF0ZS5wYXNzd29yZCk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIExvZ2luRmllbGQuUGhvbmU6XG4gICAgICAgICAgICAgICAgdGhpcy5wcm9wcy5vblN1Ym1pdCh1bmRlZmluZWQsIHRoaXMucHJvcHMucGhvbmVDb3VudHJ5LCB0aGlzLnByb3BzLnBob25lTnVtYmVyLCB0aGlzLnN0YXRlLnBhc3N3b3JkKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBwcml2YXRlIG9uVXNlcm5hbWVDaGFuZ2VkID0gKGV2OiBSZWFjdC5DaGFuZ2VFdmVudDxIVE1MSW5wdXRFbGVtZW50Pik6IHZvaWQgPT4ge1xuICAgICAgICB0aGlzLnByb3BzLm9uVXNlcm5hbWVDaGFuZ2VkPy4oZXYudGFyZ2V0LnZhbHVlKTtcbiAgICB9O1xuXG4gICAgcHJpdmF0ZSBvblVzZXJuYW1lQmx1ciA9IChldjogUmVhY3QuRm9jdXNFdmVudDxIVE1MSW5wdXRFbGVtZW50Pik6IHZvaWQgPT4ge1xuICAgICAgICB0aGlzLnByb3BzLm9uVXNlcm5hbWVCbHVyPy4oZXYudGFyZ2V0LnZhbHVlKTtcbiAgICB9O1xuXG4gICAgcHJpdmF0ZSBvbkxvZ2luVHlwZUNoYW5nZSA9IChldjogUmVhY3QuQ2hhbmdlRXZlbnQ8SFRNTFNlbGVjdEVsZW1lbnQ+KTogdm9pZCA9PiB7XG4gICAgICAgIGNvbnN0IGxvZ2luVHlwZSA9IGV2LnRhcmdldC52YWx1ZSBhcyBJU3RhdGVbXCJsb2dpblR5cGVcIl07XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoeyBsb2dpblR5cGUgfSk7XG4gICAgICAgIHRoaXMucHJvcHMub25Vc2VybmFtZUNoYW5nZWQ/LihcIlwiKTsgLy8gUmVzZXQgYmVjYXVzZSBlbWFpbCBhbmQgdXNlcm5hbWUgdXNlIHRoZSBzYW1lIHN0YXRlXG4gICAgfTtcblxuICAgIHByaXZhdGUgb25QaG9uZUNvdW50cnlDaGFuZ2VkID0gKGNvdW50cnk6IFBob25lTnVtYmVyQ291bnRyeURlZmluaXRpb24pOiB2b2lkID0+IHtcbiAgICAgICAgdGhpcy5wcm9wcy5vblBob25lQ291bnRyeUNoYW5nZWQ/Lihjb3VudHJ5LmlzbzIpO1xuICAgIH07XG5cbiAgICBwcml2YXRlIG9uUGhvbmVOdW1iZXJDaGFuZ2VkID0gKGV2OiBSZWFjdC5DaGFuZ2VFdmVudDxIVE1MSW5wdXRFbGVtZW50Pik6IHZvaWQgPT4ge1xuICAgICAgICB0aGlzLnByb3BzLm9uUGhvbmVOdW1iZXJDaGFuZ2VkPy4oZXYudGFyZ2V0LnZhbHVlKTtcbiAgICB9O1xuXG4gICAgcHJpdmF0ZSBvblBhc3N3b3JkQ2hhbmdlZCA9IChldjogUmVhY3QuQ2hhbmdlRXZlbnQ8SFRNTElucHV0RWxlbWVudD4pOiB2b2lkID0+IHtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7IHBhc3N3b3JkOiBldi50YXJnZXQudmFsdWUgfSk7XG4gICAgfTtcblxuICAgIHByaXZhdGUgYXN5bmMgdmVyaWZ5RmllbGRzQmVmb3JlU3VibWl0KCk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgICAgICAvLyBCbHVyIHRoZSBhY3RpdmUgZWxlbWVudCBpZiBhbnksIHNvIHdlIGZpcnN0IHJ1biBpdHMgYmx1ciB2YWxpZGF0aW9uLFxuICAgICAgICAvLyB3aGljaCBpcyBsZXNzIHN0cmljdCB0aGFuIHRoZSBwYXNzIHdlJ3JlIGFib3V0IHRvIGRvIGJlbG93IGZvciBhbGwgZmllbGRzLlxuICAgICAgICBjb25zdCBhY3RpdmVFbGVtZW50ID0gZG9jdW1lbnQuYWN0aXZlRWxlbWVudCBhcyBIVE1MRWxlbWVudDtcbiAgICAgICAgaWYgKGFjdGl2ZUVsZW1lbnQpIHtcbiAgICAgICAgICAgIGFjdGl2ZUVsZW1lbnQuYmx1cigpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgZmllbGRJRHNJbkRpc3BsYXlPcmRlciA9IFt0aGlzLnN0YXRlLmxvZ2luVHlwZSwgTG9naW5GaWVsZC5QYXNzd29yZF07XG5cbiAgICAgICAgLy8gUnVuIGFsbCBmaWVsZHMgd2l0aCBzdHJpY3RlciB2YWxpZGF0aW9uIHRoYXQgbm8gbG9uZ2VyIGFsbG93cyBlbXB0eVxuICAgICAgICAvLyB2YWx1ZXMgZm9yIHJlcXVpcmVkIGZpZWxkcy5cbiAgICAgICAgZm9yIChjb25zdCBmaWVsZElEIG9mIGZpZWxkSURzSW5EaXNwbGF5T3JkZXIpIHtcbiAgICAgICAgICAgIGNvbnN0IGZpZWxkID0gdGhpc1tmaWVsZElEXTtcbiAgICAgICAgICAgIGlmICghZmllbGQpIHtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIFdlIG11c3Qgd2FpdCBmb3IgdGhlc2UgdmFsaWRhdGlvbnMgdG8gZmluaXNoIGJlZm9yZSBxdWV1ZWluZ1xuICAgICAgICAgICAgLy8gdXAgdGhlIHNldFN0YXRlIGJlbG93IHNvIG91ciBzZXRTdGF0ZSBnb2VzIGluIHRoZSBxdWV1ZSBhZnRlclxuICAgICAgICAgICAgLy8gYWxsIHRoZSBzZXRTdGF0ZXMgZnJvbSB0aGVzZSB2YWxpZGF0ZSBjYWxscyAodGhhdCdzIGhvdyB3ZVxuICAgICAgICAgICAgLy8ga25vdyB0aGV5J3ZlIGZpbmlzaGVkKS5cbiAgICAgICAgICAgIGF3YWl0IGZpZWxkLnZhbGlkYXRlKHsgYWxsb3dFbXB0eTogZmFsc2UgfSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBWYWxpZGF0aW9uIGFuZCBzdGF0ZSB1cGRhdGVzIGFyZSBhc3luYywgc28gd2UgbmVlZCB0byB3YWl0IGZvciB0aGVtIHRvIGNvbXBsZXRlXG4gICAgICAgIC8vIGZpcnN0LiBRdWV1ZSBhIGBzZXRTdGF0ZWAgY2FsbGJhY2sgYW5kIHdhaXQgZm9yIGl0IHRvIHJlc29sdmUuXG4gICAgICAgIGF3YWl0IG5ldyBQcm9taXNlPHZvaWQ+KChyZXNvbHZlKSA9PiB0aGlzLnNldFN0YXRlKHt9LCByZXNvbHZlKSk7XG5cbiAgICAgICAgaWYgKHRoaXMuYWxsRmllbGRzVmFsaWQoKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBpbnZhbGlkRmllbGQgPSB0aGlzLmZpbmRGaXJzdEludmFsaWRGaWVsZChmaWVsZElEc0luRGlzcGxheU9yZGVyKTtcblxuICAgICAgICBpZiAoIWludmFsaWRGaWVsZCkge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBGb2N1cyB0aGUgZmlyc3QgaW52YWxpZCBmaWVsZCBhbmQgc2hvdyBmZWVkYmFjayBpbiB0aGUgc3RyaWN0ZXIgbW9kZVxuICAgICAgICAvLyB0aGF0IG5vIGxvbmdlciBhbGxvd3MgZW1wdHkgdmFsdWVzIGZvciByZXF1aXJlZCBmaWVsZHMuXG4gICAgICAgIGludmFsaWRGaWVsZC5mb2N1cygpO1xuICAgICAgICBpbnZhbGlkRmllbGQudmFsaWRhdGUoeyBhbGxvd0VtcHR5OiBmYWxzZSwgZm9jdXNlZDogdHJ1ZSB9KTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHByaXZhdGUgYWxsRmllbGRzVmFsaWQoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiBPYmplY3QudmFsdWVzKHRoaXMuc3RhdGUuZmllbGRWYWxpZCkuZXZlcnkoQm9vbGVhbik7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBmaW5kRmlyc3RJbnZhbGlkRmllbGQoZmllbGRJRHM6IExvZ2luRmllbGRbXSk6IEZpZWxkIHwgbnVsbCB7XG4gICAgICAgIGZvciAoY29uc3QgZmllbGRJRCBvZiBmaWVsZElEcykge1xuICAgICAgICAgICAgaWYgKCF0aGlzLnN0YXRlLmZpZWxkVmFsaWRbZmllbGRJRF0gJiYgdGhpc1tmaWVsZElEXSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzW2ZpZWxkSURdO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHByaXZhdGUgbWFya0ZpZWxkVmFsaWQoZmllbGRJRDogTG9naW5GaWVsZCwgdmFsaWQ/OiBib29sZWFuKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IHsgZmllbGRWYWxpZCB9ID0gdGhpcy5zdGF0ZTtcbiAgICAgICAgZmllbGRWYWxpZFtmaWVsZElEXSA9IHZhbGlkO1xuICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgIGZpZWxkVmFsaWQsXG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgdmFsaWRhdGVVc2VybmFtZVJ1bGVzID0gd2l0aFZhbGlkYXRpb24oe1xuICAgICAgICBydWxlczogW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIGtleTogXCJyZXF1aXJlZFwiLFxuICAgICAgICAgICAgICAgIHRlc3QoeyB2YWx1ZSwgYWxsb3dFbXB0eSB9KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBhbGxvd0VtcHR5IHx8ICEhdmFsdWU7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBpbnZhbGlkOiAoKSA9PiBfdChcImF1dGh8dXNlcm5hbWVfZmllbGRfcmVxdWlyZWRfaW52YWxpZFwiKSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgfSk7XG5cbiAgICBwcml2YXRlIG9uVXNlcm5hbWVWYWxpZGF0ZSA9IGFzeW5jIChmaWVsZFN0YXRlOiBJRmllbGRTdGF0ZSk6IFByb21pc2U8SVZhbGlkYXRpb25SZXN1bHQ+ID0+IHtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdGhpcy52YWxpZGF0ZVVzZXJuYW1lUnVsZXMoZmllbGRTdGF0ZSk7XG4gICAgICAgIHRoaXMubWFya0ZpZWxkVmFsaWQoTG9naW5GaWVsZC5NYXRyaXhJZCwgcmVzdWx0LnZhbGlkKTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9O1xuXG4gICAgcHJpdmF0ZSBvbkVtYWlsVmFsaWRhdGUgPSAocmVzdWx0OiBJVmFsaWRhdGlvblJlc3VsdCk6IHZvaWQgPT4ge1xuICAgICAgICB0aGlzLm1hcmtGaWVsZFZhbGlkKExvZ2luRmllbGQuRW1haWwsIHJlc3VsdC52YWxpZCk7XG4gICAgfTtcblxuICAgIHByaXZhdGUgdmFsaWRhdGVQaG9uZU51bWJlclJ1bGVzID0gd2l0aFZhbGlkYXRpb24oe1xuICAgICAgICBydWxlczogW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIGtleTogXCJyZXF1aXJlZFwiLFxuICAgICAgICAgICAgICAgIHRlc3QoeyB2YWx1ZSwgYWxsb3dFbXB0eSB9KTogYm9vbGVhbiB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBhbGxvd0VtcHR5IHx8ICEhdmFsdWU7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBpbnZhbGlkOiAoKTogc3RyaW5nID0+IF90KFwiYXV0aHxtc2lzZG5fZmllbGRfcmVxdWlyZWRfaW52YWxpZFwiKSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAga2V5OiBcIm51bWJlclwiLFxuICAgICAgICAgICAgICAgIHRlc3Q6ICh7IHZhbHVlIH0pOiBib29sZWFuID0+ICF2YWx1ZSB8fCBQSE9ORV9OVU1CRVJfUkVHRVgudGVzdCh2YWx1ZSksXG4gICAgICAgICAgICAgICAgaW52YWxpZDogKCk6IHN0cmluZyA9PiBfdChcImF1dGh8bXNpc2RuX2ZpZWxkX251bWJlcl9pbnZhbGlkXCIpLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICB9KTtcblxuICAgIHByaXZhdGUgb25QaG9uZU51bWJlclZhbGlkYXRlID0gYXN5bmMgKGZpZWxkU3RhdGU6IElGaWVsZFN0YXRlKTogUHJvbWlzZTxJVmFsaWRhdGlvblJlc3VsdD4gPT4ge1xuICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLnZhbGlkYXRlUGhvbmVOdW1iZXJSdWxlcyhmaWVsZFN0YXRlKTtcbiAgICAgICAgdGhpcy5tYXJrRmllbGRWYWxpZChMb2dpbkZpZWxkLlBhc3N3b3JkLCByZXN1bHQudmFsaWQpO1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH07XG5cbiAgICBwcml2YXRlIHZhbGlkYXRlUGFzc3dvcmRSdWxlcyA9IHdpdGhWYWxpZGF0aW9uKHtcbiAgICAgICAgcnVsZXM6IFtcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBrZXk6IFwicmVxdWlyZWRcIixcbiAgICAgICAgICAgICAgICB0ZXN0KHsgdmFsdWUsIGFsbG93RW1wdHkgfSk6IGJvb2xlYW4ge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gYWxsb3dFbXB0eSB8fCAhIXZhbHVlO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgaW52YWxpZDogKCk6IHN0cmluZyA9PiBfdChcImF1dGh8cGFzc3dvcmRfZmllbGRfbGFiZWxcIiksXG4gICAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgIH0pO1xuXG4gICAgcHJpdmF0ZSBvblBhc3N3b3JkVmFsaWRhdGUgPSBhc3luYyAoZmllbGRTdGF0ZTogSUZpZWxkU3RhdGUpOiBQcm9taXNlPElWYWxpZGF0aW9uUmVzdWx0PiA9PiB7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMudmFsaWRhdGVQYXNzd29yZFJ1bGVzKGZpZWxkU3RhdGUpO1xuICAgICAgICB0aGlzLm1hcmtGaWVsZFZhbGlkKExvZ2luRmllbGQuUGFzc3dvcmQsIHJlc3VsdC52YWxpZCk7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfTtcblxuICAgIHByaXZhdGUgcmVuZGVyTG9naW5GaWVsZChsb2dpblR5cGU6IElTdGF0ZVtcImxvZ2luVHlwZVwiXSwgYXV0b0ZvY3VzOiBib29sZWFuKTogSlNYLkVsZW1lbnQge1xuICAgICAgICBjb25zdCBjbGFzc2VzID0ge1xuICAgICAgICAgICAgZXJyb3I6IGZhbHNlLFxuICAgICAgICB9O1xuXG4gICAgICAgIHN3aXRjaCAobG9naW5UeXBlKSB7XG4gICAgICAgICAgICBjYXNlIExvZ2luRmllbGQuRW1haWw6XG4gICAgICAgICAgICAgICAgY2xhc3Nlcy5lcnJvciA9IHRoaXMucHJvcHMubG9naW5JbmNvcnJlY3QgJiYgIXRoaXMucHJvcHMudXNlcm5hbWU7XG4gICAgICAgICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgICAgICAgICAgPEVtYWlsRmllbGRcbiAgICAgICAgICAgICAgICAgICAgICAgIGlkPVwibXhfTG9naW5Gb3JtX2VtYWlsXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzTmFtZT17Y2xhc3NOYW1lcyhjbGFzc2VzKX1cbiAgICAgICAgICAgICAgICAgICAgICAgIG5hbWU9XCJ1c2VybmFtZVwiIC8vIG1ha2UgaXQgYSBsaXR0bGUgZWFzaWVyIGZvciBicm93c2VyJ3MgcmVtZW1iZXItcGFzc3dvcmRcbiAgICAgICAgICAgICAgICAgICAgICAgIGF1dG9Db21wbGV0ZT1cImVtYWlsXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU9XCJlbWFpbFwiXG4gICAgICAgICAgICAgICAgICAgICAgICBrZXk9XCJlbWFpbF9pbnB1dFwiXG4gICAgICAgICAgICAgICAgICAgICAgICBwbGFjZWhvbGRlcj1cImpvZUBleGFtcGxlLmNvbVwiXG4gICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZT17dGhpcy5wcm9wcy51c2VybmFtZX1cbiAgICAgICAgICAgICAgICAgICAgICAgIG9uQ2hhbmdlPXt0aGlzLm9uVXNlcm5hbWVDaGFuZ2VkfVxuICAgICAgICAgICAgICAgICAgICAgICAgb25CbHVyPXt0aGlzLm9uVXNlcm5hbWVCbHVyfVxuICAgICAgICAgICAgICAgICAgICAgICAgZGlzYWJsZWQ9e3RoaXMucHJvcHMuYnVzeX1cbiAgICAgICAgICAgICAgICAgICAgICAgIGF1dG9Gb2N1cz17YXV0b0ZvY3VzfVxuICAgICAgICAgICAgICAgICAgICAgICAgb25WYWxpZGF0ZT17dGhpcy5vbkVtYWlsVmFsaWRhdGV9XG4gICAgICAgICAgICAgICAgICAgICAgICBmaWVsZFJlZj17KGZpZWxkKTogdm9pZCA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpc1tMb2dpbkZpZWxkLkVtYWlsXSA9IGZpZWxkO1xuICAgICAgICAgICAgICAgICAgICAgICAgfX1cbiAgICAgICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgY2FzZSBMb2dpbkZpZWxkLk1hdHJpeElkOlxuICAgICAgICAgICAgICAgIGNsYXNzZXMuZXJyb3IgPSB0aGlzLnByb3BzLmxvZ2luSW5jb3JyZWN0ICYmICF0aGlzLnByb3BzLnVzZXJuYW1lO1xuICAgICAgICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAgICAgICAgIDxGaWVsZFxuICAgICAgICAgICAgICAgICAgICAgICAgaWQ9XCJteF9Mb2dpbkZvcm1fdXNlcm5hbWVcIlxuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3NOYW1lPXtjbGFzc05hbWVzKGNsYXNzZXMpfVxuICAgICAgICAgICAgICAgICAgICAgICAgbmFtZT1cInVzZXJuYW1lXCIgLy8gbWFrZSBpdCBhIGxpdHRsZSBlYXNpZXIgZm9yIGJyb3dzZXIncyByZW1lbWJlci1wYXNzd29yZFxuICAgICAgICAgICAgICAgICAgICAgICAgYXV0b0NvbXBsZXRlPVwidXNlcm5hbWVcIlxuICAgICAgICAgICAgICAgICAgICAgICAga2V5PVwidXNlcm5hbWVfaW5wdXRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZT1cInRleHRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWw9e190KFwiY29tbW9ufHVzZXJuYW1lXCIpfVxuICAgICAgICAgICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI9e190KFwiY29tbW9ufHVzZXJuYW1lXCIpfVxuICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU9e3RoaXMucHJvcHMudXNlcm5hbWV9XG4gICAgICAgICAgICAgICAgICAgICAgICBvbkNoYW5nZT17dGhpcy5vblVzZXJuYW1lQ2hhbmdlZH1cbiAgICAgICAgICAgICAgICAgICAgICAgIG9uQmx1cj17dGhpcy5vblVzZXJuYW1lQmx1cn1cbiAgICAgICAgICAgICAgICAgICAgICAgIGRpc2FibGVkPXt0aGlzLnByb3BzLmJ1c3l9XG4gICAgICAgICAgICAgICAgICAgICAgICBhdXRvRm9jdXM9e2F1dG9Gb2N1c31cbiAgICAgICAgICAgICAgICAgICAgICAgIG9uVmFsaWRhdGU9e3RoaXMub25Vc2VybmFtZVZhbGlkYXRlfVxuICAgICAgICAgICAgICAgICAgICAgICAgcmVmPXsoZmllbGQpOiB2b2lkID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzW0xvZ2luRmllbGQuTWF0cml4SWRdID0gZmllbGQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB9fVxuICAgICAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICBjYXNlIExvZ2luRmllbGQuUGhvbmU6IHtcbiAgICAgICAgICAgICAgICBjbGFzc2VzLmVycm9yID0gdGhpcy5wcm9wcy5sb2dpbkluY29ycmVjdCAmJiAhdGhpcy5wcm9wcy5waG9uZU51bWJlcjtcblxuICAgICAgICAgICAgICAgIGNvbnN0IHBob25lQ291bnRyeSA9IChcbiAgICAgICAgICAgICAgICAgICAgPENvdW50cnlEcm9wZG93blxuICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU9e3RoaXMucHJvcHMucGhvbmVDb3VudHJ5fVxuICAgICAgICAgICAgICAgICAgICAgICAgaXNTbWFsbD17dHJ1ZX1cbiAgICAgICAgICAgICAgICAgICAgICAgIHNob3dQcmVmaXg9e3RydWV9XG4gICAgICAgICAgICAgICAgICAgICAgICBvbk9wdGlvbkNoYW5nZT17dGhpcy5vblBob25lQ291bnRyeUNoYW5nZWR9XG4gICAgICAgICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAgICAgICAgIDxGaWVsZFxuICAgICAgICAgICAgICAgICAgICAgICAgaWQ9XCJteF9Mb2dpbkZvcm1fcGhvbmVcIlxuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3NOYW1lPXtjbGFzc05hbWVzKGNsYXNzZXMpfVxuICAgICAgICAgICAgICAgICAgICAgICAgbmFtZT1cInBob25lTnVtYmVyXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIGF1dG9Db21wbGV0ZT1cInRlbC1uYXRpb25hbFwiXG4gICAgICAgICAgICAgICAgICAgICAgICBrZXk9XCJwaG9uZV9pbnB1dFwiXG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlPVwidGV4dFwiXG4gICAgICAgICAgICAgICAgICAgICAgICBsYWJlbD17X3QoXCJhdXRofG1zaXNkbl9maWVsZF9sYWJlbFwiKX1cbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlPXt0aGlzLnByb3BzLnBob25lTnVtYmVyfVxuICAgICAgICAgICAgICAgICAgICAgICAgcHJlZml4Q29tcG9uZW50PXtwaG9uZUNvdW50cnl9XG4gICAgICAgICAgICAgICAgICAgICAgICBvbkNoYW5nZT17dGhpcy5vblBob25lTnVtYmVyQ2hhbmdlZH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGRpc2FibGVkPXt0aGlzLnByb3BzLmJ1c3l9XG4gICAgICAgICAgICAgICAgICAgICAgICBhdXRvRm9jdXM9e2F1dG9Gb2N1c31cbiAgICAgICAgICAgICAgICAgICAgICAgIG9uVmFsaWRhdGU9e3RoaXMub25QaG9uZU51bWJlclZhbGlkYXRlfVxuICAgICAgICAgICAgICAgICAgICAgICAgcmVmPXsoZmllbGQpOiB2b2lkID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzW0xvZ2luRmllbGQuUGFzc3dvcmRdID0gZmllbGQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB9fVxuICAgICAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGlzTG9naW5FbXB0eSgpOiBib29sZWFuIHtcbiAgICAgICAgc3dpdGNoICh0aGlzLnN0YXRlLmxvZ2luVHlwZSkge1xuICAgICAgICAgICAgY2FzZSBMb2dpbkZpZWxkLkVtYWlsOlxuICAgICAgICAgICAgY2FzZSBMb2dpbkZpZWxkLk1hdHJpeElkOlxuICAgICAgICAgICAgICAgIHJldHVybiAhdGhpcy5wcm9wcy51c2VybmFtZTtcbiAgICAgICAgICAgIGNhc2UgTG9naW5GaWVsZC5QaG9uZTpcbiAgICAgICAgICAgICAgICByZXR1cm4gIXRoaXMucHJvcHMucGhvbmVDb3VudHJ5IHx8ICF0aGlzLnByb3BzLnBob25lTnVtYmVyO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHVibGljIHJlbmRlcigpOiBSZWFjdC5SZWFjdE5vZGUge1xuICAgICAgICBsZXQgZm9yZ290UGFzc3dvcmRKc3g6IEpTWC5FbGVtZW50IHwgdW5kZWZpbmVkO1xuXG4gICAgICAgIGlmICh0aGlzLnByb3BzLm9uRm9yZ290UGFzc3dvcmRDbGljaykge1xuICAgICAgICAgICAgZm9yZ290UGFzc3dvcmRKc3ggPSAoXG4gICAgICAgICAgICAgICAgPEFjY2Vzc2libGVCdXR0b25cbiAgICAgICAgICAgICAgICAgICAgY2xhc3NOYW1lPVwibXhfTG9naW5fZm9yZ290XCJcbiAgICAgICAgICAgICAgICAgICAgZGlzYWJsZWQ9e3RoaXMucHJvcHMuYnVzeX1cbiAgICAgICAgICAgICAgICAgICAga2luZD1cImxpbmtcIlxuICAgICAgICAgICAgICAgICAgICBvbkNsaWNrPXt0aGlzLm9uRm9yZ290UGFzc3dvcmRDbGlja31cbiAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgIHtfdChcImF1dGh8cmVzZXRfcGFzc3dvcmRfYnV0dG9uXCIpfVxuICAgICAgICAgICAgICAgIDwvQWNjZXNzaWJsZUJ1dHRvbj5cbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBwd0ZpZWxkQ2xhc3MgPSBjbGFzc05hbWVzKHtcbiAgICAgICAgICAgIGVycm9yOiB0aGlzLnByb3BzLmxvZ2luSW5jb3JyZWN0ICYmICF0aGlzLmlzTG9naW5FbXB0eSgpLCAvLyBvbmx5IGVycm9yIHBhc3N3b3JkIGlmIGVycm9yIGlzbid0IHRvcCBmaWVsZFxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBJZiBsb2dpbiBpcyBlbXB0eSwgYXV0b0ZvY3VzIGxvZ2luLCBvdGhlcndpc2UgYXV0b0ZvY3VzIHBhc3N3b3JkLlxuICAgICAgICAvLyB0aGlzIGlzIGZvciB3aGVuIGF1dG8gc2VydmVyIGRpc2NvdmVyeSByZW1vdW50cyB1cyB3aGVuIHRoZSB1c2VyIHRyaWVzIHRvIHRhYiBmcm9tIHVzZXJuYW1lIHRvIHBhc3N3b3JkXG4gICAgICAgIGNvbnN0IGF1dG9Gb2N1c1Bhc3N3b3JkID0gIXRoaXMuaXNMb2dpbkVtcHR5KCk7XG4gICAgICAgIGNvbnN0IGxvZ2luRmllbGQgPSB0aGlzLnJlbmRlckxvZ2luRmllbGQodGhpcy5zdGF0ZS5sb2dpblR5cGUsICFhdXRvRm9jdXNQYXNzd29yZCk7XG5cbiAgICAgICAgbGV0IGxvZ2luVHlwZTtcbiAgICAgICAgaWYgKCFTZGtDb25maWcuZ2V0KCkuZGlzYWJsZV8zcGlkX2xvZ2luKSB7XG4gICAgICAgICAgICBsb2dpblR5cGUgPSAoXG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJteF9Mb2dpbl90eXBlX2NvbnRhaW5lclwiPlxuICAgICAgICAgICAgICAgICAgICA8bGFiZWwgY2xhc3NOYW1lPVwibXhfTG9naW5fdHlwZV9sYWJlbFwiPntfdChcImF1dGh8aWRlbnRpZmllcl9sYWJlbFwiKX08L2xhYmVsPlxuICAgICAgICAgICAgICAgICAgICA8RmllbGRcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnQ9XCJzZWxlY3RcIlxuICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU9e3RoaXMuc3RhdGUubG9naW5UeXBlfVxuICAgICAgICAgICAgICAgICAgICAgICAgb25DaGFuZ2U9e3RoaXMub25Mb2dpblR5cGVDaGFuZ2V9XG4gICAgICAgICAgICAgICAgICAgICAgICBkaXNhYmxlZD17dGhpcy5wcm9wcy5idXN5fVxuICAgICAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgICAgICA8b3B0aW9uIGtleT17TG9naW5GaWVsZC5NYXRyaXhJZH0gdmFsdWU9e0xvZ2luRmllbGQuTWF0cml4SWR9PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHtfdChcImNvbW1vbnx1c2VybmFtZVwiKX1cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvb3B0aW9uPlxuICAgICAgICAgICAgICAgICAgICAgICAgPG9wdGlvbiBrZXk9e0xvZ2luRmllbGQuRW1haWx9IHZhbHVlPXtMb2dpbkZpZWxkLkVtYWlsfT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB7X3QoXCJjb21tb258ZW1haWxfYWRkcmVzc1wiKX1cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvb3B0aW9uPlxuICAgICAgICAgICAgICAgICAgICAgICAgPG9wdGlvbiBrZXk9e0xvZ2luRmllbGQuUGFzc3dvcmR9IHZhbHVlPXtMb2dpbkZpZWxkLlBhc3N3b3JkfT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB7X3QoXCJhdXRofG1zaXNkbl9maWVsZF9sYWJlbFwiKX1cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvb3B0aW9uPlxuICAgICAgICAgICAgICAgICAgICA8L0ZpZWxkPlxuICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICA8ZGl2PlxuICAgICAgICAgICAgICAgIDxmb3JtIG9uU3VibWl0PXt0aGlzLm9uU3VibWl0Rm9ybX0+XG4gICAgICAgICAgICAgICAgICAgIHtsb2dpblR5cGV9XG4gICAgICAgICAgICAgICAgICAgIHtsb2dpbkZpZWxkfVxuICAgICAgICAgICAgICAgICAgICA8RmllbGRcbiAgICAgICAgICAgICAgICAgICAgICAgIGlkPVwibXhfTG9naW5Gb3JtX3Bhc3N3b3JkXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzTmFtZT17cHdGaWVsZENsYXNzfVxuICAgICAgICAgICAgICAgICAgICAgICAgYXV0b0NvbXBsZXRlPVwiY3VycmVudC1wYXNzd29yZFwiXG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlPVwicGFzc3dvcmRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgbmFtZT1cInBhc3N3b3JkXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVsPXtfdChcImNvbW1vbnxwYXNzd29yZFwiKX1cbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlPXt0aGlzLnN0YXRlLnBhc3N3b3JkfVxuICAgICAgICAgICAgICAgICAgICAgICAgb25DaGFuZ2U9e3RoaXMub25QYXNzd29yZENoYW5nZWR9XG4gICAgICAgICAgICAgICAgICAgICAgICBkaXNhYmxlZD17dGhpcy5wcm9wcy5idXN5fVxuICAgICAgICAgICAgICAgICAgICAgICAgYXV0b0ZvY3VzPXthdXRvRm9jdXNQYXNzd29yZH1cbiAgICAgICAgICAgICAgICAgICAgICAgIG9uVmFsaWRhdGU9e3RoaXMub25QYXNzd29yZFZhbGlkYXRlfVxuICAgICAgICAgICAgICAgICAgICAgICAgcmVmPXsoZmllbGQpID0+ICh0aGlzW0xvZ2luRmllbGQuUGFzc3dvcmRdID0gZmllbGQpfVxuICAgICAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICAgICAgICB7Zm9yZ290UGFzc3dvcmRKc3h9XG4gICAgICAgICAgICAgICAgICAgIHshdGhpcy5wcm9wcy5idXN5ICYmIChcbiAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzTmFtZT1cIm14X0xvZ2luX3N1Ym1pdFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZT1cInN1Ym1pdFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU9e190KFwiYWN0aW9ufHNpZ25faW5cIil9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlzYWJsZWQ9e3RoaXMucHJvcHMuZGlzYWJsZVN1Ym1pdH1cbiAgICAgICAgICAgICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICAgICAgICAgICl9XG4gICAgICAgICAgICAgICAgPC9mb3JtPlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICk7XG4gICAgfVxufVxuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7OztBQVFBLElBQUFBLE1BQUEsR0FBQUMsc0JBQUEsQ0FBQUMsT0FBQTtBQUNBLElBQUFDLFdBQUEsR0FBQUYsc0JBQUEsQ0FBQUMsT0FBQTtBQUVBLElBQUFFLGdCQUFBLEdBQUFGLE9BQUE7QUFDQSxJQUFBRyxVQUFBLEdBQUFKLHNCQUFBLENBQUFDLE9BQUE7QUFFQSxJQUFBSSxpQkFBQSxHQUFBTCxzQkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQUssV0FBQSxHQUFBTixzQkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQU0sTUFBQSxHQUFBUCxzQkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQU8sZ0JBQUEsR0FBQVIsc0JBQUEsQ0FBQUMsT0FBQTtBQUNBLElBQUFRLFdBQUEsR0FBQVQsc0JBQUEsQ0FBQUMsT0FB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