UNPKG

matrix-react-sdk

Version:
250 lines (243 loc) 45.2 kB
"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 = _interopRequireWildcard(require("react")); var _matrix = require("matrix-js-sdk/src/matrix"); var _logger = require("matrix-js-sdk/src/logger"); var _files = _interopRequireDefault(require("@vector-im/compound-design-tokens/assets/web/icons/files")); var _MatrixClientPeg = require("../../MatrixClientPeg"); var _EventIndexPeg = _interopRequireDefault(require("../../indexing/EventIndexPeg")); var _languageHandler = require("../../languageHandler"); var _SearchWarning = _interopRequireWildcard(require("../views/elements/SearchWarning")); var _BaseCard = _interopRequireDefault(require("../views/right_panel/BaseCard")); var _TimelinePanel = _interopRequireDefault(require("./TimelinePanel")); var _Spinner = _interopRequireDefault(require("../views/elements/Spinner")); var _Layout = require("../../settings/enums/Layout"); var _RoomContext = _interopRequireWildcard(require("../../contexts/RoomContext")); var _Measured = _interopRequireDefault(require("../views/elements/Measured")); var _EmptyState = _interopRequireDefault(require("../views/right_panel/EmptyState")); function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); } function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; } function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } /* Copyright 2024 New Vector Ltd. Copyright 2019-2022 The Matrix.org Foundation C.I.C. Copyright 2016 OpenMarket Ltd SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ /* * Component which shows the filtered file using a TimelinePanel */ class FilePanel extends _react.default.Component { constructor(...args) { super(...args); // This is used to track if a decrypted event was a live event and should be // added to the timeline. (0, _defineProperty2.default)(this, "decryptingEvents", new Set()); (0, _defineProperty2.default)(this, "noRoom", false); (0, _defineProperty2.default)(this, "card", /*#__PURE__*/(0, _react.createRef)()); (0, _defineProperty2.default)(this, "state", { timelineSet: null, narrow: false }); (0, _defineProperty2.default)(this, "onRoomTimeline", (ev, room, toStartOfTimeline, removed, data) => { if (room?.roomId !== this.props.roomId) return; if (toStartOfTimeline || !data || !data.liveEvent || ev.isRedacted()) return; const client = _MatrixClientPeg.MatrixClientPeg.safeGet(); client.decryptEventIfNeeded(ev); if (ev.isBeingDecrypted()) { this.decryptingEvents.add(ev.getId()); } else { this.addEncryptedLiveEvent(ev); } }); (0, _defineProperty2.default)(this, "onEventDecrypted", (ev, err) => { if (ev.getRoomId() !== this.props.roomId) return; const eventId = ev.getId(); if (!this.decryptingEvents.delete(eventId)) return; if (err) return; this.addEncryptedLiveEvent(ev); }); (0, _defineProperty2.default)(this, "onPaginationRequest", (timelineWindow, direction, limit) => { const client = _MatrixClientPeg.MatrixClientPeg.safeGet(); const eventIndex = _EventIndexPeg.default.get(); const roomId = this.props.roomId; const room = client.getRoom(roomId); // We override the pagination request for encrypted rooms so that we ask // the event index to fulfill the pagination request. Asking the server // to paginate won't ever work since the server can't correctly filter // out events containing URLs if (room && client.isRoomEncrypted(roomId) && eventIndex !== null) { return eventIndex.paginateTimelineWindow(room, timelineWindow, direction, limit); } else { return timelineWindow.paginate(direction, limit); } }); (0, _defineProperty2.default)(this, "onMeasurement", narrow => { this.setState({ narrow }); }); } addEncryptedLiveEvent(ev) { if (!this.state.timelineSet) return; const timeline = this.state.timelineSet.getLiveTimeline(); if (ev.getType() !== "m.room.message") return; if (!["m.file", "m.image", "m.video", "m.audio"].includes(ev.getContent().msgtype)) { return; } if (!this.state.timelineSet.eventIdToTimeline(ev.getId())) { this.state.timelineSet.addEventToTimeline(ev, timeline, false); } } async componentDidMount() { const client = _MatrixClientPeg.MatrixClientPeg.safeGet(); await this.updateTimelineSet(this.props.roomId); if (!client.isRoomEncrypted(this.props.roomId)) return; // The timelineSets filter makes sure that encrypted events that contain // URLs never get added to the timeline, even if they are live events. // These methods are here to manually listen for such events and add // them despite the filter's best efforts. // // We do this only for encrypted rooms and if an event index exists, // this could be made more general in the future or the filter logic // could be fixed. if (_EventIndexPeg.default.get() !== null) { client.on(_matrix.RoomEvent.Timeline, this.onRoomTimeline); client.on(_matrix.MatrixEventEvent.Decrypted, this.onEventDecrypted); } } componentWillUnmount() { const client = _MatrixClientPeg.MatrixClientPeg.get(); if (client === null) return; if (!client.isRoomEncrypted(this.props.roomId)) return; if (_EventIndexPeg.default.get() !== null) { client.removeListener(_matrix.RoomEvent.Timeline, this.onRoomTimeline); client.removeListener(_matrix.MatrixEventEvent.Decrypted, this.onEventDecrypted); } } async fetchFileEventsServer(room) { const client = _MatrixClientPeg.MatrixClientPeg.safeGet(); const filter = new _matrix.Filter(client.getSafeUserId()); filter.setDefinition({ room: { timeline: { contains_url: true, types: ["m.room.message"] } } }); filter.filterId = await client.getOrCreateFilter("FILTER_FILES_" + client.credentials.userId, filter); return room.getOrCreateFilteredTimelineSet(filter); } async updateTimelineSet(roomId) { const client = _MatrixClientPeg.MatrixClientPeg.safeGet(); const room = client.getRoom(roomId); const eventIndex = _EventIndexPeg.default.get(); this.noRoom = !room; if (room) { let timelineSet; try { timelineSet = await this.fetchFileEventsServer(room); // If this room is encrypted the file panel won't be populated // correctly since the defined filter doesn't support encrypted // events and the server can't check if encrypted events contain // URLs. // // This is where our event index comes into place, we ask the // event index to populate the timelineSet for us. This call // will add 10 events to the live timeline of the set. More can // be requested using pagination. if (client.isRoomEncrypted(roomId) && eventIndex !== null) { const timeline = timelineSet.getLiveTimeline(); await eventIndex.populateFileTimeline(timelineSet, timeline, room, 10); } this.setState({ timelineSet: timelineSet }); } catch (error) { _logger.logger.error("Failed to get or create file panel filter", error); } } else { _logger.logger.error("Failed to add filtered timelineSet for FilePanel as no room!"); } } render() { if (_MatrixClientPeg.MatrixClientPeg.safeGet().isGuest()) { return /*#__PURE__*/_react.default.createElement(_BaseCard.default, { className: "mx_FilePanel mx_RoomView_messageListWrapper", onClose: this.props.onClose, header: (0, _languageHandler._t)("right_panel|files_button") }, /*#__PURE__*/_react.default.createElement("div", { className: "mx_RoomView_empty" }, (0, _languageHandler._t)("file_panel|guest_note", {}, { a: sub => /*#__PURE__*/_react.default.createElement("a", { href: "#/register", key: "sub" }, sub) }))); } else if (this.noRoom) { return /*#__PURE__*/_react.default.createElement(_BaseCard.default, { className: "mx_FilePanel mx_RoomView_messageListWrapper", onClose: this.props.onClose, header: (0, _languageHandler._t)("right_panel|files_button") }, /*#__PURE__*/_react.default.createElement("div", { className: "mx_RoomView_empty" }, (0, _languageHandler._t)("file_panel|peek_note"))); } // wrap a TimelinePanel with the jump-to-event bits turned off. const emptyState = /*#__PURE__*/_react.default.createElement(_EmptyState.default, { Icon: _files.default, title: (0, _languageHandler._t)("file_panel|empty_heading"), description: (0, _languageHandler._t)("file_panel|empty_description") }); const isRoomEncrypted = this.noRoom ? false : _MatrixClientPeg.MatrixClientPeg.safeGet().isRoomEncrypted(this.props.roomId); if (this.state.timelineSet) { return /*#__PURE__*/_react.default.createElement(_RoomContext.default.Provider, { value: _objectSpread(_objectSpread({}, this.context), {}, { timelineRenderingType: _RoomContext.TimelineRenderingType.File, narrow: this.state.narrow }) }, /*#__PURE__*/_react.default.createElement(_BaseCard.default, { className: "mx_FilePanel", onClose: this.props.onClose, withoutScrollContainer: true, ref: this.card, header: (0, _languageHandler._t)("right_panel|files_button") }, this.card.current && /*#__PURE__*/_react.default.createElement(_Measured.default, { sensor: this.card.current, onMeasurement: this.onMeasurement }), /*#__PURE__*/_react.default.createElement(_SearchWarning.default, { isRoomEncrypted: isRoomEncrypted, kind: _SearchWarning.WarningKind.Files }), /*#__PURE__*/_react.default.createElement(_TimelinePanel.default, { manageReadReceipts: false, manageReadMarkers: false, timelineSet: this.state.timelineSet, showUrlPreview: false, onPaginationRequest: this.onPaginationRequest, resizeNotifier: this.props.resizeNotifier, empty: emptyState, layout: _Layout.Layout.Group }))); } else { return /*#__PURE__*/_react.default.createElement(_RoomContext.default.Provider, { value: _objectSpread(_objectSpread({}, this.context), {}, { timelineRenderingType: _RoomContext.TimelineRenderingType.File }) }, /*#__PURE__*/_react.default.createElement(_BaseCard.default, { className: "mx_FilePanel", onClose: this.props.onClose, header: (0, _languageHandler._t)("right_panel|files_button") }, /*#__PURE__*/_react.default.createElement(_Spinner.default, null))); } } } (0, _defineProperty2.default)(FilePanel, "contextType", _RoomContext.default); var _default = exports.default = FilePanel; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfcmVhY3QiLCJfaW50ZXJvcFJlcXVpcmVXaWxkY2FyZCIsInJlcXVpcmUiLCJfbWF0cml4IiwiX2xvZ2dlciIsIl9maWxlcyIsIl9pbnRlcm9wUmVxdWlyZURlZmF1bHQiLCJfTWF0cml4Q2xpZW50UGVnIiwiX0V2ZW50SW5kZXhQZWciLCJfbGFuZ3VhZ2VIYW5kbGVyIiwiX1NlYXJjaFdhcm5pbmciLCJfQmFzZUNhcmQiLCJfVGltZWxpbmVQYW5lbCIsIl9TcGlubmVyIiwiX0xheW91dCIsIl9Sb29tQ29udGV4dCIsIl9NZWFzdXJlZCIsIl9FbXB0eVN0YXRlIiwiX2dldFJlcXVpcmVXaWxkY2FyZENhY2hlIiwiZSIsIldlYWtNYXAiLCJyIiwidCIsIl9fZXNNb2R1bGUiLCJkZWZhdWx0IiwiaGFzIiwiZ2V0IiwibiIsIl9fcHJvdG9fXyIsImEiLCJPYmplY3QiLCJkZWZpbmVQcm9wZXJ0eSIsImdldE93blByb3BlcnR5RGVzY3JpcHRvciIsInUiLCJoYXNPd25Qcm9wZXJ0eSIsImNhbGwiLCJpIiwic2V0Iiwib3duS2V5cyIsImtleXMiLCJnZXRPd25Qcm9wZXJ0eVN5bWJvbHMiLCJvIiwiZmlsdGVyIiwiZW51bWVyYWJsZSIsInB1c2giLCJhcHBseSIsIl9vYmplY3RTcHJlYWQiLCJhcmd1bWVudHMiLCJsZW5ndGgiLCJmb3JFYWNoIiwiX2RlZmluZVByb3BlcnR5MiIsImdldE93blByb3BlcnR5RGVzY3JpcHRvcnMiLCJkZWZpbmVQcm9wZXJ0aWVzIiwiRmlsZVBhbmVsIiwiUmVhY3QiLCJDb21wb25lbnQiLCJjb25zdHJ1Y3RvciIsImFyZ3MiLCJTZXQiLCJjcmVhdGVSZWYiLCJ0aW1lbGluZVNldCIsIm5hcnJvdyIsImV2Iiwicm9vbSIsInRvU3RhcnRPZlRpbWVsaW5lIiwicmVtb3ZlZCIsImRhdGEiLCJyb29tSWQiLCJwcm9wcyIsImxpdmVFdmVudCIsImlzUmVkYWN0ZWQiLCJjbGllbnQiLCJNYXRyaXhDbGllbnRQZWciLCJzYWZlR2V0IiwiZGVjcnlwdEV2ZW50SWZOZWVkZWQiLCJpc0JlaW5nRGVjcnlwdGVkIiwiZGVjcnlwdGluZ0V2ZW50cyIsImFkZCIsImdldElkIiwiYWRkRW5jcnlwdGVkTGl2ZUV2ZW50IiwiZXJyIiwiZ2V0Um9vbUlkIiwiZXZlbnRJZCIsImRlbGV0ZSIsInRpbWVsaW5lV2luZG93IiwiZGlyZWN0aW9uIiwibGltaXQiLCJldmVudEluZGV4IiwiRXZlbnRJbmRleFBlZyIsImdldFJvb20iLCJpc1Jvb21FbmNyeXB0ZWQiLCJwYWdpbmF0ZVRpbWVsaW5lV2luZG93IiwicGFnaW5hdGUiLCJzZXRTdGF0ZSIsInN0YXRlIiwidGltZWxpbmUiLCJnZXRMaXZlVGltZWxpbmUiLCJnZXRUeXBlIiwiaW5jbHVkZXMiLCJnZXRDb250ZW50IiwibXNndHlwZSIsImV2ZW50SWRUb1RpbWVsaW5lIiwiYWRkRXZlbnRUb1RpbWVsaW5lIiwiY29tcG9uZW50RGlkTW91bnQiLCJ1cGRhdGVUaW1lbGluZVNldCIsIm9uIiwiUm9vbUV2ZW50IiwiVGltZWxpbmUiLCJvblJvb21UaW1lbGluZSIsIk1hdHJpeEV2ZW50RXZlbnQiLCJEZWNyeXB0ZWQiLCJvbkV2ZW50RGVjcnlwdGVkIiwiY29tcG9uZW50V2lsbFVubW91bnQiLCJyZW1vdmVMaXN0ZW5lciIsImZldGNoRmlsZUV2ZW50c1NlcnZlciIsIkZpbHRlciIsImdldFNhZmVVc2VySWQiLCJzZXREZWZpbml0aW9uIiwiY29udGFpbnNfdXJsIiwidHlwZXMiLCJmaWx0ZXJJZCIsImdldE9yQ3JlYXRlRmlsdGVyIiwiY3JlZGVudGlhbHMiLCJ1c2VySWQiLCJnZXRPckNyZWF0ZUZpbHRlcmVkVGltZWxpbmVTZXQiLCJub1Jvb20iLCJwb3B1bGF0ZUZpbGVUaW1lbGluZSIsImVycm9yIiwibG9nZ2VyIiwicmVuZGVyIiwiaXNHdWVzdCIsImNyZWF0ZUVsZW1lbnQiLCJjbGFzc05hbWUiLCJvbkNsb3NlIiwiaGVhZGVyIiwiX3QiLCJzdWIiLCJocmVmIiwia2V5IiwiZW1wdHlTdGF0ZSIsIkljb24iLCJGaWxlc0ljb24iLCJ0aXRsZSIsImRlc2NyaXB0aW9uIiwiUHJvdmlkZXIiLCJ2YWx1ZSIsImNvbnRleHQiLCJ0aW1lbGluZVJlbmRlcmluZ1R5cGUiLCJUaW1lbGluZVJlbmRlcmluZ1R5cGUiLCJGaWxlIiwid2l0aG91dFNjcm9sbENvbnRhaW5lciIsInJlZiIsImNhcmQiLCJjdXJyZW50Iiwic2Vuc29yIiwib25NZWFzdXJlbWVudCIsImtpbmQiLCJXYXJuaW5nS2luZCIsIkZpbGVzIiwibWFuYWdlUmVhZFJlY2VpcHRzIiwibWFuYWdlUmVhZE1hcmtlcnMiLCJzaG93VXJsUHJldmlldyIsIm9uUGFnaW5hdGlvblJlcXVlc3QiLCJyZXNpemVOb3RpZmllciIsImVtcHR5IiwibGF5b3V0IiwiTGF5b3V0IiwiR3JvdXAiLCJSb29tQ29udGV4dCIsIl9kZWZhdWx0IiwiZXhwb3J0cyJdLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9jb21wb25lbnRzL3N0cnVjdHVyZXMvRmlsZVBhbmVsLnRzeCJdLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuQ29weXJpZ2h0IDIwMjQgTmV3IFZlY3RvciBMdGQuXG5Db3B5cmlnaHQgMjAxOS0yMDIyIFRoZSBNYXRyaXgub3JnIEZvdW5kYXRpb24gQy5JLkMuXG5Db3B5cmlnaHQgMjAxNiBPcGVuTWFya2V0IEx0ZFxuXG5TUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQUdQTC0zLjAtb25seSBPUiBHUEwtMy4wLW9ubHlcblBsZWFzZSBzZWUgTElDRU5TRSBmaWxlcyBpbiB0aGUgcmVwb3NpdG9yeSByb290IGZvciBmdWxsIGRldGFpbHMuXG4qL1xuXG5pbXBvcnQgUmVhY3QsIHsgY3JlYXRlUmVmIH0gZnJvbSBcInJlYWN0XCI7XG5pbXBvcnQge1xuICAgIEZpbHRlcixcbiAgICBFdmVudFRpbWVsaW5lU2V0LFxuICAgIElSb29tVGltZWxpbmVEYXRhLFxuICAgIERpcmVjdGlvbixcbiAgICBNYXRyaXhFdmVudCxcbiAgICBNYXRyaXhFdmVudEV2ZW50LFxuICAgIFJvb20sXG4gICAgUm9vbUV2ZW50LFxuICAgIFRpbWVsaW5lV2luZG93LFxufSBmcm9tIFwibWF0cml4LWpzLXNkay9zcmMvbWF0cml4XCI7XG5pbXBvcnQgeyBsb2dnZXIgfSBmcm9tIFwibWF0cml4LWpzLXNkay9zcmMvbG9nZ2VyXCI7XG5pbXBvcnQgRmlsZXNJY29uIGZyb20gXCJAdmVjdG9yLWltL2NvbXBvdW5kLWRlc2lnbi10b2tlbnMvYXNzZXRzL3dlYi9pY29ucy9maWxlc1wiO1xuXG5pbXBvcnQgeyBNYXRyaXhDbGllbnRQZWcgfSBmcm9tIFwiLi4vLi4vTWF0cml4Q2xpZW50UGVnXCI7XG5pbXBvcnQgRXZlbnRJbmRleFBlZyBmcm9tIFwiLi4vLi4vaW5kZXhpbmcvRXZlbnRJbmRleFBlZ1wiO1xuaW1wb3J0IHsgX3QgfSBmcm9tIFwiLi4vLi4vbGFuZ3VhZ2VIYW5kbGVyXCI7XG5pbXBvcnQgU2VhcmNoV2FybmluZywgeyBXYXJuaW5nS2luZCB9IGZyb20gXCIuLi92aWV3cy9lbGVtZW50cy9TZWFyY2hXYXJuaW5nXCI7XG5pbXBvcnQgQmFzZUNhcmQgZnJvbSBcIi4uL3ZpZXdzL3JpZ2h0X3BhbmVsL0Jhc2VDYXJkXCI7XG5pbXBvcnQgUmVzaXplTm90aWZpZXIgZnJvbSBcIi4uLy4uL3V0aWxzL1Jlc2l6ZU5vdGlmaWVyXCI7XG5pbXBvcnQgVGltZWxpbmVQYW5lbCBmcm9tIFwiLi9UaW1lbGluZVBhbmVsXCI7XG5pbXBvcnQgU3Bpbm5lciBmcm9tIFwiLi4vdmlld3MvZWxlbWVudHMvU3Bpbm5lclwiO1xuaW1wb3J0IHsgTGF5b3V0IH0gZnJvbSBcIi4uLy4uL3NldHRpbmdzL2VudW1zL0xheW91dFwiO1xuaW1wb3J0IFJvb21Db250ZXh0LCB7IFRpbWVsaW5lUmVuZGVyaW5nVHlwZSB9IGZyb20gXCIuLi8uLi9jb250ZXh0cy9Sb29tQ29udGV4dFwiO1xuaW1wb3J0IE1lYXN1cmVkIGZyb20gXCIuLi92aWV3cy9lbGVtZW50cy9NZWFzdXJlZFwiO1xuaW1wb3J0IEVtcHR5U3RhdGUgZnJvbSBcIi4uL3ZpZXdzL3JpZ2h0X3BhbmVsL0VtcHR5U3RhdGVcIjtcblxuaW50ZXJmYWNlIElQcm9wcyB7XG4gICAgcm9vbUlkOiBzdHJpbmc7XG4gICAgb25DbG9zZTogKCkgPT4gdm9pZDtcbiAgICByZXNpemVOb3RpZmllcjogUmVzaXplTm90aWZpZXI7XG59XG5cbmludGVyZmFjZSBJU3RhdGUge1xuICAgIHRpbWVsaW5lU2V0OiBFdmVudFRpbWVsaW5lU2V0IHwgbnVsbDtcbiAgICBuYXJyb3c6IGJvb2xlYW47XG59XG5cbi8qXG4gKiBDb21wb25lbnQgd2hpY2ggc2hvd3MgdGhlIGZpbHRlcmVkIGZpbGUgdXNpbmcgYSBUaW1lbGluZVBhbmVsXG4gKi9cbmNsYXNzIEZpbGVQYW5lbCBleHRlbmRzIFJlYWN0LkNvbXBvbmVudDxJUHJvcHMsIElTdGF0ZT4ge1xuICAgIHB1YmxpYyBzdGF0aWMgY29udGV4dFR5cGUgPSBSb29tQ29udGV4dDtcbiAgICBwdWJsaWMgZGVjbGFyZSBjb250ZXh0OiBSZWFjdC5Db250ZXh0VHlwZTx0eXBlb2YgUm9vbUNvbnRleHQ+O1xuXG4gICAgLy8gVGhpcyBpcyB1c2VkIHRvIHRyYWNrIGlmIGEgZGVjcnlwdGVkIGV2ZW50IHdhcyBhIGxpdmUgZXZlbnQgYW5kIHNob3VsZCBiZVxuICAgIC8vIGFkZGVkIHRvIHRoZSB0aW1lbGluZS5cbiAgICBwcml2YXRlIGRlY3J5cHRpbmdFdmVudHMgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgICBwdWJsaWMgbm9Sb29tID0gZmFsc2U7XG4gICAgcHJpdmF0ZSBjYXJkID0gY3JlYXRlUmVmPEhUTUxEaXZFbGVtZW50PigpO1xuXG4gICAgcHVibGljIHN0YXRlOiBJU3RhdGUgPSB7XG4gICAgICAgIHRpbWVsaW5lU2V0OiBudWxsLFxuICAgICAgICBuYXJyb3c6IGZhbHNlLFxuICAgIH07XG5cbiAgICBwcml2YXRlIG9uUm9vbVRpbWVsaW5lID0gKFxuICAgICAgICBldjogTWF0cml4RXZlbnQsXG4gICAgICAgIHJvb206IFJvb20gfCB1bmRlZmluZWQsXG4gICAgICAgIHRvU3RhcnRPZlRpbWVsaW5lOiBib29sZWFuIHwgdW5kZWZpbmVkLFxuICAgICAgICByZW1vdmVkOiBib29sZWFuLFxuICAgICAgICBkYXRhOiBJUm9vbVRpbWVsaW5lRGF0YSxcbiAgICApOiB2b2lkID0+IHtcbiAgICAgICAgaWYgKHJvb20/LnJvb21JZCAhPT0gdGhpcy5wcm9wcy5yb29tSWQpIHJldHVybjtcbiAgICAgICAgaWYgKHRvU3RhcnRPZlRpbWVsaW5lIHx8ICFkYXRhIHx8ICFkYXRhLmxpdmVFdmVudCB8fCBldi5pc1JlZGFjdGVkKCkpIHJldHVybjtcblxuICAgICAgICBjb25zdCBjbGllbnQgPSBNYXRyaXhDbGllbnRQZWcuc2FmZUdldCgpO1xuICAgICAgICBjbGllbnQuZGVjcnlwdEV2ZW50SWZOZWVkZWQoZXYpO1xuXG4gICAgICAgIGlmIChldi5pc0JlaW5nRGVjcnlwdGVkKCkpIHtcbiAgICAgICAgICAgIHRoaXMuZGVjcnlwdGluZ0V2ZW50cy5hZGQoZXYuZ2V0SWQoKSEpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5hZGRFbmNyeXB0ZWRMaXZlRXZlbnQoZXYpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIHByaXZhdGUgb25FdmVudERlY3J5cHRlZCA9IChldjogTWF0cml4RXZlbnQsIGVycj86IGFueSk6IHZvaWQgPT4ge1xuICAgICAgICBpZiAoZXYuZ2V0Um9vbUlkKCkgIT09IHRoaXMucHJvcHMucm9vbUlkKSByZXR1cm47XG4gICAgICAgIGNvbnN0IGV2ZW50SWQgPSBldi5nZXRJZCgpITtcblxuICAgICAgICBpZiAoIXRoaXMuZGVjcnlwdGluZ0V2ZW50cy5kZWxldGUoZXZlbnRJZCkpIHJldHVybjtcbiAgICAgICAgaWYgKGVycikgcmV0dXJuO1xuXG4gICAgICAgIHRoaXMuYWRkRW5jcnlwdGVkTGl2ZUV2ZW50KGV2KTtcbiAgICB9O1xuXG4gICAgcHVibGljIGFkZEVuY3J5cHRlZExpdmVFdmVudChldjogTWF0cml4RXZlbnQpOiB2b2lkIHtcbiAgICAgICAgaWYgKCF0aGlzLnN0YXRlLnRpbWVsaW5lU2V0KSByZXR1cm47XG5cbiAgICAgICAgY29uc3QgdGltZWxpbmUgPSB0aGlzLnN0YXRlLnRpbWVsaW5lU2V0LmdldExpdmVUaW1lbGluZSgpO1xuICAgICAgICBpZiAoZXYuZ2V0VHlwZSgpICE9PSBcIm0ucm9vbS5tZXNzYWdlXCIpIHJldHVybjtcbiAgICAgICAgaWYgKCFbXCJtLmZpbGVcIiwgXCJtLmltYWdlXCIsIFwibS52aWRlb1wiLCBcIm0uYXVkaW9cIl0uaW5jbHVkZXMoZXYuZ2V0Q29udGVudCgpLm1zZ3R5cGUhKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCF0aGlzLnN0YXRlLnRpbWVsaW5lU2V0LmV2ZW50SWRUb1RpbWVsaW5lKGV2LmdldElkKCkhKSkge1xuICAgICAgICAgICAgdGhpcy5zdGF0ZS50aW1lbGluZVNldC5hZGRFdmVudFRvVGltZWxpbmUoZXYsIHRpbWVsaW5lLCBmYWxzZSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgY29tcG9uZW50RGlkTW91bnQoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGNvbnN0IGNsaWVudCA9IE1hdHJpeENsaWVudFBlZy5zYWZlR2V0KCk7XG5cbiAgICAgICAgYXdhaXQgdGhpcy51cGRhdGVUaW1lbGluZVNldCh0aGlzLnByb3BzLnJvb21JZCk7XG5cbiAgICAgICAgaWYgKCFjbGllbnQuaXNSb29tRW5jcnlwdGVkKHRoaXMucHJvcHMucm9vbUlkKSkgcmV0dXJuO1xuXG4gICAgICAgIC8vIFRoZSB0aW1lbGluZVNldHMgZmlsdGVyIG1ha2VzIHN1cmUgdGhhdCBlbmNyeXB0ZWQgZXZlbnRzIHRoYXQgY29udGFpblxuICAgICAgICAvLyBVUkxzIG5ldmVyIGdldCBhZGRlZCB0byB0aGUgdGltZWxpbmUsIGV2ZW4gaWYgdGhleSBhcmUgbGl2ZSBldmVudHMuXG4gICAgICAgIC8vIFRoZXNlIG1ldGhvZHMgYXJlIGhlcmUgdG8gbWFudWFsbHkgbGlzdGVuIGZvciBzdWNoIGV2ZW50cyBhbmQgYWRkXG4gICAgICAgIC8vIHRoZW0gZGVzcGl0ZSB0aGUgZmlsdGVyJ3MgYmVzdCBlZmZvcnRzLlxuICAgICAgICAvL1xuICAgICAgICAvLyBXZSBkbyB0aGlzIG9ubHkgZm9yIGVuY3J5cHRlZCByb29tcyBhbmQgaWYgYW4gZXZlbnQgaW5kZXggZXhpc3RzLFxuICAgICAgICAvLyB0aGlzIGNvdWxkIGJlIG1hZGUgbW9yZSBnZW5lcmFsIGluIHRoZSBmdXR1cmUgb3IgdGhlIGZpbHRlciBsb2dpY1xuICAgICAgICAvLyBjb3VsZCBiZSBmaXhlZC5cbiAgICAgICAgaWYgKEV2ZW50SW5kZXhQZWcuZ2V0KCkgIT09IG51bGwpIHtcbiAgICAgICAgICAgIGNsaWVudC5vbihSb29tRXZlbnQuVGltZWxpbmUsIHRoaXMub25Sb29tVGltZWxpbmUpO1xuICAgICAgICAgICAgY2xpZW50Lm9uKE1hdHJpeEV2ZW50RXZlbnQuRGVjcnlwdGVkLCB0aGlzLm9uRXZlbnREZWNyeXB0ZWQpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHVibGljIGNvbXBvbmVudFdpbGxVbm1vdW50KCk6IHZvaWQge1xuICAgICAgICBjb25zdCBjbGllbnQgPSBNYXRyaXhDbGllbnRQZWcuZ2V0KCk7XG4gICAgICAgIGlmIChjbGllbnQgPT09IG51bGwpIHJldHVybjtcblxuICAgICAgICBpZiAoIWNsaWVudC5pc1Jvb21FbmNyeXB0ZWQodGhpcy5wcm9wcy5yb29tSWQpKSByZXR1cm47XG5cbiAgICAgICAgaWYgKEV2ZW50SW5kZXhQZWcuZ2V0KCkgIT09IG51bGwpIHtcbiAgICAgICAgICAgIGNsaWVudC5yZW1vdmVMaXN0ZW5lcihSb29tRXZlbnQuVGltZWxpbmUsIHRoaXMub25Sb29tVGltZWxpbmUpO1xuICAgICAgICAgICAgY2xpZW50LnJlbW92ZUxpc3RlbmVyKE1hdHJpeEV2ZW50RXZlbnQuRGVjcnlwdGVkLCB0aGlzLm9uRXZlbnREZWNyeXB0ZWQpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIGZldGNoRmlsZUV2ZW50c1NlcnZlcihyb29tOiBSb29tKTogUHJvbWlzZTxFdmVudFRpbWVsaW5lU2V0PiB7XG4gICAgICAgIGNvbnN0IGNsaWVudCA9IE1hdHJpeENsaWVudFBlZy5zYWZlR2V0KCk7XG5cbiAgICAgICAgY29uc3QgZmlsdGVyID0gbmV3IEZpbHRlcihjbGllbnQuZ2V0U2FmZVVzZXJJZCgpKTtcbiAgICAgICAgZmlsdGVyLnNldERlZmluaXRpb24oe1xuICAgICAgICAgICAgcm9vbToge1xuICAgICAgICAgICAgICAgIHRpbWVsaW5lOiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRhaW5zX3VybDogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgdHlwZXM6IFtcIm0ucm9vbS5tZXNzYWdlXCJdLFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9LFxuICAgICAgICB9KTtcblxuICAgICAgICBmaWx0ZXIuZmlsdGVySWQgPSBhd2FpdCBjbGllbnQuZ2V0T3JDcmVhdGVGaWx0ZXIoXCJGSUxURVJfRklMRVNfXCIgKyBjbGllbnQuY3JlZGVudGlhbHMudXNlcklkLCBmaWx0ZXIpO1xuICAgICAgICByZXR1cm4gcm9vbS5nZXRPckNyZWF0ZUZpbHRlcmVkVGltZWxpbmVTZXQoZmlsdGVyKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIG9uUGFnaW5hdGlvblJlcXVlc3QgPSAoXG4gICAgICAgIHRpbWVsaW5lV2luZG93OiBUaW1lbGluZVdpbmRvdyxcbiAgICAgICAgZGlyZWN0aW9uOiBEaXJlY3Rpb24sXG4gICAgICAgIGxpbWl0OiBudW1iZXIsXG4gICAgKTogUHJvbWlzZTxib29sZWFuPiA9PiB7XG4gICAgICAgIGNvbnN0IGNsaWVudCA9IE1hdHJpeENsaWVudFBlZy5zYWZlR2V0KCk7XG4gICAgICAgIGNvbnN0IGV2ZW50SW5kZXggPSBFdmVudEluZGV4UGVnLmdldCgpO1xuICAgICAgICBjb25zdCByb29tSWQgPSB0aGlzLnByb3BzLnJvb21JZDtcblxuICAgICAgICBjb25zdCByb29tID0gY2xpZW50LmdldFJvb20ocm9vbUlkKTtcblxuICAgICAgICAvLyBXZSBvdmVycmlkZSB0aGUgcGFnaW5hdGlvbiByZXF1ZXN0IGZvciBlbmNyeXB0ZWQgcm9vbXMgc28gdGhhdCB3ZSBhc2tcbiAgICAgICAgLy8gdGhlIGV2ZW50IGluZGV4IHRvIGZ1bGZpbGwgdGhlIHBhZ2luYXRpb24gcmVxdWVzdC4gQXNraW5nIHRoZSBzZXJ2ZXJcbiAgICAgICAgLy8gdG8gcGFnaW5hdGUgd29uJ3QgZXZlciB3b3JrIHNpbmNlIHRoZSBzZXJ2ZXIgY2FuJ3QgY29ycmVjdGx5IGZpbHRlclxuICAgICAgICAvLyBvdXQgZXZlbnRzIGNvbnRhaW5pbmcgVVJMc1xuICAgICAgICBpZiAocm9vbSAmJiBjbGllbnQuaXNSb29tRW5jcnlwdGVkKHJvb21JZCkgJiYgZXZlbnRJbmRleCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuIGV2ZW50SW5kZXgucGFnaW5hdGVUaW1lbGluZVdpbmRvdyhyb29tLCB0aW1lbGluZVdpbmRvdywgZGlyZWN0aW9uLCBsaW1pdCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gdGltZWxpbmVXaW5kb3cucGFnaW5hdGUoZGlyZWN0aW9uLCBsaW1pdCk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgcHJpdmF0ZSBvbk1lYXN1cmVtZW50ID0gKG5hcnJvdzogYm9vbGVhbik6IHZvaWQgPT4ge1xuICAgICAgICB0aGlzLnNldFN0YXRlKHsgbmFycm93IH0pO1xuICAgIH07XG5cbiAgICBwdWJsaWMgYXN5bmMgdXBkYXRlVGltZWxpbmVTZXQocm9vbUlkOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgY29uc3QgY2xpZW50ID0gTWF0cml4Q2xpZW50UGVnLnNhZmVHZXQoKTtcbiAgICAgICAgY29uc3Qgcm9vbSA9IGNsaWVudC5nZXRSb29tKHJvb21JZCk7XG4gICAgICAgIGNvbnN0IGV2ZW50SW5kZXggPSBFdmVudEluZGV4UGVnLmdldCgpO1xuXG4gICAgICAgIHRoaXMubm9Sb29tID0gIXJvb207XG5cbiAgICAgICAgaWYgKHJvb20pIHtcbiAgICAgICAgICAgIGxldCB0aW1lbGluZVNldDtcblxuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICB0aW1lbGluZVNldCA9IGF3YWl0IHRoaXMuZmV0Y2hGaWxlRXZlbnRzU2VydmVyKHJvb20pO1xuXG4gICAgICAgICAgICAgICAgLy8gSWYgdGhpcyByb29tIGlzIGVuY3J5cHRlZCB0aGUgZmlsZSBwYW5lbCB3b24ndCBiZSBwb3B1bGF0ZWRcbiAgICAgICAgICAgICAgICAvLyBjb3JyZWN0bHkgc2luY2UgdGhlIGRlZmluZWQgZmlsdGVyIGRvZXNuJ3Qgc3VwcG9ydCBlbmNyeXB0ZWRcbiAgICAgICAgICAgICAgICAvLyBldmVudHMgYW5kIHRoZSBzZXJ2ZXIgY2FuJ3QgY2hlY2sgaWYgZW5jcnlwdGVkIGV2ZW50cyBjb250YWluXG4gICAgICAgICAgICAgICAgLy8gVVJMcy5cbiAgICAgICAgICAgICAgICAvL1xuICAgICAgICAgICAgICAgIC8vIFRoaXMgaXMgd2hlcmUgb3VyIGV2ZW50IGluZGV4IGNvbWVzIGludG8gcGxhY2UsIHdlIGFzayB0aGVcbiAgICAgICAgICAgICAgICAvLyBldmVudCBpbmRleCB0byBwb3B1bGF0ZSB0aGUgdGltZWxpbmVTZXQgZm9yIHVzLiBUaGlzIGNhbGxcbiAgICAgICAgICAgICAgICAvLyB3aWxsIGFkZCAxMCBldmVudHMgdG8gdGhlIGxpdmUgdGltZWxpbmUgb2YgdGhlIHNldC4gTW9yZSBjYW5cbiAgICAgICAgICAgICAgICAvLyBiZSByZXF1ZXN0ZWQgdXNpbmcgcGFnaW5hdGlvbi5cbiAgICAgICAgICAgICAgICBpZiAoY2xpZW50LmlzUm9vbUVuY3J5cHRlZChyb29tSWQpICYmIGV2ZW50SW5kZXggIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgdGltZWxpbmUgPSB0aW1lbGluZVNldC5nZXRMaXZlVGltZWxpbmUoKTtcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgZXZlbnRJbmRleC5wb3B1bGF0ZUZpbGVUaW1lbGluZSh0aW1lbGluZVNldCwgdGltZWxpbmUsIHJvb20sIDEwKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLnNldFN0YXRlKHsgdGltZWxpbmVTZXQ6IHRpbWVsaW5lU2V0IH0pO1xuICAgICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICBsb2dnZXIuZXJyb3IoXCJGYWlsZWQgdG8gZ2V0IG9yIGNyZWF0ZSBmaWxlIHBhbmVsIGZpbHRlclwiLCBlcnJvcik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBsb2dnZXIuZXJyb3IoXCJGYWlsZWQgdG8gYWRkIGZpbHRlcmVkIHRpbWVsaW5lU2V0IGZvciBGaWxlUGFuZWwgYXMgbm8gcm9vbSFcIik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwdWJsaWMgcmVuZGVyKCk6IFJlYWN0LlJlYWN0Tm9kZSB7XG4gICAgICAgIGlmIChNYXRyaXhDbGllbnRQZWcuc2FmZUdldCgpLmlzR3Vlc3QoKSkge1xuICAgICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgICAgICA8QmFzZUNhcmRcbiAgICAgICAgICAgICAgICAgICAgY2xhc3NOYW1lPVwibXhfRmlsZVBhbmVsIG14X1Jvb21WaWV3X21lc3NhZ2VMaXN0V3JhcHBlclwiXG4gICAgICAgICAgICAgICAgICAgIG9uQ2xvc2U9e3RoaXMucHJvcHMub25DbG9zZX1cbiAgICAgICAgICAgICAgICAgICAgaGVhZGVyPXtfdChcInJpZ2h0X3BhbmVsfGZpbGVzX2J1dHRvblwiKX1cbiAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3NOYW1lPVwibXhfUm9vbVZpZXdfZW1wdHlcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIHtfdChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImZpbGVfcGFuZWx8Z3Vlc3Rfbm90ZVwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHt9LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYTogKHN1YikgPT4gKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGEgaHJlZj1cIiMvcmVnaXN0ZXJcIiBrZXk9XCJzdWJcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7c3VifVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9hPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICApfVxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICA8L0Jhc2VDYXJkPlxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLm5vUm9vbSkge1xuICAgICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgICAgICA8QmFzZUNhcmRcbiAgICAgICAgICAgICAgICAgICAgY2xhc3NOYW1lPVwibXhfRmlsZVBhbmVsIG14X1Jvb21WaWV3X21lc3NhZ2VMaXN0V3JhcHBlclwiXG4gICAgICAgICAgICAgICAgICAgIG9uQ2xvc2U9e3RoaXMucHJvcHMub25DbG9zZX1cbiAgICAgICAgICAgICAgICAgICAgaGVhZGVyPXtfdChcInJpZ2h0X3BhbmVsfGZpbGVzX2J1dHRvblwiKX1cbiAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3NOYW1lPVwibXhfUm9vbVZpZXdfZW1wdHlcIj57X3QoXCJmaWxlX3BhbmVsfHBlZWtfbm90ZVwiKX08L2Rpdj5cbiAgICAgICAgICAgICAgICA8L0Jhc2VDYXJkPlxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHdyYXAgYSBUaW1lbGluZVBhbmVsIHdpdGggdGhlIGp1bXAtdG8tZXZlbnQgYml0cyB0dXJuZWQgb2ZmLlxuXG4gICAgICAgIGNvbnN0IGVtcHR5U3RhdGUgPSAoXG4gICAgICAgICAgICA8RW1wdHlTdGF0ZVxuICAgICAgICAgICAgICAgIEljb249e0ZpbGVzSWNvbn1cbiAgICAgICAgICAgICAgICB0aXRsZT17X3QoXCJmaWxlX3BhbmVsfGVtcHR5X2hlYWRpbmdcIil9XG4gICAgICAgICAgICAgICAgZGVzY3JpcHRpb249e190KFwiZmlsZV9wYW5lbHxlbXB0eV9kZXNjcmlwdGlvblwiKX1cbiAgICAgICAgICAgIC8+XG4gICAgICAgICk7XG5cbiAgICAgICAgY29uc3QgaXNSb29tRW5jcnlwdGVkID0gdGhpcy5ub1Jvb20gPyBmYWxzZSA6IE1hdHJpeENsaWVudFBlZy5zYWZlR2V0KCkuaXNSb29tRW5jcnlwdGVkKHRoaXMucHJvcHMucm9vbUlkKTtcblxuICAgICAgICBpZiAodGhpcy5zdGF0ZS50aW1lbGluZVNldCkge1xuICAgICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgICAgICA8Um9vbUNvbnRleHQuUHJvdmlkZXJcbiAgICAgICAgICAgICAgICAgICAgdmFsdWU9e3tcbiAgICAgICAgICAgICAgICAgICAgICAgIC4uLnRoaXMuY29udGV4dCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRpbWVsaW5lUmVuZGVyaW5nVHlwZTogVGltZWxpbmVSZW5kZXJpbmdUeXBlLkZpbGUsXG4gICAgICAgICAgICAgICAgICAgICAgICBuYXJyb3c6IHRoaXMuc3RhdGUubmFycm93LFxuICAgICAgICAgICAgICAgICAgICB9fVxuICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAgPEJhc2VDYXJkXG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc05hbWU9XCJteF9GaWxlUGFuZWxcIlxuICAgICAgICAgICAgICAgICAgICAgICAgb25DbG9zZT17dGhpcy5wcm9wcy5vbkNsb3NlfVxuICAgICAgICAgICAgICAgICAgICAgICAgd2l0aG91dFNjcm9sbENvbnRhaW5lclxuICAgICAgICAgICAgICAgICAgICAgICAgcmVmPXt0aGlzLmNhcmR9XG4gICAgICAgICAgICAgICAgICAgICAgICBoZWFkZXI9e190KFwicmlnaHRfcGFuZWx8ZmlsZXNfYnV0dG9uXCIpfVxuICAgICAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgICAgICB7dGhpcy5jYXJkLmN1cnJlbnQgJiYgKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxNZWFzdXJlZCBzZW5zb3I9e3RoaXMuY2FyZC5jdXJyZW50fSBvbk1lYXN1cmVtZW50PXt0aGlzLm9uTWVhc3VyZW1lbnR9IC8+XG4gICAgICAgICAgICAgICAgICAgICAgICApfVxuICAgICAgICAgICAgICAgICAgICAgICAgPFNlYXJjaFdhcm5pbmcgaXNSb29tRW5jcnlwdGVkPXtpc1Jvb21FbmNyeXB0ZWR9IGtpbmQ9e1dhcm5pbmdLaW5kLkZpbGVzfSAvPlxuICAgICAgICAgICAgICAgICAgICAgICAgPFRpbWVsaW5lUGFuZWxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYW5hZ2VSZWFkUmVjZWlwdHM9e2ZhbHNlfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hbmFnZVJlYWRNYXJrZXJzPXtmYWxzZX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aW1lbGluZVNldD17dGhpcy5zdGF0ZS50aW1lbGluZVNldH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaG93VXJsUHJldmlldz17ZmFsc2V9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb25QYWdpbmF0aW9uUmVxdWVzdD17dGhpcy5vblBhZ2luYXRpb25SZXF1ZXN0fVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc2l6ZU5vdGlmaWVyPXt0aGlzLnByb3BzLnJlc2l6ZU5vdGlmaWVyfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVtcHR5PXtlbXB0eVN0YXRlfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxheW91dD17TGF5b3V0Lkdyb3VwfVxuICAgICAgICAgICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICAgICAgPC9CYXNlQ2FyZD5cbiAgICAgICAgICAgICAgICA8L1Jvb21Db250ZXh0LlByb3ZpZGVyPlxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAgICAgPFJvb21Db250ZXh0LlByb3ZpZGVyXG4gICAgICAgICAgICAgICAgICAgIHZhbHVlPXt7XG4gICAgICAgICAgICAgICAgICAgICAgICAuLi50aGlzLmNvbnRleHQsXG4gICAgICAgICAgICAgICAgICAgICAgICB0aW1lbGluZVJlbmRlcmluZ1R5cGU6IFRpbWVsaW5lUmVuZGVyaW5nVHlwZS5GaWxlLFxuICAgICAgICAgICAgICAgICAgICB9fVxuICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAgPEJhc2VDYXJkXG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc05hbWU9XCJteF9GaWxlUGFuZWxcIlxuICAgICAgICAgICAgICAgICAgICAgICAgb25DbG9zZT17dGhpcy5wcm9wcy5vbkNsb3NlfVxuICAgICAgICAgICAgICAgICAgICAgICAgaGVhZGVyPXtfdChcInJpZ2h0X3BhbmVsfGZpbGVzX2J1dHRvblwiKX1cbiAgICAgICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgICAgICAgPFNwaW5uZXIgLz5cbiAgICAgICAgICAgICAgICAgICAgPC9CYXNlQ2FyZD5cbiAgICAgICAgICAgICAgICA8L1Jvb21Db250ZXh0LlByb3ZpZGVyPlxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgRmlsZVBhbmVsO1xuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7OztBQVNBLElBQUFBLE1BQUEsR0FBQUMsdUJBQUEsQ0FBQUMsT0FBQTtBQUNBLElBQUFDLE9BQUEsR0FBQUQsT0FBQTtBQVdBLElBQUFFLE9BQUEsR0FBQUYsT0FBQTtBQUNBLElBQUFHLE1BQUEsR0FBQUMsc0JBQUEsQ0FBQUosT0FBQTtBQUVBLElBQUFLLGdCQUFBLEdBQUFMLE9BQUE7QUFDQSxJQUFBTSxjQUFBLEdBQUFGLHNCQUFBLENBQUFKLE9BQUE7QUFDQSxJQUFBTyxnQkFBQSxHQUFBUCxPQUFBO0FBQ0EsSUFBQVEsY0FBQSxHQUFBVCx1QkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQVMsU0FBQSxHQUFBTCxzQkFBQSxDQUFBSixPQUFBO0FBRUEsSUFBQVUsY0FBQSxHQUFBTixzQkFBQSxDQUFBSixPQUFBO0FBQ0EsSUFBQVcsUUFBQSxHQUFBUCxzQkFBQSxDQUFBSixPQUFBO0FBQ0EsSUFBQVksT0FBQSxHQUFBWixPQUFBO0FBQ0EsSUFBQWEsWUFBQSxHQUFBZCx1QkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQWMsU0FBQSxHQUFBVixzQkFBQSxDQUFBSixPQUFBO0FBQ0EsSUFBQWUsV0FBQSxHQUFBWCxzQkFBQSxDQUFBSixPQUFBO0FBQXlELFNBQUFnQix5QkFBQUMsQ0FBQSw2QkFBQUMsT0FBQSxtQkFBQUMsQ0FBQSxPQUFBRCxPQUFBLElBQUFFLENBQUEsT0FBQUYsT0FBQSxZQUFBRix3QkFBQSxZQUFBQSxDQUFBQyxDQUFBLFdBQUFBLENBQUEsR0FBQUcsQ0FBQSxHQUFBRCxDQUFBLEtBQUFGLENBQUE7QUFBQSxTQUFBbEIsd0JBQUFrQixDQUFBLEVBQUFFLENBQUEsU0FBQUEsQ0FBQSxJQUFBRixDQUFBLElBQUFBLENBQUEsQ0FB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