matrix-react-sdk
Version:
SDK for matrix.org using React
365 lines (359 loc) • 58.6 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = exports.ABUSE_EVENT_TYPE = void 0;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _react = _interopRequireDefault(require("react"));
var _logger = require("matrix-js-sdk/src/logger");
var _languageHandler = require("../../../languageHandler");
var _createRoom = require("../../../createRoom");
var _MatrixClientPeg = require("../../../MatrixClientPeg");
var _SdkConfig = _interopRequireDefault(require("../../../SdkConfig"));
var _Markdown = _interopRequireDefault(require("../../../Markdown"));
var _SettingsStore = _interopRequireDefault(require("../../../settings/SettingsStore"));
var _StyledRadioButton = _interopRequireDefault(require("../elements/StyledRadioButton"));
var _BaseDialog = _interopRequireDefault(require("./BaseDialog"));
var _DialogButtons = _interopRequireDefault(require("../elements/DialogButtons"));
var _Field = _interopRequireDefault(require("../elements/Field"));
var _Spinner = _interopRequireDefault(require("../elements/Spinner"));
var _LabelledCheckbox = _interopRequireDefault(require("../elements/LabelledCheckbox"));
/*
Copyright 2024 New Vector Ltd.
Copyright 2022 The Matrix.org Foundation C.I.C.
Copyright 2019 Michael Telatynski <7t3chguy@gmail.com>
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
Please see LICENSE files in the repository root for full details.
*/
const MODERATED_BY_STATE_EVENT_TYPE = ["org.matrix.msc3215.room.moderation.moderated_by"
/**
* Unprefixed state event. Not ready for prime time.
*
* "m.room.moderation.moderated_by"
*/];
const ABUSE_EVENT_TYPE = exports.ABUSE_EVENT_TYPE = "org.matrix.msc3215.abuse.report";
// Standard abuse natures.
var Nature = /*#__PURE__*/function (Nature) {
Nature["Disagreement"] = "org.matrix.msc3215.abuse.nature.disagreement";
Nature["Toxic"] = "org.matrix.msc3215.abuse.nature.toxic";
Nature["Illegal"] = "org.matrix.msc3215.abuse.nature.illegal";
Nature["Spam"] = "org.matrix.msc3215.abuse.nature.spam";
Nature["Other"] = "org.matrix.msc3215.abuse.nature.other";
return Nature;
}(Nature || {});
var NonStandardValue = /*#__PURE__*/function (NonStandardValue) {
NonStandardValue["Admin"] = "non-standard.abuse.nature.admin";
return NonStandardValue;
}(NonStandardValue || {});
/*
* A dialog for reporting an event.
*
* The actual content of the dialog will depend on two things:
*
* 1. Is `feature_report_to_moderators` enabled?
* 2. Does the room support moderation as per MSC3215, i.e. is there
* a well-formed state event `m.room.moderation.moderated_by`
* /`org.matrix.msc3215.room.moderation.moderated_by`?
*/
class ReportEventDialog extends _react.default.Component {
constructor(props) {
super(props);
// If the room supports moderation, the moderation information.
(0, _defineProperty2.default)(this, "moderation", void 0);
(0, _defineProperty2.default)(this, "onIgnoreUserTooChanged", newVal => {
this.setState({
ignoreUserToo: newVal
});
});
// The user has written down a freeform description of the abuse.
(0, _defineProperty2.default)(this, "onReasonChange", ({
target: {
value: reason
}
}) => {
this.setState({
reason
});
});
// The user has clicked on a nature.
(0, _defineProperty2.default)(this, "onNatureChosen", e => {
this.setState({
nature: e.currentTarget.value
});
});
// The user has clicked "cancel".
(0, _defineProperty2.default)(this, "onCancel", () => {
this.props.onFinished(false);
});
// The user has clicked "submit".
(0, _defineProperty2.default)(this, "onSubmit", async () => {
let reason = this.state.reason || "";
reason = reason.trim();
if (this.moderation) {
// This room supports moderation.
// We need a nature.
// If the nature is `NATURE.OTHER` or `NON_STANDARD_NATURE.ADMIN`, we also need a `reason`.
if (!this.state.nature || (this.state.nature == Nature.Other || this.state.nature == NonStandardValue.Admin) && !reason) {
this.setState({
err: (0, _languageHandler._t)("report_content|missing_reason")
});
return;
}
} else {
// This room does not support moderation.
// We need a `reason`.
if (!reason) {
this.setState({
err: (0, _languageHandler._t)("report_content|missing_reason")
});
return;
}
}
this.setState({
busy: true,
err: undefined
});
try {
const client = _MatrixClientPeg.MatrixClientPeg.safeGet();
const ev = this.props.mxEvent;
if (this.moderation && this.state.nature !== NonStandardValue.Admin) {
const nature = this.state.nature;
// Report to moderators through to the dedicated bot,
// as configured in the room's state events.
const dmRoomId = await (0, _createRoom.ensureDMExists)(client, this.moderation.moderationBotUserId);
if (!dmRoomId) {
throw new _languageHandler.UserFriendlyError("report_content|error_create_room_moderation_bot");
}
await client.sendEvent(dmRoomId, ABUSE_EVENT_TYPE, {
event_id: ev.getId(),
room_id: ev.getRoomId(),
moderated_by_id: this.moderation.moderationRoomId,
nature,
reporter: client.getUserId(),
comment: this.state.reason.trim()
});
} else {
// Report to homeserver admin through the dedicated Matrix API.
await client.reportEvent(ev.getRoomId(), ev.getId(), -100, this.state.reason.trim());
}
// if the user should also be ignored, do that
if (this.state.ignoreUserToo) {
await client.setIgnoredUsers([...client.getIgnoredUsers(), ev.getSender()]);
}
this.props.onFinished(true);
} catch (e) {
_logger.logger.error(e);
this.setState({
busy: false,
err: e instanceof Error ? e.message : String(e)
});
}
});
let moderatedByRoomId = null;
let moderatedByUserId = null;
if (_SettingsStore.default.getValue("feature_report_to_moderators")) {
// The client supports reporting to moderators.
// Does the room support it, too?
// Extract state events to determine whether we should display
const client = _MatrixClientPeg.MatrixClientPeg.safeGet();
const room = client.getRoom(props.mxEvent.getRoomId());
for (const stateEventType of MODERATED_BY_STATE_EVENT_TYPE) {
const stateEvent = room?.currentState.getStateEvents(stateEventType, stateEventType);
if (!stateEvent) {
continue;
}
if (Array.isArray(stateEvent)) {
// Internal error.
throw new TypeError(`getStateEvents(${stateEventType}, ${stateEventType}) ` + "should return at most one state event");
}
const event = stateEvent.event;
if (!("content" in event) || typeof event["content"] != "object") {
// The room is improperly configured.
// Display this debug message for the sake of moderators.
console.debug("Moderation error", "state event", stateEventType, "should have an object field `content`, got", event);
continue;
}
const content = event["content"];
if (!("room_id" in content) || typeof content["room_id"] != "string") {
// The room is improperly configured.
// Display this debug message for the sake of moderators.
console.debug("Moderation error", "state event", stateEventType, "should have a string field `content.room_id`, got", event);
continue;
}
if (!("user_id" in content) || typeof content["user_id"] != "string") {
// The room is improperly configured.
// Display this debug message for the sake of moderators.
console.debug("Moderation error", "state event", stateEventType, "should have a string field `content.user_id`, got", event);
continue;
}
moderatedByRoomId = content["room_id"];
moderatedByUserId = content["user_id"];
}
if (moderatedByRoomId && moderatedByUserId) {
// The room supports moderation.
this.moderation = {
moderationRoomId: moderatedByRoomId,
moderationBotUserId: moderatedByUserId
};
}
}
this.state = {
// A free-form text describing the abuse.
reason: "",
busy: false,
err: undefined,
// If specified, the nature of the abuse, as specified by MSC3215.
nature: undefined,
ignoreUserToo: false // default false, for now. Could easily be argued as default true
};
}
render() {
let error;
if (this.state.err) {
error = /*#__PURE__*/_react.default.createElement("div", {
className: "error"
}, this.state.err);
}
let progress;
if (this.state.busy) {
progress = /*#__PURE__*/_react.default.createElement("div", {
className: "progress"
}, /*#__PURE__*/_react.default.createElement(_Spinner.default, null));
}
const ignoreUserCheckbox = /*#__PURE__*/_react.default.createElement(_LabelledCheckbox.default, {
value: this.state.ignoreUserToo,
label: (0, _languageHandler._t)("report_content|ignore_user"),
byline: (0, _languageHandler._t)("report_content|hide_messages_from_user"),
onChange: this.onIgnoreUserTooChanged,
disabled: this.state.busy
});
const adminMessageMD = _SdkConfig.default.getObject("report_event")?.get("admin_message_md", "adminMessageMD");
let adminMessage;
if (adminMessageMD) {
const html = new _Markdown.default(adminMessageMD).toHTML({
externalLinks: true
});
adminMessage = /*#__PURE__*/_react.default.createElement("p", {
dangerouslySetInnerHTML: {
__html: html
}
});
}
if (this.moderation) {
// Display report-to-moderator dialog.
// We let the user pick a nature.
const client = _MatrixClientPeg.MatrixClientPeg.safeGet();
const homeServerName = _SdkConfig.default.get("validated_server_config").hsName;
let subtitle;
switch (this.state.nature) {
case Nature.Disagreement:
subtitle = (0, _languageHandler._t)("report_content|nature_disagreement");
break;
case Nature.Toxic:
subtitle = (0, _languageHandler._t)("report_content|nature_toxic");
break;
case Nature.Illegal:
subtitle = (0, _languageHandler._t)("report_content|nature_illegal");
break;
case Nature.Spam:
subtitle = (0, _languageHandler._t)("report_content|nature_spam");
break;
case NonStandardValue.Admin:
if (client.isRoomEncrypted(this.props.mxEvent.getRoomId())) {
subtitle = (0, _languageHandler._t)("report_content|nature_nonstandard_admin_encrypted", {
homeserver: homeServerName
});
} else {
subtitle = (0, _languageHandler._t)("report_content|nature_nonstandard_admin", {
homeserver: homeServerName
});
}
break;
case Nature.Other:
subtitle = (0, _languageHandler._t)("report_content|nature_other");
break;
default:
subtitle = (0, _languageHandler._t)("report_content|nature");
break;
}
return /*#__PURE__*/_react.default.createElement(_BaseDialog.default, {
className: "mx_ReportEventDialog",
onFinished: this.props.onFinished,
title: (0, _languageHandler._t)("action|report_content"),
contentId: "mx_ReportEventDialog"
}, /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement(_StyledRadioButton.default, {
name: "nature",
value: Nature.Disagreement,
checked: this.state.nature == Nature.Disagreement,
onChange: this.onNatureChosen
}, (0, _languageHandler._t)("report_content|disagree")), /*#__PURE__*/_react.default.createElement(_StyledRadioButton.default, {
name: "nature",
value: Nature.Toxic,
checked: this.state.nature == Nature.Toxic,
onChange: this.onNatureChosen
}, (0, _languageHandler._t)("report_content|toxic_behaviour")), /*#__PURE__*/_react.default.createElement(_StyledRadioButton.default, {
name: "nature",
value: Nature.Illegal,
checked: this.state.nature == Nature.Illegal,
onChange: this.onNatureChosen
}, (0, _languageHandler._t)("report_content|illegal_content")), /*#__PURE__*/_react.default.createElement(_StyledRadioButton.default, {
name: "nature",
value: Nature.Spam,
checked: this.state.nature == Nature.Spam,
onChange: this.onNatureChosen
}, (0, _languageHandler._t)("report_content|spam_or_propaganda")), /*#__PURE__*/_react.default.createElement(_StyledRadioButton.default, {
name: "nature",
value: NonStandardValue.Admin,
checked: this.state.nature == NonStandardValue.Admin,
onChange: this.onNatureChosen
}, (0, _languageHandler._t)("report_content|report_entire_room")), /*#__PURE__*/_react.default.createElement(_StyledRadioButton.default, {
name: "nature",
value: Nature.Other,
checked: this.state.nature == Nature.Other,
onChange: this.onNatureChosen
}, (0, _languageHandler._t)("report_content|other_label")), /*#__PURE__*/_react.default.createElement("p", null, subtitle), /*#__PURE__*/_react.default.createElement(_Field.default, {
className: "mx_ReportEventDialog_reason",
element: "textarea",
label: (0, _languageHandler._t)("room_settings|permissions|ban_reason"),
rows: 5,
onChange: this.onReasonChange,
value: this.state.reason,
disabled: this.state.busy
}), progress, error, ignoreUserCheckbox), /*#__PURE__*/_react.default.createElement(_DialogButtons.default, {
primaryButton: (0, _languageHandler._t)("action|send_report"),
onPrimaryButtonClick: this.onSubmit,
focus: true,
onCancel: this.onCancel,
disabled: this.state.busy
}));
}
// Report to homeserver admin.
// Currently, the API does not support natures.
return /*#__PURE__*/_react.default.createElement(_BaseDialog.default, {
className: "mx_ReportEventDialog",
onFinished: this.props.onFinished,
title: (0, _languageHandler._t)("report_content|report_content_to_homeserver"),
contentId: "mx_ReportEventDialog"
}, /*#__PURE__*/_react.default.createElement("div", {
className: "mx_ReportEventDialog",
id: "mx_ReportEventDialog"
}, /*#__PURE__*/_react.default.createElement("p", null, (0, _languageHandler._t)("report_content|description")), adminMessage, /*#__PURE__*/_react.default.createElement(_Field.default, {
className: "mx_ReportEventDialog_reason",
element: "textarea",
label: (0, _languageHandler._t)("room_settings|permissions|ban_reason"),
rows: 5,
onChange: this.onReasonChange,
value: this.state.reason,
disabled: this.state.busy
}), progress, error, ignoreUserCheckbox), /*#__PURE__*/_react.default.createElement(_DialogButtons.default, {
primaryButton: (0, _languageHandler._t)("action|send_report"),
onPrimaryButtonClick: this.onSubmit,
focus: true,
onCancel: this.onCancel,
disabled: this.state.busy
}));
}
}
exports.default = ReportEventDialog;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfcmVhY3QiLCJfaW50ZXJvcFJlcXVpcmVEZWZhdWx0IiwicmVxdWlyZSIsIl9sb2dnZXIiLCJfbGFuZ3VhZ2VIYW5kbGVyIiwiX2NyZWF0ZVJvb20iLCJfTWF0cml4Q2xpZW50UGVnIiwiX1Nka0NvbmZpZyIsIl9NYXJrZG93biIsIl9TZXR0aW5nc1N0b3JlIiwiX1N0eWxlZFJhZGlvQnV0dG9uIiwiX0Jhc2VEaWFsb2ciLCJfRGlhbG9nQnV0dG9ucyIsIl9GaWVsZCIsIl9TcGlubmVyIiwiX0xhYmVsbGVkQ2hlY2tib3giLCJNT0RFUkFURURfQllfU1RBVEVfRVZFTlRfVFlQRSIsIkFCVVNFX0VWRU5UX1RZUEUiLCJleHBvcnRzIiwiTmF0dXJlIiwiTm9uU3RhbmRhcmRWYWx1ZSIsIlJlcG9ydEV2ZW50RGlhbG9nIiwiUmVhY3QiLCJDb21wb25lbnQiLCJjb25zdHJ1Y3RvciIsInByb3BzIiwiX2RlZmluZVByb3BlcnR5MiIsImRlZmF1bHQiLCJuZXdWYWwiLCJzZXRTdGF0ZSIsImlnbm9yZVVzZXJUb28iLCJ0YXJnZXQiLCJ2YWx1ZSIsInJlYXNvbiIsImUiLCJuYXR1cmUiLCJjdXJyZW50VGFyZ2V0Iiwib25GaW5pc2hlZCIsInN0YXRlIiwidHJpbSIsIm1vZGVyYXRpb24iLCJPdGhlciIsIkFkbWluIiwiZXJyIiwiX3QiLCJidXN5IiwidW5kZWZpbmVkIiwiY2xpZW50IiwiTWF0cml4Q2xpZW50UGVnIiwic2FmZUdldCIsImV2IiwibXhFdmVudCIsImRtUm9vbUlkIiwiZW5zdXJlRE1FeGlzdHMiLCJtb2RlcmF0aW9uQm90VXNlcklkIiwiVXNlckZyaWVuZGx5RXJyb3IiLCJzZW5kRXZlbnQiLCJldmVudF9pZCIsImdldElkIiwicm9vbV9pZCIsImdldFJvb21JZCIsIm1vZGVyYXRlZF9ieV9pZCIsIm1vZGVyYXRpb25Sb29tSWQiLCJyZXBvcnRlciIsImdldFVzZXJJZCIsImNvbW1lbnQiLCJyZXBvcnRFdmVudCIsInNldElnbm9yZWRVc2VycyIsImdldElnbm9yZWRVc2VycyIsImdldFNlbmRlciIsImxvZ2dlciIsImVycm9yIiwiRXJyb3IiLCJtZXNzYWdlIiwiU3RyaW5nIiwibW9kZXJhdGVkQnlSb29tSWQiLCJtb2RlcmF0ZWRCeVVzZXJJZCIsIlNldHRpbmdzU3RvcmUiLCJnZXRWYWx1ZSIsInJvb20iLCJnZXRSb29tIiwic3RhdGVFdmVudFR5cGUiLCJzdGF0ZUV2ZW50IiwiY3VycmVudFN0YXRlIiwiZ2V0U3RhdGVFdmVudHMiLCJBcnJheSIsImlzQXJyYXkiLCJUeXBlRXJyb3IiLCJldmVudCIsImNvbnNvbGUiLCJkZWJ1ZyIsImNvbnRlbnQiLCJyZW5kZXIiLCJjcmVhdGVFbGVtZW50IiwiY2xhc3NOYW1lIiwicHJvZ3Jlc3MiLCJpZ25vcmVVc2VyQ2hlY2tib3giLCJsYWJlbCIsImJ5bGluZSIsIm9uQ2hhbmdlIiwib25JZ25vcmVVc2VyVG9vQ2hhbmdlZCIsImRpc2FibGVkIiwiYWRtaW5NZXNzYWdlTUQiLCJTZGtDb25maWciLCJnZXRPYmplY3QiLCJnZXQiLCJhZG1pbk1lc3NhZ2UiLCJodG1sIiwiTWFya2Rvd24iLCJ0b0hUTUwiLCJleHRlcm5hbExpbmtzIiwiZGFuZ2Vyb3VzbHlTZXRJbm5lckhUTUwiLCJfX2h0bWwiLCJob21lU2VydmVyTmFtZSIsImhzTmFtZSIsInN1YnRpdGxlIiwiRGlzYWdyZWVtZW50IiwiVG94aWMiLCJJbGxlZ2FsIiwiU3BhbSIsImlzUm9vbUVuY3J5cHRlZCIsImhvbWVzZXJ2ZXIiLCJ0aXRsZSIsImNvbnRlbnRJZCIsIm5hbWUiLCJjaGVja2VkIiwib25OYXR1cmVDaG9zZW4iLCJlbGVtZW50Iiwicm93cyIsIm9uUmVhc29uQ2hhbmdlIiwicHJpbWFyeUJ1dHRvbiIsIm9uUHJpbWFyeUJ1dHRvbkNsaWNrIiwib25TdWJtaXQiLCJmb2N1cyIsIm9uQ2FuY2VsIiwiaWQiXSwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvY29tcG9uZW50cy92aWV3cy9kaWFsb2dzL1JlcG9ydEV2ZW50RGlhbG9nLnRzeCJdLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuQ29weXJpZ2h0IDIwMjQgTmV3IFZlY3RvciBMdGQuXG5Db3B5cmlnaHQgMjAyMiBUaGUgTWF0cml4Lm9yZyBGb3VuZGF0aW9uIEMuSS5DLlxuQ29weXJpZ2h0IDIwMTkgTWljaGFlbCBUZWxhdHluc2tpIDw3dDNjaGd1eUBnbWFpbC5jb20+XG5cblNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBR1BMLTMuMC1vbmx5IE9SIEdQTC0zLjAtb25seVxuUGxlYXNlIHNlZSBMSUNFTlNFIGZpbGVzIGluIHRoZSByZXBvc2l0b3J5IHJvb3QgZm9yIGZ1bGwgZGV0YWlscy5cbiovXG5cbmltcG9ydCBSZWFjdCwgeyBDaGFuZ2VFdmVudCB9IGZyb20gXCJyZWFjdFwiO1xuaW1wb3J0IHsgTWF0cml4RXZlbnQgfSBmcm9tIFwibWF0cml4LWpzLXNkay9zcmMvbWF0cml4XCI7XG5pbXBvcnQgeyBsb2dnZXIgfSBmcm9tIFwibWF0cml4LWpzLXNkay9zcmMvbG9nZ2VyXCI7XG5cbmltcG9ydCB7IF90LCBVc2VyRnJpZW5kbHlFcnJvciB9IGZyb20gXCIuLi8uLi8uLi9sYW5ndWFnZUhhbmRsZXJcIjtcbmltcG9ydCB7IGVuc3VyZURNRXhpc3RzIH0gZnJvbSBcIi4uLy4uLy4uL2NyZWF0ZVJvb21cIjtcbmltcG9ydCB7IE1hdHJpeENsaWVudFBlZyB9IGZyb20gXCIuLi8uLi8uLi9NYXRyaXhDbGllbnRQZWdcIjtcbmltcG9ydCBTZGtDb25maWcgZnJvbSBcIi4uLy4uLy4uL1Nka0NvbmZpZ1wiO1xuaW1wb3J0IE1hcmtkb3duIGZyb20gXCIuLi8uLi8uLi9NYXJrZG93blwiO1xuaW1wb3J0IFNldHRpbmdzU3RvcmUgZnJvbSBcIi4uLy4uLy4uL3NldHRpbmdzL1NldHRpbmdzU3RvcmVcIjtcbmltcG9ydCBTdHlsZWRSYWRpb0J1dHRvbiBmcm9tIFwiLi4vZWxlbWVudHMvU3R5bGVkUmFkaW9CdXR0b25cIjtcbmltcG9ydCBCYXNlRGlhbG9nIGZyb20gXCIuL0Jhc2VEaWFsb2dcIjtcbmltcG9ydCBEaWFsb2dCdXR0b25zIGZyb20gXCIuLi9lbGVtZW50cy9EaWFsb2dCdXR0b25zXCI7XG5pbXBvcnQgRmllbGQgZnJvbSBcIi4uL2VsZW1lbnRzL0ZpZWxkXCI7XG5pbXBvcnQgU3Bpbm5lciBmcm9tIFwiLi4vZWxlbWVudHMvU3Bpbm5lclwiO1xuaW1wb3J0IExhYmVsbGVkQ2hlY2tib3ggZnJvbSBcIi4uL2VsZW1lbnRzL0xhYmVsbGVkQ2hlY2tib3hcIjtcblxuZGVjbGFyZSBtb2R1bGUgXCJtYXRyaXgtanMtc2RrL3NyYy90eXBlc1wiIHtcbiAgICBpbnRlcmZhY2UgVGltZWxpbmVFdmVudHMge1xuICAgICAgICBbQUJVU0VfRVZFTlRfVFlQRV06IEFidXNlRXZlbnRDb250ZW50O1xuICAgIH1cbn1cblxuaW50ZXJmYWNlIElQcm9wcyB7XG4gICAgbXhFdmVudDogTWF0cml4RXZlbnQ7XG4gICAgb25GaW5pc2hlZChyZXBvcnQ/OiBib29sZWFuKTogdm9pZDtcbn1cblxuaW50ZXJmYWNlIElTdGF0ZSB7XG4gICAgLy8gQSBmcmVlLWZvcm0gdGV4dCBkZXNjcmliaW5nIHRoZSBhYnVzZS5cbiAgICByZWFzb246IHN0cmluZztcbiAgICBidXN5OiBib29sZWFuO1xuICAgIGVycj86IHN0cmluZztcbiAgICAvLyBJZiB3ZSBrbm93IGl0LCB0aGUgbmF0dXJlIG9mIHRoZSBhYnVzZSwgYXMgc3BlY2lmaWVkIGJ5IE1TQzMyMTUuXG4gICAgbmF0dXJlPzogRXh0ZW5kZWROYXR1cmU7XG4gICAgaWdub3JlVXNlclRvbzogYm9vbGVhbjsgLy8gaWYgdHJ1ZSwgdXNlciB3aWxsIGJlIGlnbm9yZWQvYmxvY2tlZCBvbiBzdWJtaXRcbn1cblxuY29uc3QgTU9ERVJBVEVEX0JZX1NUQVRFX0VWRU5UX1RZUEUgPSBbXG4gICAgXCJvcmcubWF0cml4Lm1zYzMyMTUucm9vbS5tb2RlcmF0aW9uLm1vZGVyYXRlZF9ieVwiLFxuICAgIC8qKlxuICAgICAqIFVucHJlZml4ZWQgc3RhdGUgZXZlbnQuIE5vdCByZWFkeSBmb3IgcHJpbWUgdGltZS5cbiAgICAgKlxuICAgICAqIFwibS5yb29tLm1vZGVyYXRpb24ubW9kZXJhdGVkX2J5XCJcbiAgICAgKi9cbl07XG5cbmV4cG9ydCBjb25zdCBBQlVTRV9FVkVOVF9UWVBFID0gXCJvcmcubWF0cml4Lm1zYzMyMTUuYWJ1c2UucmVwb3J0XCI7XG5cbmludGVyZmFjZSBBYnVzZUV2ZW50Q29udGVudCB7XG4gICAgZXZlbnRfaWQ6IHN0cmluZztcbiAgICByb29tX2lkOiBzdHJpbmc7XG4gICAgbW9kZXJhdGVkX2J5X2lkOiBzdHJpbmc7XG4gICAgbmF0dXJlPzogRXh0ZW5kZWROYXR1cmU7XG4gICAgcmVwb3J0ZXI6IHN0cmluZztcbiAgICBjb21tZW50OiBzdHJpbmc7XG59XG5cbi8vIFN0YW5kYXJkIGFidXNlIG5hdHVyZXMuXG5lbnVtIE5hdHVyZSB7XG4gICAgRGlzYWdyZWVtZW50ID0gXCJvcmcubWF0cml4Lm1zYzMyMTUuYWJ1c2UubmF0dXJlLmRpc2FncmVlbWVudFwiLFxuICAgIFRveGljID0gXCJvcmcubWF0cml4Lm1zYzMyMTUuYWJ1c2UubmF0dXJlLnRveGljXCIsXG4gICAgSWxsZWdhbCA9IFwib3JnLm1hdHJpeC5tc2MzMjE1LmFidXNlLm5hdHVyZS5pbGxlZ2FsXCIsXG4gICAgU3BhbSA9IFwib3JnLm1hdHJpeC5tc2MzMjE1LmFidXNlLm5hdHVyZS5zcGFtXCIsXG4gICAgT3RoZXIgPSBcIm9yZy5tYXRyaXgubXNjMzIxNS5hYnVzZS5uYXR1cmUub3RoZXJcIixcbn1cblxuZW51bSBOb25TdGFuZGFyZFZhbHVlIHtcbiAgICAvLyBOb24tc3RhbmRhcmQgYWJ1c2UgbmF0dXJlLlxuICAgIC8vIEl0IHNob3VsZCBuZXZlciBsZWF2ZSB0aGUgY2xpZW50IC0gd2UgdXNlIGl0IHRvIGZhbGxiYWNrIHRvXG4gICAgLy8gc2VydmVyLXdpZGUgYWJ1c2UgcmVwb3J0aW5nLlxuICAgIEFkbWluID0gXCJub24tc3RhbmRhcmQuYWJ1c2UubmF0dXJlLmFkbWluXCIsXG59XG5cbnR5cGUgRXh0ZW5kZWROYXR1cmUgPSBOYXR1cmUgfCBOb25TdGFuZGFyZFZhbHVlO1xuXG50eXBlIE1vZGVyYXRpb24gPSB7XG4gICAgLy8gVGhlIGlkIG9mIHRoZSBtb2RlcmF0aW9uIHJvb20uXG4gICAgbW9kZXJhdGlvblJvb21JZDogc3RyaW5nO1xuICAgIC8vIFRoZSBpZCBvZiB0aGUgYm90IGluIGNoYXJnZSBvZiBmb3J3YXJkaW5nIGFidXNlIHJlcG9ydHMgdG8gdGhlIG1vZGVyYXRpb24gcm9vbS5cbiAgICBtb2RlcmF0aW9uQm90VXNlcklkOiBzdHJpbmc7XG59O1xuLypcbiAqIEEgZGlhbG9nIGZvciByZXBvcnRpbmcgYW4gZXZlbnQuXG4gKlxuICogVGhlIGFjdHVhbCBjb250ZW50IG9mIHRoZSBkaWFsb2cgd2lsbCBkZXBlbmQgb24gdHdvIHRoaW5nczpcbiAqXG4gKiAxLiBJcyBgZmVhdHVyZV9yZXBvcnRfdG9fbW9kZXJhdG9yc2AgZW5hYmxlZD9cbiAqIDIuIERvZXMgdGhlIHJvb20gc3VwcG9ydCBtb2RlcmF0aW9uIGFzIHBlciBNU0MzMjE1LCBpLmUuIGlzIHRoZXJlXG4gKiAgICBhIHdlbGwtZm9ybWVkIHN0YXRlIGV2ZW50IGBtLnJvb20ubW9kZXJhdGlvbi5tb2RlcmF0ZWRfYnlgXG4gKiAgICAvYG9yZy5tYXRyaXgubXNjMzIxNS5yb29tLm1vZGVyYXRpb24ubW9kZXJhdGVkX2J5YD9cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgUmVwb3J0RXZlbnREaWFsb2cgZXh0ZW5kcyBSZWFjdC5Db21wb25lbnQ8SVByb3BzLCBJU3RhdGU+IHtcbiAgICAvLyBJZiB0aGUgcm9vbSBzdXBwb3J0cyBtb2RlcmF0aW9uLCB0aGUgbW9kZXJhdGlvbiBpbmZvcm1hdGlvbi5cbiAgICBwcml2YXRlIG1vZGVyYXRpb24/OiBNb2RlcmF0aW9uO1xuXG4gICAgcHVibGljIGNvbnN0cnVjdG9yKHByb3BzOiBJUHJvcHMpIHtcbiAgICAgICAgc3VwZXIocHJvcHMpO1xuXG4gICAgICAgIGxldCBtb2RlcmF0ZWRCeVJvb21JZDogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG4gICAgICAgIGxldCBtb2RlcmF0ZWRCeVVzZXJJZDogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG5cbiAgICAgICAgaWYgKFNldHRpbmdzU3RvcmUuZ2V0VmFsdWUoXCJmZWF0dXJlX3JlcG9ydF90b19tb2RlcmF0b3JzXCIpKSB7XG4gICAgICAgICAgICAvLyBUaGUgY2xpZW50IHN1cHBvcnRzIHJlcG9ydGluZyB0byBtb2RlcmF0b3JzLlxuICAgICAgICAgICAgLy8gRG9lcyB0aGUgcm9vbSBzdXBwb3J0IGl0LCB0b28/XG5cbiAgICAgICAgICAgIC8vIEV4dHJhY3Qgc3RhdGUgZXZlbnRzIHRvIGRldGVybWluZSB3aGV0aGVyIHdlIHNob3VsZCBkaXNwbGF5XG4gICAgICAgICAgICBjb25zdCBjbGllbnQgPSBNYXRyaXhDbGllbnRQZWcuc2FmZUdldCgpO1xuICAgICAgICAgICAgY29uc3Qgcm9vbSA9IGNsaWVudC5nZXRSb29tKHByb3BzLm14RXZlbnQuZ2V0Um9vbUlkKCkpO1xuXG4gICAgICAgICAgICBmb3IgKGNvbnN0IHN0YXRlRXZlbnRUeXBlIG9mIE1PREVSQVRFRF9CWV9TVEFURV9FVkVOVF9UWVBFKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3RhdGVFdmVudCA9IHJvb20/LmN1cnJlbnRTdGF0ZS5nZXRTdGF0ZUV2ZW50cyhzdGF0ZUV2ZW50VHlwZSwgc3RhdGVFdmVudFR5cGUpO1xuICAgICAgICAgICAgICAgIGlmICghc3RhdGVFdmVudCkge1xuICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkoc3RhdGVFdmVudCkpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gSW50ZXJuYWwgZXJyb3IuXG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXG4gICAgICAgICAgICAgICAgICAgICAgICBgZ2V0U3RhdGVFdmVudHMoJHtzdGF0ZUV2ZW50VHlwZX0sICR7c3RhdGVFdmVudFR5cGV9KSBgICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcInNob3VsZCByZXR1cm4gYXQgbW9zdCBvbmUgc3RhdGUgZXZlbnRcIixcbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY29uc3QgZXZlbnQgPSBzdGF0ZUV2ZW50LmV2ZW50O1xuICAgICAgICAgICAgICAgIGlmICghKFwiY29udGVudFwiIGluIGV2ZW50KSB8fCB0eXBlb2YgZXZlbnRbXCJjb250ZW50XCJdICE9IFwib2JqZWN0XCIpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gVGhlIHJvb20gaXMgaW1wcm9wZXJseSBjb25maWd1cmVkLlxuICAgICAgICAgICAgICAgICAgICAvLyBEaXNwbGF5IHRoaXMgZGVidWcgbWVzc2FnZSBmb3IgdGhlIHNha2Ugb2YgbW9kZXJhdG9ycy5cbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5kZWJ1ZyhcbiAgICAgICAgICAgICAgICAgICAgICAgIFwiTW9kZXJhdGlvbiBlcnJvclwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgXCJzdGF0ZSBldmVudFwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgc3RhdGVFdmVudFR5cGUsXG4gICAgICAgICAgICAgICAgICAgICAgICBcInNob3VsZCBoYXZlIGFuIG9iamVjdCBmaWVsZCBgY29udGVudGAsIGdvdFwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnQsXG4gICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjb25zdCBjb250ZW50ID0gZXZlbnRbXCJjb250ZW50XCJdO1xuICAgICAgICAgICAgICAgIGlmICghKFwicm9vbV9pZFwiIGluIGNvbnRlbnQpIHx8IHR5cGVvZiBjb250ZW50W1wicm9vbV9pZFwiXSAhPSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFRoZSByb29tIGlzIGltcHJvcGVybHkgY29uZmlndXJlZC5cbiAgICAgICAgICAgICAgICAgICAgLy8gRGlzcGxheSB0aGlzIGRlYnVnIG1lc3NhZ2UgZm9yIHRoZSBzYWtlIG9mIG1vZGVyYXRvcnMuXG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZGVidWcoXG4gICAgICAgICAgICAgICAgICAgICAgICBcIk1vZGVyYXRpb24gZXJyb3JcIixcbiAgICAgICAgICAgICAgICAgICAgICAgIFwic3RhdGUgZXZlbnRcIixcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRlRXZlbnRUeXBlLFxuICAgICAgICAgICAgICAgICAgICAgICAgXCJzaG91bGQgaGF2ZSBhIHN0cmluZyBmaWVsZCBgY29udGVudC5yb29tX2lkYCwgZ290XCIsXG4gICAgICAgICAgICAgICAgICAgICAgICBldmVudCxcbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICghKFwidXNlcl9pZFwiIGluIGNvbnRlbnQpIHx8IHR5cGVvZiBjb250ZW50W1widXNlcl9pZFwiXSAhPSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFRoZSByb29tIGlzIGltcHJvcGVybHkgY29uZmlndXJlZC5cbiAgICAgICAgICAgICAgICAgICAgLy8gRGlzcGxheSB0aGlzIGRlYnVnIG1lc3NhZ2UgZm9yIHRoZSBzYWtlIG9mIG1vZGVyYXRvcnMuXG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZGVidWcoXG4gICAgICAgICAgICAgICAgICAgICAgICBcIk1vZGVyYXRpb24gZXJyb3JcIixcbiAgICAgICAgICAgICAgICAgICAgICAgIFwic3RhdGUgZXZlbnRcIixcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRlRXZlbnRUeXBlLFxuICAgICAgICAgICAgICAgICAgICAgICAgXCJzaG91bGQgaGF2ZSBhIHN0cmluZyBmaWVsZCBgY29udGVudC51c2VyX2lkYCwgZ290XCIsXG4gICAgICAgICAgICAgICAgICAgICAgICBldmVudCxcbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIG1vZGVyYXRlZEJ5Um9vbUlkID0gY29udGVudFtcInJvb21faWRcIl07XG4gICAgICAgICAgICAgICAgbW9kZXJhdGVkQnlVc2VySWQgPSBjb250ZW50W1widXNlcl9pZFwiXTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKG1vZGVyYXRlZEJ5Um9vbUlkICYmIG1vZGVyYXRlZEJ5VXNlcklkKSB7XG4gICAgICAgICAgICAgICAgLy8gVGhlIHJvb20gc3VwcG9ydHMgbW9kZXJhdGlvbi5cbiAgICAgICAgICAgICAgICB0aGlzLm1vZGVyYXRpb24gPSB7XG4gICAgICAgICAgICAgICAgICAgIG1vZGVyYXRpb25Sb29tSWQ6IG1vZGVyYXRlZEJ5Um9vbUlkLFxuICAgICAgICAgICAgICAgICAgICBtb2RlcmF0aW9uQm90VXNlcklkOiBtb2RlcmF0ZWRCeVVzZXJJZCxcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5zdGF0ZSA9IHtcbiAgICAgICAgICAgIC8vIEEgZnJlZS1mb3JtIHRleHQgZGVzY3JpYmluZyB0aGUgYWJ1c2UuXG4gICAgICAgICAgICByZWFzb246IFwiXCIsXG4gICAgICAgICAgICBidXN5OiBmYWxzZSxcbiAgICAgICAgICAgIGVycjogdW5kZWZpbmVkLFxuICAgICAgICAgICAgLy8gSWYgc3BlY2lmaWVkLCB0aGUgbmF0dXJlIG9mIHRoZSBhYnVzZSwgYXMgc3BlY2lmaWVkIGJ5IE1TQzMyMTUuXG4gICAgICAgICAgICBuYXR1cmU6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIGlnbm9yZVVzZXJUb286IGZhbHNlLCAvLyBkZWZhdWx0IGZhbHNlLCBmb3Igbm93LiBDb3VsZCBlYXNpbHkgYmUgYXJndWVkIGFzIGRlZmF1bHQgdHJ1ZVxuICAgICAgICB9O1xuICAgIH1cblxuICAgIHByaXZhdGUgb25JZ25vcmVVc2VyVG9vQ2hhbmdlZCA9IChuZXdWYWw6IGJvb2xlYW4pOiB2b2lkID0+IHtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7IGlnbm9yZVVzZXJUb286IG5ld1ZhbCB9KTtcbiAgICB9O1xuXG4gICAgLy8gVGhlIHVzZXIgaGFzIHdyaXR0ZW4gZG93biBhIGZyZWVmb3JtIGRlc2NyaXB0aW9uIG9mIHRoZSBhYnVzZS5cbiAgICBwcml2YXRlIG9uUmVhc29uQ2hhbmdlID0gKHsgdGFyZ2V0OiB7IHZhbHVlOiByZWFzb24gfSB9OiBDaGFuZ2VFdmVudDxIVE1MVGV4dEFyZWFFbGVtZW50Pik6IHZvaWQgPT4ge1xuICAgICAgICB0aGlzLnNldFN0YXRlKHsgcmVhc29uIH0pO1xuICAgIH07XG5cbiAgICAvLyBUaGUgdXNlciBoYXMgY2xpY2tlZCBvbiBhIG5hdHVyZS5cbiAgICBwcml2YXRlIG9uTmF0dXJlQ2hvc2VuID0gKGU6IFJlYWN0LkZvcm1FdmVudDxIVE1MSW5wdXRFbGVtZW50Pik6IHZvaWQgPT4ge1xuICAgICAgICB0aGlzLnNldFN0YXRlKHsgbmF0dXJlOiBlLmN1cnJlbnRUYXJnZXQudmFsdWUgYXMgRXh0ZW5kZWROYXR1cmUgfSk7XG4gICAgfTtcblxuICAgIC8vIFRoZSB1c2VyIGhhcyBjbGlja2VkIFwiY2FuY2VsXCIuXG4gICAgcHJpdmF0ZSBvbkNhbmNlbCA9ICgpOiB2b2lkID0+IHtcbiAgICAgICAgdGhpcy5wcm9wcy5vbkZpbmlzaGVkKGZhbHNlKTtcbiAgICB9O1xuXG4gICAgLy8gVGhlIHVzZXIgaGFzIGNsaWNrZWQgXCJzdWJtaXRcIi5cbiAgICBwcml2YXRlIG9uU3VibWl0ID0gYXN5bmMgKCk6IFByb21pc2U8dm9pZD4gPT4ge1xuICAgICAgICBsZXQgcmVhc29uID0gdGhpcy5zdGF0ZS5yZWFzb24gfHwgXCJcIjtcbiAgICAgICAgcmVhc29uID0gcmVhc29uLnRyaW0oKTtcbiAgICAgICAgaWYgKHRoaXMubW9kZXJhdGlvbikge1xuICAgICAgICAgICAgLy8gVGhpcyByb29tIHN1cHBvcnRzIG1vZGVyYXRpb24uXG4gICAgICAgICAgICAvLyBXZSBuZWVkIGEgbmF0dXJlLlxuICAgICAgICAgICAgLy8gSWYgdGhlIG5hdHVyZSBpcyBgTkFUVVJFLk9USEVSYCBvciBgTk9OX1NUQU5EQVJEX05BVFVSRS5BRE1JTmAsIHdlIGFsc28gbmVlZCBhIGByZWFzb25gLlxuICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgICF0aGlzLnN0YXRlLm5hdHVyZSB8fFxuICAgICAgICAgICAgICAgICgodGhpcy5zdGF0ZS5uYXR1cmUgPT0gTmF0dXJlLk90aGVyIHx8IHRoaXMuc3RhdGUubmF0dXJlID09IE5vblN0YW5kYXJkVmFsdWUuQWRtaW4pICYmICFyZWFzb24pXG4gICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgICAgICAgICAgZXJyOiBfdChcInJlcG9ydF9jb250ZW50fG1pc3NpbmdfcmVhc29uXCIpLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIFRoaXMgcm9vbSBkb2VzIG5vdCBzdXBwb3J0IG1vZGVyYXRpb24uXG4gICAgICAgICAgICAvLyBXZSBuZWVkIGEgYHJlYXNvbmAuXG4gICAgICAgICAgICBpZiAoIXJlYXNvbikge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgICAgICAgICBlcnI6IF90KFwicmVwb3J0X2NvbnRlbnR8bWlzc2luZ19yZWFzb25cIiksXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICBidXN5OiB0cnVlLFxuICAgICAgICAgICAgZXJyOiB1bmRlZmluZWQsXG4gICAgICAgIH0pO1xuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCBjbGllbnQgPSBNYXRyaXhDbGllbnRQZWcuc2FmZUdldCgpO1xuICAgICAgICAgICAgY29uc3QgZXYgPSB0aGlzLnByb3BzLm14RXZlbnQ7XG4gICAgICAgICAgICBpZiAodGhpcy5tb2RlcmF0aW9uICYmIHRoaXMuc3RhdGUubmF0dXJlICE9PSBOb25TdGFuZGFyZFZhbHVlLkFkbWluKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgbmF0dXJlID0gdGhpcy5zdGF0ZS5uYXR1cmU7XG5cbiAgICAgICAgICAgICAgICAvLyBSZXBvcnQgdG8gbW9kZXJhdG9ycyB0aHJvdWdoIHRvIHRoZSBkZWRpY2F0ZWQgYm90LFxuICAgICAgICAgICAgICAgIC8vIGFzIGNvbmZpZ3VyZWQgaW4gdGhlIHJvb20ncyBzdGF0ZSBldmVudHMuXG4gICAgICAgICAgICAgICAgY29uc3QgZG1Sb29tSWQgPSBhd2FpdCBlbnN1cmVETUV4aXN0cyhjbGllbnQsIHRoaXMubW9kZXJhdGlvbi5tb2RlcmF0aW9uQm90VXNlcklkKTtcbiAgICAgICAgICAgICAgICBpZiAoIWRtUm9vbUlkKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBVc2VyRnJpZW5kbHlFcnJvcihcInJlcG9ydF9jb250ZW50fGVycm9yX2NyZWF0ZV9yb29tX21vZGVyYXRpb25fYm90XCIpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGF3YWl0IGNsaWVudC5zZW5kRXZlbnQoZG1Sb29tSWQsIEFCVVNFX0VWRU5UX1RZUEUsIHtcbiAgICAgICAgICAgICAgICAgICAgZXZlbnRfaWQ6IGV2LmdldElkKCkhLFxuICAgICAgICAgICAgICAgICAgICByb29tX2lkOiBldi5nZXRSb29tSWQoKSEsXG4gICAgICAgICAgICAgICAgICAgIG1vZGVyYXRlZF9ieV9pZDogdGhpcy5tb2RlcmF0aW9uLm1vZGVyYXRpb25Sb29tSWQsXG4gICAgICAgICAgICAgICAgICAgIG5hdHVyZSxcbiAgICAgICAgICAgICAgICAgICAgcmVwb3J0ZXI6IGNsaWVudC5nZXRVc2VySWQoKSEsXG4gICAgICAgICAgICAgICAgICAgIGNvbW1lbnQ6IHRoaXMuc3RhdGUucmVhc29uLnRyaW0oKSxcbiAgICAgICAgICAgICAgICB9IHNhdGlzZmllcyBBYnVzZUV2ZW50Q29udGVudCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIFJlcG9ydCB0byBob21lc2VydmVyIGFkbWluIHRocm91Z2ggdGhlIGRlZGljYXRlZCBNYXRyaXggQVBJLlxuICAgICAgICAgICAgICAgIGF3YWl0IGNsaWVudC5yZXBvcnRFdmVudChldi5nZXRSb29tSWQoKSEsIGV2LmdldElkKCkhLCAtMTAwLCB0aGlzLnN0YXRlLnJlYXNvbi50cmltKCkpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBpZiB0aGUgdXNlciBzaG91bGQgYWxzbyBiZSBpZ25vcmVkLCBkbyB0aGF0XG4gICAgICAgICAgICBpZiAodGhpcy5zdGF0ZS5pZ25vcmVVc2VyVG9vKSB7XG4gICAgICAgICAgICAgICAgYXdhaXQgY2xpZW50LnNldElnbm9yZWRVc2VycyhbLi4uY2xpZW50LmdldElnbm9yZWRVc2VycygpLCBldi5nZXRTZW5kZXIoKSFdKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5wcm9wcy5vbkZpbmlzaGVkKHRydWUpO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICBsb2dnZXIuZXJyb3IoZSk7XG4gICAgICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgICAgICBidXN5OiBmYWxzZSxcbiAgICAgICAgICAgICAgICBlcnI6IGUgaW5zdGFuY2VvZiBFcnJvciA/IGUubWVzc2FnZSA6IFN0cmluZyhlKSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIHB1YmxpYyByZW5kZXIoKTogUmVhY3QuUmVhY3ROb2RlIHtcbiAgICAgICAgbGV0IGVycm9yOiBKU1guRWxlbWVudCB8IHVuZGVmaW5lZDtcbiAgICAgICAgaWYgKHRoaXMuc3RhdGUuZXJyKSB7XG4gICAgICAgICAgICBlcnJvciA9IDxkaXYgY2xhc3NOYW1lPVwiZXJyb3JcIj57dGhpcy5zdGF0ZS5lcnJ9PC9kaXY+O1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHByb2dyZXNzOiBKU1guRWxlbWVudCB8IHVuZGVmaW5lZDtcbiAgICAgICAgaWYgKHRoaXMuc3RhdGUuYnVzeSkge1xuICAgICAgICAgICAgcHJvZ3Jlc3MgPSAoXG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJwcm9ncmVzc1wiPlxuICAgICAgICAgICAgICAgICAgICA8U3Bpbm5lciAvPlxuICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGlnbm9yZVVzZXJDaGVja2JveCA9IChcbiAgICAgICAgICAgIDxMYWJlbGxlZENoZWNrYm94XG4gICAgICAgICAgICAgICAgdmFsdWU9e3RoaXMuc3RhdGUuaWdub3JlVXNlclRvb31cbiAgICAgICAgICAgICAgICBsYWJlbD17X3QoXCJyZXBvcnRfY29udGVudHxpZ25vcmVfdXNlclwiKX1cbiAgICAgICAgICAgICAgICBieWxpbmU9e190KFwicmVwb3J0X2NvbnRlbnR8aGlkZV9tZXNzYWdlc19mcm9tX3VzZXJcIil9XG4gICAgICAgICAgICAgICAgb25DaGFuZ2U9e3RoaXMub25JZ25vcmVVc2VyVG9vQ2hhbmdlZH1cbiAgICAgICAgICAgICAgICBkaXNhYmxlZD17dGhpcy5zdGF0ZS5idXN5fVxuICAgICAgICAgICAgLz5cbiAgICAgICAgKTtcblxuICAgICAgICBjb25zdCBhZG1pbk1lc3NhZ2VNRCA9IFNka0NvbmZpZy5nZXRPYmplY3QoXCJyZXBvcnRfZXZlbnRcIik/LmdldChcImFkbWluX21lc3NhZ2VfbWRcIiwgXCJhZG1pbk1lc3NhZ2VNRFwiKTtcbiAgICAgICAgbGV0IGFkbWluTWVzc2FnZTogSlNYLkVsZW1lbnQgfCB1bmRlZmluZWQ7XG4gICAgICAgIGlmIChhZG1pbk1lc3NhZ2VNRCkge1xuICAgICAgICAgICAgY29uc3QgaHRtbCA9IG5ldyBNYXJrZG93bihhZG1pbk1lc3NhZ2VNRCkudG9IVE1MKHsgZXh0ZXJuYWxMaW5rczogdHJ1ZSB9KTtcbiAgICAgICAgICAgIGFkbWluTWVzc2FnZSA9IDxwIGRhbmdlcm91c2x5U2V0SW5uZXJIVE1MPXt7IF9faHRtbDogaHRtbCB9fSAvPjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLm1vZGVyYXRpb24pIHtcbiAgICAgICAgICAgIC8vIERpc3BsYXkgcmVwb3J0LXRvLW1vZGVyYXRvciBkaWFsb2cuXG4gICAgICAgICAgICAvLyBXZSBsZXQgdGhlIHVzZXIgcGljayBhIG5hdHVyZS5cbiAgICAgICAgICAgIGNvbnN0IGNsaWVudCA9IE1hdHJpeENsaWVudFBlZy5zYWZlR2V0KCk7XG4gICAgICAgICAgICBjb25zdCBob21lU2VydmVyTmFtZSA9IFNka0NvbmZpZy5nZXQoXCJ2YWxpZGF0ZWRfc2VydmVyX2NvbmZpZ1wiKSEuaHNOYW1lO1xuICAgICAgICAgICAgbGV0IHN1YnRpdGxlOiBzdHJpbmc7XG4gICAgICAgICAgICBzd2l0Y2ggKHRoaXMuc3RhdGUubmF0dXJlKSB7XG4gICAgICAgICAgICAgICAgY2FzZSBOYXR1cmUuRGlzYWdyZWVtZW50OlxuICAgICAgICAgICAgICAgICAgICBzdWJ0aXRsZSA9IF90KFwicmVwb3J0X2NvbnRlbnR8bmF0dXJlX2Rpc2FncmVlbWVudFwiKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSBOYXR1cmUuVG94aWM6XG4gICAgICAgICAgICAgICAgICAgIHN1YnRpdGxlID0gX3QoXCJyZXBvcnRfY29udGVudHxuYXR1cmVfdG94aWNcIik7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgTmF0dXJlLklsbGVnYWw6XG4gICAgICAgICAgICAgICAgICAgIHN1YnRpdGxlID0gX3QoXCJyZXBvcnRfY29udGVudHxuYXR1cmVfaWxsZWdhbFwiKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSBOYXR1cmUuU3BhbTpcbiAgICAgICAgICAgICAgICAgICAgc3VidGl0bGUgPSBfdChcInJlcG9ydF9jb250ZW50fG5hdHVyZV9zcGFtXCIpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIE5vblN0YW5kYXJkVmFsdWUuQWRtaW46XG4gICAgICAgICAgICAgICAgICAgIGlmIChjbGllbnQuaXNSb29tRW5jcnlwdGVkKHRoaXMucHJvcHMubXhFdmVudC5nZXRSb29tSWQoKSEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzdWJ0aXRsZSA9IF90KFwicmVwb3J0X2NvbnRlbnR8bmF0dXJlX25vbnN0YW5kYXJkX2FkbWluX2VuY3J5cHRlZFwiLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaG9tZXNlcnZlcjogaG9tZVNlcnZlck5hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHN1YnRpdGxlID0gX3QoXCJyZXBvcnRfY29udGVudHxuYXR1cmVfbm9uc3RhbmRhcmRfYWRtaW5cIiwgeyBob21lc2VydmVyOiBob21lU2VydmVyTmFtZSB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIE5hdHVyZS5PdGhlcjpcbiAgICAgICAgICAgICAgICAgICAgc3VidGl0bGUgPSBfdChcInJlcG9ydF9jb250ZW50fG5hdHVyZV9vdGhlclwiKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgc3VidGl0bGUgPSBfdChcInJlcG9ydF9jb250ZW50fG5hdHVyZVwiKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAgICAgPEJhc2VEaWFsb2dcbiAgICAgICAgICAgICAgICAgICAgY2xhc3NOYW1lPVwibXhfUmVwb3J0RXZlbnREaWFsb2dcIlxuICAgICAgICAgICAgICAgICAgICBvbkZpbmlzaGVkPXt0aGlzLnByb3BzLm9uRmluaXNoZWR9XG4gICAgICAgICAgICAgICAgICAgIHRpdGxlPXtfdChcImFjdGlvbnxyZXBvcnRfY29udGVudFwiKX1cbiAgICAgICAgICAgICAgICAgICAgY29udGVudElkPVwibXhfUmVwb3J0RXZlbnREaWFsb2dcIlxuICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAgPGRpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxTdHlsZWRSYWRpb0J1dHRvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWU9XCJuYXR1cmVcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlPXtOYXR1cmUuRGlzYWdyZWVtZW50fVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoZWNrZWQ9e3RoaXMuc3RhdGUubmF0dXJlID09IE5hdHVyZS5EaXNhZ3JlZW1lbnR9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb25DaGFuZ2U9e3RoaXMub25OYXR1cmVDaG9zZW59XG4gICAgICAgICAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAge190KFwicmVwb3J0X2NvbnRlbnR8ZGlzYWdyZWVcIil9XG4gICAgICAgICAgICAgICAgICAgICAgICA8L1N0eWxlZFJhZGlvQnV0dG9uPlxuICAgICAgICAgICAgICAgICAgICAgICAgPFN0eWxlZFJhZGlvQnV0dG9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZT1cIm5hdHVyZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU9e05hdHVyZS5Ub3hpY31cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVja2VkPXt0aGlzLnN0YXRlLm5hdHVyZSA9PSBOYXR1cmUuVG94aWN9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb25DaGFuZ2U9e3RoaXMub25OYXR1cmVDaG9zZW59XG4gICAgICAgICAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAge190KFwicmVwb3J0X2NvbnRlbnR8dG94aWNfYmVoYXZpb3VyXCIpfVxuICAgICAgICAgICAgICAgICAgICAgICAgPC9TdHlsZWRSYWRpb0J1dHRvbj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxTdHlsZWRSYWRpb0J1dHRvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWU9XCJuYXR1cmVcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlPXtOYXR1cmUuSWxsZWdhbH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVja2VkPXt0aGlzLnN0YXRlLm5hdHVyZSA9PSBOYXR1cmUuSWxsZWdhbH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbkNoYW5nZT17dGhpcy5vbk5hdHVyZUNob3Nlbn1cbiAgICAgICAgICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB7X3QoXCJyZXBvcnRfY29udGVudHxpbGxlZ2FsX2NvbnRlbnRcIil9XG4gICAgICAgICAgICAgICAgICAgICAgICA8L1N0eWxlZFJhZGlvQnV0dG9uPlxuICAgICAgICAgICAgICAgICAgICAgICAgPFN0eWxlZFJhZGlvQnV0dG9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZT1cIm5hdHVyZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU9e05hdHVyZS5TcGFtfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoZWNrZWQ9e3RoaXMuc3RhdGUubmF0dXJlID09IE5hdHVyZS5TcGFtfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9uQ2hhbmdlPXt0aGlzLm9uTmF0dXJlQ2hvc2VufVxuICAgICAgICAgICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHtfdChcInJlcG9ydF9jb250ZW50fHNwYW1fb3JfcHJvcGFnYW5kYVwiKX1cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvU3R5bGVkUmFkaW9CdXR0b24+XG4gICAgICAgICAgICAgICAgICAgICAgICA8U3R5bGVkUmFkaW9CdXR0b25cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lPVwibmF0dXJlXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZT17Tm9uU3RhbmRhcmRWYWx1ZS5BZG1pbn1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVja2VkPXt0aGlzLnN0YXRlLm5hdHVyZSA9PSBOb25TdGFuZGFyZFZhbHVlLkFkbWlufVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9uQ2hhbmdlPXt0aGlzLm9uTmF0dXJlQ2hvc2VufVxuICAgICAgICAgICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHtfdChcInJlcG9ydF9jb250ZW50fHJlcG9ydF9lbnRpcmVfcm9vbVwiKX1cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvU3R5bGVkUmFkaW9CdXR0b24+XG4gICAgICAgICAgICAgICAgICAgICAgICA8U3R5bGVkUmFkaW9CdXR0b25cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lPVwibmF0dXJlXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZT17TmF0dXJlLk90aGVyfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoZWNrZWQ9e3RoaXMuc3RhdGUubmF0dXJlID09IE5hdHVyZS5PdGhlcn1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbkNoYW5nZT17dGhpcy5vbk5hdHVyZUNob3Nlbn1cbiAgICAgICAgICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB7X3QoXCJyZXBvcnRfY29udGVudHxvdGhlcl9sYWJlbFwiKX1cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvU3R5bGVkUmFkaW9CdXR0b24+XG4gICAgICAgICAgICAgICAgICAgICAgICA8cD57c3VidGl0bGV9PC9wPlxuICAgICAgICAgICAgICAgICAgICAgICAgPEZpZWxkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3NOYW1lPVwibXhfUmVwb3J0RXZlbnREaWFsb2dfcmVhc29uXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50PVwidGV4dGFyZWFcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVsPXtfdChcInJvb21fc2V0dGluZ3N8cGVybWlzc2lvbnN8YmFuX3JlYXNvblwiKX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb3dzPXs1fVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9uQ2hhbmdlPXt0aGlzLm9uUmVhc29uQ2hhbmdlfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlPXt0aGlzLnN0YXRlLnJlYXNvbn1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXNhYmxlZD17dGhpcy5zdGF0ZS5idXN5fVxuICAgICAgICAgICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICAgICAgICAgIHtwcm9ncmVzc31cbiAgICAgICAgICAgICAgICAgICAgICAgIHtlcnJvcn1cbiAgICAgICAgICAgICAgICAgICAgICAgIHtpZ25vcmVVc2VyQ2hlY2tib3h9XG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICA8RGlhbG9nQnV0dG9uc1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJpbWFyeUJ1dHRvbj17X3QoXCJhY3Rpb258c2VuZF9yZXBvcnRcIil9XG4gICAgICAgICAgICAgICAgICAgICAgICBvblByaW1hcnlCdXR0b25DbGljaz17dGhpcy5vblN1Ym1pdH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGZvY3VzPXt0cnVlfVxuICAgICAgICAgICAgICAgICAgICAgICAgb25DYW5jZWw9e3RoaXMub25DYW5jZWx9XG4gICAgICAgICAgICAgICAgICAgICAgICBkaXNhYmxlZD17dGhpcy5zdGF0ZS5idXN5fVxuICAgICAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICAgIDwvQmFzZURpYWxvZz5cbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gUmVwb3J0IHRvIGhvbWVzZXJ2ZXIgYWRtaW4uXG4gICAgICAgIC8vIEN1cnJlbnRseSwgdGhlIEFQSSBkb2VzIG5vdCBzdXBwb3J0IG5hdHVyZXMuXG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICA8QmFzZURpYWxvZ1xuICAgICAgICAgICAgICAgIGNsYXNzTmFtZT1cIm14X1JlcG9ydEV2ZW50RGlhbG9nXCJcbiAgICAgICAgICAgICAgICBvbkZpbmlzaGVkPXt0aGlzLnByb3BzLm9uRmluaXNoZWR9XG4gICAgICAgICAgICAgICAgdGl0bGU9e190KFwicmVwb3J0X2NvbnRlbnR8cmVwb3J0X2NvbnRlbnRfdG9faG9tZXNlcnZlclwiKX1cbiAgICAgICAgICAgICAgICBjb250ZW50SWQ9XCJteF9SZXBvcnRFdmVudERpYWxvZ1wiXG4gICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJteF9SZXBvcnRFdmVudERpYWxvZ1wiIGlkPVwibXhfUmVwb3J0RXZlbnREaWFsb2dcIj5cbiAgICAgICAgICAgICAgICAgICAgPHA+e190KFwicmVwb3J0X2NvbnRlbnR8ZGVzY3JpcHRpb25cIil9PC9wPlxuICAgICAgICAgICAgICAgICAgICB7YWRtaW5NZXNzYWdlfVxuICAgICAgICAgICAgICAgICAgICA8RmllbGRcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzTmFtZT1cIm14X1JlcG9ydEV2ZW50RGlhbG9nX3JlYXNvblwiXG4gICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50PVwidGV4dGFyZWFcIlxuICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWw9e190KFwicm9vbV9zZXR0aW5nc3xwZXJtaXNzaW9uc3xiYW5fcmVhc29uXCIpfVxuICAgICAgICAgICAgICAgICAgICAgICAgcm93cz17NX1cbiAgICAgICAgICAgICAgICAgICAgICAgIG9uQ2hhbmdlPXt0aGlzLm9uUmVhc29uQ2hhbmdlfVxuICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU9e3RoaXMuc3RhdGUucmVhc29ufVxuICAgICAgICAgICAgICAgICAgICAgICAgZGlzYWJsZWQ9e3RoaXMuc3RhdGUuYnVzeX1cbiAgICAgICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICAgICAge3Byb2dyZXNzfVxuICAgICAgICAgICAgICAgICAgICB7ZXJyb3J9XG4gICAgICAgICAgICAgICAgICAgIHtpZ25vcmVVc2VyQ2hlY2tib3h9XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgPERpYWxvZ0J1dHRvbnNcbiAgICAgICAgICAgICAgICAgICAgcHJpbWFyeUJ1dHRvbj17X3QoXCJhY3Rpb258c2VuZF9yZXBvcnRcIil9XG4gICAgICAgICAgICAgICAgICAgIG9uUHJpbWFyeUJ1dHRvbkNsaWNrPXt0aGlzLm9uU3VibWl0fVxuICAgICAgICAgICAgICAgICAgICBmb2N1cz17dHJ1ZX1cbiAgICAgICAgICAgICAgICAgICAgb25DYW5jZWw9e3RoaXMub25DYW5jZWx9XG4gICAgICAgICAgICAgICAgICAgIGRpc2FibGVkPXt0aGlzLnN0YXRlLmJ1c3l9XG4gICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgIDwvQmFzZURpYWxvZz5cbiAgICAgICAgKTtcbiAgICB9XG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7O0FBU0EsSUFBQUEsTUFBQSxHQUFBQyxzQkFBQSxDQUFBQyxPQUFBO0FBRUEsSUFBQUMsT0FBQSxHQUFBRCxPQUFBO0FBRUEsSUFBQUUsZ0JBQUEsR0FBQUYsT0FBQTtBQUNBLElBQUFHLFdBQUEsR0FBQUgsT0FBQTtBQUNBLElBQUFJLGdCQUFBLEdBQUFKLE9BQUE7QUFDQSxJQUFBSyxVQUFBLEdBQUFOLHNCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBTSxTQUFBLEdBQUFQLHNCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBTyxjQUFBLEdBQUFSLHNCQUFBLENBQUFDLE9BQUE7QUFDQSxJQUFBUSxrQkFBQSxHQUFBVCxzQkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQVMsV0FBQSxHQUFBVixzQkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQVUsY0FBQSxHQUFBWCxzQkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQVcsTUFBQSxHQUFBWixzQkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQVksUUFBQSxHQUFBYixzQkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQWEsaUJBQUEsR0FBQWQsc0JBQUEsQ0FBQUMsT0FBQTtBQXhCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtB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