matrix-react-sdk
Version:
SDK for matrix.org using React
663 lines (659 loc) • 98.2 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 _matrix = require("matrix-js-sdk/src/matrix");
var _types = require("matrix-js-sdk/src/types");
var _classnames = _interopRequireDefault(require("classnames"));
var _RoomViewLifecycle = require("@matrix-org/react-sdk-module-api/lib/lifecycles/RoomViewLifecycle");
var _MatrixClientPeg = require("../../../MatrixClientPeg");
var _dispatcher = _interopRequireDefault(require("../../../dispatcher/dispatcher"));
var _languageHandler = require("../../../languageHandler");
var _SdkConfig = _interopRequireDefault(require("../../../SdkConfig"));
var _IdentityAuthClient = _interopRequireDefault(require("../../../IdentityAuthClient"));
var _InviteReason = _interopRequireDefault(require("../elements/InviteReason"));
var _Spinner = _interopRequireDefault(require("../elements/Spinner"));
var _AccessibleButton = _interopRequireDefault(require("../elements/AccessibleButton"));
var _RoomAvatar = _interopRequireDefault(require("../avatars/RoomAvatar"));
var _SettingsStore = _interopRequireDefault(require("../../../settings/SettingsStore"));
var _UIFeature = require("../../../settings/UIFeature");
var _ModuleRunner = require("../../../modules/ModuleRunner");
var _askToJoin = require("../../../../res/img/element-icons/ask-to-join.svg");
var _Field = _interopRequireDefault(require("../elements/Field"));
/*
Copyright 2024 New Vector Ltd.
Copyright 2015-2021 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
Please see LICENSE files in the repository root for full details.
*/
const MemberEventHtmlReasonField = "io.element.html_reason";
var MessageCase = /*#__PURE__*/function (MessageCase) {
MessageCase["NotLoggedIn"] = "NotLoggedIn";
MessageCase["Joining"] = "Joining";
MessageCase["Loading"] = "Loading";
MessageCase["Rejecting"] = "Rejecting";
MessageCase["Kicked"] = "Kicked";
MessageCase["Banned"] = "Banned";
MessageCase["OtherThreePIDError"] = "OtherThreePIDError";
MessageCase["InvitedEmailNotFoundInAccount"] = "InvitedEmailNotFoundInAccount";
MessageCase["InvitedEmailNoIdentityServer"] = "InvitedEmailNoIdentityServer";
MessageCase["InvitedEmailMismatch"] = "InvitedEmailMismatch";
MessageCase["Invite"] = "Invite";
MessageCase["ViewingRoom"] = "ViewingRoom";
MessageCase["RoomNotFound"] = "RoomNotFound";
MessageCase["OtherError"] = "OtherError";
MessageCase["PromptAskToJoin"] = "PromptAskToJoin";
MessageCase["Knocked"] = "Knocked";
MessageCase["RequestDenied"] = "requestDenied";
return MessageCase;
}(MessageCase || {});
class RoomPreviewBar extends _react.default.Component {
constructor(props) {
super(props);
(0, _defineProperty2.default)(this, "onLoginClick", () => {
_dispatcher.default.dispatch({
action: "start_login",
screenAfterLogin: this.makeScreenAfterLogin()
});
});
(0, _defineProperty2.default)(this, "onRegisterClick", () => {
_dispatcher.default.dispatch({
action: "start_registration",
screenAfterLogin: this.makeScreenAfterLogin()
});
});
(0, _defineProperty2.default)(this, "onChangeReason", event => {
this.setState({
reason: event.target.value
});
});
this.state = {
busy: false
};
}
componentDidMount() {
this.checkInvitedEmail();
}
componentDidUpdate(prevProps, prevState) {
if (this.props.invitedEmail !== prevProps.invitedEmail || this.props.inviterName !== prevProps.inviterName) {
this.checkInvitedEmail();
}
}
async checkInvitedEmail() {
// If this is an invite and we've been told what email address was
// invited, fetch the user's account emails and discovery bindings so we
// can check them against the email that was invited.
if (this.props.inviterName && this.props.invitedEmail) {
this.setState({
busy: true
});
try {
// Gather the account 3PIDs
const account3pids = await _MatrixClientPeg.MatrixClientPeg.safeGet().getThreePids();
this.setState({
accountEmails: account3pids.threepids.filter(b => b.medium === "email").map(b => b.address)
});
// If we have an IS connected, use that to lookup the email and
// check the bound MXID.
if (!_MatrixClientPeg.MatrixClientPeg.safeGet().getIdentityServerUrl()) {
this.setState({
busy: false
});
return;
}
const authClient = new _IdentityAuthClient.default();
const identityAccessToken = await authClient.getAccessToken();
const result = await _MatrixClientPeg.MatrixClientPeg.safeGet().lookupThreePid("email", this.props.invitedEmail, identityAccessToken);
if (!("mxid" in result)) {
throw new _languageHandler.UserFriendlyError("room|error_3pid_invite_email_lookup");
}
this.setState({
invitedEmailMxid: result.mxid
});
} catch (err) {
this.setState({
threePidFetchError: err
});
}
this.setState({
busy: false
});
}
}
getMessageCase() {
const isGuest = _MatrixClientPeg.MatrixClientPeg.safeGet().isGuest();
if (isGuest) {
return MessageCase.NotLoggedIn;
}
const myMember = this.getMyMember();
if (myMember) {
const previousMembership = myMember.events.member?.getPrevContent().membership;
if (myMember.isKicked()) {
if (previousMembership === _types.KnownMembership.Knock) {
return MessageCase.RequestDenied;
} else if (this.props.promptAskToJoin) {
return MessageCase.PromptAskToJoin;
}
return MessageCase.Kicked;
} else if (myMember.membership === _types.KnownMembership.Ban) {
return MessageCase.Banned;
}
}
if (this.props.joining) {
return MessageCase.Joining;
} else if (this.props.rejecting) {
return MessageCase.Rejecting;
} else if (this.props.loading || this.state.busy) {
return MessageCase.Loading;
} else if (this.props.knocked) {
return MessageCase.Knocked;
} else if (this.props.canAskToJoinAndMembershipIsLeave || this.props.promptAskToJoin) {
return MessageCase.PromptAskToJoin;
}
if (this.props.inviterName) {
if (this.props.invitedEmail) {
if (this.state.threePidFetchError) {
return MessageCase.OtherThreePIDError;
} else if (this.state.accountEmails && !this.state.accountEmails.includes(this.props.invitedEmail)) {
return MessageCase.InvitedEmailNotFoundInAccount;
} else if (!_MatrixClientPeg.MatrixClientPeg.safeGet().getIdentityServerUrl()) {
return MessageCase.InvitedEmailNoIdentityServer;
} else if (this.state.invitedEmailMxid != _MatrixClientPeg.MatrixClientPeg.safeGet().getUserId()) {
return MessageCase.InvitedEmailMismatch;
}
}
return MessageCase.Invite;
} else if (this.props.error) {
if (this.props.error.errcode == "M_NOT_FOUND") {
return MessageCase.RoomNotFound;
} else {
return MessageCase.OtherError;
}
} else {
return MessageCase.ViewingRoom;
}
}
getKickOrBanInfo() {
const myMember = this.getMyMember();
if (!myMember) {
return {};
}
const kickerUserId = myMember.events.member?.getSender();
const kickerMember = kickerUserId ? this.props.room?.currentState.getMember(kickerUserId) : undefined;
const memberName = kickerMember?.name ?? kickerUserId;
const reason = myMember.events.member?.getContent().reason;
return {
memberName,
reason
};
}
joinRule() {
return this.props.room?.currentState.getStateEvents(_matrix.EventType.RoomJoinRules, "")?.getContent().join_rule ?? null;
}
getMyMember() {
return this.props.room?.getMember(_MatrixClientPeg.MatrixClientPeg.safeGet().getSafeUserId()) ?? null;
}
getInviteMember() {
const {
room
} = this.props;
if (!room) {
return null;
}
const myUserId = _MatrixClientPeg.MatrixClientPeg.safeGet().getSafeUserId();
const inviteEvent = room.currentState.getMember(myUserId);
if (!inviteEvent) {
return null;
}
const inviterUserId = inviteEvent.events.member?.getSender();
return inviterUserId ? room.currentState.getMember(inviterUserId) : null;
}
isDMInvite() {
const myMember = this.getMyMember();
if (!myMember) {
return false;
}
const memberContent = myMember.events.member?.getContent();
return memberContent?.membership === _types.KnownMembership.Invite && memberContent.is_direct;
}
makeScreenAfterLogin() {
return {
screen: "room",
params: {
email: this.props.invitedEmail,
signurl: this.props.signUrl,
room_name: this.props.oobData?.name ?? null,
room_avatar_url: this.props.oobData?.avatarUrl ?? null,
inviter_name: this.props.oobData?.inviterName ?? null
}
};
}
render() {
const brand = _SdkConfig.default.get().brand;
const roomName = this.props.room?.name ?? this.props.roomAlias ?? "";
const isSpace = this.props.room?.isSpaceRoom() ?? this.props.oobData?.roomType === _matrix.RoomType.Space;
let showSpinner = false;
let title;
let subTitle;
let reasonElement;
let primaryActionHandler;
let primaryActionLabel;
let secondaryActionHandler;
let secondaryActionLabel;
let footer;
const extraComponents = [];
const messageCase = this.getMessageCase();
switch (messageCase) {
case MessageCase.Joining:
{
if (this.props.oobData?.roomType || isSpace) {
title = isSpace ? (0, _languageHandler._t)("room|joining_space") : (0, _languageHandler._t)("room|joining_room");
} else {
title = (0, _languageHandler._t)("room|joining");
}
showSpinner = true;
break;
}
case MessageCase.Loading:
{
title = (0, _languageHandler._t)("common|loading");
showSpinner = true;
break;
}
case MessageCase.Rejecting:
{
title = (0, _languageHandler._t)("room|rejecting");
showSpinner = true;
break;
}
case MessageCase.NotLoggedIn:
{
const opts = {
canJoin: false
};
if (this.props.roomId) {
_ModuleRunner.ModuleRunner.instance.invoke(_RoomViewLifecycle.RoomViewLifecycle.PreviewRoomNotLoggedIn, opts, this.props.roomId);
}
if (opts.canJoin) {
title = (0, _languageHandler._t)("room|join_title");
primaryActionLabel = (0, _languageHandler._t)("action|join");
primaryActionHandler = () => {
_ModuleRunner.ModuleRunner.instance.invoke(_RoomViewLifecycle.RoomViewLifecycle.JoinFromRoomPreview, this.props.roomId);
};
} else {
title = (0, _languageHandler._t)("room|join_title_account");
if (_SettingsStore.default.getValue(_UIFeature.UIFeature.Registration)) {
primaryActionLabel = (0, _languageHandler._t)("room|join_button_account");
primaryActionHandler = this.onRegisterClick;
}
secondaryActionLabel = (0, _languageHandler._t)("action|sign_in");
secondaryActionHandler = this.onLoginClick;
}
if (this.props.previewLoading) {
footer = /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement(_Spinner.default, {
w: 20,
h: 20
}), (0, _languageHandler._t)("room|loading_preview"));
}
break;
}
case MessageCase.Kicked:
{
const {
memberName,
reason
} = this.getKickOrBanInfo();
if (roomName) {
title = (0, _languageHandler._t)("room|kicked_from_room_by", {
memberName,
roomName
});
} else {
title = (0, _languageHandler._t)("room|kicked_by", {
memberName
});
}
subTitle = reason ? (0, _languageHandler._t)("room|kick_reason", {
reason
}) : undefined;
if (isSpace) {
primaryActionLabel = (0, _languageHandler._t)("room|forget_space");
} else {
primaryActionLabel = (0, _languageHandler._t)("room|forget_room");
}
primaryActionHandler = this.props.onForgetClick;
if (this.joinRule() !== _matrix.JoinRule.Invite) {
secondaryActionLabel = primaryActionLabel;
secondaryActionHandler = primaryActionHandler;
primaryActionLabel = (0, _languageHandler._t)("room|rejoin_button");
primaryActionHandler = this.props.onJoinClick;
}
break;
}
case MessageCase.RequestDenied:
{
title = (0, _languageHandler._t)("room|knock_denied_title");
subTitle = (0, _languageHandler._t)("room|knock_denied_subtitle");
if (isSpace) {
primaryActionLabel = (0, _languageHandler._t)("room|forget_space");
} else {
primaryActionLabel = (0, _languageHandler._t)("room|forget_room");
}
primaryActionHandler = this.props.onForgetClick;
break;
}
case MessageCase.Banned:
{
const {
memberName,
reason
} = this.getKickOrBanInfo();
if (roomName) {
title = (0, _languageHandler._t)("room|banned_from_room_by", {
memberName,
roomName
});
} else {
title = (0, _languageHandler._t)("room|banned_by", {
memberName
});
}
subTitle = reason ? (0, _languageHandler._t)("room|kick_reason", {
reason
}) : undefined;
if (isSpace) {
primaryActionLabel = (0, _languageHandler._t)("room|forget_space");
} else {
primaryActionLabel = (0, _languageHandler._t)("room|forget_room");
}
primaryActionHandler = this.props.onForgetClick;
break;
}
case MessageCase.OtherThreePIDError:
{
if (roomName) {
title = (0, _languageHandler._t)("room|3pid_invite_error_title_room", {
roomName
});
} else {
title = (0, _languageHandler._t)("room|3pid_invite_error_title");
}
const joinRule = this.joinRule();
const errCodeMessage = (0, _languageHandler._t)("room|3pid_invite_error_description", {
errcode: this.state.threePidFetchError?.errcode || (0, _languageHandler._t)("error|unknown_error_code")
});
switch (joinRule) {
case "invite":
subTitle = [(0, _languageHandler._t)("room|3pid_invite_error_invite_subtitle"), errCodeMessage];
primaryActionLabel = (0, _languageHandler._t)("room|3pid_invite_error_invite_action");
primaryActionHandler = this.props.onJoinClick;
break;
case "public":
subTitle = (0, _languageHandler._t)("room|3pid_invite_error_public_subtitle");
primaryActionLabel = (0, _languageHandler._t)("room|join_the_discussion");
primaryActionHandler = this.props.onJoinClick;
break;
default:
subTitle = errCodeMessage;
primaryActionLabel = (0, _languageHandler._t)("room|3pid_invite_error_invite_action");
primaryActionHandler = this.props.onJoinClick;
break;
}
break;
}
case MessageCase.InvitedEmailNotFoundInAccount:
{
if (roomName) {
title = (0, _languageHandler._t)("room|3pid_invite_email_not_found_account_room", {
roomName,
email: this.props.invitedEmail
});
} else {
title = (0, _languageHandler._t)("room|3pid_invite_email_not_found_account", {
email: this.props.invitedEmail
});
}
subTitle = (0, _languageHandler._t)("room|link_email_to_receive_3pid_invite", {
brand
});
primaryActionLabel = (0, _languageHandler._t)("room|join_the_discussion");
primaryActionHandler = this.props.onJoinClick;
break;
}
case MessageCase.InvitedEmailNoIdentityServer:
{
if (roomName) {
title = (0, _languageHandler._t)("room|invite_sent_to_email_room", {
roomName,
email: this.props.invitedEmail
});
} else {
title = (0, _languageHandler._t)("room|invite_sent_to_email", {
email: this.props.invitedEmail
});
}
subTitle = (0, _languageHandler._t)("room|3pid_invite_no_is_subtitle", {
brand
});
primaryActionLabel = (0, _languageHandler._t)("room|join_the_discussion");
primaryActionHandler = this.props.onJoinClick;
break;
}
case MessageCase.InvitedEmailMismatch:
{
if (roomName) {
title = (0, _languageHandler._t)("room|invite_sent_to_email_room", {
roomName,
email: this.props.invitedEmail
});
} else {
title = (0, _languageHandler._t)("room|invite_sent_to_email", {
email: this.props.invitedEmail
});
}
subTitle = (0, _languageHandler._t)("room|invite_email_mismatch_suggestion", {
brand
});
primaryActionLabel = (0, _languageHandler._t)("room|join_the_discussion");
primaryActionHandler = this.props.onJoinClick;
break;
}
case MessageCase.Invite:
{
const isDM = this.isDMInvite();
const avatar = /*#__PURE__*/_react.default.createElement(_RoomAvatar.default, {
room: this.props.room,
oobData: this.props.oobData
});
const inviteMember = this.getInviteMember();
const userName = /*#__PURE__*/_react.default.createElement("span", {
className: "mx_RoomPreviewBar_inviter"
}, inviteMember?.rawDisplayName ?? this.props.inviterName);
const inviterElement = /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, isDM ? (0, _languageHandler._t)("room|dm_invite_subtitle", {}, {
userName
}) : (0, _languageHandler._t)("room|invite_subtitle", {}, {
userName
}), inviteMember && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("br", null), /*#__PURE__*/_react.default.createElement("span", {
className: "mx_RoomPreviewBar_inviter_mxid"
}, inviteMember.userId)));
if (isDM) {
title = (0, _languageHandler._t)("room|dm_invite_title", {
user: inviteMember?.name ?? this.props.inviterName
});
primaryActionLabel = (0, _languageHandler._t)("room|dm_invite_action");
} else {
title = (0, _languageHandler._t)("room|invite_title", {
roomName
});
primaryActionLabel = (0, _languageHandler._t)("action|accept");
}
subTitle = [avatar, inviterElement];
const myUserId = _MatrixClientPeg.MatrixClientPeg.safeGet().getSafeUserId();
const member = this.props.room?.currentState.getMember(myUserId);
const memberEventContent = member?.events.member?.getContent();
if (memberEventContent?.reason) {
reasonElement = /*#__PURE__*/_react.default.createElement(_InviteReason.default, {
reason: memberEventContent.reason,
htmlReason: memberEventContent[MemberEventHtmlReasonField]
});
}
primaryActionHandler = this.props.onJoinClick;
secondaryActionLabel = (0, _languageHandler._t)("action|reject");
secondaryActionHandler = this.props.onRejectClick;
if (this.props.onRejectAndIgnoreClick) {
extraComponents.push( /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, {
kind: "secondary",
onClick: this.props.onRejectAndIgnoreClick,
key: "ignore"
}, (0, _languageHandler._t)("room|invite_reject_ignore")));
}
break;
}
case MessageCase.ViewingRoom:
{
if (this.props.canPreview) {
title = (0, _languageHandler._t)("room|peek_join_prompt", {
roomName
});
} else if (roomName) {
title = (0, _languageHandler._t)("room|no_peek_join_prompt", {
roomName
});
} else {
title = (0, _languageHandler._t)("room|no_peek_no_name_join_prompt");
}
primaryActionLabel = (0, _languageHandler._t)("room|join_the_discussion");
primaryActionHandler = this.props.onJoinClick;
break;
}
case MessageCase.RoomNotFound:
{
if (roomName) {
title = (0, _languageHandler._t)("room|not_found_title_name", {
roomName
});
} else {
title = (0, _languageHandler._t)("room|not_found_title");
}
subTitle = (0, _languageHandler._t)("room|not_found_subtitle");
break;
}
case MessageCase.OtherError:
{
if (roomName) {
title = (0, _languageHandler._t)("room|inaccessible_name", {
roomName
});
} else {
title = (0, _languageHandler._t)("room|inaccessible");
}
subTitle = [(0, _languageHandler._t)("room|inaccessible_subtitle_1"), (0, _languageHandler._t)("room|inaccessible_subtitle_2", {
errcode: String(this.props.error?.errcode)
}, {
issueLink: label => /*#__PURE__*/_react.default.createElement("a", {
href: _SdkConfig.default.get().feedback.new_issue_url,
target: "_blank",
rel: "noreferrer noopener"
}, label)
})];
break;
}
case MessageCase.PromptAskToJoin:
{
if (roomName) {
title = (0, _languageHandler._t)("room|knock_prompt_name", {
roomName
});
} else {
title = (0, _languageHandler._t)("room|knock_prompt");
}
const avatar = /*#__PURE__*/_react.default.createElement(_RoomAvatar.default, {
room: this.props.room,
oobData: this.props.oobData
});
subTitle = [avatar, (0, _languageHandler._t)("room|knock_subtitle")];
reasonElement = /*#__PURE__*/_react.default.createElement(_Field.default, {
autoFocus: true,
className: "mx_RoomPreviewBar_fullWidth",
element: "textarea",
onChange: this.onChangeReason,
placeholder: (0, _languageHandler._t)("room|knock_message_field_placeholder"),
type: "text",
value: this.state.reason ?? ""
});
primaryActionHandler = () => this.props.onSubmitAskToJoin && this.props.onSubmitAskToJoin(this.state.reason);
primaryActionLabel = (0, _languageHandler._t)("room|knock_send_action");
break;
}
case MessageCase.Knocked:
{
title = (0, _languageHandler._t)("room|knock_sent");
subTitle = [/*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_askToJoin.Icon, {
className: "mx_Icon mx_Icon_16 mx_RoomPreviewBar_icon"
}), (0, _languageHandler._t)("room|knock_sent_subtitle"))];
secondaryActionHandler = this.props.onCancelAskToJoin;
secondaryActionLabel = (0, _languageHandler._t)("room|knock_cancel_action");
break;
}
}
let subTitleElements;
if (subTitle) {
if (!Array.isArray(subTitle)) {
subTitle = [subTitle];
}
subTitleElements = subTitle.map((t, i) => /*#__PURE__*/_react.default.createElement("p", {
key: `subTitle${i}`
}, t));
}
let titleElement;
if (showSpinner) {
titleElement = /*#__PURE__*/_react.default.createElement("h3", {
className: "mx_RoomPreviewBar_spinnerTitle"
}, /*#__PURE__*/_react.default.createElement(_Spinner.default, null), title);
} else {
titleElement = /*#__PURE__*/_react.default.createElement("h3", null, title);
}
let primaryButton;
if (primaryActionHandler) {
primaryButton = /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, {
kind: "primary",
onClick: primaryActionHandler
}, primaryActionLabel);
}
let secondaryButton;
if (secondaryActionHandler) {
secondaryButton = /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, {
kind: "secondary",
onClick: secondaryActionHandler
}, secondaryActionLabel);
}
const isPanel = this.props.canPreview;
const classes = (0, _classnames.default)("mx_RoomPreviewBar", `mx_RoomPreviewBar_${messageCase}`, {
mx_RoomPreviewBar_panel: isPanel,
mx_RoomPreviewBar_dialog: !isPanel
});
// ensure correct tab order for both views
const actions = isPanel ? /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, secondaryButton, extraComponents, primaryButton) : /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, primaryButton, extraComponents, secondaryButton);
return /*#__PURE__*/_react.default.createElement("div", {
role: "complementary",
className: classes
}, /*#__PURE__*/_react.default.createElement("div", {
className: "mx_RoomPreviewBar_message"
}, titleElement, subTitleElements), reasonElement, /*#__PURE__*/_react.default.createElement("div", {
className: (0, _classnames.default)("mx_RoomPreviewBar_actions", {
mx_RoomPreviewBar_fullWidth: messageCase === MessageCase.PromptAskToJoin
})
}, actions), /*#__PURE__*/_react.default.createElement("div", {
className: "mx_RoomPreviewBar_footer"
}, footer));
}
}
exports.default = RoomPreviewBar;
(0, _defineProperty2.default)(RoomPreviewBar, "defaultProps", {
onJoinClick() {}
});
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfcmVhY3QiLCJfaW50ZXJvcFJlcXVpcmVEZWZhdWx0IiwicmVxdWlyZSIsIl9tYXRyaXgiLCJfdHlwZXMiLCJfY2xhc3NuYW1lcyIsIl9Sb29tVmlld0xpZmVjeWNsZSIsIl9NYXRyaXhDbGllbnRQZWciLCJfZGlzcGF0Y2hlciIsIl9sYW5ndWFnZUhhbmRsZXIiLCJfU2RrQ29uZmlnIiwiX0lkZW50aXR5QXV0aENsaWVudCIsIl9JbnZpdGVSZWFzb24iLCJfU3Bpbm5lciIsIl9BY2Nlc3NpYmxlQnV0dG9uIiwiX1Jvb21BdmF0YXIiLCJfU2V0dGluZ3NTdG9yZSIsIl9VSUZlYXR1cmUiLCJfTW9kdWxlUnVubmVyIiwiX2Fza1RvSm9pbiIsIl9GaWVsZCIsIk1lbWJlckV2ZW50SHRtbFJlYXNvbkZpZWxkIiwiTWVzc2FnZUNhc2UiLCJSb29tUHJldmlld0JhciIsIlJlYWN0IiwiQ29tcG9uZW50IiwiY29uc3RydWN0b3IiLCJwcm9wcyIsIl9kZWZpbmVQcm9wZXJ0eTIiLCJkZWZhdWx0IiwiZGlzIiwiZGlzcGF0Y2giLCJhY3Rpb24iLCJzY3JlZW5BZnRlckxvZ2luIiwibWFrZVNjcmVlbkFmdGVyTG9naW4iLCJldmVudCIsInNldFN0YXRlIiwicmVhc29uIiwidGFyZ2V0IiwidmFsdWUiLCJzdGF0ZSIsImJ1c3kiLCJjb21wb25lbnREaWRNb3VudCIsImNoZWNrSW52aXRlZEVtYWlsIiwiY29tcG9uZW50RGlkVXBkYXRlIiwicHJldlByb3BzIiwicHJldlN0YXRlIiwiaW52aXRlZEVtYWlsIiwiaW52aXRlck5hbWUiLCJhY2NvdW50M3BpZHMiLCJNYXRyaXhDbGllbnRQZWciLCJzYWZlR2V0IiwiZ2V0VGhyZWVQaWRzIiwiYWNjb3VudEVtYWlscyIsInRocmVlcGlkcyIsImZpbHRlciIsImIiLCJtZWRpdW0iLCJtYXAiLCJhZGRyZXNzIiwiZ2V0SWRlbnRpdHlTZXJ2ZXJVcmwiLCJhdXRoQ2xpZW50IiwiSWRlbnRpdHlBdXRoQ2xpZW50IiwiaWRlbnRpdHlBY2Nlc3NUb2tlbiIsImdldEFjY2Vzc1Rva2VuIiwicmVzdWx0IiwibG9va3VwVGhyZWVQaWQiLCJVc2VyRnJpZW5kbHlFcnJvciIsImludml0ZWRFbWFpbE14aWQiLCJteGlkIiwiZXJyIiwidGhyZWVQaWRGZXRjaEVycm9yIiwiZ2V0TWVzc2FnZUNhc2UiLCJpc0d1ZXN0IiwiTm90TG9nZ2VkSW4iLCJteU1lbWJlciIsImdldE15TWVtYmVyIiwicHJldmlvdXNNZW1iZXJzaGlwIiwiZXZlbnRzIiwibWVtYmVyIiwiZ2V0UHJldkNvbnRlbnQiLCJtZW1iZXJzaGlwIiwiaXNLaWNrZWQiLCJLbm93bk1lbWJlcnNoaXAiLCJLbm9jayIsIlJlcXVlc3REZW5pZWQiLCJwcm9tcHRBc2tUb0pvaW4iLCJQcm9tcHRBc2tUb0pvaW4iLCJLaWNrZWQiLCJCYW4iLCJCYW5uZWQiLCJqb2luaW5nIiwiSm9pbmluZyIsInJlamVjdGluZyIsIlJlamVjdGluZyIsImxvYWRpbmciLCJMb2FkaW5nIiwia25vY2tlZCIsIktub2NrZWQiLCJjYW5Bc2tUb0pvaW5BbmRNZW1iZXJzaGlwSXNMZWF2ZSIsIk90aGVyVGhyZWVQSURFcnJvciIsImluY2x1ZGVzIiwiSW52aXRlZEVtYWlsTm90Rm91bmRJbkFjY291bnQiLCJJbnZpdGVkRW1haWxOb0lkZW50aXR5U2VydmVyIiwiZ2V0VXNlcklkIiwiSW52aXRlZEVtYWlsTWlzbWF0Y2giLCJJbnZpdGUiLCJlcnJvciIsImVycmNvZGUiLCJSb29tTm90Rm91bmQiLCJPdGhlckVycm9yIiwiVmlld2luZ1Jvb20iLCJnZXRLaWNrT3JCYW5JbmZvIiwia2lja2VyVXNlcklkIiwiZ2V0U2VuZGVyIiwia2lja2VyTWVtYmVyIiwicm9vbSIsImN1cnJlbnRTdGF0ZSIsImdldE1lbWJlciIsInVuZGVmaW5lZCIsIm1lbWJlck5hbWUiLCJuYW1lIiwiZ2V0Q29udGVudCIsImpvaW5SdWxlIiwiZ2V0U3RhdGVFdmVudHMiLCJFdmVudFR5cGUiLCJSb29tSm9pblJ1bGVzIiwiam9pbl9ydWxlIiwiZ2V0U2FmZVVzZXJJZCIsImdldEludml0ZU1lbWJlciIsIm15VXNlcklkIiwiaW52aXRlRXZlbnQiLCJpbnZpdGVyVXNlcklkIiwiaXNETUludml0ZSIsIm1lbWJlckNvbnRlbnQiLCJpc19kaXJlY3QiLCJzY3JlZW4iLCJwYXJhbXMiLCJlbWFpbCIsInNpZ251cmwiLCJzaWduVXJsIiwicm9vbV9uYW1lIiwib29iRGF0YSIsInJvb21fYXZhdGFyX3VybCIsImF2YXRhclVybCIsImludml0ZXJfbmFtZSIsInJlbmRlciIsImJyYW5kIiwiU2RrQ29uZmlnIiwiZ2V0Iiwicm9vbU5hbWUiLCJyb29tQWxpYXMiLCJpc1NwYWNlIiwiaXNTcGFjZVJvb20iLCJyb29tVHlwZSIsIlJvb21UeXBlIiwiU3BhY2UiLCJzaG93U3Bpbm5lciIsInRpdGxlIiwic3ViVGl0bGUiLCJyZWFzb25FbGVtZW50IiwicHJpbWFyeUFjdGlvbkhhbmRsZXIiLCJwcmltYXJ5QWN0aW9uTGFiZWwiLCJzZWNvbmRhcnlBY3Rpb25IYW5kbGVyIiwic2Vjb25kYXJ5QWN0aW9uTGFiZWwiLCJmb290ZXIiLCJleHRyYUNvbXBvbmVudHMiLCJtZXNzYWdlQ2FzZSIsIl90Iiwib3B0cyIsImNhbkpvaW4iLCJyb29tSWQiLCJNb2R1bGVSdW5uZXIiLCJpbnN0YW5jZSIsImludm9rZSIsIlJvb21WaWV3TGlmZWN5Y2xlIiwiUHJldmlld1Jvb21Ob3RMb2dnZWRJbiIsIkpvaW5Gcm9tUm9vbVByZXZpZXciLCJTZXR0aW5nc1N0b3JlIiwiZ2V0VmFsdWUiLCJVSUZlYXR1cmUiLCJSZWdpc3RyYXRpb24iLCJvblJlZ2lzdGVyQ2xpY2siLCJvbkxvZ2luQ2xpY2siLCJwcmV2aWV3TG9hZGluZyIsImNyZWF0ZUVsZW1lbnQiLCJ3IiwiaCIsIm9uRm9yZ2V0Q2xpY2siLCJKb2luUnVsZSIsIm9uSm9pbkNsaWNrIiwiZXJyQ29kZU1lc3NhZ2UiLCJpc0RNIiwiYXZhdGFyIiwiaW52aXRlTWVtYmVyIiwidXNlck5hbWUiLCJjbGFzc05hbWUiLCJyYXdEaXNwbGF5TmFtZSIsImludml0ZXJFbGVtZW50IiwiRnJhZ21lbnQiLCJ1c2VySWQiLCJ1c2VyIiwibWVtYmVyRXZlbnRDb250ZW50IiwiaHRtbFJlYXNvbiIsIm9uUmVqZWN0Q2xpY2siLCJvblJlamVjdEFuZElnbm9yZUNsaWNrIiwicHVzaCIsImtpbmQiLCJvbkNsaWNrIiwia2V5IiwiY2FuUHJldmlldyIsIlN0cmluZyIsImlzc3VlTGluayIsImxhYmVsIiwiaHJlZiIsImZlZWRiYWNrIiwibmV3X2lzc3VlX3VybCIsInJlbCIsImF1dG9Gb2N1cyIsImVsZW1lbnQiLCJvbkNoYW5nZSIsIm9uQ2hhbmdlUmVhc29uIiwicGxhY2Vob2xkZXIiLCJ0eXBlIiwib25TdWJtaXRBc2tUb0pvaW4iLCJJY29uIiwib25DYW5jZWxBc2tUb0pvaW4iLCJzdWJUaXRsZUVsZW1lbnRzIiwiQXJyYXkiLCJpc0FycmF5IiwidCIsImkiLCJ0aXRsZUVsZW1lbnQiLCJwcmltYXJ5QnV0dG9uIiwic2Vjb25kYXJ5QnV0dG9uIiwiaXNQYW5lbCIsImNsYXNzZXMiLCJjbGFzc05hbWVzIiwibXhfUm9vbVByZXZpZXdCYXJfcGFuZWwiLCJteF9Sb29tUHJldmlld0Jhcl9kaWFsb2ciLCJhY3Rpb25zIiwicm9sZSIsIm14X1Jvb21QcmV2aWV3QmFyX2Z1bGxXaWR0aCIsImV4cG9ydHMiXSwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvY29tcG9uZW50cy92aWV3cy9yb29tcy9Sb29tUHJldmlld0Jhci50c3giXSwic291cmNlc0NvbnRlbnQiOlsiLypcbkNvcHlyaWdodCAyMDI0IE5ldyBWZWN0b3IgTHRkLlxuQ29weXJpZ2h0IDIwMTUtMjAyMSBUaGUgTWF0cml4Lm9yZyBGb3VuZGF0aW9uIEMuSS5DLlxuXG5TUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQUdQTC0zLjAtb25seSBPUiBHUEwtMy4wLW9ubHlcblBsZWFzZSBzZWUgTElDRU5TRSBmaWxlcyBpbiB0aGUgcmVwb3NpdG9yeSByb290IGZvciBmdWxsIGRldGFpbHMuXG4qL1xuXG5pbXBvcnQgUmVhY3QsIHsgQ2hhbmdlRXZlbnQsIFJlYWN0Tm9kZSB9IGZyb20gXCJyZWFjdFwiO1xuaW1wb3J0IHsgUm9vbSwgUm9vbU1lbWJlciwgRXZlbnRUeXBlLCBSb29tVHlwZSwgSm9pblJ1bGUsIE1hdHJpeEVycm9yIH0gZnJvbSBcIm1hdHJpeC1qcy1zZGsvc3JjL21hdHJpeFwiO1xuaW1wb3J0IHsgS25vd25NZW1iZXJzaGlwLCBSb29tSm9pblJ1bGVzRXZlbnRDb250ZW50IH0gZnJvbSBcIm1hdHJpeC1qcy1zZGsvc3JjL3R5cGVzXCI7XG5pbXBvcnQgY2xhc3NOYW1lcyBmcm9tIFwiY2xhc3NuYW1lc1wiO1xuaW1wb3J0IHsgUm9vbVByZXZpZXdPcHRzLCBSb29tVmlld0xpZmVjeWNsZSB9IGZyb20gXCJAbWF0cml4LW9yZy9yZWFjdC1zZGstbW9kdWxlLWFwaS9saWIvbGlmZWN5Y2xlcy9Sb29tVmlld0xpZmVjeWNsZVwiO1xuXG5pbXBvcnQgeyBNYXRyaXhDbGllbnRQZWcgfSBmcm9tIFwiLi4vLi4vLi4vTWF0cml4Q2xpZW50UGVnXCI7XG5pbXBvcnQgZGlzIGZyb20gXCIuLi8uLi8uLi9kaXNwYXRjaGVyL2Rpc3BhdGNoZXJcIjtcbmltcG9ydCB7IF90LCBVc2VyRnJpZW5kbHlFcnJvciB9IGZyb20gXCIuLi8uLi8uLi9sYW5ndWFnZUhhbmRsZXJcIjtcbmltcG9ydCBTZGtDb25maWcgZnJvbSBcIi4uLy4uLy4uL1Nka0NvbmZpZ1wiO1xuaW1wb3J0IElkZW50aXR5QXV0aENsaWVudCBmcm9tIFwiLi4vLi4vLi4vSWRlbnRpdHlBdXRoQ2xpZW50XCI7XG5pbXBvcnQgSW52aXRlUmVhc29uIGZyb20gXCIuLi9lbGVtZW50cy9JbnZpdGVSZWFzb25cIjtcbmltcG9ydCB7IElPT0JEYXRhIH0gZnJvbSBcIi4uLy4uLy4uL3N0b3Jlcy9UaHJlZXBpZEludml0ZVN0b3JlXCI7XG5pbXBvcnQgU3Bpbm5lciBmcm9tIFwiLi4vZWxlbWVudHMvU3Bpbm5lclwiO1xuaW1wb3J0IEFjY2Vzc2libGVCdXR0b24gZnJvbSBcIi4uL2VsZW1lbnRzL0FjY2Vzc2libGVCdXR0b25cIjtcbmltcG9ydCBSb29tQXZhdGFyIGZyb20gXCIuLi9hdmF0YXJzL1Jvb21BdmF0YXJcIjtcbmltcG9ydCBTZXR0aW5nc1N0b3JlIGZyb20gXCIuLi8uLi8uLi9zZXR0aW5ncy9TZXR0aW5nc1N0b3JlXCI7XG5pbXBvcnQgeyBVSUZlYXR1cmUgfSBmcm9tIFwiLi4vLi4vLi4vc2V0dGluZ3MvVUlGZWF0dXJlXCI7XG5pbXBvcnQgeyBNb2R1bGVSdW5uZXIgfSBmcm9tIFwiLi4vLi4vLi4vbW9kdWxlcy9Nb2R1bGVSdW5uZXJcIjtcbmltcG9ydCB7IEljb24gYXMgQXNrVG9Kb2luSWNvbiB9IGZyb20gXCIuLi8uLi8uLi8uLi9yZXMvaW1nL2VsZW1lbnQtaWNvbnMvYXNrLXRvLWpvaW4uc3ZnXCI7XG5pbXBvcnQgRmllbGQgZnJvbSBcIi4uL2VsZW1lbnRzL0ZpZWxkXCI7XG5cbmNvbnN0IE1lbWJlckV2ZW50SHRtbFJlYXNvbkZpZWxkID0gXCJpby5lbGVtZW50Lmh0bWxfcmVhc29uXCI7XG5cbmVudW0gTWVzc2FnZUNhc2Uge1xuICAgIE5vdExvZ2dlZEluID0gXCJOb3RMb2dnZWRJblwiLFxuICAgIEpvaW5pbmcgPSBcIkpvaW5pbmdcIixcbiAgICBMb2FkaW5nID0gXCJMb2FkaW5nXCIsXG4gICAgUmVqZWN0aW5nID0gXCJSZWplY3RpbmdcIixcbiAgICBLaWNrZWQgPSBcIktpY2tlZFwiLFxuICAgIEJhbm5lZCA9IFwiQmFubmVkXCIsXG4gICAgT3RoZXJUaHJlZVBJREVycm9yID0gXCJPdGhlclRocmVlUElERXJyb3JcIixcbiAgICBJbnZpdGVkRW1haWxOb3RGb3VuZEluQWNjb3VudCA9IFwiSW52aXRlZEVtYWlsTm90Rm91bmRJbkFjY291bnRcIixcbiAgICBJbnZpdGVkRW1haWxOb0lkZW50aXR5U2VydmVyID0gXCJJbnZpdGVkRW1haWxOb0lkZW50aXR5U2VydmVyXCIsXG4gICAgSW52aXRlZEVtYWlsTWlzbWF0Y2ggPSBcIkludml0ZWRFbWFpbE1pc21hdGNoXCIsXG4gICAgSW52aXRlID0gXCJJbnZpdGVcIixcbiAgICBWaWV3aW5nUm9vbSA9IFwiVmlld2luZ1Jvb21cIixcbiAgICBSb29tTm90Rm91bmQgPSBcIlJvb21Ob3RGb3VuZFwiLFxuICAgIE90aGVyRXJyb3IgPSBcIk90aGVyRXJyb3JcIixcbiAgICBQcm9tcHRBc2tUb0pvaW4gPSBcIlByb21wdEFza1RvSm9pblwiLFxuICAgIEtub2NrZWQgPSBcIktub2NrZWRcIixcbiAgICBSZXF1ZXN0RGVuaWVkID0gXCJyZXF1ZXN0RGVuaWVkXCIsXG59XG5cbmludGVyZmFjZSBJUHJvcHMge1xuICAgIC8vIGlmIGludml0ZXJOYW1lIGlzIHNwZWNpZmllZCwgdGhlIHByZXZpZXcgYmFyIHdpbGwgc2hvd24gYW4gaW52aXRlIHRvIHRoZSByb29tLlxuICAgIC8vIFlvdSBzaG91bGQgYWxzbyBzcGVjaWZ5IG9uUmVqZWN0Q2xpY2sgaWYgc3BlY2lmeWluZyBpbnZpdGVyTmFtZVxuICAgIGludml0ZXJOYW1lPzogc3RyaW5nO1xuXG4gICAgLy8gSWYgaW52aXRlZCBieSAzcmQgcGFydHkgaW52aXRlLCB0aGUgZW1haWwgYWRkcmVzcyB0aGUgaW52aXRlIHdhcyBzZW50IHRvXG4gICAgaW52aXRlZEVtYWlsPzogc3RyaW5nO1xuXG4gICAgLy8gRm9yIHRoaXJkIHBhcnR5IGludml0ZXMsIGluZm9ybWF0aW9uIHBhc3NlZCBhYm91dCB0aGUgcm9vbSBvdXQtb2YtYmFuZFxuICAgIG9vYkRhdGE/OiBJT09CRGF0YTtcblxuICAgIC8vIEZvciB0aGlyZCBwYXJ0eSBpbnZpdGVzLCBhIFVSTCBmb3IgYSAzcGlkIGludml0ZSBzaWduaW5nIHNlcnZpY2VcbiAgICBzaWduVXJsPzogc3RyaW5nO1xuXG4gICAgLy8gQSBzdGFuZGFyZCBjbGllbnQvc2VydmVyIEFQSSBlcnJvciBvYmplY3QuIElmIHN1cHBsaWVkLCBpbmRpY2F0ZXMgdGhhdCB0aGVcbiAgICAvLyBjYWxsZXIgd2FzIHVuYWJsZSB0byBmZXRjaCBkZXRhaWxzIGFib3V0IHRoZSByb29tIGZvciB0aGUgZ2l2ZW4gcmVhc29uLlxuICAgIGVycm9yPzogTWF0cml4RXJyb3I7XG5cbiAgICBjYW5QcmV2aWV3PzogYm9vbGVhbjtcbiAgICBwcmV2aWV3TG9hZGluZz86IGJvb2xlYW47XG5cbiAgICAvLyBUaGUgaWQgb2YgdGhlIHJvb20gdG8gYmUgcHJldmlld2VkLCBpZiBpdCBpcyBrbm93bi5cbiAgICAvLyAoSXQgbWF5IGJlIHVua25vd24gaWYgd2UgYXJlIHdhaXRpbmcgZm9yIGFuIGFsaWFzIHRvIGJlIHJlc29sdmVkLilcbiAgICByb29tSWQ/OiBzdHJpbmc7XG5cbiAgICAvLyBBIGBSb29tYCBvYmplY3QgZm9yIHRoZSByb29tIHRvIGJlIHByZXZpZXdlZCwgaWYgd2UgaGF2ZSBvbmUuXG4gICAgcm9vbT86IFJvb207XG5cbiAgICBsb2FkaW5nPzogYm9vbGVhbjtcbiAgICBqb2luaW5nPzogYm9vbGVhbjtcbiAgICByZWplY3Rpbmc/OiBib29sZWFuO1xuICAgIC8vIFRoZSBhbGlhcyB0aGF0IHdhcyB1c2VkIHRvIGFjY2VzcyB0aGlzIHJvb20sIGlmIGFwcHJvcHJpYXRlXG4gICAgLy8gSWYgZ2l2ZW4sIHRoaXMgd2lsbCBiZSBob3cgdGhlIHJvb20gaXMgcmVmZXJyZWQgdG8gKGVnLlxuICAgIC8vIGluIGVycm9yIG1lc3NhZ2VzKS5cbiAgICByb29tQWxpYXM/OiBzdHJpbmc7XG5cbiAgICBvbkpvaW5DbGljaz8oKTogdm9pZDtcbiAgICBvblJlamVjdENsaWNrPygpOiB2b2lkO1xuICAgIG9uUmVqZWN0QW5kSWdub3JlQ2xpY2s/KCk6IHZvaWQ7XG4gICAgb25Gb3JnZXRDbGljaz8oKTogdm9pZDtcblxuICAgIGNhbkFza1RvSm9pbkFuZE1lbWJlcnNoaXBJc0xlYXZlPzogYm9vbGVhbjtcbiAgICBwcm9tcHRBc2tUb0pvaW4/OiBib29sZWFuO1xuICAgIGtub2NrZWQ/OiBib29sZWFuO1xuICAgIG9uU3VibWl0QXNrVG9Kb2luPyhyZWFzb24/OiBzdHJpbmcpOiB2b2lkO1xuICAgIG9uQ2FuY2VsQXNrVG9Kb2luPygpOiB2b2lkO1xufVxuXG5pbnRlcmZhY2UgSVN0YXRlIHtcbiAgICBidXN5OiBib29sZWFuO1xuICAgIGFjY291bnRFbWFpbHM/OiBzdHJpbmdbXTtcbiAgICBpbnZpdGVkRW1haWxNeGlkPzogc3RyaW5nO1xuICAgIHRocmVlUGlkRmV0Y2hFcnJvcj86IE1hdHJpeEVycm9yO1xuICAgIHJlYXNvbj86IHN0cmluZztcbn1cblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgUm9vbVByZXZpZXdCYXIgZXh0ZW5kcyBSZWFjdC5Db21wb25lbnQ8SVByb3BzLCBJU3RhdGU+IHtcbiAgICBwdWJsaWMgc3RhdGljIGRlZmF1bHRQcm9wcyA9IHtcbiAgICAgICAgb25Kb2luQ2xpY2soKSB7fSxcbiAgICB9O1xuXG4gICAgcHVibGljIGNvbnN0cnVjdG9yKHByb3BzOiBJUHJvcHMpIHtcbiAgICAgICAgc3VwZXIocHJvcHMpO1xuXG4gICAgICAgIHRoaXMuc3RhdGUgPSB7XG4gICAgICAgICAgICBidXN5OiBmYWxzZSxcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBwdWJsaWMgY29tcG9uZW50RGlkTW91bnQoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuY2hlY2tJbnZpdGVkRW1haWwoKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgY29tcG9uZW50RGlkVXBkYXRlKHByZXZQcm9wczogSVByb3BzLCBwcmV2U3RhdGU6IElTdGF0ZSk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy5wcm9wcy5pbnZpdGVkRW1haWwgIT09IHByZXZQcm9wcy5pbnZpdGVkRW1haWwgfHwgdGhpcy5wcm9wcy5pbnZpdGVyTmFtZSAhPT0gcHJldlByb3BzLmludml0ZXJOYW1lKSB7XG4gICAgICAgICAgICB0aGlzLmNoZWNrSW52aXRlZEVtYWlsKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIGNoZWNrSW52aXRlZEVtYWlsKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICAvLyBJZiB0aGlzIGlzIGFuIGludml0ZSBhbmQgd2UndmUgYmVlbiB0b2xkIHdoYXQgZW1haWwgYWRkcmVzcyB3YXNcbiAgICAgICAgLy8gaW52aXRlZCwgZmV0Y2ggdGhlIHVzZXIncyBhY2NvdW50IGVtYWlscyBhbmQgZGlzY292ZXJ5IGJpbmRpbmdzIHNvIHdlXG4gICAgICAgIC8vIGNhbiBjaGVjayB0aGVtIGFnYWluc3QgdGhlIGVtYWlsIHRoYXQgd2FzIGludml0ZWQuXG4gICAgICAgIGlmICh0aGlzLnByb3BzLmludml0ZXJOYW1lICYmIHRoaXMucHJvcHMuaW52aXRlZEVtYWlsKSB7XG4gICAgICAgICAgICB0aGlzLnNldFN0YXRlKHsgYnVzeTogdHJ1ZSB9KTtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgLy8gR2F0aGVyIHRoZSBhY2NvdW50IDNQSURzXG4gICAgICAgICAgICAgICAgY29uc3QgYWNjb3VudDNwaWRzID0gYXdhaXQgTWF0cml4Q2xpZW50UGVnLnNhZmVHZXQoKS5nZXRUaHJlZVBpZHMoKTtcbiAgICAgICAgICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgICAgICAgICAgYWNjb3VudEVtYWlsczogYWNjb3VudDNwaWRzLnRocmVlcGlkcy5maWx0ZXIoKGIpID0+IGIubWVkaXVtID09PSBcImVtYWlsXCIpLm1hcCgoYikgPT4gYi5hZGRyZXNzKSxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAvLyBJZiB3ZSBoYXZlIGFuIElTIGNvbm5lY3RlZCwgdXNlIHRoYXQgdG8gbG9va3VwIHRoZSBlbWFpbCBhbmRcbiAgICAgICAgICAgICAgICAvLyBjaGVjayB0aGUgYm91bmQgTVhJRC5cbiAgICAgICAgICAgICAgICBpZiAoIU1hdHJpeENsaWVudFBlZy5zYWZlR2V0KCkuZ2V0SWRlbnRpdHlTZXJ2ZXJVcmwoKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnNldFN0YXRlKHsgYnVzeTogZmFsc2UgfSk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY29uc3QgYXV0aENsaWVudCA9IG5ldyBJZGVudGl0eUF1dGhDbGllbnQoKTtcbiAgICAgICAgICAgICAgICBjb25zdCBpZGVudGl0eUFjY2Vzc1Rva2VuID0gYXdhaXQgYXV0aENsaWVudC5nZXRBY2Nlc3NUb2tlbigpO1xuICAgICAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IE1hdHJpeENsaWVudFBlZy5zYWZlR2V0KCkubG9va3VwVGhyZWVQaWQoXG4gICAgICAgICAgICAgICAgICAgIFwiZW1haWxcIixcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wcm9wcy5pbnZpdGVkRW1haWwsXG4gICAgICAgICAgICAgICAgICAgIGlkZW50aXR5QWNjZXNzVG9rZW4hLFxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgaWYgKCEoXCJteGlkXCIgaW4gcmVzdWx0KSkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVXNlckZyaWVuZGx5RXJyb3IoXCJyb29tfGVycm9yXzNwaWRfaW52aXRlX2VtYWlsX2xvb2t1cFwiKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7IGludml0ZWRFbWFpbE14aWQ6IHJlc3VsdC5teGlkIH0pO1xuICAgICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7IHRocmVlUGlkRmV0Y2hFcnJvcjogZXJyIGFzIE1hdHJpeEVycm9yIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7IGJ1c3k6IGZhbHNlIH0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRNZXNzYWdlQ2FzZSgpOiBNZXNzYWdlQ2FzZSB7XG4gICAgICAgIGNvbnN0IGlzR3Vlc3QgPSBNYXRyaXhDbGllbnRQZWcuc2FmZUdldCgpLmlzR3Vlc3QoKTtcblxuICAgICAgICBpZiAoaXNHdWVzdCkge1xuICAgICAgICAgICAgcmV0dXJuIE1lc3NhZ2VDYXNlLk5vdExvZ2dlZEluO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgbXlNZW1iZXIgPSB0aGlzLmdldE15TWVtYmVyKCk7XG5cbiAgICAgICAgaWYgKG15TWVtYmVyKSB7XG4gICAgICAgICAgICBjb25zdCBwcmV2aW91c01lbWJlcnNoaXAgPSBteU1lbWJlci5ldmVudHMubWVtYmVyPy5nZXRQcmV2Q29udGVudCgpLm1lbWJlcnNoaXA7XG4gICAgICAgICAgICBpZiAobXlNZW1iZXIuaXNLaWNrZWQoKSkge1xuICAgICAgICAgICAgICAgIGlmIChwcmV2aW91c01lbWJlcnNoaXAgPT09IEtub3duTWVtYmVyc2hpcC5Lbm9jaykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gTWVzc2FnZUNhc2UuUmVxdWVzdERlbmllZDtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMucHJvcHMucHJvbXB0QXNrVG9Kb2luKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBNZXNzYWdlQ2FzZS5Qcm9tcHRBc2tUb0pvaW47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBNZXNzYWdlQ2FzZS5LaWNrZWQ7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG15TWVtYmVyLm1lbWJlcnNoaXAgPT09IEtub3duTWVtYmVyc2hpcC5CYW4pIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gTWVzc2FnZUNhc2UuQmFubmVkO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMucHJvcHMuam9pbmluZykge1xuICAgICAgICAgICAgcmV0dXJuIE1lc3NhZ2VDYXNlLkpvaW5pbmc7XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5wcm9wcy5yZWplY3RpbmcpIHtcbiAgICAgICAgICAgIHJldHVybiBNZXNzYWdlQ2FzZS5SZWplY3Rpbmc7XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5wcm9wcy5sb2FkaW5nIHx8IHRoaXMuc3RhdGUuYnVzeSkge1xuICAgICAgICAgICAgcmV0dXJuIE1lc3NhZ2VDYXNlLkxvYWRpbmc7XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5wcm9wcy5rbm9ja2VkKSB7XG4gICAgICAgICAgICByZXR1cm4gTWVzc2FnZUNhc2UuS25vY2tlZDtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLnByb3BzLmNhbkFza1RvSm9pbkFuZE1lbWJlcnNoaXBJc0xlYXZlIHx8IHRoaXMucHJvcHMucHJvbXB0QXNrVG9Kb2luKSB7XG4gICAgICAgICAgICByZXR1cm4gTWVzc2FnZUNhc2UuUHJvbXB0QXNrVG9Kb2luO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMucHJvcHMuaW52aXRlck5hbWUpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnByb3BzLmludml0ZWRFbWFpbCkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0YXRlLnRocmVlUGlkRmV0Y2hFcnJvcikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gTWVzc2FnZUNhc2UuT3RoZXJUaHJlZVBJREVycm9yO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodGhpcy5zdGF0ZS5hY2NvdW50RW1haWxzICYmICF0aGlzLnN0YXRlLmFjY291bnRFbWFpbHMuaW5jbHVkZXModGhpcy5wcm9wcy5pbnZpdGVkRW1haWwpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBNZXNzYWdlQ2FzZS5JbnZpdGVkRW1haWxOb3RGb3VuZEluQWNjb3VudDtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFNYXRyaXhDbGllbnRQZWcuc2FmZUdldCgpLmdldElkZW50aXR5U2VydmVyVXJsKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE1lc3NhZ2VDYXNlLkludml0ZWRFbWFpbE5vSWRlbnRpdHlTZXJ2ZXI7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0aGlzLnN0YXRlLmludml0ZWRFbWFpbE14aWQgIT0gTWF0cml4Q2xpZW50UGVnLnNhZmVHZXQoKS5nZXRVc2VySWQoKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gTWVzc2FnZUNhc2UuSW52aXRlZEVtYWlsTWlzbWF0Y2g7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIE1lc3NhZ2VDYXNlLkludml0ZTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLnByb3BzLmVycm9yKSB7XG4gICAgICAgICAgICBpZiAoKHRoaXMucHJvcHMuZXJyb3IgYXMgTWF0cml4RXJyb3IpLmVycmNvZGUgPT0gXCJNX05PVF9GT1VORFwiKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIE1lc3NhZ2VDYXNlLlJvb21Ob3RGb3VuZDtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIE1lc3NhZ2VDYXNlLk90aGVyRXJyb3I7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gTWVzc2FnZUNhc2UuVmlld2luZ1Jvb207XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGdldEtpY2tPckJhbkluZm8oKTogeyBtZW1iZXJOYW1lPzogc3RyaW5nOyByZWFzb24/OiBzdHJpbmcgfSB7XG4gICAgICAgIGNvbnN0IG15TWVtYmVyID0gdGhpcy5nZXRNeU1lbWJlcigpO1xuICAgICAgICBpZiAoIW15TWVtYmVyKSB7XG4gICAgICAgICAgICByZXR1cm4ge307XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBraWNrZXJVc2VySWQgPSBteU1lbWJlci5ldmVudHMubWVtYmVyPy5nZXRTZW5kZXIoKTtcbiAgICAgICAgY29uc3Qga2lja2VyTWVtYmVyID0ga2lja2VyVXNlcklkID8gdGhpcy5wcm9wcy5yb29tPy5jdXJyZW50U3RhdGUuZ2V0TWVtYmVyKGtpY2tlclVzZXJJZCkgOiB1bmRlZmluZWQ7XG4gICAgICAgIGNvbnN0IG1lbWJlck5hbWUgPSBraWNrZXJNZW1iZXI/Lm5hbWUgPz8ga2lja2VyVXNlcklkO1xuICAgICAgICBjb25zdCByZWFzb24gPSBteU1lbWJlci5ldmVudHMubWVtYmVyPy5nZXRDb250ZW50KCkucmVhc29uO1xuICAgICAgICByZXR1cm4geyBtZW1iZXJOYW1lLCByZWFzb24gfTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGpvaW5SdWxlKCk6IEpvaW5SdWxlIHwgbnVsbCB7XG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICB0aGlzLnByb3BzLnJvb20/LmN1cnJlbnRTdGF0ZVxuICAgICAgICAgICAgICAgIC5nZXRTdGF0ZUV2ZW50cyhFdmVudFR5cGUuUm9vbUpvaW5SdWxlcywgXCJcIilcbiAgICAgICAgICAgICAgICA/LmdldENvbnRlbnQ8Um9vbUpvaW5SdWxlc0V2ZW50Q29udGVudD4oKS5qb2luX3J1bGUgPz8gbnVsbFxuICAgICAgICApO1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0TXlNZW1iZXIoKTogUm9vbU1lbWJlciB8IG51bGwge1xuICAgICAgICByZXR1cm4gdGhpcy5wcm9wcy5yb29tPy5nZXRNZW1iZXIoTWF0cml4Q2xpZW50UGVnLnNhZmVHZXQoKS5nZXRTYWZlVXNlcklkKCkpID8/IG51bGw7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRJbnZpdGVNZW1iZXIoKTogUm9vbU1lbWJlciB8IG51bGwge1xuICAgICAgICBjb25zdCB7IHJvb20gfSA9IHRoaXMucHJvcHM7XG4gICAgICAgIGlmICghcm9vbSkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgbXlVc2VySWQgPSBNYXRyaXhDbGllbnRQZWcuc2FmZUdldCgpLmdldFNhZmVVc2VySWQoKTtcbiAgICAgICAgY29uc3QgaW52aXRlRXZlbnQgPSByb29tLmN1cnJlbnRTdGF0ZS5nZXRNZW1iZXIobXlVc2VySWQpO1xuICAgICAgICBpZiAoIWludml0ZUV2ZW50KSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBpbnZpdGVyVXNlcklkID0gaW52aXRlRXZlbnQuZXZlbnRzLm1lbWJlcj8uZ2V0U2VuZGVyKCk7XG4gICAgICAgIHJldHVybiBpbnZpdGVyVXNlcklkID8gcm9vbS5jdXJyZW50U3RhdGUuZ2V0TWVtYmVyKGludml0ZXJVc2VySWQpIDogbnVsbDtcbiAgICB9XG5cbiAgICBwcml2YXRlIGlzRE1JbnZpdGUoKTogYm9vbGVhbiB7XG4gICAgICAgIGNvbnN0IG15TWVtYmVyID0gdGhpcy5nZXRNeU1lbWJlcigpO1xuICAgICAgICBpZiAoIW15TWVtYmVyKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgbWVtYmVyQ29udGVudCA9IG15TWVtYmVyLmV2ZW50cy5tZW1iZXI/LmdldENvbnRlbnQoKTtcbiAgICAgICAgcmV0dXJuIG1lbWJlckNvbnRlbnQ/Lm1lbWJlcnNoaXAgPT09IEtub3duTWVtYmVyc2hpcC5JbnZpdGUgJiYgbWVtYmVyQ29udGVudC5pc19kaXJlY3Q7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBtYWtlU2NyZWVuQWZ0ZXJMb2dpbigpOiB7IHNjcmVlbjogc3RyaW5nOyBwYXJhbXM6IFJlY29yZDxzdHJpbmcsIGFueT4gfSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBzY3JlZW46IFwicm9vbVwiLFxuICAgICAgICAgICAgcGFyYW1zOiB7XG4gICAgICAgICAgICAgICAgZW1haWw6IHRoaXMucHJvcHMuaW52aXRlZEVtYWlsLFxuICAgICAgICAgICAgICAgIHNpZ251cmw6IHRoaXMucHJvcHMuc2lnblVybCxcbiAgICAgICAgICAgICAgICByb29tX25hbWU6IHRoaXMucHJvcHMub29iRGF0YT8ubmFtZSA/PyBudWxsLFxuICAgICAgICAgICAgICAgIHJvb21fYXZhdGFyX3VybDogdGhpcy5wcm9wcy5vb2JEYXRhPy5hdmF0YXJVcmwgPz8gbnVsbCxcbiAgICAgICAgICAgICAgICBpbnZpdGVyX25hbWU6IHRoaXMucHJvcHMub29iRGF0YT8uaW52aXRlck5hbWUgPz8gbnVsbCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBvbkxvZ2luQ2xpY2sgPSAoKTogdm9pZCA9PiB7XG4gICAgICAgIGRpcy5kaXNwYXRjaCh7IGFjdGlvbjogXCJzdGFydF9sb2dpblwiLCBzY3JlZW5BZnRlckxvZ2luOiB0aGlzLm1ha2VTY3JlZW5BZnRlckxvZ2luKCkgfSk7XG4gICAgfTtcblxuICAgIHByaXZhdGUgb25SZWdpc3RlckNsaWNrID0gKCk6IHZvaWQgPT4ge1xuICAgICAgICBkaXMuZGlzcGF0Y2goeyBhY3Rpb246IFwic3RhcnRfcmVnaXN0cmF0aW9uXCIsIHNjcmVlbkFmdGVyTG9naW46IHRoaXMubWFrZVNjcmVlbkFmdGVyTG9naW4oKSB9KTtcbiAgICB9O1xuXG4gICAgcHJpdmF0ZSBvbkNoYW5nZVJlYXNvbiA9IChldmVudDogQ2hhbmdlRXZlbnQ8SFRNTFRleHRBcmVhRWxlbWVudD4pOiB2b2lkID0+IHtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7IHJlYXNvbjogZXZlbnQudGFyZ2V0LnZhbHVlIH0pO1xuICAgIH07XG5cbiAgICBwdWJsaWMgcmVuZGVyKCk6IFJlYWN0LlJlYWN0Tm9kZSB7XG4gICAgICAgIGNvbnN0IGJyYW5kID0gU2RrQ29uZmlnLmdldCgpLmJyYW5kO1xuICAgICAgICBjb25zdCByb29tTmFtZSA9IHRoaXMucHJvcHMucm9vbT8ubmFtZSA/PyB0aGlzLnByb3BzLnJvb21BbGlhcyA/PyBcIlwiO1xuICAgICAgICBjb25zdCBpc1NwYWNlID0gdGhpcy5wcm9wcy5yb29tPy5pc1NwYWNlUm9vbSgpID8/IHRoaXMucHJvcHMub29iRGF0YT8ucm9vbVR5cGUgPT09IFJvb21UeXBlLlNwYWNlO1xuXG4gICAgICAgIGxldCBzaG93U3Bpbm5lciA9IGZhbHNlO1xuICAgICAgICBsZXQgdGl0bGU6IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgICAgICAgbGV0IHN1YlRpdGxlOiBzdHJpbmcgfCBSZWFjdE5vZGVbXSB8IHVuZGVmaW5lZDtcbiAgICAgICAgbGV0IHJlYXNvbkVsZW1lbnQ6IEpTWC5FbGVtZW50IHwgdW5kZWZpbmVkO1xuICAgICAgICBsZXQgcHJpbWFyeUFjdGlvbkhhbmRsZXI6ICgoKSA9PiB2b2lkKSB8IHVuZGVmaW5lZDtcbiAgICAgICAgbGV0IHByaW1hcnlBY3Rpb25MYWJlbDogc3RyaW5nIHwgdW5kZWZpbmVkO1xuICAgICAgICBsZXQgc2Vjb25kYXJ5QWN0aW9uSGFuZGxlcjogKCgpID0+IHZvaWQpIHwgdW5kZWZpbmVkO1xuICAgICAgICBsZXQgc2Vjb25kYXJ5QWN0aW9uTGFiZWw6IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgICAgICAgbGV0IGZvb3RlcjogSlNYLkVsZW1lbnQgfCB1bmRlZmluZWQ7XG4gICAgICAgIGNvbnN0IGV4dHJhQ29tcG9uZW50czogSlNYLkVsZW1lbnRbXSA9IFtdO1xuXG4gICAgICAgIGNvbnN0IG1lc3NhZ2VDYXNlID0gdGhpcy5nZXRNZXNzYWdlQ2FzZSgpO1xuICAgICAgICBzd2l0Y2ggKG1lc3NhZ2VDYXNlKSB7XG4gICAgICAgICAgICBjYXNlIE1lc3NhZ2VDYXNlLkpvaW5pbmc6IHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5wcm9wcy5vb2JEYXRhPy5yb29tVHlwZSB8fCBpc1NwYWNlKSB7XG4gICAgICAgICAgICAgICAgICAgIHRpdGxlID0gaXNTcGFjZSA/IF90KFwicm9vbXxqb2luaW5nX3NwYWNlXCIpIDogX3QoXCJyb29tfGpvaW5pbmdfcm9vbVwiKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aXRsZSA9IF90KFwicm9vbXxqb2luaW5nXCIpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHNob3dTcGlubmVyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhc2UgTWVzc2FnZUNhc2UuTG9hZGluZzoge1xuICAgICAgICAgICAgICAgIHRpdGxlID0gX3QoXCJjb21tb258bG9hZGluZ1wiKTtcbiAgICAgICAgICAgICAgICBzaG93U3Bpbm5lciA9IHRydWU7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYXNlIE1lc3NhZ2VDYXNlLlJlamVjdGluZzoge1xuICAgICAgICAgICAgICAgIHRpdGxlID0gX3QoXCJyb29tfHJlamVjdGluZ1wiKTtcbiAgICAgICAgICAgICAgICBzaG93U3Bpbm5lciA9IHRydWU7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYXNlIE1lc3NhZ2VDYXNlLk5vdExvZ2dlZEluOiB7XG4gICAgICAgICAgICAgICAgY29uc3Qgb3B0czogUm9vbVByZXZpZXdPcHRzID0geyBjYW5Kb2luOiBmYWxzZSB9O1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnByb3BzLnJvb21JZCkge1xuICAgICAgICAgICAgICAgICAgICBNb2R1bGVSdW5uZXIuaW5zdGFuY2UuaW52b2tlKFJvb21WaWV3TGlmZWN5Y2xlLlByZXZpZXdSb29tTm90TG9nZ2VkSW4sIG9wdHMsIHRoaXMucHJvcHMucm9vbUlkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKG9wdHMuY2FuSm9pbikge1xuICAgICAgICAgICAgICAgICAgICB0aXRsZSA9IF90KFwicm9vbXxqb2luX3RpdGxlXCIpO1xuICAgICAgICAgICAgICAgICAgICBwcmltYXJ5QWN0aW9uTGFiZWwgPSBfdChcImFjdGlvbnxqb2luXCIpO1xuICAgICAgICAgICAgICAgICAgICBwcmltYXJ5QWN0aW9uSGFuZGxlciA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIE1v