matrix-react-sdk
Version:
SDK for matrix.org using React
496 lines (403 loc) • 51.5 kB
JavaScript
"use strict";
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");
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 _utils = require("flux/utils");
var _dispatcher = _interopRequireDefault(require("../dispatcher/dispatcher"));
var _MatrixClientPeg = require("../MatrixClientPeg");
var sdk = _interopRequireWildcard(require("../index"));
var _Modal = _interopRequireDefault(require("../Modal"));
var _languageHandler = require("../languageHandler");
var _RoomAliasCache = require("../RoomAliasCache");
var _promise = require("../utils/promise");
var _CountlyAnalytics = _interopRequireDefault(require("../CountlyAnalytics"));
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { (0, _defineProperty2.default)(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
const NUM_JOIN_RETRY = 5;
const INITIAL_STATE = {
// Whether we're joining the currently viewed room (see isJoining())
joining: false,
// Any error that has occurred during joining
joinError: null,
// The room ID of the room currently being viewed
roomId: null,
// The event to scroll to when the room is first viewed
initialEventId: null,
initialEventPixelOffset: null,
// Whether to highlight the initial event
isInitialEventHighlighted: false,
// The room alias of the room (or null if not originally specified in view_room)
roomAlias: null,
// Whether the current room is loading
roomLoading: false,
// Any error that has occurred during loading
roomLoadError: null,
forwardingEvent: null,
quotingEvent: null,
replyingToEvent: null,
shouldPeek: false,
viaServers: [],
wasContextSwitch: false
};
/**
* A class for storing application state for RoomView. This is the RoomView's interface
* with a subset of the js-sdk.
* ```
*/
class RoomViewStore extends _utils.Store
/*:: <ActionPayload>*/
{
// initialize state
constructor() {
super(_dispatcher.default);
(0, _defineProperty2.default)(this, "state", INITIAL_STATE);
}
setState(newState
/*: Partial<typeof INITIAL_STATE>*/
) {
// If values haven't changed, there's nothing to do.
// This only tries a shallow comparison, so unchanged objects will slip
// through, but that's probably okay for now.
let stateChanged = false;
for (const key of Object.keys(newState)) {
if (this.state[key] !== newState[key]) {
stateChanged = true;
break;
}
}
if (!stateChanged) {
return;
}
this.state = Object.assign(this.state, newState);
this.__emitChange();
}
__onDispatch(payload) {
switch (payload.action) {
// view_room:
// - room_alias: '#somealias:matrix.org'
// - room_id: '!roomid123:matrix.org'
// - event_id: '$213456782:matrix.org'
// - event_offset: 100
// - highlighted: true
case 'view_room':
this.viewRoom(payload);
break;
// for these events blank out the roomId as we are no longer in the RoomView
case 'view_create_group':
case 'view_welcome_page':
case 'view_home_page':
case 'view_my_groups':
case 'view_group':
this.setState({
roomId: null,
roomAlias: null,
viaServers: [],
wasContextSwitch: false
});
break;
case 'view_room_error':
this.viewRoomError(payload);
break;
case 'will_join':
this.setState({
joining: true
});
break;
case 'cancel_join':
this.setState({
joining: false
});
break;
// join_room:
// - opts: options for joinRoom
case 'join_room':
this.joinRoom(payload);
break;
case 'join_room_error':
this.joinRoomError(payload);
break;
case 'join_room_ready':
this.setState({
shouldPeek: false
});
break;
case 'on_client_not_viable':
case 'on_logged_out':
this.reset();
break;
case 'forward_event':
this.setState({
forwardingEvent: payload.event
});
break;
case 'reply_to_event':
// If currently viewed room does not match the room in which we wish to reply then change rooms
// this can happen when performing a search across all rooms
if (payload.event && payload.event.getRoomId() !== this.state.roomId) {
_dispatcher.default.dispatch({
action: 'view_room',
room_id: payload.event.getRoomId(),
replyingToEvent: payload.event
});
} else {
this.setState({
replyingToEvent: payload.event
});
}
break;
case 'open_room_settings':
{
const RoomSettingsDialog = sdk.getComponent("dialogs.RoomSettingsDialog");
_Modal.default.createTrackedDialog('Room settings', '', RoomSettingsDialog, {
roomId: payload.room_id || this.state.roomId
},
/*className=*/
null,
/*isPriority=*/
false,
/*isStatic=*/
true);
break;
}
}
}
async viewRoom(payload
/*: ActionPayload*/
) {
if (payload.room_id) {
const newState = {
roomId: payload.room_id,
roomAlias: payload.room_alias,
initialEventId: payload.event_id,
isInitialEventHighlighted: payload.highlighted,
forwardingEvent: null,
roomLoading: false,
roomLoadError: null,
// should peek by default
shouldPeek: payload.should_peek === undefined ? true : payload.should_peek,
// have we sent a join request for this room and are waiting for a response?
joining: payload.joining || false,
// Reset replyingToEvent because we don't want cross-room because bad UX
replyingToEvent: null,
// pull the user out of Room Settings
isEditingSettings: false,
viaServers: payload.via_servers,
wasContextSwitch: payload.context_switch
}; // Allow being given an event to be replied to when switching rooms but sanity check its for this room
if (payload.replyingToEvent && payload.replyingToEvent.getRoomId() === payload.room_id) {
newState.replyingToEvent = payload.replyingToEvent;
}
if (this.state.forwardingEvent) {
_dispatcher.default.dispatch({
action: 'send_event',
room_id: newState.roomId,
event: this.state.forwardingEvent
});
}
this.setState(newState);
if (payload.auto_join) {
this.joinRoom(payload);
}
} else if (payload.room_alias) {
// Try the room alias to room ID navigation cache first to avoid
// blocking room navigation on the homeserver.
let roomId = (0, _RoomAliasCache.getCachedRoomIDForAlias)(payload.room_alias);
if (!roomId) {
// Room alias cache miss, so let's ask the homeserver. Resolve the alias
// and then do a second dispatch with the room ID acquired.
this.setState({
roomId: null,
initialEventId: null,
initialEventPixelOffset: null,
isInitialEventHighlighted: null,
roomAlias: payload.room_alias,
roomLoading: true,
roomLoadError: null,
viaServers: payload.via_servers,
wasContextSwitch: payload.context_switch
});
try {
const result = await _MatrixClientPeg.MatrixClientPeg.get().getRoomIdForAlias(payload.room_alias);
(0, _RoomAliasCache.storeRoomAliasInCache)(payload.room_alias, result.room_id);
roomId = result.room_id;
} catch (err) {
console.error("RVS failed to get room id for alias: ", err);
_dispatcher.default.dispatch({
action: 'view_room_error',
room_id: null,
room_alias: payload.room_alias,
err
});
return;
}
}
_dispatcher.default.dispatch({
action: 'view_room',
room_id: roomId,
event_id: payload.event_id,
highlighted: payload.highlighted,
room_alias: payload.room_alias,
auto_join: payload.auto_join,
oob_data: payload.oob_data,
viaServers: payload.via_servers,
wasContextSwitch: payload.context_switch
});
}
}
viewRoomError(payload
/*: ActionPayload*/
) {
this.setState({
roomId: payload.room_id,
roomAlias: payload.room_alias,
roomLoading: false,
roomLoadError: payload.err
});
}
async joinRoom(payload
/*: ActionPayload*/
) {
const startTime = _CountlyAnalytics.default.getTimestamp();
this.setState({
joining: true
});
const cli = _MatrixClientPeg.MatrixClientPeg.get();
const address = this.state.roomAlias || this.state.roomId;
const viaServers = this.state.viaServers || [];
try {
await (0, _promise.retry)(() => cli.joinRoom(address, _objectSpread({
viaServers
}, payload.opts)), NUM_JOIN_RETRY, err => {
// if we received a Gateway timeout then retry
return err.httpStatus === 504;
});
_CountlyAnalytics.default.instance.trackRoomJoin(startTime, this.state.roomId, payload._type); // We do *not* clear the 'joining' flag because the Room object and/or our 'joined' member event may not
// have come down the sync stream yet, and that's the point at which we'd consider the user joined to the
// room.
_dispatcher.default.dispatch({
action: 'join_room_ready'
});
} catch (err) {
_dispatcher.default.dispatch({
action: 'join_room_error',
err: err
});
let msg = err.message ? err.message : JSON.stringify(err);
console.log("Failed to join room:", msg);
if (err.name === "ConnectionError") {
msg = (0, _languageHandler._t)("There was an error joining the room");
} else if (err.errcode === 'M_INCOMPATIBLE_ROOM_VERSION') {
msg = /*#__PURE__*/_react.default.createElement("div", null, (0, _languageHandler._t)("Sorry, your homeserver is too old to participate in this room."), /*#__PURE__*/_react.default.createElement("br", null), (0, _languageHandler._t)("Please contact your homeserver administrator."));
} else if (err.httpStatus === 404) {
const invitingUserId = this.getInvitingUserId(this.state.roomId); // only provide a better error message for invites
if (invitingUserId) {
// if the inviting user is on the same HS, there can only be one cause: they left.
if (invitingUserId.endsWith(`:${_MatrixClientPeg.MatrixClientPeg.get().getDomain()}`)) {
msg = (0, _languageHandler._t)("The person who invited you already left the room.");
} else {
msg = (0, _languageHandler._t)("The person who invited you already left the room, or their server is offline.");
}
}
}
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
_Modal.default.createTrackedDialog('Failed to join room', '', ErrorDialog, {
title: (0, _languageHandler._t)("Failed to join room"),
description: msg
});
}
}
getInvitingUserId(roomId
/*: string*/
)
/*: string*/
{
const cli = _MatrixClientPeg.MatrixClientPeg.get();
const room = cli.getRoom(roomId);
if (room && room.getMyMembership() === "invite") {
const myMember = room.getMember(cli.getUserId());
const inviteEvent = myMember ? myMember.events.member : null;
return inviteEvent && inviteEvent.getSender();
}
}
joinRoomError(payload
/*: ActionPayload*/
) {
this.setState({
joining: false,
joinError: payload.err
});
}
reset() {
this.state = Object.assign({}, INITIAL_STATE);
} // The room ID of the room currently being viewed
getRoomId() {
return this.state.roomId;
} // The event to scroll to when the room is first viewed
getInitialEventId() {
return this.state.initialEventId;
} // Whether to highlight the initial event
isInitialEventHighlighted() {
return this.state.isInitialEventHighlighted;
} // The room alias of the room (or null if not originally specified in view_room)
getRoomAlias() {
return this.state.roomAlias;
} // Whether the current room is loading (true whilst resolving an alias)
isRoomLoading() {
return this.state.roomLoading;
} // Any error that has occurred during loading
getRoomLoadError() {
return this.state.roomLoadError;
} // True if we're expecting the user to be joined to the room currently being
// viewed. Note that this is left true after the join request has finished,
// since we should still consider a join to be in progress until the room
// & member events come down the sync.
//
// This flag remains true after the room has been sucessfully joined,
// (this store doesn't listen for the appropriate member events)
// so you should always observe the joined state from the member event
// if a room object is present.
// ie. The correct logic is:
// if (room) {
// if (myMember.membership == 'joined') {
// // user is joined to the room
// } else {
// // Not joined
// }
// } else {
// if (RoomViewStore.isJoining()) {
// // show spinner
// } else {
// // show join prompt
// }
// }
isJoining() {
return this.state.joining;
} // Any error that has occurred during joining
getJoinError() {
return this.state.joinError;
} // The mxEvent if one is about to be forwarded
getForwardingEvent() {
return this.state.forwardingEvent;
} // The mxEvent if one is currently being replied to/quoted
getQuotingEvent() {
return this.state.replyingToEvent;
}
shouldPeek() {
return this.state.shouldPeek;
}
getWasContextSwitch() {
return this.state.wasContextSwitch;
}
}
let singletonRoomViewStore = null;
if (!singletonRoomViewStore) {
singletonRoomViewStore = new RoomViewStore();
}
var _default = singletonRoomViewStore;
exports.default = _default;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zdG9yZXMvUm9vbVZpZXdTdG9yZS50c3giXSwibmFtZXMiOlsiTlVNX0pPSU5fUkVUUlkiLCJJTklUSUFMX1NUQVRFIiwiam9pbmluZyIsImpvaW5FcnJvciIsInJvb21JZCIsImluaXRpYWxFdmVudElkIiwiaW5pdGlhbEV2ZW50UGl4ZWxPZmZzZXQiLCJpc0luaXRpYWxFdmVudEhpZ2hsaWdodGVkIiwicm9vbUFsaWFzIiwicm9vbUxvYWRpbmciLCJyb29tTG9hZEVycm9yIiwiZm9yd2FyZGluZ0V2ZW50IiwicXVvdGluZ0V2ZW50IiwicmVwbHlpbmdUb0V2ZW50Iiwic2hvdWxkUGVlayIsInZpYVNlcnZlcnMiLCJ3YXNDb250ZXh0U3dpdGNoIiwiUm9vbVZpZXdTdG9yZSIsIlN0b3JlIiwiY29uc3RydWN0b3IiLCJkaXMiLCJzZXRTdGF0ZSIsIm5ld1N0YXRlIiwic3RhdGVDaGFuZ2VkIiwia2V5IiwiT2JqZWN0Iiwia2V5cyIsInN0YXRlIiwiYXNzaWduIiwiX19lbWl0Q2hhbmdlIiwiX19vbkRpc3BhdGNoIiwicGF5bG9hZCIsImFjdGlvbiIsInZpZXdSb29tIiwidmlld1Jvb21FcnJvciIsImpvaW5Sb29tIiwiam9pblJvb21FcnJvciIsInJlc2V0IiwiZXZlbnQiLCJnZXRSb29tSWQiLCJkaXNwYXRjaCIsInJvb21faWQiLCJSb29tU2V0dGluZ3NEaWFsb2ciLCJzZGsiLCJnZXRDb21wb25lbnQiLCJNb2RhbCIsImNyZWF0ZVRyYWNrZWREaWFsb2ciLCJyb29tX2FsaWFzIiwiZXZlbnRfaWQiLCJoaWdobGlnaHRlZCIsInNob3VsZF9wZWVrIiwidW5kZWZpbmVkIiwiaXNFZGl0aW5nU2V0dGluZ3MiLCJ2aWFfc2VydmVycyIsImNvbnRleHRfc3dpdGNoIiwiYXV0b19qb2luIiwicmVzdWx0IiwiTWF0cml4Q2xpZW50UGVnIiwiZ2V0IiwiZ2V0Um9vbUlkRm9yQWxpYXMiLCJlcnIiLCJjb25zb2xlIiwiZXJyb3IiLCJvb2JfZGF0YSIsInN0YXJ0VGltZSIsIkNvdW50bHlBbmFseXRpY3MiLCJnZXRUaW1lc3RhbXAiLCJjbGkiLCJhZGRyZXNzIiwib3B0cyIsImh0dHBTdGF0dXMiLCJpbnN0YW5jZSIsInRyYWNrUm9vbUpvaW4iLCJfdHlwZSIsIm1zZyIsIm1lc3NhZ2UiLCJKU09OIiwic3RyaW5naWZ5IiwibG9nIiwibmFtZSIsImVycmNvZGUiLCJpbnZpdGluZ1VzZXJJZCIsImdldEludml0aW5nVXNlcklkIiwiZW5kc1dpdGgiLCJnZXREb21haW4iLCJFcnJvckRpYWxvZyIsInRpdGxlIiwiZGVzY3JpcHRpb24iLCJyb29tIiwiZ2V0Um9vbSIsImdldE15TWVtYmVyc2hpcCIsIm15TWVtYmVyIiwiZ2V0TWVtYmVyIiwiZ2V0VXNlcklkIiwiaW52aXRlRXZlbnQiLCJldmVudHMiLCJtZW1iZXIiLCJnZXRTZW5kZXIiLCJnZXRJbml0aWFsRXZlbnRJZCIsImdldFJvb21BbGlhcyIsImlzUm9vbUxvYWRpbmciLCJnZXRSb29tTG9hZEVycm9yIiwiaXNKb2luaW5nIiwiZ2V0Sm9pbkVycm9yIiwiZ2V0Rm9yd2FyZGluZ0V2ZW50IiwiZ2V0UXVvdGluZ0V2ZW50IiwiZ2V0V2FzQ29udGV4dFN3aXRjaCIsInNpbmdsZXRvblJvb21WaWV3U3RvcmUiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7QUFrQkE7O0FBQ0E7O0FBR0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBRUE7O0FBQ0E7Ozs7OztBQUVBLE1BQU1BLGNBQWMsR0FBRyxDQUF2QjtBQUVBLE1BQU1DLGFBQWEsR0FBRztBQUNsQjtBQUNBQyxFQUFBQSxPQUFPLEVBQUUsS0FGUztBQUdsQjtBQUNBQyxFQUFBQSxTQUFTLEVBQUUsSUFKTztBQUtsQjtBQUNBQyxFQUFBQSxNQUFNLEVBQUUsSUFOVTtBQVFsQjtBQUNBQyxFQUFBQSxjQUFjLEVBQUUsSUFURTtBQVVsQkMsRUFBQUEsdUJBQXVCLEVBQUUsSUFWUDtBQVdsQjtBQUNBQyxFQUFBQSx5QkFBeUIsRUFBRSxLQVpUO0FBY2xCO0FBQ0FDLEVBQUFBLFNBQVMsRUFBRSxJQWZPO0FBZ0JsQjtBQUNBQyxFQUFBQSxXQUFXLEVBQUUsS0FqQks7QUFrQmxCO0FBQ0FDLEVBQUFBLGFBQWEsRUFBRSxJQW5CRztBQXFCbEJDLEVBQUFBLGVBQWUsRUFBRSxJQXJCQztBQXVCbEJDLEVBQUFBLFlBQVksRUFBRSxJQXZCSTtBQXlCbEJDLEVBQUFBLGVBQWUsRUFBRSxJQXpCQztBQTJCbEJDLEVBQUFBLFVBQVUsRUFBRSxLQTNCTTtBQTZCbEJDLEVBQUFBLFVBQVUsRUFBRSxFQTdCTTtBQStCbEJDLEVBQUFBLGdCQUFnQixFQUFFO0FBL0JBLENBQXRCO0FBa0NBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBQ0EsTUFBTUMsYUFBTixTQUE0QkM7QUFBNUI7QUFBaUQ7QUFDZDtBQUUvQkMsRUFBQUEsV0FBVyxHQUFHO0FBQ1YsVUFBTUMsbUJBQU47QUFEVSxpREFGRW5CLGFBRUY7QUFFYjs7QUFFRG9CLEVBQUFBLFFBQVEsQ0FBQ0M7QUFBRDtBQUFBLElBQTBDO0FBQzlDO0FBQ0E7QUFDQTtBQUNBLFFBQUlDLFlBQVksR0FBRyxLQUFuQjs7QUFDQSxTQUFLLE1BQU1DLEdBQVgsSUFBa0JDLE1BQU0sQ0FBQ0MsSUFBUCxDQUFZSixRQUFaLENBQWxCLEVBQXlDO0FBQ3JDLFVBQUksS0FBS0ssS0FBTCxDQUFXSCxHQUFYLE1BQW9CRixRQUFRLENBQUNFLEdBQUQsQ0FBaEMsRUFBdUM7QUFDbkNELFFBQUFBLFlBQVksR0FBRyxJQUFmO0FBQ0E7QUFDSDtBQUNKOztBQUNELFFBQUksQ0FBQ0EsWUFBTCxFQUFtQjtBQUNmO0FBQ0g7O0FBRUQsU0FBS0ksS0FBTCxHQUFhRixNQUFNLENBQUNHLE1BQVAsQ0FBYyxLQUFLRCxLQUFuQixFQUEwQkwsUUFBMUIsQ0FBYjs7QUFDQSxTQUFLTyxZQUFMO0FBQ0g7O0FBRURDLEVBQUFBLFlBQVksQ0FBQ0MsT0FBRCxFQUFVO0FBQ2xCLFlBQVFBLE9BQU8sQ0FBQ0MsTUFBaEI7QUFDSTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFLLFdBQUw7QUFDSSxhQUFLQyxRQUFMLENBQWNGLE9BQWQ7QUFDQTtBQUNKOztBQUNBLFdBQUssbUJBQUw7QUFDQSxXQUFLLG1CQUFMO0FBQ0EsV0FBSyxnQkFBTDtBQUNBLFdBQUssZ0JBQUw7QUFDQSxXQUFLLFlBQUw7QUFDSSxhQUFLVixRQUFMLENBQWM7QUFDVmpCLFVBQUFBLE1BQU0sRUFBRSxJQURFO0FBRVZJLFVBQUFBLFNBQVMsRUFBRSxJQUZEO0FBR1ZPLFVBQUFBLFVBQVUsRUFBRSxFQUhGO0FBSVZDLFVBQUFBLGdCQUFnQixFQUFFO0FBSlIsU0FBZDtBQU1BOztBQUNKLFdBQUssaUJBQUw7QUFDSSxhQUFLa0IsYUFBTCxDQUFtQkgsT0FBbkI7QUFDQTs7QUFDSixXQUFLLFdBQUw7QUFDSSxhQUFLVixRQUFMLENBQWM7QUFDVm5CLFVBQUFBLE9BQU8sRUFBRTtBQURDLFNBQWQ7QUFHQTs7QUFDSixXQUFLLGFBQUw7QUFDSSxhQUFLbUIsUUFBTCxDQUFjO0FBQ1ZuQixVQUFBQSxPQUFPLEVBQUU7QUFEQyxTQUFkO0FBR0E7QUFDSjtBQUNBOztBQUNBLFdBQUssV0FBTDtBQUNJLGFBQUtpQyxRQUFMLENBQWNKLE9BQWQ7QUFDQTs7QUFDSixXQUFLLGlCQUFMO0FBQ0ksYUFBS0ssYUFBTCxDQUFtQkwsT0FBbkI7QUFDQTs7QUFDSixXQUFLLGlCQUFMO0FBQ0ksYUFBS1YsUUFBTCxDQUFjO0FBQUVQLFVBQUFBLFVBQVUsRUFBRTtBQUFkLFNBQWQ7QUFDQTs7QUFDSixXQUFLLHNCQUFMO0FBQ0EsV0FBSyxlQUFMO0FBQ0ksYUFBS3VCLEtBQUw7QUFDQTs7QUFDSixXQUFLLGVBQUw7QUFDSSxhQUFLaEIsUUFBTCxDQUFjO0FBQ1ZWLFVBQUFBLGVBQWUsRUFBRW9CLE9BQU8sQ0FBQ087QUFEZixTQUFkO0FBR0E7O0FBQ0osV0FBSyxnQkFBTDtBQUNJO0FBQ0E7QUFDQSxZQUFJUCxPQUFPLENBQUNPLEtBQVIsSUFBaUJQLE9BQU8sQ0FBQ08sS0FBUixDQUFjQyxTQUFkLE9BQThCLEtBQUtaLEtBQUwsQ0FBV3ZCLE1BQTlELEVBQXNFO0FBQ2xFZ0IsOEJBQUlvQixRQUFKLENBQWE7QUFDVFIsWUFBQUEsTUFBTSxFQUFFLFdBREM7QUFFVFMsWUFBQUEsT0FBTyxFQUFFVixPQUFPLENBQUNPLEtBQVIsQ0FBY0MsU0FBZCxFQUZBO0FBR1QxQixZQUFBQSxlQUFlLEVBQUVrQixPQUFPLENBQUNPO0FBSGhCLFdBQWI7QUFLSCxTQU5ELE1BTU87QUFDSCxlQUFLakIsUUFBTCxDQUFjO0FBQ1ZSLFlBQUFBLGVBQWUsRUFBRWtCLE9BQU8sQ0FBQ087QUFEZixXQUFkO0FBR0g7O0FBQ0Q7O0FBQ0osV0FBSyxvQkFBTDtBQUEyQjtBQUN2QixnQkFBTUksa0JBQWtCLEdBQUdDLEdBQUcsQ0FBQ0MsWUFBSixDQUFpQiw0QkFBakIsQ0FBM0I7O0FBQ0FDLHlCQUFNQyxtQkFBTixDQUEwQixlQUExQixFQUEyQyxFQUEzQyxFQUErQ0osa0JBQS9DLEVBQW1FO0FBQy9EdEMsWUFBQUEsTUFBTSxFQUFFMkIsT0FBTyxDQUFDVSxPQUFSLElBQW1CLEtBQUtkLEtBQUwsQ0FBV3ZCO0FBRHlCLFdBQW5FO0FBRUc7QUFBYyxjQUZqQjtBQUV1QjtBQUFlLGVBRnRDO0FBRTZDO0FBQWEsY0FGMUQ7O0FBR0E7QUFDSDtBQTdFTDtBQStFSDs7QUFFRCxRQUFjNkIsUUFBZCxDQUF1QkY7QUFBdkI7QUFBQSxJQUErQztBQUMzQyxRQUFJQSxPQUFPLENBQUNVLE9BQVosRUFBcUI7QUFDakIsWUFBTW5CLFFBQVEsR0FBRztBQUNibEIsUUFBQUEsTUFBTSxFQUFFMkIsT0FBTyxDQUFDVSxPQURIO0FBRWJqQyxRQUFBQSxTQUFTLEVBQUV1QixPQUFPLENBQUNnQixVQUZOO0FBR2IxQyxRQUFBQSxjQUFjLEVBQUUwQixPQUFPLENBQUNpQixRQUhYO0FBSWJ6QyxRQUFBQSx5QkFBeUIsRUFBRXdCLE9BQU8sQ0FBQ2tCLFdBSnRCO0FBS2J0QyxRQUFBQSxlQUFlLEVBQUUsSUFMSjtBQU1iRixRQUFBQSxXQUFXLEVBQUUsS0FOQTtBQU9iQyxRQUFBQSxhQUFhLEVBQUUsSUFQRjtBQVFiO0FBQ0FJLFFBQUFBLFVBQVUsRUFBRWlCLE9BQU8sQ0FBQ21CLFdBQVIsS0FBd0JDLFNBQXhCLEdBQW9DLElBQXBDLEdBQTJDcEIsT0FBTyxDQUFDbUIsV0FUbEQ7QUFVYjtBQUNBaEQsUUFBQUEsT0FBTyxFQUFFNkIsT0FBTyxDQUFDN0IsT0FBUixJQUFtQixLQVhmO0FBWWI7QUFDQVcsUUFBQUEsZUFBZSxFQUFFLElBYko7QUFjYjtBQUNBdUMsUUFBQUEsaUJBQWlCLEVBQUUsS0FmTjtBQWdCYnJDLFFBQUFBLFVBQVUsRUFBRWdCLE9BQU8sQ0FBQ3NCLFdBaEJQO0FBaUJickMsUUFBQUEsZ0JBQWdCLEVBQUVlLE9BQU8sQ0FBQ3VCO0FBakJiLE9BQWpCLENBRGlCLENBcUJqQjs7QUFDQSxVQUFJdkIsT0FBTyxDQUFDbEIsZUFBUixJQUEyQmtCLE9BQU8sQ0FBQ2xCLGVBQVIsQ0FBd0IwQixTQUF4QixPQUF3Q1IsT0FBTyxDQUFDVSxPQUEvRSxFQUF3RjtBQUNwRm5CLFFBQUFBLFFBQVEsQ0FBQ1QsZUFBVCxHQUEyQmtCLE9BQU8sQ0FBQ2xCLGVBQW5DO0FBQ0g7O0FBRUQsVUFBSSxLQUFLYyxLQUFMLENBQVdoQixlQUFmLEVBQWdDO0FBQzVCUyw0QkFBSW9CLFFBQUosQ0FBYTtBQUNUUixVQUFBQSxNQUFNLEVBQUUsWUFEQztBQUVUUyxVQUFBQSxPQUFPLEVBQUVuQixRQUFRLENBQUNsQixNQUZUO0FBR1RrQyxVQUFBQSxLQUFLLEVBQUUsS0FBS1gsS0FBTCxDQUFXaEI7QUFIVCxTQUFiO0FBS0g7O0FBRUQsV0FBS1UsUUFBTCxDQUFjQyxRQUFkOztBQUVBLFVBQUlTLE9BQU8sQ0FBQ3dCLFNBQVosRUFBdUI7QUFDbkIsYUFBS3BCLFFBQUwsQ0FBY0osT0FBZDtBQUNIO0FBQ0osS0F2Q0QsTUF1Q08sSUFBSUEsT0FBTyxDQUFDZ0IsVUFBWixFQUF3QjtBQUMzQjtBQUNBO0FBQ0EsVUFBSTNDLE1BQU0sR0FBRyw2Q0FBd0IyQixPQUFPLENBQUNnQixVQUFoQyxDQUFiOztBQUNBLFVBQUksQ0FBQzNDLE1BQUwsRUFBYTtBQUNUO0FBQ0E7QUFDQSxhQUFLaUIsUUFBTCxDQUFjO0FBQ1ZqQixVQUFBQSxNQUFNLEVBQUUsSUFERTtBQUVWQyxVQUFBQSxjQUFjLEVBQUUsSUFGTjtBQUdWQyxVQUFBQSx1QkFBdUIsRUFBRSxJQUhmO0FBSVZDLFVBQUFBLHlCQUF5QixFQUFFLElBSmpCO0FBS1ZDLFVBQUFBLFNBQVMsRUFBRXVCLE9BQU8sQ0FBQ2dCLFVBTFQ7QUFNVnRDLFVBQUFBLFdBQVcsRUFBRSxJQU5IO0FBT1ZDLFVBQUFBLGFBQWEsRUFBRSxJQVBMO0FBUVZLLFVBQUFBLFVBQVUsRUFBRWdCLE9BQU8sQ0FBQ3NCLFdBUlY7QUFTVnJDLFVBQUFBLGdCQUFnQixFQUFFZSxPQUFPLENBQUN1QjtBQVRoQixTQUFkOztBQVdBLFlBQUk7QUFDQSxnQkFBTUUsTUFBTSxHQUFHLE1BQU1DLGlDQUFnQkMsR0FBaEIsR0FBc0JDLGlCQUF0QixDQUF3QzVCLE9BQU8sQ0FBQ2dCLFVBQWhELENBQXJCO0FBQ0EscURBQXNCaEIsT0FBTyxDQUFDZ0IsVUFBOUIsRUFBMENTLE1BQU0sQ0FBQ2YsT0FBakQ7QUFDQXJDLFVBQUFBLE1BQU0sR0FBR29ELE1BQU0sQ0FBQ2YsT0FBaEI7QUFDSCxTQUpELENBSUUsT0FBT21CLEdBQVAsRUFBWTtBQUNWQyxVQUFBQSxPQUFPLENBQUNDLEtBQVIsQ0FBYyx1Q0FBZCxFQUF1REYsR0FBdkQ7O0FBQ0F4Qyw4QkFBSW9CLFFBQUosQ0FBYTtBQUNUUixZQUFBQSxNQUFNLEVBQUUsaUJBREM7QUFFVFMsWUFBQUEsT0FBTyxFQUFFLElBRkE7QUFHVE0sWUFBQUEsVUFBVSxFQUFFaEIsT0FBTyxDQUFDZ0IsVUFIWDtBQUlUYSxZQUFBQTtBQUpTLFdBQWI7O0FBTUE7QUFDSDtBQUNKOztBQUVEeEMsMEJBQUlvQixRQUFKLENBQWE7QUFDVFIsUUFBQUEsTUFBTSxFQUFFLFdBREM7QUFFVFMsUUFBQUEsT0FBTyxFQUFFckMsTUFGQTtBQUdUNEMsUUFBQUEsUUFBUSxFQUFFakIsT0FBTyxDQUFDaUIsUUFIVDtBQUlUQyxRQUFBQSxXQUFXLEVBQUVsQixPQUFPLENBQUNrQixXQUpaO0FBS1RGLFFBQUFBLFVBQVUsRUFBRWhCLE9BQU8sQ0FBQ2dCLFVBTFg7QUFNVFEsUUFBQUEsU0FBUyxFQUFFeEIsT0FBTyxDQUFDd0IsU0FOVjtBQU9UUSxRQUFBQSxRQUFRLEVBQUVoQyxPQUFPLENBQUNnQyxRQVBUO0FBUVRoRCxRQUFBQSxVQUFVLEVBQUVnQixPQUFPLENBQUNzQixXQVJYO0FBU1RyQyxRQUFBQSxnQkFBZ0IsRUFBRWUsT0FBTyxDQUFDdUI7QUFUakIsT0FBYjtBQVdIO0FBQ0o7O0FBRU9wQixFQUFBQSxhQUFSLENBQXNCSDtBQUF0QjtBQUFBLElBQThDO0FBQzFDLFNBQUtWLFFBQUwsQ0FBYztBQUNWakIsTUFBQUEsTUFBTSxFQUFFMkIsT0FBTyxDQUFDVSxPQUROO0FBRVZqQyxNQUFBQSxTQUFTLEVBQUV1QixPQUFPLENBQUNnQixVQUZUO0FBR1Z0QyxNQUFBQSxXQUFXLEVBQUUsS0FISDtBQUlWQyxNQUFBQSxhQUFhLEVBQUVxQixPQUFPLENBQUM2QjtBQUpiLEtBQWQ7QUFNSDs7QUFFRCxRQUFjekIsUUFBZCxDQUF1Qko7QUFBdkI7QUFBQSxJQUErQztBQUMzQyxVQUFNaUMsU0FBUyxHQUFHQywwQkFBaUJDLFlBQWpCLEVBQWxCOztBQUNBLFNBQUs3QyxRQUFMLENBQWM7QUFDVm5CLE1BQUFBLE9BQU8sRUFBRTtBQURDLEtBQWQ7O0FBSUEsVUFBTWlFLEdBQUcsR0FBR1YsaUNBQWdCQyxHQUFoQixFQUFaOztBQUNBLFVBQU1VLE9BQU8sR0FBRyxLQUFLekMsS0FBTCxDQUFXbkIsU0FBWCxJQUF3QixLQUFLbUIsS0FBTCxDQUFXdkIsTUFBbkQ7QUFDQSxVQUFNVyxVQUFVLEdBQUcsS0FBS1ksS0FBTCxDQUFXWixVQUFYLElBQXlCLEVBQTVDOztBQUNBLFFBQUk7QUFDQSxZQUFNLG9CQUF5QixNQUFNb0QsR0FBRyxDQUFDaEMsUUFBSixDQUFhaUMsT0FBYjtBQUNqQ3JELFFBQUFBO0FBRGlDLFNBRTlCZ0IsT0FBTyxDQUFDc0MsSUFGc0IsRUFBL0IsRUFHRnJFLGNBSEUsRUFHZTRELEdBQUQsSUFBUztBQUN6QjtBQUNBLGVBQU9BLEdBQUcsQ0FBQ1UsVUFBSixLQUFtQixHQUExQjtBQUNILE9BTkssQ0FBTjs7QUFPQUwsZ0NBQWlCTSxRQUFqQixDQUEwQkMsYUFBMUIsQ0FBd0NSLFNBQXhDLEVBQW1ELEtBQUtyQyxLQUFMLENBQVd2QixNQUE5RCxFQUFzRTJCLE9BQU8sQ0FBQzBDLEtBQTlFLEVBUkEsQ0FVQTtBQUNBO0FBQ0E7OztBQUNBckQsMEJBQUlvQixRQUFKLENBQWE7QUFBRVIsUUFBQUEsTUFBTSxFQUFFO0FBQVYsT0FBYjtBQUNILEtBZEQsQ0FjRSxPQUFPNEIsR0FBUCxFQUFZO0FBQ1Z4QywwQkFBSW9CLFFBQUosQ0FBYTtBQUNUUixRQUFBQSxNQUFNLEVBQUUsaUJBREM7QUFFVDRCLFFBQUFBLEdBQUcsRUFBRUE7QUFGSSxPQUFiOztBQUtBLFVBQUljLEdBQUcsR0FBR2QsR0FBRyxDQUFDZSxPQUFKLEdBQWNmLEdBQUcsQ0FBQ2UsT0FBbEIsR0FBNEJDLElBQUksQ0FBQ0MsU0FBTCxDQUFlakIsR0FBZixDQUF0QztBQUNBQyxNQUFBQSxPQUFPLENBQUNpQixHQUFSLENBQVksc0JBQVosRUFBb0NKLEdBQXBDOztBQUVBLFVBQUlkLEdBQUcsQ0FBQ21CLElBQUosS0FBYSxpQkFBakIsRUFBb0M7QUFDaENMLFFBQUFBLEdBQUcsR0FBRyx5QkFBRyxxQ0FBSCxDQUFOO0FBQ0gsT0FGRCxNQUVPLElBQUlkLEdBQUcsQ0FBQ29CLE9BQUosS0FBZ0IsNkJBQXBCLEVBQW1EO0FBQ3RETixRQUFBQSxHQUFHLGdCQUFHLDBDQUNELHlCQUFHLGdFQUFILENBREMsZUFDb0Usd0NBRHBFLEVBRUQseUJBQUcsK0NBQUgsQ0FGQyxDQUFOO0FBSUgsT0FMTSxNQUtBLElBQUlkLEdBQUcsQ0FBQ1UsVUFBSixLQUFtQixHQUF2QixFQUE0QjtBQUMvQixjQUFNVyxjQUFjLEdBQUcsS0FBS0MsaUJBQUwsQ0FBdUIsS0FBS3ZELEtBQUwsQ0FBV3ZCLE1BQWxDLENBQXZCLENBRCtCLENBRS9COztBQUNBLFlBQUk2RSxjQUFKLEVBQW9CO0FBQ2hCO0FBQ0EsY0FBSUEsY0FBYyxDQUFDRSxRQUFmLENBQXlCLElBQUcxQixpQ0FBZ0JDLEdBQWhCLEdBQXNCMEIsU0FBdEIsRUFBa0MsRUFBOUQsQ0FBSixFQUFzRTtBQUNsRVYsWUFBQUEsR0FBRyxHQUFHLHlCQUFHLG1EQUFILENBQU47QUFDSCxXQUZELE1BRU87QUFDSEEsWUFBQUEsR0FBRyxHQUFHLHlCQUFHLCtFQUFILENBQU47QUFDSDtBQUNKO0FBQ0o7O0FBRUQsWUFBTVcsV0FBVyxHQUFHMUMsR0FBRyxDQUFDQyxZQUFKLENBQWlCLHFCQUFqQixDQUFwQjs7QUFDQUMscUJBQU1DLG1CQUFOLENBQTBCLHFCQUExQixFQUFpRCxFQUFqRCxFQUFxRHVDLFdBQXJELEVBQWtFO0FBQzlEQyxRQUFBQSxLQUFLLEVBQUUseUJBQUcscUJBQUgsQ0FEdUQ7QUFFOURDLFFBQUFBLFdBQVcsRUFBRWI7QUFGaUQsT0FBbEU7QUFJSDtBQUNKOztBQUVPUSxFQUFBQSxpQkFBUixDQUEwQjlFO0FBQTFCO0FBQUE7QUFBQTtBQUFrRDtBQUM5QyxVQUFNK0QsR0FBRyxHQUFHVixpQ0FBZ0JDLEdBQWhCLEVBQVo7O0FBQ0EsVUFBTThCLElBQUksR0FBR3JCLEdBQUcsQ0FBQ3NCLE9BQUosQ0FBWXJGLE1BQVosQ0FBYjs7QUFDQSxRQUFJb0YsSUFBSSxJQUFJQSxJQUFJLENBQUNFLGVBQUwsT0FBMkIsUUFBdkMsRUFBaUQ7QUFDN0MsWUFBTUMsUUFBUSxHQUFHSCxJQUFJLENBQUNJLFNBQUwsQ0FBZXpCLEdBQUcsQ0FBQzBCLFNBQUosRUFBZixDQUFqQjtBQUNBLFlBQU1DLFdBQVcsR0FBR0gsUUFBUSxHQUFHQSxRQUFRLENBQUNJLE1BQVQsQ0FBZ0JDLE1BQW5CLEdBQTRCLElBQXhEO0FBQ0EsYUFBT0YsV0FBVyxJQUFJQSxXQUFXLENBQUNHLFNBQVosRUFBdEI7QUFDSDtBQUNKOztBQUVPN0QsRUFBQUEsYUFBUixDQUFzQkw7QUFBdEI7QUFBQSxJQUE4QztBQUMxQyxTQUFLVixRQUFMLENBQWM7QUFDVm5CLE1BQUFBLE9BQU8sRUFBRSxLQURDO0FBRVZDLE1BQUFBLFNBQVMsRUFBRTRCLE9BQU8sQ0FBQzZCO0FBRlQsS0FBZDtBQUlIOztBQUVNdkIsRUFBQUEsS0FBUCxHQUFlO0FBQ1gsU0FBS1YsS0FBTCxHQUFhRixNQUFNLENBQUNHLE1BQVAsQ0FBYyxFQUFkLEVBQWtCM0IsYUFBbEIsQ0FBYjtBQUNILEdBNVI0QyxDQThSN0M7OztBQUNPc0MsRUFBQUEsU0FBUCxHQUFtQjtBQUNmLFdBQU8sS0FBS1osS0FBTCxDQUFXdkIsTUFBbEI7QUFDSCxHQWpTNEMsQ0FtUzdDOzs7QUFDTzhGLEVBQUFBLGlCQUFQLEdBQTJCO0FBQ3ZCLFdBQU8sS0FBS3ZFLEtBQUwsQ0FBV3RCLGNBQWxCO0FBQ0gsR0F0UzRDLENBd1M3Qzs7O0FBQ09FLEVBQUFBLHlCQUFQLEdBQW1DO0FBQy9CLFdBQU8sS0FBS29CLEtBQUwsQ0FBV3BCLHlCQUFsQjtBQUNILEdBM1M0QyxDQTZTN0M7OztBQUNPNEYsRUFBQUEsWUFBUCxHQUFzQjtBQUNsQixXQUFPLEtBQUt4RSxLQUFMLENBQVduQixTQUFsQjtBQUNILEdBaFQ0QyxDQWtUN0M7OztBQUNPNEYsRUFBQUEsYUFBUCxHQUF1QjtBQUNuQixXQUFPLEtBQUt6RSxLQUFMLENBQVdsQixXQUFsQjtBQUNILEdBclQ0QyxDQXVUN0M7OztBQUNPNEYsRUFBQUEsZ0JBQVAsR0FBMEI7QUFDdEIsV0FBTyxLQUFLMUUsS0FBTCxDQUFXakIsYUFBbEI7QUFDSCxHQTFUNEMsQ0E0VDdDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUNPNEYsRUFBQUEsU0FBUCxHQUFtQjtBQUNmLFdBQU8sS0FBSzNFLEtBQUwsQ0FBV3pCLE9BQWxCO0FBQ0gsR0FyVjRDLENBdVY3Qzs7O0FBQ09xRyxFQUFBQSxZQUFQLEdBQXNCO0FBQ2xCLFdBQU8sS0FBSzVFLEtBQUwsQ0FBV3hCLFNBQWxCO0FBQ0gsR0ExVjRDLENBNFY3Qzs7O0FBQ09xRyxFQUFBQSxrQkFBUCxHQUE0QjtBQUN4QixXQUFPLEtBQUs3RSxLQUFMLENBQVdoQixlQUFsQjtBQUNILEdBL1Y0QyxDQWlXN0M7OztBQUNPOEYsRUFBQUEsZUFBUCxHQUF5QjtBQUNyQixXQUFPLEtBQUs5RSxLQUFMLENBQVdkLGVBQWxCO0FBQ0g7O0FBRU1DLEVBQUFBLFVBQVAsR0FBb0I7QUFDaEIsV0FBTyxLQUFLYSxLQUFMLENBQVdiLFVBQWxCO0FBQ0g7O0FBRU00RixFQUFBQSxtQkFBUCxHQUE2QjtBQUN6QixXQUFPLEtBQUsvRSxLQUFMLENBQVdYLGdCQUFsQjtBQUNIOztBQTVXNEM7O0FBK1dqRCxJQUFJMkYsc0JBQXNCLEdBQUcsSUFBN0I7O0FBQ0EsSUFBSSxDQUFDQSxzQkFBTCxFQUE2QjtBQUN6QkEsRUFBQUEsc0JBQXNCLEdBQUcsSUFBSTFGLGFBQUosRUFBekI7QUFDSDs7ZUFDYzBGLHNCIiwic291cmNlc0NvbnRlbnQiOlsiLypcbkNvcHlyaWdodCAyMDE3IFZlY3RvciBDcmVhdGlvbnMgTHRkXG5Db3B5cmlnaHQgMjAxNywgMjAxOCBOZXcgVmVjdG9yIEx0ZFxuQ29weXJpZ2h0IDIwMTkgVGhlIE1hdHJpeC5vcmcgRm91bmRhdGlvbiBDLkkuQy5cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4qL1xuXG5pbXBvcnQgUmVhY3QgZnJvbSBcInJlYWN0XCI7XG5pbXBvcnQge1N0b3JlfSBmcm9tICdmbHV4L3V0aWxzJztcbmltcG9ydCB7TWF0cml4RXJyb3J9IGZyb20gXCJtYXRyaXgtanMtc2RrL3NyYy9odHRwLWFwaVwiO1xuXG5pbXBvcnQgZGlzIGZyb20gJy4uL2Rpc3BhdGNoZXIvZGlzcGF0Y2hlcic7XG5pbXBvcnQge01hdHJpeENsaWVudFBlZ30gZnJvbSAnLi4vTWF0cml4Q2xpZW50UGVnJztcbmltcG9ydCAqIGFzIHNkayBmcm9tICcuLi9pbmRleCc7XG5pbXBvcnQgTW9kYWwgZnJvbSAnLi4vTW9kYWwnO1xuaW1wb3J0IHsgX3QgfSBmcm9tICcuLi9sYW5ndWFnZUhhbmRsZXInO1xuaW1wb3J0IHsgZ2V0Q2FjaGVkUm9vbUlERm9yQWxpYXMsIHN0b3JlUm9vbUFsaWFzSW5DYWNoZSB9IGZyb20gJy4uL1Jvb21BbGlhc0NhY2hlJztcbmltcG9ydCB7QWN0aW9uUGF5bG9hZH0gZnJvbSBcIi4uL2Rpc3BhdGNoZXIvcGF5bG9hZHNcIjtcbmltcG9ydCB7cmV0cnl9IGZyb20gXCIuLi91dGlscy9wcm9taXNlXCI7XG5pbXBvcnQgQ291bnRseUFuYWx5dGljcyBmcm9tIFwiLi4vQ291bnRseUFuYWx5dGljc1wiO1xuXG5jb25zdCBOVU1fSk9JTl9SRVRSWSA9IDU7XG5cbmNvbnN0IElOSVRJQUxfU1RBVEUgPSB7XG4gICAgLy8gV2hldGhlciB3ZSdyZSBqb2luaW5nIHRoZSBjdXJyZW50bHkgdmlld2VkIHJvb20gKHNlZSBpc0pvaW5pbmcoKSlcbiAgICBqb2luaW5nOiBmYWxzZSxcbiAgICAvLyBBbnkgZXJyb3IgdGhhdCBoYXMgb2NjdXJyZWQgZHVyaW5nIGpvaW5pbmdcbiAgICBqb2luRXJyb3I6IG51bGwsXG4gICAgLy8gVGhlIHJvb20gSUQgb2YgdGhlIHJvb20gY3VycmVudGx5IGJlaW5nIHZpZXdlZFxuICAgIHJvb21JZDogbnVsbCxcblxuICAgIC8vIFRoZSBldmVudCB0byBzY3JvbGwgdG8gd2hlbiB0aGUgcm9vbSBpcyBmaXJzdCB2aWV3ZWRcbiAgICBpbml0aWFsRXZlbnRJZDogbnVsbCxcbiAgICBpbml0aWFsRXZlbnRQaXhlbE9mZnNldDogbnVsbCxcbiAgICAvLyBXaGV0aGVyIHRvIGhpZ2hsaWdodCB0aGUgaW5pdGlhbCBldmVudFxuICAgIGlzSW5pdGlhbEV2ZW50SGlnaGxpZ2h0ZWQ6IGZhbHNlLFxuXG4gICAgLy8gVGhlIHJvb20gYWxpYXMgb2YgdGhlIHJvb20gKG9yIG51bGwgaWYgbm90IG9yaWdpbmFsbHkgc3BlY2lmaWVkIGluIHZpZXdfcm9vbSlcbiAgICByb29tQWxpYXM6IG51bGwsXG4gICAgLy8gV2hldGhlciB0aGUgY3VycmVudCByb29tIGlzIGxvYWRpbmdcbiAgICByb29tTG9hZGluZzogZmFsc2UsXG4gICAgLy8gQW55IGVycm9yIHRoYXQgaGFzIG9jY3VycmVkIGR1cmluZyBsb2FkaW5nXG4gICAgcm9vbUxvYWRFcnJvcjogbnVsbCxcblxuICAgIGZvcndhcmRpbmdFdmVudDogbnVsbCxcblxuICAgIHF1b3RpbmdFdmVudDogbnVsbCxcblxuICAgIHJlcGx5aW5nVG9FdmVudDogbnVsbCxcblxuICAgIHNob3VsZFBlZWs6IGZhbHNlLFxuXG4gICAgdmlhU2VydmVyczogW10sXG5cbiAgICB3YXNDb250ZXh0U3dpdGNoOiBmYWxzZSxcbn07XG5cbi8qKlxuICogQSBjbGFzcyBmb3Igc3RvcmluZyBhcHBsaWNhdGlvbiBzdGF0ZSBmb3IgUm9vbVZpZXcuIFRoaXMgaXMgdGhlIFJvb21WaWV3J3MgaW50ZXJmYWNlXG4qICB3aXRoIGEgc3Vic2V0IG9mIHRoZSBqcy1zZGsuXG4gKiAgYGBgXG4gKi9cbmNsYXNzIFJvb21WaWV3U3RvcmUgZXh0ZW5kcyBTdG9yZTxBY3Rpb25QYXlsb2FkPiB7XG4gICAgcHJpdmF0ZSBzdGF0ZSA9IElOSVRJQUxfU1RBVEU7IC8vIGluaXRpYWxpemUgc3RhdGVcblxuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICBzdXBlcihkaXMpO1xuICAgIH1cblxuICAgIHNldFN0YXRlKG5ld1N0YXRlOiBQYXJ0aWFsPHR5cGVvZiBJTklUSUFMX1NUQVRFPikge1xuICAgICAgICAvLyBJZiB2YWx1ZXMgaGF2ZW4ndCBjaGFuZ2VkLCB0aGVyZSdzIG5vdGhpbmcgdG8gZG8uXG4gICAgICAgIC8vIFRoaXMgb25seSB0cmllcyBhIHNoYWxsb3cgY29tcGFyaXNvbiwgc28gdW5jaGFuZ2VkIG9iamVjdHMgd2lsbCBzbGlwXG4gICAgICAgIC8vIHRocm91Z2gsIGJ1dCB0aGF0J3MgcHJvYmFibHkgb2theSBmb3Igbm93LlxuICAgICAgICBsZXQgc3RhdGVDaGFuZ2VkID0gZmFsc2U7XG4gICAgICAgIGZvciAoY29uc3Qga2V5IG9mIE9iamVjdC5rZXlzKG5ld1N0YXRlKSkge1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RhdGVba2V5XSAhPT0gbmV3U3RhdGVba2V5XSkge1xuICAgICAgICAgICAgICAgIHN0YXRlQ2hhbmdlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFzdGF0ZUNoYW5nZWQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuc3RhdGUgPSBPYmplY3QuYXNzaWduKHRoaXMuc3RhdGUsIG5ld1N0YXRlKTtcbiAgICAgICAgdGhpcy5fX2VtaXRDaGFuZ2UoKTtcbiAgICB9XG5cbiAgICBfX29uRGlzcGF0Y2gocGF5bG9hZCkge1xuICAgICAgICBzd2l0Y2ggKHBheWxvYWQuYWN0aW9uKSB7XG4gICAgICAgICAgICAvLyB2aWV3X3Jvb206XG4gICAgICAgICAgICAvLyAgICAgIC0gcm9vbV9hbGlhczogICAnI3NvbWVhbGlhczptYXRyaXgub3JnJ1xuICAgICAgICAgICAgLy8gICAgICAtIHJvb21faWQ6ICAgICAgJyFyb29taWQxMjM6bWF0cml4Lm9yZydcbiAgICAgICAgICAgIC8vICAgICAgLSBldmVudF9pZDogICAgICckMjEzNDU2NzgyOm1hdHJpeC5vcmcnXG4gICAgICAgICAgICAvLyAgICAgIC0gZXZlbnRfb2Zmc2V0OiAxMDBcbiAgICAgICAgICAgIC8vICAgICAgLSBoaWdobGlnaHRlZDogIHRydWVcbiAgICAgICAgICAgIGNhc2UgJ3ZpZXdfcm9vbSc6XG4gICAgICAgICAgICAgICAgdGhpcy52aWV3Um9vbShwYXlsb2FkKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIC8vIGZvciB0aGVzZSBldmVudHMgYmxhbmsgb3V0IHRoZSByb29tSWQgYXMgd2UgYXJlIG5vIGxvbmdlciBpbiB0aGUgUm9vbVZpZXdcbiAgICAgICAgICAgIGNhc2UgJ3ZpZXdfY3JlYXRlX2dyb3VwJzpcbiAgICAgICAgICAgIGNhc2UgJ3ZpZXdfd2VsY29tZV9wYWdlJzpcbiAgICAgICAgICAgIGNhc2UgJ3ZpZXdfaG9tZV9wYWdlJzpcbiAgICAgICAgICAgIGNhc2UgJ3ZpZXdfbXlfZ3JvdXBzJzpcbiAgICAgICAgICAgIGNhc2UgJ3ZpZXdfZ3JvdXAnOlxuICAgICAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgICAgICAgICByb29tSWQ6IG51bGwsXG4gICAgICAgICAgICAgICAgICAgIHJvb21BbGlhczogbnVsbCxcbiAgICAgICAgICAgICAgICAgICAgdmlhU2VydmVyczogW10sXG4gICAgICAgICAgICAgICAgICAgIHdhc0NvbnRleHRTd2l0Y2g6IGZhbHNlLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAndmlld19yb29tX2Vycm9yJzpcbiAgICAgICAgICAgICAgICB0aGlzLnZpZXdSb29tRXJyb3IocGF5bG9hZCk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICd3aWxsX2pvaW4nOlxuICAgICAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgICAgICAgICBqb2luaW5nOiB0cnVlLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnY2FuY2VsX2pvaW4nOlxuICAgICAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgICAgICAgICBqb2luaW5nOiBmYWxzZSxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIC8vIGpvaW5fcm9vbTpcbiAgICAgICAgICAgIC8vICAgICAgLSBvcHRzOiBvcHRpb25zIGZvciBqb2luUm9vbVxuICAgICAgICAgICAgY2FzZSAnam9pbl9yb29tJzpcbiAgICAgICAgICAgICAgICB0aGlzLmpvaW5Sb29tKHBheWxvYWQpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnam9pbl9yb29tX2Vycm9yJzpcbiAgICAgICAgICAgICAgICB0aGlzLmpvaW5Sb29tRXJyb3IocGF5bG9hZCk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdqb2luX3Jvb21fcmVhZHknOlxuICAgICAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoeyBzaG91bGRQZWVrOiBmYWxzZSB9KTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ29uX2NsaWVudF9ub3RfdmlhYmxlJzpcbiAgICAgICAgICAgIGNhc2UgJ29uX2xvZ2dlZF9vdXQnOlxuICAgICAgICAgICAgICAgIHRoaXMucmVzZXQoKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ2ZvcndhcmRfZXZlbnQnOlxuICAgICAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgICAgICAgICBmb3J3YXJkaW5nRXZlbnQ6IHBheWxvYWQuZXZlbnQsXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdyZXBseV90b19ldmVudCc6XG4gICAgICAgICAgICAgICAgLy8gSWYgY3VycmVudGx5IHZpZXdlZCByb29tIGRvZXMgbm90IG1hdGNoIHRoZSByb29tIGluIHdoaWNoIHdlIHdpc2ggdG8gcmVwbHkgdGhlbiBjaGFuZ2Ugcm9vbXNcbiAgICAgICAgICAgICAgICAvLyB0aGlzIGNhbiBoYXBwZW4gd2hlbiBwZXJmb3JtaW5nIGEgc2VhcmNoIGFjcm9zcyBhbGwgcm9vbXNcbiAgICAgICAgICAgICAgICBpZiAocGF5bG9hZC5ldmVudCAmJiBwYXlsb2FkLmV2ZW50LmdldFJvb21JZCgpICE9PSB0aGlzLnN0YXRlLnJvb21JZCkge1xuICAgICAgICAgICAgICAgICAgICBkaXMuZGlzcGF0Y2goe1xuICAgICAgICAgICAgICAgICAgICAgICAgYWN0aW9uOiAndmlld19yb29tJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHJvb21faWQ6IHBheWxvYWQuZXZlbnQuZ2V0Um9vbUlkKCksXG4gICAgICAgICAgICAgICAgICAgICAgICByZXBseWluZ1RvRXZlbnQ6IHBheWxvYWQuZXZlbnQsXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVwbHlpbmdUb0V2ZW50OiBwYXlsb2FkLmV2ZW50LFxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdvcGVuX3Jvb21fc2V0dGluZ3MnOiB7XG4gICAgICAgICAgICAgICAgY29uc3QgUm9vbVNldHRpbmdzRGlhbG9nID0gc2RrLmdldENvbXBvbmVudChcImRpYWxvZ3MuUm9vbVNldHRpbmdzRGlhbG9nXCIpO1xuICAgICAgICAgICAgICAgIE1vZGFsLmNyZWF0ZVRyYWNrZWREaWFsb2coJ1Jvb20gc2V0dGluZ3MnLCAnJywgUm9vbVNldHRpbmdzRGlhbG9nLCB7XG4gICAgICAgICAgICAgICAgICAgIHJvb21JZDogcGF5bG9hZC5yb29tX2lkIHx8IHRoaXMuc3RhdGUucm9vbUlkLFxuICAgICAgICAgICAgICAgIH0sIC8qY2xhc3NOYW1lPSovbnVsbCwgLyppc1ByaW9yaXR5PSovZmFsc2UsIC8qaXNTdGF0aWM9Ki90cnVlKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgdmlld1Jvb20ocGF5bG9hZDogQWN0aW9uUGF5bG9hZCkge1xuICAgICAgICBpZiAocGF5bG9hZC5yb29tX2lkKSB7XG4gICAgICAgICAgICBjb25zdCBuZXdTdGF0ZSA9IHtcbiAgICAgICAgICAgICAgICByb29tSWQ6IHBheWxvYWQucm9vbV9pZCxcbiAgICAgICAgICAgICAgICByb29tQWxpYXM6IHBheWxvYWQucm9vbV9hbGlhcyxcbiAgICAgICAgICAgICAgICBpbml0aWFsRXZlbnRJZDogcGF5bG9hZC5ldmVudF9pZCxcbiAgICAgICAgICAgICAgICBpc0luaXRpYWxFdmVudEhpZ2hsaWdodGVkOiBwYXlsb2FkLmhpZ2hsaWdodGVkLFxuICAgICAgICAgICAgICAgIGZvcndhcmRpbmdFdmVudDogbnVsbCxcbiAgICAgICAgICAgICAgICByb29tTG9hZGluZzogZmFsc2UsXG4gICAgICAgICAgICAgICAgcm9vbUxvYWRFcnJvcjogbnVsbCxcbiAgICAgICAgICAgICAgICAvLyBzaG91bGQgcGVlayBieSBkZWZhdWx0XG4gICAgICAgICAgICAgICAgc2hvdWxkUGVlazogcGF5bG9hZC5zaG91bGRfcGVlayA9PT0gdW5kZWZpbmVkID8gdHJ1ZSA6IHBheWxvYWQuc2hvdWxkX3BlZWssXG4gICAgICAgICAgICAgICAgLy8gaGF2ZSB3ZSBzZW50IGEgam9pbiByZXF1ZXN0IGZvciB0aGlzIHJvb20gYW5kIGFyZSB3YWl0aW5nIGZvciBhIHJlc3BvbnNlP1xuICAgICAgICAgICAgICAgIGpvaW5pbmc6IHBheWxvYWQuam9pbmluZyB8fCBmYWxzZSxcbiAgICAgICAgICAgICAgICAvLyBSZXNldCByZXBseWluZ1RvRXZlbnQgYmVjYXVzZSB3ZSBkb24ndCB3YW50IGNyb3NzLXJvb20gYmVjYXVzZSBiYWQgVVhcbiAgICAgICAgICAgICAgICByZXBseWluZ1RvRXZlbnQ6IG51bGwsXG4gICAgICAgICAgICAgICAgLy8gcHVsbCB0aGUgdXNlciBvdXQgb2YgUm9vbSBTZXR0aW5nc1xuICAgICAgICAgICAgICAgIGlzRWRpdGluZ1NldHRpbmdzOiBmYWxzZSxcbiAgICAgICAgICAgICAgICB2aWFTZXJ2ZXJzOiBwYXlsb2FkLnZpYV9zZXJ2ZXJzLFxuICAgICAgICAgICAgICAgIHdhc0NvbnRleHRTd2l0Y2g6IHBheWxvYWQuY29udGV4dF9zd2l0Y2gsXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAvLyBBbGxvdyBiZWluZyBnaXZlbiBhbiBldmVudCB0byBiZSByZXBsaWVkIHRvIHdoZW4gc3dpdGNoaW5nIHJvb21zIGJ1dCBzYW5pdHkgY2hlY2sgaXRzIGZvciB0aGlzIHJvb21cbiAgICAgICAgICAgIGlmIChwYXlsb2FkLnJlcGx5aW5nVG9FdmVudCAmJiBwYXlsb2FkLnJlcGx5aW5nVG9FdmVudC5nZXRSb29tSWQoKSA9PT0gcGF5bG9hZC5yb29tX2lkKSB7XG4gICAgICAgICAgICAgICAgbmV3U3RhdGUucmVwbHlpbmdUb0V2ZW50ID0gcGF5bG9hZC5yZXBseWluZ1RvRXZlbnQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0aGlzLnN0YXRlLmZvcndhcmRpbmdFdmVudCkge1xuICAgICAgICAgICAgICAgIGRpcy5kaXNwYXRjaCh7XG4gICAgICAgICAgICAgICAgICAgIGFjdGlvbjogJ3NlbmRfZXZlbnQnLFxuICAgICAgICAgICAgICAgICAgICByb29tX2lkOiBuZXdTdGF0ZS5yb29tSWQsXG4gICAgICAgICAgICAgICAgICAgIGV2ZW50OiB0aGlzLnN0YXRlLmZvcndhcmRpbmdFdmVudCxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZShuZXdTdGF0ZSk7XG5cbiAgICAgICAgICAgIGlmIChwYXlsb2FkLmF1dG9fam9pbikge1xuICAgICAgICAgICAgICAgIHRoaXMuam9pblJvb20ocGF5bG9hZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAocGF5bG9hZC5yb29tX2FsaWFzKSB7XG4gICAgICAgICAgICAvLyBUcnkgdGhlIHJvb20gYWxpYXMgdG8gcm9vbSBJRCBuYXZpZ2F0aW9uIGNhY2hlIGZpcnN0IHRvIGF2b2lkXG4gICAgICAgICAgICAvLyBibG9ja2luZyByb29tIG5hdmlnYXRpb24gb24gdGhlIGhvbWVzZXJ2ZXIuXG4gICAgICAgICAgICBsZXQgcm9vbUlkID0gZ2V0Q2FjaGVkUm9vbUlERm9yQWxpYXMocGF5bG9hZC5yb29tX2FsaWFzKTtcbiAgICAgICAgICAgIGlmICghcm9vbUlkKSB7XG4gICAgICAgICAgICAgICAgLy8gUm9vbSBhbGlhcyBjYWNoZSBtaXNzLCBzbyBsZXQncyBhc2sgdGhlIGhvbWVzZXJ2ZXIuIFJlc29sdmUgdGhlIGFsaWFzXG4gICAgICAgICAgICAgICAgLy8gYW5kIHRoZW4gZG8gYSBzZWNvbmQgZGlzcGF0Y2ggd2l0aCB0aGUgcm9vbSBJRCBhY3F1aXJlZC5cbiAgICAgICAgICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgICAgICAgICAgcm9vbUlkOiBudWxsLFxuICAgICAgICAgICAgICAgICAgICBpbml0aWFsRXZlbnRJZDogbnVsbCxcbiAgICAgICAgICAgICAgICAgICAgaW5pdGlhbEV2ZW50UGl4ZWxPZmZzZXQ6IG51bGwsXG4gICAgICAgICAgICAgICAgICAgIGlzSW5pdGlhbEV2ZW50SGlnaGxpZ2h0ZWQ6IG51bGwsXG4gICAgICAgICAgICAgICAgICAgIHJvb21BbGlhczogcGF5bG9hZC5yb29tX2FsaWFzLFxuICAgICAgICAgICAgICAgICAgICByb29tTG9hZGluZzogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgcm9vbUxvYWRFcnJvcjogbnVsbCxcbiAgICAgICAgICAgICAgICAgICAgdmlhU2VydmVyczogcGF5bG9hZC52aWFfc2VydmVycyxcbiAgICAgICAgICAgICAgICAgICAgd2FzQ29udGV4dFN3aXRjaDogcGF5bG9hZC5jb250ZXh0X3N3aXRjaCxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBNYXRyaXhDbGllbnRQZWcuZ2V0KCkuZ2V0Um9vbUlkRm9yQWxpYXMocGF5bG9hZC5yb29tX2FsaWFzKTtcbiAgICAgICAgICAgICAgICAgICAgc3RvcmVSb29tQWxpYXNJbkNhY2hlKHBheWxvYWQucm9vbV9hbGlhcywgcmVzdWx0LnJvb21faWQpO1xuICAgICAgICAgICAgICAgICAgICByb29tSWQgPSByZXN1bHQucm9vbV9pZDtcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihcIlJWUyBmYWlsZWQgdG8gZ2V0IHJvb20gaWQgZm9yIGFsaWFzOiBcIiwgZXJyKTtcbiAgICAgICAgICAgICAgICAgICAgZGlzLmRpc3BhdGNoKHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFjdGlvbjogJ3ZpZXdfcm9vbV9lcnJvcicsXG4gICAgICAgICAgICAgICAgICAgICAgICByb29tX2lkOiBudWxsLFxuICAgICAgICAgICAgICAgICAgICAgICAgcm9vbV9hbGlhczogcGF5bG9hZC5yb29tX2FsaWFzLFxuICAgICAgICAgICAgICAgICAgICAgICAgZXJyLFxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZGlzLmRpc3BhdGNoKHtcbiAgICAgICAgICAgICAgICBhY3Rpb246ICd2aWV3X3Jvb20nLFxuICAgICAgICAgICAgICAgIHJvb21faWQ6IHJvb21JZCxcbiAgICAgICAgICAgICAgICBldmVudF9pZDogcGF5bG9hZC5ldmVudF9pZCxcbiAgICAgICAgICAgICAgICBoaWdobGlnaHRlZDogcGF5bG9hZC5oaWdobGlnaHRlZCxcbiAgICAgICAgICAgICAgICByb29tX2FsaWFzOiBwYXlsb2FkLnJvb21fYWxpYXMsXG4gICAgICAgICAgICAgICAgYXV0b19qb2luOiBwYXlsb2FkLmF1dG9fam9pbixcbiAgICAgICAgICAgICAgICBvb2JfZGF0YTogcGF5bG9hZC5vb2JfZGF0YSxcbiAgICAgICAgICAgICAgICB2aWFTZXJ2ZXJzOiBwYXlsb2FkLnZpYV9zZXJ2ZXJzLFxuICAgICAgICAgICAgICAgIHdhc0NvbnRleHRTd2l0Y2g6IHBheWxvYWQuY29udGV4dF9zd2l0Y2gsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgdmlld1Jvb21FcnJvcihwYXlsb2FkOiBBY3Rpb25QYXlsb2FkKSB7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgcm9vbUlkOiBwYXlsb2FkLnJvb21faWQsXG4gICAgICAgICAgICByb29tQWxpYXM6IHBheWxvYWQucm9vbV9hbGlhcyxcbiAgICAgICAgICAgIHJvb21Mb2FkaW5nOiBmYWxzZSxcbiAgICAgICAgICAgIHJvb21Mb2FkRXJyb3I6IHBheWxvYWQuZXJyLFxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIGpvaW5Sb29tKHBheWxvYWQ6IEFjdGlvblBheWxvYWQpIHtcbiAgICAgICAgY29uc3Qgc3RhcnRUaW1lID0gQ291bnRseUFuYWx5dGljcy5nZXRUaW1lc3RhbXAoKTtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICBqb2luaW5nOiB0cnVlLFxuICAgICAgICB9KTtcblxuICAgICAgICBjb25zdCBjbGkgPSBNYXRyaXhDbGllbnRQZWcuZ2V0KCk7XG4gICAgICAgIGNvbnN0IGFkZHJlc3MgPSB0aGlzLnN0YXRlLnJvb21BbGlhcyB8fCB0aGlzLnN0YXRlLnJvb21JZDtcbiAgICAgICAgY29uc3QgdmlhU2VydmVycyA9IHRoaXMuc3RhdGUudmlhU2VydmVycyB8fCBbXTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGF3YWl0IHJldHJ5PHZvaWQsIE1hdHJpeEVycm9yPigoKSA9PiBjbGkuam9pblJvb20oYWRkcmVzcywge1xuICAgICAgICAgICAgICAgIHZpYVNlcnZlcnMsXG4gICAgICAgICAgICAgICAgLi4ucGF5bG9hZC5vcHRzLFxuICAgICAgICAgICAgfSksIE5VTV9KT0lOX1JFVFJZLCAoZXJyKSA9PiB7XG4gICAgICAgICAgICAgICAgLy8gaWYgd2UgcmVjZWl2ZWQgYSBHYXRld2F5IHRpbWVvdXQgdGhlbiByZXRyeVxuICAgICAgICAgICAgICAgIHJldHVybiBlcnIuaHR0cFN0YXR1cyA9PT0gNTA0O1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBDb3VudGx5QW5hbHl0aWNzLmluc3RhbmNlLnRyYWNrUm9vbUpvaW4oc3RhcnRUaW1lLCB0aGlzLnN0YXRlLnJvb21JZCwgcGF5bG9hZC5fdHlwZSk7XG5cbiAgICAgICAgICAgIC8vIFdlIGRvICpub3QqIGNsZWFyIHRoZSAnam9pbmluZycgZmxhZyBiZWNhdXNlIHRoZSBSb29tIG9iamVjdCBhbmQvb3Igb3VyICdqb2luZWQnIG1lbWJlciBldmVudCBtYXkgbm90XG4gICAgICAgICAgICAvLyBoYXZlIGNvbWUgZG93biB0aGUgc3luYyBzdHJlYW0geWV0LCBhbmQgdGhhdCdzIHRoZSBwb2ludCBhdCB3aGljaCB3ZSdkIGNvbnNpZGVyIHRoZSB1c2VyIGpvaW5lZCB0byB0aGVcbiAgICAgICAgICAgIC8vIHJvb20uXG4gICAgICAgICAgICBkaXMuZGlzcGF0Y2goeyBhY3Rpb246ICdqb2luX3Jvb21fcmVhZHknIH0pO1xuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgIGRpcy5kaXNwYXRjaCh7XG4gICAgICAgICAgICAgICAgYWN0aW9uOiAnam9pbl9yb29tX2Vycm9yJyxcbiAgICAgICAgICAgICAgICBlcnI6IGVycixcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBsZXQgbXNnID0gZXJyLm1lc3NhZ2UgPyBlcnIubWVzc2FnZSA6IEpTT04uc3RyaW5naWZ5KGVycik7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhcIkZhaWxlZCB0byBqb2luIHJvb206XCIsIG1zZyk7XG5cbiAgICAgICAgICAgIGlmIChlcnIubmFtZSA9PT0gXCJDb25uZWN0aW9uRXJyb3JcIikge1xuICAgICAgICAgICAgICAgIG1zZyA9IF90KFwiVGhlcmUgd2FzIGFuIGVycm9yIGpvaW5pbmcgdGhlIHJvb21cIik7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGVyci5lcnJjb2RlID09PSAnTV9JTkNPTVBBVElCTEVfUk9PTV9WRVJTSU9OJykge1xuICAgICAgICAgICAgICAgIG1zZyA9IDxkaXY+XG4gICAgICAgICAgICAgICAgICAgIHtfdChcIlNvcnJ5LCB5b3VyIGhvbWVzZXJ2ZXIgaXMgdG9vIG9sZCB0byBwYXJ0aWNpcGF0ZSBpbiB0aGlzIHJvb20uXCIpfTxiciAvPlxuICAgICAgICAgICAgICAgICAgICB7X3QoXCJQbGVhc2UgY29udGFjdCB5b3VyIGhvbWVzZXJ2ZXIgYWRtaW5pc3RyYXRvci5cIil9XG4gICAgICAgICAgICAgICAgPC9kaXY+O1xuICAgICAgICAgICAgfSBlbHNlIGlmIChlcnIuaHR0cFN0YXR1cyA9PT0gNDA0KSB7XG4gICAgICAgICAgICAgICAgY29uc3QgaW52aXRpbmdVc2VySWQgPSB0aGlzLmdldEludml0aW5nVXNlcklkKHRoaXMuc3RhdGUucm9vbUlkKTtcbiAgICAgICAgICAgICAgICAvLyBvbmx5IHByb3ZpZGUgYSBiZXR0ZXIgZXJyb3IgbWVzc2FnZSBmb3IgaW52aXRlc1xuICAgICAgICAgICAgICAgIGlmIChpbnZpdGluZ1VzZXJJZCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBpZiB0aGUgaW52aXRpbmcgdXNlciBpcyBvbiB0aGUgc2FtZSBIUywgdGhlcmUgY2FuIG9ubHkgYmUgb25lIGNhdXNlOiB0aGV5IGxlZnQuXG4gICAgICAgICAgICAgICAgICAgIGlmIChpbnZpdGluZ1VzZXJJZC5lbmRzV2l0aChgOiR7TWF0cml4Q2xpZW50UGVnLmdldCgpLmdldERvbWFpbigpfWApKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtc2cgPSBfdChcIlRoZSBwZXJzb24gd2hvIGludml0ZWQgeW91IGFscmVhZHkgbGVmdCB0aGUgcm9vbS5cIik7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtc2cgPSBfdChcIlRoZSBwZXJzb24gd2hvIGludml0ZWQgeW91IGFscmVhZHkgbGVmdCB0aGUgcm9vbSwgb3IgdGhlaXIgc2VydmVyIGlzIG9mZmxpbmUuXCIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjb25zdCBFcnJvckRpYWxvZyA9IHNkay5nZXRDb21wb25lbnQoXCJkaWFsb2dzLkVycm9yRGlhbG9nXCIpO1xuICAgICAgICAgICAgTW9kYWwuY3JlYXRlVHJhY2tlZERpYWxvZygnRmFpbGVkIHRvIGpvaW4gcm9vbScsICcnLCBFcnJvckRpYWxvZywge1xuICAgICAgICAgICAgICAgIHRpdGxlOiBfdChcIkZhaWxlZCB0byBqb2luIHJvb21cIiksXG4gICAgICAgICAgICAgICAgZGVzY3JpcHRpb246IG1zZyxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRJbnZpdGluZ1VzZXJJZChyb29tSWQ6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgICAgIGNvbnN0IGNsaSA9IE1hdHJpeENsaWVudFBlZy5nZXQoKTtcbiAgICAgICAgY29uc3Qgcm9vbSA9IGNsaS5nZXRSb29tKHJvb21JZCk7XG4gICAgICAgIGlmIChyb29tICYmIHJvb20uZ2V0TXlNZW1iZXJzaGlwKCkgPT09IFwiaW52aXRlXCIpIHtcbiAgICAgICAgICAgIGNvbnN0IG15TWVtYmVyID0gcm9vbS5nZXRNZW1iZXIoY2xpLmdldFVzZXJJZCgpKTtcbiAgICAgICAgICAgIGNvbnN0IGludml0ZUV2ZW50ID0gbXlNZW1iZXIgPyBteU1lbWJlci5ldmVudHMubWVtYmVyIDogbnVsbDtcbiAgICAgICAgICAgIHJldHVybiBpbnZpdGVFdmVudCAmJiBpbnZpdGVFdmVudC5nZXRTZW5kZXIoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgam9pblJvb21FcnJvcihwYXlsb2FkOiBBY3Rpb25QYXlsb2FkKSB7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgam9pbmluZzogZmFsc2UsXG4gICAgICAgICAgICBqb2luRXJyb3I6IHBheWxvYWQuZXJyLFxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwdWJsaWMgcmVzZXQoKSB7XG4gICAgICAgIHRoaXMuc3RhdGUgPSBPYmplY3QuYXNzaWduKHt9LCBJTklUSUFMX1NUQVRFKTtcbiAgICB9XG5cbiAgICAvLyBUaGUgcm9vbSBJRCBvZiB0aGUgcm9vbSBjdXJyZW50bHkgYmVpbmcgdmlld2VkXG4gICAgcHVibGljIGdldFJvb21JZCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc3RhdGUucm9vbUlkO1xuICAgIH1cblxuICAgIC8vIFRoZSBldmVudCB0byBzY3JvbGwgdG8gd2hlbiB0aGUgcm9vbSBpcyBmaXJzdCB2aWV3ZWRcbiAgICBwdWJsaWMgZ2V0SW5pdGlhbEV2ZW50SWQoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnN0YXRlLmluaXRpYWxFdmVudElkO1xuICAgIH1cblxuICAgIC8vIFdoZXRoZXIgdG8gaGlnaGxpZ2h0IHRoZSBpbml0aWFsIGV2ZW50XG4gICAgcHVibGljIGlzSW5pdGlhbEV2ZW50SGlnaGxpZ2h0ZWQoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnN0YXRlLmlzSW5pdGlhbEV2ZW50SGlnaGxpZ2h0ZWQ7XG4gICAgfVxuXG4gICAgLy8gVGhlIHJvb20gYWxpYXMgb2YgdGhlIHJvb20gKG9yIG51bGwgaWYgbm90IG9yaWdpbmFsbHkgc3BlY2lmaWVkIGluIHZpZXdfcm9vbSlcbiAgICBwdWJsaWMgZ2V0Um9vbUFsaWFzKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5zdGF0ZS5yb29tQWxpYXM7XG4gICAgfVxuXG4gICAgLy8gV2hldGhlciB0aGUgY3VycmVudCByb29tIGlzIGxvYWRpbmcgKHRydWUgd2hpbHN0IHJlc29sdmluZyBhbiBhbGlhcylcbiAgICBwdWJsaWMgaXNSb29tTG9hZGluZygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc3RhdGUucm9vbUxvYWRpbmc7XG4gICAgfVxuXG4gICAgLy8gQW55IGVycm9yIHRoYXQgaGFzIG9jY3VycmVkIGR1cmluZyBsb2FkaW5nXG4gICAgcHVibGljIGdldFJvb21Mb2FkRXJyb3IoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnN0YXRlLnJvb21Mb2FkRXJyb3I7XG4gICAgfVxuXG4gICAgLy8gVHJ1ZSBpZiB3ZSdyZSBleHBlY3RpbmcgdGhlIHVzZXIgdG8gYmUgam9pbmVkIHRvIHRoZSByb29tIGN1cnJlbnRseSBiZWluZ1xuICAgIC8vIHZpZXdlZC4gTm90ZSB0aGF0IHRoaXMgaXMgbGVmdCB0cnVlIGFmdGVyIHRoZSBqb2luIHJlcXVlc3QgaGFzIGZpbmlzaGVkLFxuICAgIC8vIHNpbmNlIHdlIHNob3VsZCBzdGlsbCBjb25zaWRlciBhIGpvaW4gdG8gYmUgaW4gcHJvZ3Jlc3MgdW50aWwgdGhlIHJvb21cbiAgICAvLyAmIG1lbWJlciBldmVudHMgY29tZSBkb3duIHRoZSBzeW5jLlxuICAgIC8vXG4gICAgLy8gVGhpcyBmbGFnIHJlbWFpbnMgdHJ1ZSBhZnRlciB0aGUgcm9vbSBoYXMgYmVlbiBzdWNlc3NmdWxseSBqb2luZWQsXG4gICAgLy8gKHRoaXMgc3RvcmUgZG9lc24ndCBsaXN0ZW4gZm9yIHRoZSBhcHByb3ByaWF0ZSBtZW1iZXIgZXZlbnRzKVxuICAgIC8vIHNvIHlvdSBzaG91bGQgYWx3YXlzIG9ic2VydmUgdGhlIGpvaW5lZCBzdGF0ZSBmcm9tIHRoZSBtZW1iZXIgZXZlbnRcbiAgICAvLyBpZiBhIHJvb20gb2JqZWN0IGlzIHByZXNlbnQuXG4gICAgLy8gaWUuIFRoZSBjb3JyZWN0IGxvZ2ljIGlzOlxuICAgIC8vIGlmIChyb29tKSB7XG4gICAgLy8gICAgIGlmIChteU1lbWJlci5tZW1iZXJzaGlwID09ICdqb2luZWQnKSB7XG4gICAgLy8gICAgIC