matrix-react-sdk
Version:
SDK for matrix.org using React
390 lines (385 loc) • 71 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.AddRemoveThreepids = void 0;
var _react = _interopRequireWildcard(require("react"));
var _logger = require("matrix-js-sdk/src/logger");
var _matrix = require("matrix-js-sdk/src/matrix");
var _AddThreepid = _interopRequireDefault(require("../../../AddThreepid"));
var _languageHandler = require("../../../languageHandler");
var _AccessibleButton = _interopRequireDefault(require("../elements/AccessibleButton"));
var _MatrixClientContext = require("../../../contexts/MatrixClientContext");
var _Modal = _interopRequireDefault(require("../../../Modal"));
var _ErrorDialog = _interopRequireWildcard(require("../dialogs/ErrorDialog"));
var _Field = _interopRequireDefault(require("../elements/Field"));
var _email = require("../../../email");
var _CountryDropdown = _interopRequireDefault(require("../auth/CountryDropdown"));
var _InlineSpinner = _interopRequireDefault(require("../elements/InlineSpinner"));
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
/*
Copyright 2024 New Vector Ltd.
Copyright 2024 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.
*/
// Whether we're adding 3pids to the user's account on the homeserver or sharing them on an identity server
const ExistingThreepid = ({
mode,
threepid,
onChange,
disabled
}) => {
const [isConfirming, setIsConfirming] = (0, _react.useState)(false);
const client = (0, _MatrixClientContext.useMatrixClientContext)();
const bindTask = (0, _react.useRef)();
const [isVerifyingBind, setIsVerifyingBind] = (0, _react.useState)(false);
const [continueDisabled, setContinueDisabled] = (0, _react.useState)(false);
const [verificationCode, setVerificationCode] = (0, _react.useState)("");
const onRemoveClick = (0, _react.useCallback)(e => {
e.stopPropagation();
e.preventDefault();
setIsConfirming(true);
}, []);
const onCancelClick = (0, _react.useCallback)(e => {
e.stopPropagation();
e.preventDefault();
setIsConfirming(false);
}, []);
const onConfirmRemoveClick = (0, _react.useCallback)(e => {
e.stopPropagation();
e.preventDefault();
client.deleteThreePid(threepid.medium, threepid.address).then(() => {
return onChange(threepid);
}).catch(err => {
_logger.logger.error("Unable to remove contact information: " + err);
_Modal.default.createDialog(_ErrorDialog.default, {
title: (0, _languageHandler._t)("settings|general|error_remove_3pid"),
description: err && err.message ? err.message : (0, _languageHandler._t)("invite|failed_generic")
});
});
}, [client, threepid, onChange]);
const changeBinding = (0, _react.useCallback)(async ({
bind,
label,
errorTitle
}) => {
try {
if (bind) {
bindTask.current = new _AddThreepid.default(client);
setContinueDisabled(true);
if (threepid.medium === _matrix.ThreepidMedium.Email) {
await bindTask.current.bindEmailAddress(threepid.address);
} else {
// XXX: Sydent will accept a number without country code if you add
// a leading plus sign to a number in E.164 format (which the 3PID
// address is), but this goes against the spec.
// See https://github.com/matrix-org/matrix-doc/issues/2222
await bindTask.current.bindMsisdn(null, `+${threepid.address}`);
}
setContinueDisabled(false);
setIsVerifyingBind(true);
} else {
await client.unbindThreePid(threepid.medium, threepid.address);
onChange(threepid);
}
} catch (err) {
_logger.logger.error(`changeBinding: Unable to ${label} email address ${threepid.address}`, err);
setIsVerifyingBind(false);
setContinueDisabled(false);
bindTask.current = undefined;
_Modal.default.createDialog(_ErrorDialog.default, {
title: errorTitle,
description: (0, _ErrorDialog.extractErrorMessageFromError)(err, (0, _languageHandler._t)("invite|failed_generic"))
});
}
}, [client, threepid, onChange]);
const onRevokeClick = (0, _react.useCallback)(e => {
e.stopPropagation();
e.preventDefault();
changeBinding({
bind: false,
label: "revoke",
errorTitle: threepid.medium === "email" ? (0, _languageHandler._t)("settings|general|error_revoke_email_discovery") : (0, _languageHandler._t)("settings|general|error_revoke_msisdn_discovery")
}).then();
}, [changeBinding, threepid.medium]);
const onShareClick = (0, _react.useCallback)(e => {
e.stopPropagation();
e.preventDefault();
changeBinding({
bind: true,
label: "share",
errorTitle: threepid.medium === "email" ? (0, _languageHandler._t)("settings|general|error_share_email_discovery") : (0, _languageHandler._t)("settings|general|error_share_msisdn_discovery")
}).then();
}, [changeBinding, threepid.medium]);
const onContinueClick = (0, _react.useCallback)(async e => {
e.stopPropagation();
e.preventDefault();
setContinueDisabled(true);
try {
if (threepid.medium === _matrix.ThreepidMedium.Email) {
await bindTask.current?.checkEmailLinkClicked();
} else {
await bindTask.current?.haveMsisdnToken(verificationCode);
}
setIsVerifyingBind(false);
onChange(threepid);
bindTask.current = undefined;
} catch (err) {
_logger.logger.error(`Unable to verify threepid:`, err);
let underlyingError = err;
if (err instanceof _languageHandler.UserFriendlyError) {
underlyingError = err.cause;
}
if (underlyingError instanceof _matrix.MatrixError && underlyingError.errcode === "M_THREEPID_AUTH_FAILED") {
_Modal.default.createDialog(_ErrorDialog.default, {
title: threepid.medium === "email" ? (0, _languageHandler._t)("settings|general|email_not_verified") : (0, _languageHandler._t)("settings|general|error_msisdn_verification"),
description: threepid.medium === "email" ? (0, _languageHandler._t)("settings|general|email_verification_instructions") : (0, _ErrorDialog.extractErrorMessageFromError)(err, (0, _languageHandler._t)("invite|failed_generic"))
});
} else {
_logger.logger.error("Unable to verify email address: " + err);
_Modal.default.createDialog(_ErrorDialog.default, {
title: (0, _languageHandler._t)("settings|general|error_email_verification"),
description: (0, _ErrorDialog.extractErrorMessageFromError)(err, (0, _languageHandler._t)("invite|failed_generic"))
});
}
} finally {
setContinueDisabled(false);
}
}, [verificationCode, onChange, threepid]);
const onVerificationCodeChange = (0, _react.useCallback)(e => {
setVerificationCode(e.target.value);
}, []);
if (isConfirming) {
return /*#__PURE__*/_react.default.createElement("div", {
className: "mx_AddRemoveThreepids_existing"
}, /*#__PURE__*/_react.default.createElement("span", {
className: "mx_AddRemoveThreepids_existing_promptText"
}, threepid.medium === _matrix.ThreepidMedium.Email ? (0, _languageHandler._t)("settings|general|remove_email_prompt", {
email: threepid.address
}) : (0, _languageHandler._t)("settings|general|remove_msisdn_prompt", {
phone: threepid.address
})), /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, {
onClick: onConfirmRemoveClick,
kind: "danger_sm",
className: "mx_AddRemoveThreepids_existing_button"
}, (0, _languageHandler._t)("action|remove")), /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, {
onClick: onCancelClick,
kind: "link_sm",
className: "mx_AddRemoveThreepids_existing_button"
}, (0, _languageHandler._t)("action|cancel")));
}
if (isVerifyingBind) {
if (threepid.medium === _matrix.ThreepidMedium.Email) {
return /*#__PURE__*/_react.default.createElement("div", {
className: "mx_EmailAddressesPhoneNumbers_verify"
}, /*#__PURE__*/_react.default.createElement("span", {
className: "mx_EmailAddressesPhoneNumbers_verify_instructions"
}, (0, _languageHandler._t)("settings|general|discovery_email_verification_instructions")), /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, {
className: "mx_EmailAddressesPhoneNumbers_existing_button",
kind: "primary_sm",
onClick: onContinueClick,
disabled: continueDisabled
}, (0, _languageHandler._t)("action|complete")));
} else {
return /*#__PURE__*/_react.default.createElement("div", {
className: "mx_EmailAddressesPhoneNumbers_verify"
}, /*#__PURE__*/_react.default.createElement("span", {
className: "mx_EmailAddressesPhoneNumbers_verify_instructions"
}, (0, _languageHandler._t)("settings|general|msisdn_verification_instructions")), /*#__PURE__*/_react.default.createElement("form", {
onSubmit: onContinueClick,
autoComplete: "off",
noValidate: true
}, /*#__PURE__*/_react.default.createElement(_Field.default, {
type: "text",
label: (0, _languageHandler._t)("settings|general|msisdn_verification_field_label"),
autoComplete: "off",
disabled: continueDisabled,
value: verificationCode,
onChange: onVerificationCodeChange
})));
}
}
return /*#__PURE__*/_react.default.createElement("div", {
className: "mx_AddRemoveThreepids_existing"
}, /*#__PURE__*/_react.default.createElement("span", {
className: "mx_AddRemoveThreepids_existing_address"
}, threepid.address), /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, {
onClick: mode === "hs" ? onRemoveClick : threepid.bound ? onRevokeClick : onShareClick,
kind: mode === "hs" || threepid.bound ? "danger_sm" : "primary_sm",
disabled: disabled
}, mode === "hs" ? (0, _languageHandler._t)("action|remove") : threepid.bound ? (0, _languageHandler._t)("action|revoke") : (0, _languageHandler._t)("action|share")));
};
function isMsisdnResponse(resp) {
return resp.msisdn !== undefined;
}
const AddThreepidSection = ({
medium,
disabled,
onChange
}) => {
const addTask = (0, _react.useRef)();
const [newThreepidInput, setNewThreepidInput] = (0, _react.useState)("");
const [phoneCountryInput, setPhoneCountryInput] = (0, _react.useState)("");
const [verificationCodeInput, setVerificationCodeInput] = (0, _react.useState)("");
const [isVerifying, setIsVerifying] = (0, _react.useState)(false);
const [continueDisabled, setContinueDisabled] = (0, _react.useState)(false);
const [sentToMsisdn, setSentToMsisdn] = (0, _react.useState)("");
const client = (0, _MatrixClientContext.useMatrixClientContext)();
const onPhoneCountryChanged = (0, _react.useCallback)(country => {
setPhoneCountryInput(country.iso2);
}, []);
const onContinueClick = (0, _react.useCallback)(e => {
e.stopPropagation();
e.preventDefault();
if (!addTask.current) return;
setContinueDisabled(true);
const checkPromise = medium === "email" ? addTask.current?.checkEmailLinkClicked() : addTask.current?.haveMsisdnToken(verificationCodeInput);
checkPromise.then(([finished]) => {
if (finished) {
addTask.current = undefined;
setIsVerifying(false);
setNewThreepidInput("");
onChange();
}
setContinueDisabled(false);
}).catch(err => {
_logger.logger.error("Unable to verify 3pid: ", err);
setContinueDisabled(false);
let underlyingError = err;
if (err instanceof _languageHandler.UserFriendlyError) {
underlyingError = err.cause;
}
if (underlyingError instanceof _matrix.MatrixError && underlyingError.errcode === "M_THREEPID_AUTH_FAILED") {
_Modal.default.createDialog(_ErrorDialog.default, {
title: medium === "email" ? (0, _languageHandler._t)("settings|general|email_not_verified") : (0, _languageHandler._t)("settings|general|error_msisdn_verification"),
description: (0, _languageHandler._t)("settings|general|email_verification_instructions")
});
} else {
_Modal.default.createDialog(_ErrorDialog.default, {
title: medium == "email" ? (0, _languageHandler._t)("settings|general|error_email_verification") : (0, _languageHandler._t)("settings|general|error_msisdn_verification"),
description: (0, _ErrorDialog.extractErrorMessageFromError)(err, (0, _languageHandler._t)("invite|failed_generic"))
});
}
});
}, [onChange, medium, verificationCodeInput]);
const onNewThreepidInputChange = (0, _react.useCallback)(e => {
setNewThreepidInput(e.target.value);
}, []);
const onAddClick = (0, _react.useCallback)(e => {
e.stopPropagation();
e.preventDefault();
if (!newThreepidInput) return;
// TODO: Inline field validation
if (medium === "email" && !(0, _email.looksValid)(newThreepidInput)) {
_Modal.default.createDialog(_ErrorDialog.default, {
title: (0, _languageHandler._t)("settings|general|error_invalid_email"),
description: (0, _languageHandler._t)("settings|general|error_invalid_email_detail")
});
return;
}
addTask.current = new _AddThreepid.default(client);
setIsVerifying(true);
setContinueDisabled(true);
const addPromise = medium === "email" ? addTask.current.addEmailAddress(newThreepidInput) : addTask.current.addMsisdn(phoneCountryInput, newThreepidInput);
addPromise.then(resp => {
setContinueDisabled(false);
if (isMsisdnResponse(resp)) {
setSentToMsisdn(resp.msisdn);
}
}).catch(err => {
_logger.logger.error(`Unable to add threepid ${newThreepidInput}`, err);
setIsVerifying(false);
setContinueDisabled(false);
addTask.current = undefined;
_Modal.default.createDialog(_ErrorDialog.default, {
title: medium === "email" ? (0, _languageHandler._t)("settings|general|error_add_email") : (0, _languageHandler._t)("common|error"),
description: (0, _ErrorDialog.extractErrorMessageFromError)(err, (0, _languageHandler._t)("invite|failed_generic"))
});
});
}, [client, phoneCountryInput, newThreepidInput, medium]);
const onVerificationCodeInputChange = (0, _react.useCallback)(e => {
setVerificationCodeInput(e.target.value);
}, []);
if (isVerifying && medium === "email") {
return /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("div", null, (0, _languageHandler._t)("settings|general|add_email_instructions")), /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, {
onClick: onContinueClick,
kind: "primary",
disabled: continueDisabled
}, (0, _languageHandler._t)("action|continue")));
} else if (isVerifying) {
return /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("div", null, (0, _languageHandler._t)("settings|general|add_msisdn_instructions", {
msisdn: sentToMsisdn
}), /*#__PURE__*/_react.default.createElement("br", null)), /*#__PURE__*/_react.default.createElement("form", {
onSubmit: onContinueClick,
autoComplete: "off",
noValidate: true
}, /*#__PURE__*/_react.default.createElement(_Field.default, {
type: "text",
label: (0, _languageHandler._t)("settings|general|msisdn_verification_field_label"),
autoComplete: "off",
disabled: disabled || continueDisabled,
value: verificationCodeInput,
onChange: onVerificationCodeInputChange
}), /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, {
onClick: onContinueClick,
kind: "primary",
disabled: disabled || continueDisabled || verificationCodeInput.length === 0
}, (0, _languageHandler._t)("action|continue"))));
}
const phoneCountry = medium === "msisdn" ? /*#__PURE__*/_react.default.createElement(_CountryDropdown.default, {
onOptionChange: onPhoneCountryChanged,
className: "mx_PhoneNumbers_country",
value: phoneCountryInput,
disabled: isVerifying,
isSmall: true,
showPrefix: true
}) : undefined;
return /*#__PURE__*/_react.default.createElement("form", {
onSubmit: onAddClick,
autoComplete: "off",
noValidate: true
}, /*#__PURE__*/_react.default.createElement(_Field.default, {
type: "text",
label: medium === "email" ? (0, _languageHandler._t)("settings|general|email_address_label") : (0, _languageHandler._t)("settings|general|msisdn_label"),
autoComplete: medium === "email" ? "email" : "tel-national",
disabled: disabled || isVerifying,
value: newThreepidInput,
onChange: onNewThreepidInputChange,
prefixComponent: phoneCountry
}), /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, {
onClick: onAddClick,
kind: "primary",
disabled: disabled
}, (0, _languageHandler._t)("action|add")));
};
const AddRemoveThreepids = ({
mode,
medium,
threepids,
disabled,
onChange,
isLoading
}) => {
if (isLoading) {
return /*#__PURE__*/_react.default.createElement(_InlineSpinner.default, null);
}
const existingEmailElements = threepids.map(e => {
return /*#__PURE__*/_react.default.createElement(ExistingThreepid, {
mode: mode,
threepid: e,
onChange: onChange,
key: e.address,
disabled: disabled
});
});
return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, existingEmailElements, mode === "hs" && /*#__PURE__*/_react.default.createElement(AddThreepidSection, {
medium: medium,
disabled: disabled,
onChange: onChange
}));
};
exports.AddRemoveThreepids = AddRemoveThreepids;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfcmVhY3QiLCJfaW50ZXJvcFJlcXVpcmVXaWxkY2FyZCIsInJlcXVpcmUiLCJfbG9nZ2VyIiwiX21hdHJpeCIsIl9BZGRUaHJlZXBpZCIsIl9pbnRlcm9wUmVxdWlyZURlZmF1bHQiLCJfbGFuZ3VhZ2VIYW5kbGVyIiwiX0FjY2Vzc2libGVCdXR0b24iLCJfTWF0cml4Q2xpZW50Q29udGV4dCIsIl9Nb2RhbCIsIl9FcnJvckRpYWxvZyIsIl9GaWVsZCIsIl9lbWFpbCIsIl9Db3VudHJ5RHJvcGRvd24iLCJfSW5saW5lU3Bpbm5lciIsIl9nZXRSZXF1aXJlV2lsZGNhcmRDYWNoZSIsImUiLCJXZWFrTWFwIiwiciIsInQiLCJfX2VzTW9kdWxlIiwiZGVmYXVsdCIsImhhcyIsImdldCIsIm4iLCJfX3Byb3RvX18iLCJhIiwiT2JqZWN0IiwiZGVmaW5lUHJvcGVydHkiLCJnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IiLCJ1IiwiaGFzT3duUHJvcGVydHkiLCJjYWxsIiwiaSIsInNldCIsIkV4aXN0aW5nVGhyZWVwaWQiLCJtb2RlIiwidGhyZWVwaWQiLCJvbkNoYW5nZSIsImRpc2FibGVkIiwiaXNDb25maXJtaW5nIiwic2V0SXNDb25maXJtaW5nIiwidXNlU3RhdGUiLCJjbGllbnQiLCJ1c2VNYXRyaXhDbGllbnRDb250ZXh0IiwiYmluZFRhc2siLCJ1c2VSZWYiLCJpc1ZlcmlmeWluZ0JpbmQiLCJzZXRJc1ZlcmlmeWluZ0JpbmQiLCJjb250aW51ZURpc2FibGVkIiwic2V0Q29udGludWVEaXNhYmxlZCIsInZlcmlmaWNhdGlvbkNvZGUiLCJzZXRWZXJpZmljYXRpb25Db2RlIiwib25SZW1vdmVDbGljayIsInVzZUNhbGxiYWNrIiwic3RvcFByb3BhZ2F0aW9uIiwicHJldmVudERlZmF1bHQiLCJvbkNhbmNlbENsaWNrIiwib25Db25maXJtUmVtb3ZlQ2xpY2siLCJkZWxldGVUaHJlZVBpZCIsIm1lZGl1bSIsImFkZHJlc3MiLCJ0aGVuIiwiY2F0Y2giLCJlcnIiLCJsb2dnZXIiLCJlcnJvciIsIk1vZGFsIiwiY3JlYXRlRGlhbG9nIiwiRXJyb3JEaWFsb2ciLCJ0aXRsZSIsIl90IiwiZGVzY3JpcHRpb24iLCJtZXNzYWdlIiwiY2hhbmdlQmluZGluZyIsImJpbmQiLCJsYWJlbCIsImVycm9yVGl0bGUiLCJjdXJyZW50IiwiQWRkVGhyZWVwaWQiLCJUaHJlZXBpZE1lZGl1bSIsIkVtYWlsIiwiYmluZEVtYWlsQWRkcmVzcyIsImJpbmRNc2lzZG4iLCJ1bmJpbmRUaHJlZVBpZCIsInVuZGVmaW5lZCIsImV4dHJhY3RFcnJvck1lc3NhZ2VGcm9tRXJyb3IiLCJvblJldm9rZUNsaWNrIiwib25TaGFyZUNsaWNrIiwib25Db250aW51ZUNsaWNrIiwiY2hlY2tFbWFpbExpbmtDbGlja2VkIiwiaGF2ZU1zaXNkblRva2VuIiwidW5kZXJseWluZ0Vycm9yIiwiVXNlckZyaWVuZGx5RXJyb3IiLCJjYXVzZSIsIk1hdHJpeEVycm9yIiwiZXJyY29kZSIsIm9uVmVyaWZpY2F0aW9uQ29kZUNoYW5nZSIsInRhcmdldCIsInZhbHVlIiwiY3JlYXRlRWxlbWVudCIsImNsYXNzTmFtZSIsImVtYWlsIiwicGhvbmUiLCJvbkNsaWNrIiwia2luZCIsIm9uU3VibWl0IiwiYXV0b0NvbXBsZXRlIiwibm9WYWxpZGF0ZSIsInR5cGUiLCJib3VuZCIsImlzTXNpc2RuUmVzcG9uc2UiLCJyZXNwIiwibXNpc2RuIiwiQWRkVGhyZWVwaWRTZWN0aW9uIiwiYWRkVGFzayIsIm5ld1RocmVlcGlkSW5wdXQiLCJzZXROZXdUaHJlZXBpZElucHV0IiwicGhvbmVDb3VudHJ5SW5wdXQiLCJzZXRQaG9uZUNvdW50cnlJbnB1dCIsInZlcmlmaWNhdGlvbkNvZGVJbnB1dCIsInNldFZlcmlmaWNhdGlvbkNvZGVJbnB1dCIsImlzVmVyaWZ5aW5nIiwic2V0SXNWZXJpZnlpbmciLCJzZW50VG9Nc2lzZG4iLCJzZXRTZW50VG9Nc2lzZG4iLCJvblBob25lQ291bnRyeUNoYW5nZWQiLCJjb3VudHJ5IiwiaXNvMiIsImNoZWNrUHJvbWlzZSIsImZpbmlzaGVkIiwib25OZXdUaHJlZXBpZElucHV0Q2hhbmdlIiwib25BZGRDbGljayIsImVtYWlsTG9va3NWYWxpZCIsImFkZFByb21pc2UiLCJhZGRFbWFpbEFkZHJlc3MiLCJhZGRNc2lzZG4iLCJvblZlcmlmaWNhdGlvbkNvZGVJbnB1dENoYW5nZSIsImxlbmd0aCIsInBob25lQ291bnRyeSIsIm9uT3B0aW9uQ2hhbmdlIiwiaXNTbWFsbCIsInNob3dQcmVmaXgiLCJwcmVmaXhDb21wb25lbnQiLCJBZGRSZW1vdmVUaHJlZXBpZHMiLCJ0aHJlZXBpZHMiLCJpc0xvYWRpbmciLCJleGlzdGluZ0VtYWlsRWxlbWVudHMiLCJtYXAiLCJrZXkiLCJGcmFnbWVudCIsImV4cG9ydHMiXSwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvY29tcG9uZW50cy92aWV3cy9zZXR0aW5ncy9BZGRSZW1vdmVUaHJlZXBpZHMudHN4Il0sInNvdXJjZXNDb250ZW50IjpbIi8qXG5Db3B5cmlnaHQgMjAyNCBOZXcgVmVjdG9yIEx0ZC5cbkNvcHlyaWdodCAyMDI0IFRoZSBNYXRyaXgub3JnIEZvdW5kYXRpb24gQy5JLkMuXG5cblNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBR1BMLTMuMC1vbmx5IE9SIEdQTC0zLjAtb25seVxuUGxlYXNlIHNlZSBMSUNFTlNFIGZpbGVzIGluIHRoZSByZXBvc2l0b3J5IHJvb3QgZm9yIGZ1bGwgZGV0YWlscy5cbiovXG5cbmltcG9ydCBSZWFjdCwgeyB1c2VDYWxsYmFjaywgdXNlUmVmLCB1c2VTdGF0ZSB9IGZyb20gXCJyZWFjdFwiO1xuaW1wb3J0IHsgbG9nZ2VyIH0gZnJvbSBcIm1hdHJpeC1qcy1zZGsvc3JjL2xvZ2dlclwiO1xuaW1wb3J0IHtcbiAgICBJUmVxdWVzdE1zaXNkblRva2VuUmVzcG9uc2UsXG4gICAgSVJlcXVlc3RUb2tlblJlc3BvbnNlLFxuICAgIE1hdHJpeEVycm9yLFxuICAgIFRocmVlcGlkTWVkaXVtLFxufSBmcm9tIFwibWF0cml4LWpzLXNkay9zcmMvbWF0cml4XCI7XG5cbmltcG9ydCBBZGRUaHJlZXBpZCwgeyBCaW5kaW5nLCBUaGlyZFBhcnR5SWRlbnRpZmllciB9IGZyb20gXCIuLi8uLi8uLi9BZGRUaHJlZXBpZFwiO1xuaW1wb3J0IHsgX3QsIFVzZXJGcmllbmRseUVycm9yIH0gZnJvbSBcIi4uLy4uLy4uL2xhbmd1YWdlSGFuZGxlclwiO1xuaW1wb3J0IEFjY2Vzc2libGVCdXR0b24sIHsgQnV0dG9uRXZlbnQgfSBmcm9tIFwiLi4vZWxlbWVudHMvQWNjZXNzaWJsZUJ1dHRvblwiO1xuaW1wb3J0IHsgdXNlTWF0cml4Q2xpZW50Q29udGV4dCB9IGZyb20gXCIuLi8uLi8uLi9jb250ZXh0cy9NYXRyaXhDbGllbnRDb250ZXh0XCI7XG5pbXBvcnQgTW9kYWwgZnJvbSBcIi4uLy4uLy4uL01vZGFsXCI7XG5pbXBvcnQgRXJyb3JEaWFsb2csIHsgZXh0cmFjdEVycm9yTWVzc2FnZUZyb21FcnJvciB9IGZyb20gXCIuLi9kaWFsb2dzL0Vycm9yRGlhbG9nXCI7XG5pbXBvcnQgRmllbGQgZnJvbSBcIi4uL2VsZW1lbnRzL0ZpZWxkXCI7XG5pbXBvcnQgeyBsb29rc1ZhbGlkIGFzIGVtYWlsTG9va3NWYWxpZCB9IGZyb20gXCIuLi8uLi8uLi9lbWFpbFwiO1xuaW1wb3J0IENvdW50cnlEcm9wZG93biBmcm9tIFwiLi4vYXV0aC9Db3VudHJ5RHJvcGRvd25cIjtcbmltcG9ydCB7IFBob25lTnVtYmVyQ291bnRyeURlZmluaXRpb24gfSBmcm9tIFwiLi4vLi4vLi4vcGhvbmVudW1iZXJcIjtcbmltcG9ydCBJbmxpbmVTcGlubmVyIGZyb20gXCIuLi9lbGVtZW50cy9JbmxpbmVTcGlubmVyXCI7XG5cbi8vIFdoZXRoZXIgd2UncmUgYWRkaW5nIDNwaWRzIHRvIHRoZSB1c2VyJ3MgYWNjb3VudCBvbiB0aGUgaG9tZXNlcnZlciBvciBzaGFyaW5nIHRoZW0gb24gYW4gaWRlbnRpdHkgc2VydmVyXG50eXBlIFRoZWVwaWRDb250cm9sTW9kZSA9IFwiaHNcIiB8IFwiaXNcIjtcblxuaW50ZXJmYWNlIEV4aXN0aW5nVGhyZWVwaWRQcm9wcyB7XG4gICAgbW9kZTogVGhlZXBpZENvbnRyb2xNb2RlO1xuICAgIHRocmVlcGlkOiBUaGlyZFBhcnR5SWRlbnRpZmllcjtcbiAgICBvbkNoYW5nZTogKHRocmVlcGlkOiBUaGlyZFBhcnR5SWRlbnRpZmllcikgPT4gdm9pZDtcbiAgICBkaXNhYmxlZD86IGJvb2xlYW47XG59XG5cbmNvbnN0IEV4aXN0aW5nVGhyZWVwaWQ6IFJlYWN0LkZDPEV4aXN0aW5nVGhyZWVwaWRQcm9wcz4gPSAoeyBtb2RlLCB0aHJlZXBpZCwgb25DaGFuZ2UsIGRpc2FibGVkIH0pID0+IHtcbiAgICBjb25zdCBbaXNDb25maXJtaW5nLCBzZXRJc0NvbmZpcm1pbmddID0gdXNlU3RhdGUoZmFsc2UpO1xuICAgIGNvbnN0IGNsaWVudCA9IHVzZU1hdHJpeENsaWVudENvbnRleHQoKTtcbiAgICBjb25zdCBiaW5kVGFzayA9IHVzZVJlZjxBZGRUaHJlZXBpZCB8IHVuZGVmaW5lZD4oKTtcblxuICAgIGNvbnN0IFtpc1ZlcmlmeWluZ0JpbmQsIHNldElzVmVyaWZ5aW5nQmluZF0gPSB1c2VTdGF0ZShmYWxzZSk7XG4gICAgY29uc3QgW2NvbnRpbnVlRGlzYWJsZWQsIHNldENvbnRpbnVlRGlzYWJsZWRdID0gdXNlU3RhdGUoZmFsc2UpO1xuICAgIGNvbnN0IFt2ZXJpZmljYXRpb25Db2RlLCBzZXRWZXJpZmljYXRpb25Db2RlXSA9IHVzZVN0YXRlKFwiXCIpO1xuXG4gICAgY29uc3Qgb25SZW1vdmVDbGljayA9IHVzZUNhbGxiYWNrKChlOiBCdXR0b25FdmVudCkgPT4ge1xuICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICAgICAgc2V0SXNDb25maXJtaW5nKHRydWUpO1xuICAgIH0sIFtdKTtcblxuICAgIGNvbnN0IG9uQ2FuY2VsQ2xpY2sgPSB1c2VDYWxsYmFjaygoZTogQnV0dG9uRXZlbnQpID0+IHtcbiAgICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgICAgIHNldElzQ29uZmlybWluZyhmYWxzZSk7XG4gICAgfSwgW10pO1xuXG4gICAgY29uc3Qgb25Db25maXJtUmVtb3ZlQ2xpY2sgPSB1c2VDYWxsYmFjayhcbiAgICAgICAgKGU6IEJ1dHRvbkV2ZW50KSA9PiB7XG4gICAgICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgICAgICAgICBjbGllbnRcbiAgICAgICAgICAgICAgICAuZGVsZXRlVGhyZWVQaWQodGhyZWVwaWQubWVkaXVtLCB0aHJlZXBpZC5hZGRyZXNzKVxuICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG9uQ2hhbmdlKHRocmVlcGlkKTtcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5jYXRjaCgoZXJyKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGxvZ2dlci5lcnJvcihcIlVuYWJsZSB0byByZW1vdmUgY29udGFjdCBpbmZvcm1hdGlvbjogXCIgKyBlcnIpO1xuICAgICAgICAgICAgICAgICAgICBNb2RhbC5jcmVhdGVEaWFsb2coRXJyb3JEaWFsb2csIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRpdGxlOiBfdChcInNldHRpbmdzfGdlbmVyYWx8ZXJyb3JfcmVtb3ZlXzNwaWRcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbjogZXJyICYmIGVyci5tZXNzYWdlID8gZXJyLm1lc3NhZ2UgOiBfdChcImludml0ZXxmYWlsZWRfZ2VuZXJpY1wiKSxcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgIH0sXG4gICAgICAgIFtjbGllbnQsIHRocmVlcGlkLCBvbkNoYW5nZV0sXG4gICAgKTtcblxuICAgIGNvbnN0IGNoYW5nZUJpbmRpbmcgPSB1c2VDYWxsYmFjayhcbiAgICAgICAgYXN5bmMgKHsgYmluZCwgbGFiZWwsIGVycm9yVGl0bGUgfTogQmluZGluZykgPT4ge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBpZiAoYmluZCkge1xuICAgICAgICAgICAgICAgICAgICBiaW5kVGFzay5jdXJyZW50ID0gbmV3IEFkZFRocmVlcGlkKGNsaWVudCk7XG4gICAgICAgICAgICAgICAgICAgIHNldENvbnRpbnVlRGlzYWJsZWQodHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aHJlZXBpZC5tZWRpdW0gPT09IFRocmVlcGlkTWVkaXVtLkVtYWlsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhd2FpdCBiaW5kVGFzay5jdXJyZW50LmJpbmRFbWFpbEFkZHJlc3ModGhyZWVwaWQuYWRkcmVzcyk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBYWFg6IFN5ZGVudCB3aWxsIGFjY2VwdCBhIG51bWJlciB3aXRob3V0IGNvdW50cnkgY29kZSBpZiB5b3UgYWRkXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBhIGxlYWRpbmcgcGx1cyBzaWduIHRvIGEgbnVtYmVyIGluIEUuMTY0IGZvcm1hdCAod2hpY2ggdGhlIDNQSURcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGFkZHJlc3MgaXMpLCBidXQgdGhpcyBnb2VzIGFnYWluc3QgdGhlIHNwZWMuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBTZWUgaHR0cHM6Ly9naXRodWIuY29tL21hdHJpeC1vcmcvbWF0cml4LWRvYy9pc3N1ZXMvMjIyMlxuICAgICAgICAgICAgICAgICAgICAgICAgYXdhaXQgYmluZFRhc2suY3VycmVudC5iaW5kTXNpc2RuKG51bGwgYXMgdW5rbm93biBhcyBzdHJpbmcsIGArJHt0aHJlZXBpZC5hZGRyZXNzfWApO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHNldENvbnRpbnVlRGlzYWJsZWQoZmFsc2UpO1xuICAgICAgICAgICAgICAgICAgICBzZXRJc1ZlcmlmeWluZ0JpbmQodHJ1ZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgY2xpZW50LnVuYmluZFRocmVlUGlkKHRocmVlcGlkLm1lZGl1bSwgdGhyZWVwaWQuYWRkcmVzcyk7XG4gICAgICAgICAgICAgICAgICAgIG9uQ2hhbmdlKHRocmVlcGlkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICBsb2dnZXIuZXJyb3IoYGNoYW5nZUJpbmRpbmc6IFVuYWJsZSB0byAke2xhYmVsfSBlbWFpbCBhZGRyZXNzICR7dGhyZWVwaWQuYWRkcmVzc31gLCBlcnIpO1xuICAgICAgICAgICAgICAgIHNldElzVmVyaWZ5aW5nQmluZChmYWxzZSk7XG4gICAgICAgICAgICAgICAgc2V0Q29udGludWVEaXNhYmxlZChmYWxzZSk7XG4gICAgICAgICAgICAgICAgYmluZFRhc2suY3VycmVudCA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICBNb2RhbC5jcmVhdGVEaWFsb2coRXJyb3JEaWFsb2csIHtcbiAgICAgICAgICAgICAgICAgICAgdGl0bGU6IGVycm9yVGl0bGUsXG4gICAgICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uOiBleHRyYWN0RXJyb3JNZXNzYWdlRnJvbUVycm9yKGVyciwgX3QoXCJpbnZpdGV8ZmFpbGVkX2dlbmVyaWNcIikpLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBbY2xpZW50LCB0aHJlZXBpZCwgb25DaGFuZ2VdLFxuICAgICk7XG5cbiAgICBjb25zdCBvblJldm9rZUNsaWNrID0gdXNlQ2FsbGJhY2soXG4gICAgICAgIChlOiBCdXR0b25FdmVudCk6IHZvaWQgPT4ge1xuICAgICAgICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgIGNoYW5nZUJpbmRpbmcoe1xuICAgICAgICAgICAgICAgIGJpbmQ6IGZhbHNlLFxuICAgICAgICAgICAgICAgIGxhYmVsOiBcInJldm9rZVwiLFxuICAgICAgICAgICAgICAgIGVycm9yVGl0bGU6XG4gICAgICAgICAgICAgICAgICAgIHRocmVlcGlkLm1lZGl1bSA9PT0gXCJlbWFpbFwiXG4gICAgICAgICAgICAgICAgICAgICAgICA/IF90KFwic2V0dGluZ3N8Z2VuZXJhbHxlcnJvcl9yZXZva2VfZW1haWxfZGlzY292ZXJ5XCIpXG4gICAgICAgICAgICAgICAgICAgICAgICA6IF90KFwic2V0dGluZ3N8Z2VuZXJhbHxlcnJvcl9yZXZva2VfbXNpc2RuX2Rpc2NvdmVyeVwiKSxcbiAgICAgICAgICAgIH0pLnRoZW4oKTtcbiAgICAgICAgfSxcbiAgICAgICAgW2NoYW5nZUJpbmRpbmcsIHRocmVlcGlkLm1lZGl1bV0sXG4gICAgKTtcblxuICAgIGNvbnN0IG9uU2hhcmVDbGljayA9IHVzZUNhbGxiYWNrKFxuICAgICAgICAoZTogQnV0dG9uRXZlbnQpOiB2b2lkID0+IHtcbiAgICAgICAgICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICBjaGFuZ2VCaW5kaW5nKHtcbiAgICAgICAgICAgICAgICBiaW5kOiB0cnVlLFxuICAgICAgICAgICAgICAgIGxhYmVsOiBcInNoYXJlXCIsXG4gICAgICAgICAgICAgICAgZXJyb3JUaXRsZTpcbiAgICAgICAgICAgICAgICAgICAgdGhyZWVwaWQubWVkaXVtID09PSBcImVtYWlsXCJcbiAgICAgICAgICAgICAgICAgICAgICAgID8gX3QoXCJzZXR0aW5nc3xnZW5lcmFsfGVycm9yX3NoYXJlX2VtYWlsX2Rpc2NvdmVyeVwiKVxuICAgICAgICAgICAgICAgICAgICAgICAgOiBfdChcInNldHRpbmdzfGdlbmVyYWx8ZXJyb3Jfc2hhcmVfbXNpc2RuX2Rpc2NvdmVyeVwiKSxcbiAgICAgICAgICAgIH0pLnRoZW4oKTtcbiAgICAgICAgfSxcbiAgICAgICAgW2NoYW5nZUJpbmRpbmcsIHRocmVlcGlkLm1lZGl1bV0sXG4gICAgKTtcblxuICAgIGNvbnN0IG9uQ29udGludWVDbGljayA9IHVzZUNhbGxiYWNrKFxuICAgICAgICBhc3luYyAoZTogQnV0dG9uRXZlbnQpID0+IHtcbiAgICAgICAgICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICAgICAgICAgIHNldENvbnRpbnVlRGlzYWJsZWQodHJ1ZSk7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGlmICh0aHJlZXBpZC5tZWRpdW0gPT09IFRocmVlcGlkTWVkaXVtLkVtYWlsKSB7XG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IGJpbmRUYXNrLmN1cnJlbnQ/LmNoZWNrRW1haWxMaW5rQ2xpY2tlZCgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IGJpbmRUYXNrLmN1cnJlbnQ/LmhhdmVNc2lzZG5Ub2tlbih2ZXJpZmljYXRpb25Db2RlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgc2V0SXNWZXJpZnlpbmdCaW5kKGZhbHNlKTtcbiAgICAgICAgICAgICAgICBvbkNoYW5nZSh0aHJlZXBpZCk7XG4gICAgICAgICAgICAgICAgYmluZFRhc2suY3VycmVudCA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICAgIGxvZ2dlci5lcnJvcihgVW5hYmxlIHRvIHZlcmlmeSB0aHJlZXBpZDpgLCBlcnIpO1xuXG4gICAgICAgICAgICAgICAgbGV0IHVuZGVybHlpbmdFcnJvciA9IGVycjtcbiAgICAgICAgICAgICAgICBpZiAoZXJyIGluc3RhbmNlb2YgVXNlckZyaWVuZGx5RXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgdW5kZXJseWluZ0Vycm9yID0gZXJyLmNhdXNlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICh1bmRlcmx5aW5nRXJyb3IgaW5zdGFuY2VvZiBNYXRyaXhFcnJvciAmJiB1bmRlcmx5aW5nRXJyb3IuZXJyY29kZSA9PT0gXCJNX1RIUkVFUElEX0FVVEhfRkFJTEVEXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgTW9kYWwuY3JlYXRlRGlhbG9nKEVycm9yRGlhbG9nLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aXRsZTpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJlZXBpZC5tZWRpdW0gPT09IFwiZW1haWxcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA/IF90KFwic2V0dGluZ3N8Z2VuZXJhbHxlbWFpbF9ub3RfdmVyaWZpZWRcIilcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgOiBfdChcInNldHRpbmdzfGdlbmVyYWx8ZXJyb3JfbXNpc2RuX3ZlcmlmaWNhdGlvblwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocmVlcGlkLm1lZGl1bSA9PT0gXCJlbWFpbFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgID8gX3QoXCJzZXR0aW5nc3xnZW5lcmFsfGVtYWlsX3ZlcmlmaWNhdGlvbl9pbnN0cnVjdGlvbnNcIilcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgOiBleHRyYWN0RXJyb3JNZXNzYWdlRnJvbUVycm9yKGVyciwgX3QoXCJpbnZpdGV8ZmFpbGVkX2dlbmVyaWNcIikpLFxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBsb2dnZXIuZXJyb3IoXCJVbmFibGUgdG8gdmVyaWZ5IGVtYWlsIGFkZHJlc3M6IFwiICsgZXJyKTtcbiAgICAgICAgICAgICAgICAgICAgTW9kYWwuY3JlYXRlRGlhbG9nKEVycm9yRGlhbG9nLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aXRsZTogX3QoXCJzZXR0aW5nc3xnZW5lcmFsfGVycm9yX2VtYWlsX3ZlcmlmaWNhdGlvblwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uOiBleHRyYWN0RXJyb3JNZXNzYWdlRnJvbUVycm9yKGVyciwgX3QoXCJpbnZpdGV8ZmFpbGVkX2dlbmVyaWNcIikpLFxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGZpbmFsbHkge1xuICAgICAgICAgICAgICAgIHNldENvbnRpbnVlRGlzYWJsZWQoZmFsc2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBbdmVyaWZpY2F0aW9uQ29kZSwgb25DaGFuZ2UsIHRocmVlcGlkXSxcbiAgICApO1xuXG4gICAgY29uc3Qgb25WZXJpZmljYXRpb25Db2RlQ2hhbmdlID0gdXNlQ2FsbGJhY2soKGU6IFJlYWN0LkNoYW5nZUV2ZW50PEhUTUxJbnB1dEVsZW1lbnQ+KSA9PiB7XG4gICAgICAgIHNldFZlcmlmaWNhdGlvbkNvZGUoZS50YXJnZXQudmFsdWUpO1xuICAgIH0sIFtdKTtcblxuICAgIGlmIChpc0NvbmZpcm1pbmcpIHtcbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIDxkaXYgY2xhc3NOYW1lPVwibXhfQWRkUmVtb3ZlVGhyZWVwaWRzX2V4aXN0aW5nXCI+XG4gICAgICAgICAgICAgICAgPHNwYW4gY2xhc3NOYW1lPVwibXhfQWRkUmVtb3ZlVGhyZWVwaWRzX2V4aXN0aW5nX3Byb21wdFRleHRcIj5cbiAgICAgICAgICAgICAgICAgICAge3RocmVlcGlkLm1lZGl1bSA9PT0gVGhyZWVwaWRNZWRpdW0uRW1haWxcbiAgICAgICAgICAgICAgICAgICAgICAgID8gX3QoXCJzZXR0aW5nc3xnZW5lcmFsfHJlbW92ZV9lbWFpbF9wcm9tcHRcIiwgeyBlbWFpbDogdGhyZWVwaWQuYWRkcmVzcyB9KVxuICAgICAgICAgICAgICAgICAgICAgICAgOiBfdChcInNldHRpbmdzfGdlbmVyYWx8cmVtb3ZlX21zaXNkbl9wcm9tcHRcIiwgeyBwaG9uZTogdGhyZWVwaWQuYWRkcmVzcyB9KX1cbiAgICAgICAgICAgICAgICA8L3NwYW4+XG4gICAgICAgICAgICAgICAgPEFjY2Vzc2libGVCdXR0b25cbiAgICAgICAgICAgICAgICAgICAgb25DbGljaz17b25Db25maXJtUmVtb3ZlQ2xpY2t9XG4gICAgICAgICAgICAgICAgICAgIGtpbmQ9XCJkYW5nZXJfc21cIlxuICAgICAgICAgICAgICAgICAgICBjbGFzc05hbWU9XCJteF9BZGRSZW1vdmVUaHJlZXBpZHNfZXhpc3RpbmdfYnV0dG9uXCJcbiAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgIHtfdChcImFjdGlvbnxyZW1vdmVcIil9XG4gICAgICAgICAgICAgICAgPC9BY2Nlc3NpYmxlQnV0dG9uPlxuICAgICAgICAgICAgICAgIDxBY2Nlc3NpYmxlQnV0dG9uXG4gICAgICAgICAgICAgICAgICAgIG9uQ2xpY2s9e29uQ2FuY2VsQ2xpY2t9XG4gICAgICAgICAgICAgICAgICAgIGtpbmQ9XCJsaW5rX3NtXCJcbiAgICAgICAgICAgICAgICAgICAgY2xhc3NOYW1lPVwibXhfQWRkUmVtb3ZlVGhyZWVwaWRzX2V4aXN0aW5nX2J1dHRvblwiXG4gICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgICB7X3QoXCJhY3Rpb258Y2FuY2VsXCIpfVxuICAgICAgICAgICAgICAgIDwvQWNjZXNzaWJsZUJ1dHRvbj5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICApO1xuICAgIH1cblxuICAgIGlmIChpc1ZlcmlmeWluZ0JpbmQpIHtcbiAgICAgICAgaWYgKHRocmVlcGlkLm1lZGl1bSA9PT0gVGhyZWVwaWRNZWRpdW0uRW1haWwpIHtcbiAgICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJteF9FbWFpbEFkZHJlc3Nlc1Bob25lTnVtYmVyc192ZXJpZnlcIj5cbiAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3NOYW1lPVwibXhfRW1haWxBZGRyZXNzZXNQaG9uZU51bWJlcnNfdmVyaWZ5X2luc3RydWN0aW9uc1wiPlxuICAgICAgICAgICAgICAgICAgICAgICAge190KFwic2V0dGluZ3N8Z2VuZXJhbHxkaXNjb3ZlcnlfZW1haWxfdmVyaWZpY2F0aW9uX2luc3RydWN0aW9uc1wiKX1cbiAgICAgICAgICAgICAgICAgICAgPC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICA8QWNjZXNzaWJsZUJ1dHRvblxuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3NOYW1lPVwibXhfRW1haWxBZGRyZXNzZXNQaG9uZU51bWJlcnNfZXhpc3RpbmdfYnV0dG9uXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIGtpbmQ9XCJwcmltYXJ5X3NtXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIG9uQ2xpY2s9e29uQ29udGludWVDbGlja31cbiAgICAgICAgICAgICAgICAgICAgICAgIGRpc2FibGVkPXtjb250aW51ZURpc2FibGVkfVxuICAgICAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgICAgICB7X3QoXCJhY3Rpb258Y29tcGxldGVcIil9XG4gICAgICAgICAgICAgICAgICAgIDwvQWNjZXNzaWJsZUJ1dHRvbj5cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3NOYW1lPVwibXhfRW1haWxBZGRyZXNzZXNQaG9uZU51bWJlcnNfdmVyaWZ5XCI+XG4gICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzTmFtZT1cIm14X0VtYWlsQWRkcmVzc2VzUGhvbmVOdW1iZXJzX3ZlcmlmeV9pbnN0cnVjdGlvbnNcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIHtfdChcInNldHRpbmdzfGdlbmVyYWx8bXNpc2RuX3ZlcmlmaWNhdGlvbl9pbnN0cnVjdGlvbnNcIil9XG4gICAgICAgICAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgPGZvcm0gb25TdWJtaXQ9e29uQ29udGludWVDbGlja30gYXV0b0NvbXBsZXRlPVwib2ZmXCIgbm9WYWxpZGF0ZT17dHJ1ZX0+XG4gICAgICAgICAgICAgICAgICAgICAgICA8RmllbGRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlPVwidGV4dFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWw9e190KFwic2V0dGluZ3N8Z2VuZXJhbHxtc2lzZG5fdmVyaWZpY2F0aW9uX2ZpZWxkX2xhYmVsXCIpfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF1dG9Db21wbGV0ZT1cIm9mZlwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlzYWJsZWQ9e2NvbnRpbnVlRGlzYWJsZWR9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU9e3ZlcmlmaWNhdGlvbkNvZGV9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb25DaGFuZ2U9e29uVmVyaWZpY2F0aW9uQ29kZUNoYW5nZX1cbiAgICAgICAgICAgICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICAgICAgICAgIDwvZm9ybT5cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gKFxuICAgICAgICA8ZGl2IGNsYXNzTmFtZT1cIm14X0FkZFJlbW92ZVRocmVlcGlkc19leGlzdGluZ1wiPlxuICAgICAgICAgICAgPHNwYW4gY2xhc3NOYW1lPVwibXhfQWRkUmVtb3ZlVGhyZWVwaWRzX2V4aXN0aW5nX2FkZHJlc3NcIj57dGhyZWVwaWQuYWRkcmVzc308L3NwYW4+XG4gICAgICAgICAgICA8QWNjZXNzaWJsZUJ1dHRvblxuICAgICAgICAgICAgICAgIG9uQ2xpY2s9e21vZGUgPT09IFwiaHNcIiA/IG9uUmVtb3ZlQ2xpY2sgOiB0aHJlZXBpZC5ib3VuZCA/IG9uUmV2b2tlQ2xpY2sgOiBvblNoYXJlQ2xpY2t9XG4gICAgICAgICAgICAgICAga2luZD17bW9kZSA9PT0gXCJoc1wiIHx8IHRocmVlcGlkLmJvdW5kID8gXCJkYW5nZXJfc21cIiA6IFwicHJpbWFyeV9zbVwifVxuICAgICAgICAgICAgICAgIGRpc2FibGVkPXtkaXNhYmxlZH1cbiAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICB7bW9kZSA9PT0gXCJoc1wiID8gX3QoXCJhY3Rpb258cmVtb3ZlXCIpIDogdGhyZWVwaWQuYm91bmQgPyBfdChcImFjdGlvbnxyZXZva2VcIikgOiBfdChcImFjdGlvbnxzaGFyZVwiKX1cbiAgICAgICAgICAgIDwvQWNjZXNzaWJsZUJ1dHRvbj5cbiAgICAgICAgPC9kaXY+XG4gICAgKTtcbn07XG5cbmZ1bmN0aW9uIGlzTXNpc2RuUmVzcG9uc2UoXG4gICAgcmVzcDogSVJlcXVlc3RUb2tlblJlc3BvbnNlIHwgSVJlcXVlc3RNc2lzZG5Ub2tlblJlc3BvbnNlLFxuKTogcmVzcCBpcyBJUmVxdWVzdE1zaXNkblRva2VuUmVzcG9uc2Uge1xuICAgIHJldHVybiAocmVzcCBhcyBJUmVxdWVzdE1zaXNkblRva2VuUmVzcG9uc2UpLm1zaXNkbiAhPT0gdW5kZWZpbmVkO1xufVxuXG5jb25zdCBBZGRUaHJlZXBpZFNlY3Rpb246IFJlYWN0LkZDPHsgbWVkaXVtOiBcImVtYWlsXCIgfCBcIm1zaXNkblwiOyBkaXNhYmxlZD86IGJvb2xlYW47IG9uQ2hhbmdlOiAoKSA9PiB2b2lkIH0+ID0gKHtcbiAgICBtZWRpdW0sXG4gICAgZGlzYWJsZWQsXG4gICAgb25DaGFuZ2UsXG59KSA9PiB7XG4gICAgY29uc3QgYWRkVGFzayA9IHVzZVJlZjxBZGRUaHJlZXBpZCB8IHVuZGVmaW5lZD4oKTtcbiAgICBjb25zdCBbbmV3VGhyZWVwaWRJbnB1dCwgc2V0TmV3VGhyZWVwaWRJbnB1dF0gPSB1c2VTdGF0ZShcIlwiKTtcbiAgICBjb25zdCBbcGhvbmVDb3VudHJ5SW5wdXQsIHNldFBob25lQ291bnRyeUlucHV0XSA9IHVzZVN0YXRlKFwiXCIpO1xuICAgIGNvbnN0IFt2ZXJpZmljYXRpb25Db2RlSW5wdXQsIHNldFZlcmlmaWNhdGlvbkNvZGVJbnB1dF0gPSB1c2VTdGF0ZShcIlwiKTtcbiAgICBjb25zdCBbaXNWZXJpZnlpbmcsIHNldElzVmVyaWZ5aW5nXSA9IHVzZVN0YXRlKGZhbHNlKTtcbiAgICBjb25zdCBbY29udGludWVEaXNhYmxlZCwgc2V0Q29udGludWVEaXNhYmxlZF0gPSB1c2VTdGF0ZShmYWxzZSk7XG4gICAgY29uc3QgW3NlbnRUb01zaXNkbiwgc2V0U2VudFRvTXNpc2RuXSA9IHVzZVN0YXRlKFwiXCIpO1xuXG4gICAgY29uc3QgY2xpZW50ID0gdXNlTWF0cml4Q2xpZW50Q29udGV4dCgpO1xuXG4gICAgY29uc3Qgb25QaG9uZUNvdW50cnlDaGFuZ2VkID0gdXNlQ2FsbGJhY2soKGNvdW50cnk6IFBob25lTnVtYmVyQ291bnRyeURlZmluaXRpb24pID0+IHtcbiAgICAgICAgc2V0UGhvbmVDb3VudHJ5SW5wdXQoY291bnRyeS5pc28yKTtcbiAgICB9LCBbXSk7XG5cbiAgICBjb25zdCBvbkNvbnRpbnVlQ2xpY2sgPSB1c2VDYWxsYmFjayhcbiAgICAgICAgKGU6IEJ1dHRvbkV2ZW50KSA9PiB7XG4gICAgICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgICAgICAgICBpZiAoIWFkZFRhc2suY3VycmVudCkgcmV0dXJuO1xuXG4gICAgICAgICAgICBzZXRDb250aW51ZURpc2FibGVkKHRydWUpO1xuXG4gICAgICAgICAgICBjb25zdCBjaGVja1Byb21pc2UgPVxuICAgICAgICAgICAgICAgIG1lZGl1bSA9PT0gXCJlbWFpbFwiXG4gICAgICAgICAgICAgICAgICAgID8gYWRkVGFzay5jdXJyZW50Py5jaGVja0VtYWlsTGlua0NsaWNrZWQoKVxuICAgICAgICAgICAgICAgICAgICA6IGFkZFRhc2suY3VycmVudD8uaGF2ZU1zaXNkblRva2VuKHZlcmlmaWNhdGlvbkNvZGVJbnB1dCk7XG4gICAgICAgICAgICBjaGVja1Byb21pc2VcbiAgICAgICAgICAgICAgICAudGhlbigoW2ZpbmlzaGVkXSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZmluaXNoZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFkZFRhc2suY3VycmVudCA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNldElzVmVyaWZ5aW5nKGZhbHNlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNldE5ld1RocmVlcGlkSW5wdXQoXCJcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICBvbkNoYW5nZSgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHNldENvbnRpbnVlRGlzYWJsZWQoZmFsc2UpO1xuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLmNhdGNoKChlcnIpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmVycm9yKFwiVW5hYmxlIHRvIHZlcmlmeSAzcGlkOiBcIiwgZXJyKTtcblxuICAgICAgICAgICAgICAgICAgICBzZXRDb250aW51ZURpc2FibGVkKGZhbHNlKTtcblxuICAgICAgICAgICAgICAgICAgICBsZXQgdW5kZXJseWluZ0Vycm9yID0gZXJyO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyIGluc3RhbmNlb2YgVXNlckZyaWVuZGx5RXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHVuZGVybHlpbmdFcnJvciA9IGVyci5jYXVzZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICAgICAgICAgIHVuZGVybHlpbmdFcnJvciBpbnN0YW5jZW9mIE1hdHJpeEVycm9yICYmXG4gICAgICAgICAgICAgICAgICAgICAgICB1bmRlcmx5aW5nRXJyb3IuZXJyY29kZSA9PT0gXCJNX1RIUkVFUElEX0FVVEhfRkFJTEVEXCJcbiAgICAgICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBNb2RhbC5jcmVhdGVEaWFsb2coRXJyb3JEaWFsb2csIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aXRsZTpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVkaXVtID09PSBcImVtYWlsXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgID8gX3QoXCJzZXR0aW5nc3xnZW5lcmFsfGVtYWlsX25vdF92ZXJpZmllZFwiKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgOiBfdChcInNldHRpbmdzfGdlbmVyYWx8ZXJyb3JfbXNpc2RuX3ZlcmlmaWNhdGlvblwiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbjogX3QoXCJzZXR0aW5nc3xnZW5lcmFsfGVtYWlsX3ZlcmlmaWNhdGlvbl9pbnN0cnVjdGlvbnNcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIE1vZGFsLmNyZWF0ZURpYWxvZyhFcnJvckRpYWxvZywge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRpdGxlOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWRpdW0gPT0gXCJlbWFpbFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA/IF90KFwic2V0dGluZ3N8Z2VuZXJhbHxlcnJvcl9lbWFpbF92ZXJpZmljYXRpb25cIilcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogX3QoXCJzZXR0aW5nc3xnZW5lcmFsfGVycm9yX21zaXNkbl92ZXJpZmljYXRpb25cIiksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzY3JpcHRpb246IGV4dHJhY3RFcnJvck1lc3NhZ2VGcm9tRXJyb3IoZXJyLCBfdChcImludml0ZXxmYWlsZWRfZ2VuZXJpY1wiKSksXG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuICAgICAgICBbb25DaGFuZ2UsIG1lZGl1bSwgdmVyaWZpY2F0aW9uQ29kZUlucHV0XSxcbiAgICApO1xuXG4gICAgY29uc3Qgb25OZXdUaHJlZXBpZElucHV0Q2hhbmdlID0gdXNlQ2FsbGJhY2soKGU6IFJlYWN0LkNoYW5nZUV2ZW50PEhUTUxJbnB1dEVsZW1lbnQ+KSA9PiB7XG4gICAgICAgIHNldE5ld1RocmVlcGlkSW5wdXQoZS50YXJnZXQudmFsdWUpO1xuICAgIH0sIFtdKTtcblxuICAgIGNvbnN0IG9uQWRkQ2xpY2sgPSB1c2VDYWxsYmFjayhcbiAgICAgICAgKGU6IFJlYWN0LkZvcm1FdmVudCkgPT4ge1xuICAgICAgICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgICAgICAgaWYgKCFuZXdUaHJlZXBpZElucHV0KSByZXR1cm47XG5cbiAgICAgICAgICAgIC8vIFRPRE86IElubGluZSBmaWVsZCB2YWxpZGF0aW9uXG4gICAgICAgICAgICBpZiAobWVkaXVtID09PSBcImVtYWlsXCIgJiYgIWVtYWlsTG9va3NWYWxpZChuZXdUaHJlZXBpZElucHV0KSkge1xuICAgICAgICAgICAgICAgIE1vZGFsLmNyZWF0ZURpYWxvZyhFcnJvckRpYWxvZywge1xuICAgICAgICAgICAgICAgICAgICB0aXRsZTogX3QoXCJzZXR0aW5nc3xnZW5lcmFsfGVycm9yX2ludmFsaWRfZW1haWxcIiksXG4gICAgICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uOiBfdChcInNldHRpbmdzfGdlbmVyYWx8ZXJyb3JfaW52YWxpZF9lbWFpbF9kZXRhaWxcIiksXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBhZGRUYXNrLmN1cnJlbnQgPSBuZXcgQWRkVGhyZWVwaWQoY2xpZW50KTtcbiAgICAgICAgICAgIHNldElzVmVyaWZ5aW5nKHRydWUpO1xuICAgICAgICAgICAgc2V0Q29udGludWVEaXNhYmxlZCh0cnVlKTtcblxuICAgICAgICAgICAgY29uc3QgYWRkUHJvbWlzZSA9XG4gICAgICAgICAgICAgICAgbWVkaXVtID09PSBcImVtYWlsXCJcbiAgICAgICAgICAgICAgICAgICAgPyBhZGRUYXNrLmN1cnJlbnQuYWRkRW1haWxBZGRyZXNzKG5ld1RocmVlcGlkSW5wdXQpXG4gICAgICAgICAgICAgICAgICAgIDogYWRkVGFzay5jdXJyZW50LmFkZE1zaXNkbihwaG9uZUNvdW50cnlJbnB1dCwgbmV3VGhyZWVwaWRJbnB1dCk7XG5cbiAgICAgICAgICAgIGFkZFByb21pc2VcbiAgICAgICAgICAgICAgICAudGhlbigocmVzcDogSVJlcXVlc3RUb2tlblJlc3BvbnNlIHwgSVJlcXVlc3RNc2lzZG5Ub2tlblJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHNldENvbnRpbnVlRGlzYWJsZWQoZmFsc2UpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNNc2lzZG5SZXNwb25zZShyZXNwKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2V0U2VudFRvTXNpc2RuKHJlc3AubXNpc2RuKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLmNhdGNoKChlcnIpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmVycm9yKGBVbmFibGUgdG8gYWRkIHRocmVlcGlkICR7bmV3VGhyZWVwaWRJbnB1dH1gLCBlcnIpO1xuICAgICAgICAgICAgICAgICAgICBzZXRJc1ZlcmlmeWluZyhmYWxzZSk7XG4gICAgICAgICAgICAgICAgICAgIHNldENvbnRpbnVlRGlzYWJsZWQoZmFsc2UpO1xuICAgICAgICAgICAgICAgICAgICBhZGRUYXNrLmN1cnJlbnQgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAgIE1vZGFsLmNyZWF0ZURpYWxvZyhFcnJvckRpYWxvZywge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGl0bGU6IG1lZGl1bSA9PT0gXCJlbWFpbFwiID8gX3QoXCJzZXR0aW5nc3xnZW5lcmFsfGVycm9yX2FkZF9lbWFpbFwiKSA6IF90KFwiY29tbW9ufGVycm9yXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgZGVzY3JpcHRpb246IGV4dHJhY3RFcnJvck1lc3NhZ2VGcm9tRXJyb3IoZXJyLCBfdChcImludml0ZXxmYWlsZWRfZ2VuZXJpY1wiKSksXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuICAgICAgICBbY2xpZW50LCBwaG9uZUNvdW50cnlJbnB1dCwgbmV3VGhyZWVwaWRJbnB1dCwgbWVkaXVtXSxcbiAgICApO1xuXG4gICAgY29uc3Qgb25WZXJpZmljYXRpb25Db2RlSW5wdXRDaGFuZ2UgPSB1c2VDYWxsYmFjaygoZTogUmVhY3QuQ2hhbmdlRXZlbnQ8SFRNTElucHV0RWxlbWVudD4pID0+IHtcbiAgICAgICAgc2V0VmVyaWZpY2F0aW9uQ29kZUlucHV0KGUudGFyZ2V0LnZhbHVlKTtcbiAgICB9LCBbXSk7XG5cbiAgICBpZiAoaXNWZXJpZnlpbmcgJiYgbWVkaXVtID09PSBcImVtYWlsXCIpIHtcbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIDxkaXY+XG4gICAgICAgICAgICAgICAgPGRpdj57X3QoXCJzZXR0aW5nc3xnZW5lcmFsfGFkZF9lbWFpbF9pbnN0cnVjdGlvbnNcIil9PC9kaXY+XG4gICAgICAgICAgICAgICAgPEFjY2Vzc2libGVCdXR0b24gb25DbGljaz17b25Db250aW51ZUNsaWNrfSBraW5kPVwicHJpbWFyeVwiIGRpc2FibGVkPXtjb250aW51ZURpc2FibGVkfT5cbiAgICAgICAgICAgICAgICAgICAge190KFwiYWN0aW9ufGNvbnRpbnVlXCIpfVxuICAgICAgICAgICAgICAgIDwvQWNjZXNzaWJsZUJ1dHRvbj5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICApO1xuICAgIH0gZWxzZSBpZiAoaXNWZXJpZnlpbmcpIHtcbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIDxkaXY+XG4gICAgICAgICAgICAgICAgPGRpdj5cbiAgICAgICAgICAgICAgICAgICAge190KFwic2V0dGluZ3N8Z2VuZXJhbHxhZGRfbXNpc2RuX2luc3RydWN0aW9uc1wiLCB7IG1zaXNkbjogc2VudFRvTXNpc2RuIH0pfVxuICAgICAgICAgICAgICAgICAgICA8YnIgLz5cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICA8Zm9ybSBvblN1Ym1pdD17b25Db250aW51ZUNsaWNrfSBhdXRvQ29tcGxldGU9XCJvZmZcIiBub1ZhbGlkYXRlPXt0cnVlfT5cbiAgICAgICAgICAgICAgICAgICAgPEZpZWxkXG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlPVwidGV4dFwiXG4gICAgICAgICAgICAgICAgICAgICAgICBsYWJlbD17X3QoXCJzZXR0aW5nc3xnZW5lcmFsfG1zaXNkbl92ZXJpZmljYXRpb25fZmllbGRfbGFiZWxcIil9XG4gICAgICAgICAgICAgICAgICAgICAgICBhdXRvQ29tcGxldGU9XCJvZmZcIlxuICAgICAgICAgICAgICAgICAgICAgICAgZGlzYWJsZWQ9e2Rpc2FibGVkIHx8IGNvbnRpbnVlRGlzYWJsZWR9XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZT17dmVyaWZpY2F0aW9uQ29kZUlucHV0fVxuICAgICAgICAgICAgICAgICAgICAgICAgb25DaGFuZ2U9e29uVmVyaWZpY2F0aW9uQ29kZUlucHV0Q2hhbmdlfVxuICAgICAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICAgICAgICA8QWNjZXNzaWJsZUJ1dHRvblxuICAgICAgICAgICAgICAgICAgICAgICAgb25DbGljaz17b25Db250aW51ZUNsaWNrfVxuICAgICAgICAgICAgICAgICAgICAgICAga2luZD1cInByaW1hcnlcIlxuICAgICAgICAgICAgICAgICAgICAgICAgZGlzYWJsZWQ9e2Rpc2FibGVkIHx8IGNvbnRpbnVlRGlzYWJsZWQgfHwgdmVyaWZpY2F0aW9uQ29kZUlucHV0Lmxlbmd0aCA9PT0gMH1cbiAgICAgICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgICAgICAge190KFwiYWN0aW9ufGNvbnRpbnVlXCIpfVxuICAgICAgICAgICAgICAgICAgICA8L0FjY2Vzc2libGVCdXR0b24+XG4gICAgICAgICAgICAgICAgPC9mb3JtPlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgY29uc3QgcGhvbmVDb3VudHJ5ID1cbiAgICAgICAgbWVkaXVtID09PSBcIm1zaXNkblwiID8gKFxuICAgICAgICAgICAgPENvdW50cnlEcm9wZG93blxuICAgICAgICAgICAgICAgIG9uT3B0aW9uQ2hhbmdlPXtvblBob25lQ291bnRyeUNoYW5nZWR9XG4gICAgICAgICAgICAgICAgY2xhc3NOYW1lPVwibXhfUGhvbmVOdW1iZXJzX2NvdW50cnlcIlxuICAgICAgICAgICAgICAgIHZhbHVlPXtwaG9uZUNvdW50cnlJbnB1dH1cbiAgICAgICAgICAgICAgICBkaXNhYmxlZD17aXNWZXJpZnlpbmd9XG4gICAgICAgICAgICAgICAgaXNTbWFsbD17dHJ1ZX1cbiAgICAgICAgICAgICAgICBzaG93UHJlZml4PXt0cnVlfVxuICAgICAgICAgICAgLz5cbiAgICAgICAgKSA6IHVuZGVmaW5lZDtcblxuICAgIHJldHVybiAoXG4gICAgICAgIDxmb3JtIG9uU3VibWl0PXtvbkFkZENsaWNrfSBhdXRvQ29tcGxldGU9XCJvZmZcIiBub1ZhbGlkYXRlPXt0cnVlfT5cbiAgICAgICAgICAgIDxGaWVsZFxuICAgICAgICAgICAgICAgIHR5cGU9XCJ0ZXh0XCJcbiAgICAgICAgICAgICAgICBsYWJlbD17XG4gICAgICAgICAgICAgICAgICAgIG1lZGl1bSA9PT0gXCJlbWFpbFwiXG4gICAgICAgICAgICAgICAgICAgICAgICA/IF90KFwic2V0dGluZ3N8Z2VuZXJhbHxlbWFpbF9hZGRyZXNzX2xhYmVsXCIpXG4gICAgICAgICAgICAgICAgICAgICAgICA6IF90KFwic2V0dGluZ3N8Z2VuZXJhbHxtc2lzZG5fbGFiZWxcIilcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYXV0b0NvbXBsZXRlPXttZWRpdW0gPT09IFwiZW1haWxcIiA/IFwiZW1haWxcIiA6IFwidGVsLW5hdGlvbmFsXCJ9XG4gICAgICAgICAgICAgICAgZGlzYWJsZWQ9e2Rpc2FibGVkIHx8IGlzVmVyaWZ5aW5nfVxuICAgICAgICAgICAgICAgIHZhbHVlPXtuZXdUaHJlZXBpZElucHV0fVxuICAgICAgICAgICAgICAgIG9uQ2hhbmdlPXtvbk5ld1RocmVlcGlkSW5wdXRDaGFuZ2V9XG4gICAgICAgICAgICAgICAgcHJlZml4Q29tcG9uZW50PXtwaG9uZUNvdW50cnl9XG4gICAgICAgICAgICAvPlxuICAgICAgICAgICAgPEFjY2Vzc2libGVCdXR0b24gb25DbGljaz17b25BZGRDbGlja30ga2luZD1cInByaW1hcnlcIiBkaXNhYmxlZD17ZGlzYWJsZWR9PlxuICAgICAgICAgICAgICAgIHtfdChcImFjdGlvbnxhZGRcIil9XG4gICAgICAgICAgICA8L0FjY2Vzc2libGVCdXR0b24+XG4gICAgICAgIDwvZm9ybT5cbiAgICApO1xufTtcblxuaW50ZXJmYWNlIEFkZFJlbW92ZVRocmVlcGlkc1Byb3BzIHtcbiAgICAvLyBXaGV0aGVyIHRoZSBjb250cm9sIGlzIGZvciBhZGRpbmcgM3BpZHMgdG8gdGhlIHVzZXIncyBob21lc2VydmVyIGFjY291bnQgb3Igc2hhcmluZyB0aGVtIG9uIGFuIElTXG4gICAgbW9kZTogVGhlZXBpZENvbnRyb2xNb2RlO1xuICAgIC8vIFdoZXRoZXIgdGhlIGNvbnRyb2wgaXMgZm9yIGVtYWlscyBvciBwaG9uZSBudW1iZXJzXG4gICAgbWVkaXVtOiBUaHJlZXBpZE1lZGl1bTtcbiAgICAvLyBUaGUgY3VycmVudCBsaXN0IG9mIHRoaXJkIHBhcnR5IGlkZW50aWZpZXJzXG4gICAgdGhyZWVwaWRzOiBUaGlyZFBhcnR5SWRlbnRpZmllcltdO1xuICAgIC8vIElmIHRydWUsIHRoZSBjb21wb25lbnQgaXMgZGlzYWJsZWQgYW5kIG5vIHRoaXJkIHBhcnR5IGlkZW50aWZpZXJzIGNhbiBiZSBhZGRlZCBvciByZW1vdmVkXG4gICAgZGlzYWJsZWQ/OiBib29sZWFuO1xuICAgIC8vIENhbGxlZCB3aGVuIGNoYW5nZXMgYXJlIG1hZGUgdG8gdGhlIGxpc3Qgb2YgdGhpcmQgcGFydHkgaWRlbnRpZmllcnNcbiAgICBvbkNoYW5nZTogKCkgPT4gdm9pZDtcbiAgICAvLyBJZiB0cnVlLCBhIHNwaW5uZXIgaXMgc2hvd24gaW5zdGVhZCBvZiB0aGUgY29tcG9uZW50XG4gICAgaXNMb2FkaW5nOiBib29sZWFuO1xufVxuXG5leHBvcnQgY29uc3QgQWRkUmVtb3ZlVGhyZWVwaWRzOiBSZWFjdC5GQzxBZGRSZW1vdmVUaHJlZXBpZHNQcm9wcz4gPSAoe1xuICAgIG1vZGUsXG4gICAgbWVkaXVtLFxuICAgI