UNPKG

matrix-react-sdk

Version:
323 lines (264 loc) 35.4 kB
"use strict"; var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard"); var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.StopGapWidgetDriver = void 0; var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _matrixWidgetApi = require("matrix-widget-api"); var _iterables = require("../../utils/iterables"); var _MatrixClientPeg = require("../../MatrixClientPeg"); var _ActiveRoomObserver = _interopRequireDefault(require("../../ActiveRoomObserver")); var _Modal = _interopRequireDefault(require("../../Modal")); var _WidgetOpenIDPermissionsDialog = _interopRequireDefault(require("../../components/views/dialogs/WidgetOpenIDPermissionsDialog")); var _WidgetCapabilitiesPromptDialog = _interopRequireWildcard(require("../../components/views/dialogs/WidgetCapabilitiesPromptDialog")); var _WidgetPermissions = require("../../customisations/WidgetPermissions"); var _WidgetPermissionStore = require("./WidgetPermissionStore"); var _WidgetType = require("../../widgets/WidgetType"); var _event = require("matrix-js-sdk/src/@types/event"); var _effects = require("../../effects"); var _utils = require("../../effects/utils"); var _dispatcher = _interopRequireDefault(require("../../dispatcher/dispatcher")); var _Permalinks = require("../../utils/permalinks/Permalinks"); /* * Copyright 2020 The Matrix.org Foundation C.I.C. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // TODO: Purge this from the universe class StopGapWidgetDriver extends _matrixWidgetApi.WidgetDriver { // TODO: Refactor widgetKind into the Widget class constructor(allowedCapabilities /*: Capability[]*/ , forWidget /*: Widget*/ , forWidgetKind /*: WidgetKind*/ , inRoomId /*:: ?: string*/ ) { super(); // Always allow screenshots to be taken because it's a client-induced flow. The widget can't // spew screenshots at us and can't request screenshots of us, so it's up to us to provide the // button if the widget says it supports screenshots. this.forWidget /*:: */ = forWidget /*:: */ ; this.forWidgetKind /*:: */ = forWidgetKind /*:: */ ; this.inRoomId /*:: ?*/ = inRoomId /*:: ?*/ ; (0, _defineProperty2.default)(this, "allowedCapabilities", void 0); this.allowedCapabilities = new Set([...allowedCapabilities, _matrixWidgetApi.MatrixCapabilities.Screenshots]); // Grant the permissions that are specific to given widget types if (_WidgetType.WidgetType.JITSI.matches(this.forWidget.type) && forWidgetKind === _matrixWidgetApi.WidgetKind.Room) { this.allowedCapabilities.add(_matrixWidgetApi.MatrixCapabilities.AlwaysOnScreen); } else if (_WidgetType.WidgetType.STICKERPICKER.matches(this.forWidget.type) && forWidgetKind === _matrixWidgetApi.WidgetKind.Account) { const stickerSendingCap = _matrixWidgetApi.WidgetEventCapability.forRoomEvent(_matrixWidgetApi.EventDirection.Send, _event.EventType.Sticker).raw; this.allowedCapabilities.add(_matrixWidgetApi.MatrixCapabilities.StickerSending); // legacy as far as MSC2762 is concerned this.allowedCapabilities.add(stickerSendingCap); // Auto-approve the legacy visibility capability. We send it regardless of capability. // Widgets don't technically need to request this capability, but Scalar still does. this.allowedCapabilities.add("visibility"); } } async validateCapabilities(requested /*: Set<Capability>*/ ) /*: Promise<Set<Capability>>*/ { // Check to see if any capabilities aren't automatically accepted (such as sticker pickers // allowing stickers to be sent). If there are excess capabilities to be approved, the user // will be prompted to accept them. const diff = (0, _iterables.iterableDiff)(requested, this.allowedCapabilities); const missing = new Set(diff.removed); // "removed" is "in A (requested) but not in B (allowed)" const allowedSoFar = new Set(this.allowedCapabilities); (0, _WidgetCapabilitiesPromptDialog.getRememberedCapabilitiesForWidget)(this.forWidget).forEach(cap => { allowedSoFar.add(cap); missing.delete(cap); }); if (_WidgetPermissions.WidgetPermissionCustomisations.preapproveCapabilities) { const approved = await _WidgetPermissions.WidgetPermissionCustomisations.preapproveCapabilities(this.forWidget, requested); if (approved) { approved.forEach(cap => { allowedSoFar.add(cap); missing.delete(cap); }); } } // TODO: Do something when the widget requests new capabilities not yet asked for if (missing.size > 0) { try { const [result] = await _Modal.default.createTrackedDialog('Approve Widget Caps', '', _WidgetCapabilitiesPromptDialog.default, { requestedCapabilities: missing, widget: this.forWidget, widgetKind: this.forWidgetKind }).finished; (result.approved || []).forEach(cap => allowedSoFar.add(cap)); } catch (e) { console.error("Non-fatal error getting capabilities: ", e); } } return new Set((0, _iterables.iterableUnion)(allowedSoFar, requested)); } async sendEvent(eventType /*: string*/ , content /*: any*/ , stateKey /*: string*/ = null) /*: Promise<ISendEventDetails>*/ { const client = _MatrixClientPeg.MatrixClientPeg.get(); const roomId = _ActiveRoomObserver.default.activeRoomId; if (!client || !roomId) throw new Error("Not in a room or not attached to a client"); let r /*: { event_id: string }*/ = null; // eslint-disable-line camelcase if (stateKey !== null) { // state event r = await client.sendStateEvent(roomId, eventType, content, stateKey); } else { // message event r = await client.sendEvent(roomId, eventType, content); if (eventType === _event.EventType.RoomMessage) { _effects.CHAT_EFFECTS.forEach(effect => { if ((0, _utils.containsEmoji)(content, effect.emojis)) { _dispatcher.default.dispatch({ action: `effects.${effect.command}` }); } }); } } return { roomId, eventId: r.event_id }; } async readRoomEvents(eventType /*: string*/ , msgtype /*: string | undefined*/ , limit /*: number*/ ) /*: Promise<MatrixEvent[]>*/ { limit = limit > 0 ? Math.min(limit, 25) : 25; // arbitrary choice const client = _MatrixClientPeg.MatrixClientPeg.get(); const roomId = _ActiveRoomObserver.default.activeRoomId; const room = client.getRoom(roomId); if (!client || !roomId || !room) throw new Error("Not in a room or not attached to a client"); const results /*: MatrixEvent[]*/ = []; const events = room.getLiveTimeline().getEvents(); // timelines are most recent last for (let i = events.length - 1; i > 0; i--) { if (results.length >= limit) break; const ev = events[i]; if (ev.getType() !== eventType) continue; if (eventType === _event.EventType.RoomMessage && msgtype && msgtype !== ev.getContent()['msgtype']) continue; results.push(ev); } return results.map(e => e.event); } async readStateEvents(eventType /*: string*/ , stateKey /*: string | undefined*/ , limit /*: number*/ ) /*: Promise<MatrixEvent[]>*/ { limit = limit > 0 ? Math.min(limit, 100) : 100; // arbitrary choice const client = _MatrixClientPeg.MatrixClientPeg.get(); const roomId = _ActiveRoomObserver.default.activeRoomId; const room = client.getRoom(roomId); if (!client || !roomId || !room) throw new Error("Not in a room or not attached to a client"); const results /*: MatrixEvent[]*/ = []; const state = room.currentState.events.get(eventType); if (state) { if (stateKey === "" || !!stateKey) { const forKey = state.get(stateKey); if (forKey) results.push(forKey); } else { results.push(...Array.from(state.values())); } } return results.slice(0, limit).map(e => e.event); } async askOpenID(observer /*: SimpleObservable<IOpenIDUpdate>*/ ) { const oidcState = _WidgetPermissionStore.WidgetPermissionStore.instance.getOIDCState(this.forWidget, this.forWidgetKind, this.inRoomId); const getToken = () => /*: Promise<IOpenIDCredentials>*/ { return _MatrixClientPeg.MatrixClientPeg.get().getOpenIdToken(); }; if (oidcState === _WidgetPermissionStore.OIDCState.Denied) { return observer.update({ state: _matrixWidgetApi.OpenIDRequestState.Blocked }); } if (oidcState === _WidgetPermissionStore.OIDCState.Allowed) { return observer.update({ state: _matrixWidgetApi.OpenIDRequestState.Allowed, token: await getToken() }); } observer.update({ state: _matrixWidgetApi.OpenIDRequestState.PendingUserConfirmation }); _Modal.default.createTrackedDialog("OpenID widget permissions", '', _WidgetOpenIDPermissionsDialog.default, { widget: this.forWidget, widgetKind: this.forWidgetKind, inRoomId: this.inRoomId, onFinished: async confirm => { if (!confirm) { return observer.update({ state: _matrixWidgetApi.OpenIDRequestState.Blocked }); } return observer.update({ state: _matrixWidgetApi.OpenIDRequestState.Allowed, token: await getToken() }); } }); } async navigate(uri /*: string*/ ) /*: Promise<void>*/ { const localUri = (0, _Permalinks.tryTransformPermalinkToLocalHref)(uri); if (!localUri || localUri === uri) { // parse failure can lead to an unmodified URL throw new Error("Failed to transform URI"); } window.location.hash = localUri; // it'll just be a fragment } } exports.StopGapWidgetDriver = StopGapWidgetDriver; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9zdG9yZXMvd2lkZ2V0cy9TdG9wR2FwV2lkZ2V0RHJpdmVyLnRzIl0sIm5hbWVzIjpbIlN0b3BHYXBXaWRnZXREcml2ZXIiLCJXaWRnZXREcml2ZXIiLCJjb25zdHJ1Y3RvciIsImFsbG93ZWRDYXBhYmlsaXRpZXMiLCJmb3JXaWRnZXQiLCJmb3JXaWRnZXRLaW5kIiwiaW5Sb29tSWQiLCJTZXQiLCJNYXRyaXhDYXBhYmlsaXRpZXMiLCJTY3JlZW5zaG90cyIsIldpZGdldFR5cGUiLCJKSVRTSSIsIm1hdGNoZXMiLCJ0eXBlIiwiV2lkZ2V0S2luZCIsIlJvb20iLCJhZGQiLCJBbHdheXNPblNjcmVlbiIsIlNUSUNLRVJQSUNLRVIiLCJBY2NvdW50Iiwic3RpY2tlclNlbmRpbmdDYXAiLCJXaWRnZXRFdmVudENhcGFiaWxpdHkiLCJmb3JSb29tRXZlbnQiLCJFdmVudERpcmVjdGlvbiIsIlNlbmQiLCJFdmVudFR5cGUiLCJTdGlja2VyIiwicmF3IiwiU3RpY2tlclNlbmRpbmciLCJ2YWxpZGF0ZUNhcGFiaWxpdGllcyIsInJlcXVlc3RlZCIsImRpZmYiLCJtaXNzaW5nIiwicmVtb3ZlZCIsImFsbG93ZWRTb0ZhciIsImZvckVhY2giLCJjYXAiLCJkZWxldGUiLCJXaWRnZXRQZXJtaXNzaW9uQ3VzdG9taXNhdGlvbnMiLCJwcmVhcHByb3ZlQ2FwYWJpbGl0aWVzIiwiYXBwcm92ZWQiLCJzaXplIiwicmVzdWx0IiwiTW9kYWwiLCJjcmVhdGVUcmFja2VkRGlhbG9nIiwiV2lkZ2V0Q2FwYWJpbGl0aWVzUHJvbXB0RGlhbG9nIiwicmVxdWVzdGVkQ2FwYWJpbGl0aWVzIiwid2lkZ2V0Iiwid2lkZ2V0S2luZCIsImZpbmlzaGVkIiwiZSIsImNvbnNvbGUiLCJlcnJvciIsInNlbmRFdmVudCIsImV2ZW50VHlwZSIsImNvbnRlbnQiLCJzdGF0ZUtleSIsImNsaWVudCIsIk1hdHJpeENsaWVudFBlZyIsImdldCIsInJvb21JZCIsIkFjdGl2ZVJvb21PYnNlcnZlciIsImFjdGl2ZVJvb21JZCIsIkVycm9yIiwiciIsInNlbmRTdGF0ZUV2ZW50IiwiUm9vbU1lc3NhZ2UiLCJDSEFUX0VGRkVDVFMiLCJlZmZlY3QiLCJlbW9qaXMiLCJkaXMiLCJkaXNwYXRjaCIsImFjdGlvbiIsImNvbW1hbmQiLCJldmVudElkIiwiZXZlbnRfaWQiLCJyZWFkUm9vbUV2ZW50cyIsIm1zZ3R5cGUiLCJsaW1pdCIsIk1hdGgiLCJtaW4iLCJyb29tIiwiZ2V0Um9vbSIsInJlc3VsdHMiLCJldmVudHMiLCJnZXRMaXZlVGltZWxpbmUiLCJnZXRFdmVudHMiLCJpIiwibGVuZ3RoIiwiZXYiLCJnZXRUeXBlIiwiZ2V0Q29udGVudCIsInB1c2giLCJtYXAiLCJldmVudCIsInJlYWRTdGF0ZUV2ZW50cyIsInN0YXRlIiwiY3VycmVudFN0YXRlIiwiZm9yS2V5IiwiQXJyYXkiLCJmcm9tIiwidmFsdWVzIiwic2xpY2UiLCJhc2tPcGVuSUQiLCJvYnNlcnZlciIsIm9pZGNTdGF0ZSIsIldpZGdldFBlcm1pc3Npb25TdG9yZSIsImluc3RhbmNlIiwiZ2V0T0lEQ1N0YXRlIiwiZ2V0VG9rZW4iLCJnZXRPcGVuSWRUb2tlbiIsIk9JRENTdGF0ZSIsIkRlbmllZCIsInVwZGF0ZSIsIk9wZW5JRFJlcXVlc3RTdGF0ZSIsIkJsb2NrZWQiLCJBbGxvd2VkIiwidG9rZW4iLCJQZW5kaW5nVXNlckNvbmZpcm1hdGlvbiIsIldpZGdldE9wZW5JRFBlcm1pc3Npb25zRGlhbG9nIiwib25GaW5pc2hlZCIsImNvbmZpcm0iLCJuYXZpZ2F0ZSIsInVyaSIsImxvY2FsVXJpIiwid2luZG93IiwibG9jYXRpb24iLCJoYXNoIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7O0FBZ0JBOztBQWNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUdBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQTdDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtB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QVYsQ0FBTjtBQUNIOztBQUNEOEQsSUFBQUEsTUFBTSxDQUFDQyxRQUFQLENBQWdCQyxJQUFoQixHQUF1QkgsUUFBdkIsQ0FMOEMsQ0FLYjtBQUNwQzs7QUF0TGlEIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAyMDIwIFRoZSBNYXRyaXgub3JnIEZvdW5kYXRpb24gQy5JLkMuXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQge1xuICAgIENhcGFiaWxpdHksXG4gICAgRXZlbnREaXJlY3Rpb24sXG4gICAgSU9wZW5JRENyZWRlbnRpYWxzLFxuICAgIElPcGVuSURVcGRhdGUsXG4gICAgSVNlbmRFdmVudERldGFpbHMsXG4gICAgTWF0cml4Q2FwYWJpbGl0aWVzLFxuICAgIE9wZW5JRFJlcXVlc3RTdGF0ZSxcbiAgICBTaW1wbGVPYnNlcnZhYmxlLFxuICAgIFdpZGdldCxcbiAgICBXaWRnZXREcml2ZXIsXG4gICAgV2lkZ2V0RXZlbnRDYXBhYmlsaXR5LFxuICAgIFdpZGdldEtpbmQsXG59IGZyb20gXCJtYXRyaXgtd2lkZ2V0LWFwaVwiO1xuaW1wb3J0IHsgaXRlcmFibGVEaWZmLCBpdGVyYWJsZVVuaW9uIH0gZnJvbSBcIi4uLy4uL3V0aWxzL2l0ZXJhYmxlc1wiO1xuaW1wb3J0IHsgTWF0cml4Q2xpZW50UGVnIH0gZnJvbSBcIi4uLy4uL01hdHJpeENsaWVudFBlZ1wiO1xuaW1wb3J0IEFjdGl2ZVJvb21PYnNlcnZlciBmcm9tIFwiLi4vLi4vQWN0aXZlUm9vbU9ic2VydmVyXCI7XG5pbXBvcnQgTW9kYWwgZnJvbSBcIi4uLy4uL01vZGFsXCI7XG5pbXBvcnQgV2lkZ2V0T3BlbklEUGVybWlzc2lvbnNEaWFsb2cgZnJvbSBcIi4uLy4uL2NvbXBvbmVudHMvdmlld3MvZGlhbG9ncy9XaWRnZXRPcGVuSURQZXJtaXNzaW9uc0RpYWxvZ1wiO1xuaW1wb3J0IFdpZGdldENhcGFiaWxpdGllc1Byb21wdERpYWxvZywge1xuICAgIGdldFJlbWVtYmVyZWRDYXBhYmlsaXRpZXNGb3JXaWRnZXQsXG59IGZyb20gXCIuLi8uLi9jb21wb25lbnRzL3ZpZXdzL2RpYWxvZ3MvV2lkZ2V0Q2FwYWJpbGl0aWVzUHJvbXB0RGlhbG9nXCI7XG5pbXBvcnQgeyBXaWRnZXRQZXJtaXNzaW9uQ3VzdG9taXNhdGlvbnMgfSBmcm9tIFwiLi4vLi4vY3VzdG9taXNhdGlvbnMvV2lkZ2V0UGVybWlzc2lvbnNcIjtcbmltcG9ydCB7IE9JRENTdGF0ZSwgV2lkZ2V0UGVybWlzc2lvblN0b3JlIH0gZnJvbSBcIi4vV2lkZ2V0UGVybWlzc2lvblN0b3JlXCI7XG5pbXBvcnQgeyBXaWRnZXRUeXBlIH0gZnJvbSBcIi4uLy4uL3dpZGdldHMvV2lkZ2V0VHlwZVwiO1xuaW1wb3J0IHsgRXZlbnRUeXBlIH0gZnJvbSBcIm1hdHJpeC1qcy1zZGsvc3JjL0B0eXBlcy9ldmVudFwiO1xuaW1wb3J0IHsgQ0hBVF9FRkZFQ1RTIH0gZnJvbSBcIi4uLy4uL2VmZmVjdHNcIjtcbmltcG9ydCB7IGNvbnRhaW5zRW1vamkgfSBmcm9tIFwiLi4vLi4vZWZmZWN0cy91dGlsc1wiO1xuaW1wb3J0IGRpcyBmcm9tIFwiLi4vLi4vZGlzcGF0Y2hlci9kaXNwYXRjaGVyXCI7XG5pbXBvcnQge3RyeVRyYW5zZm9ybVBlcm1hbGlua1RvTG9jYWxIcmVmfSBmcm9tIFwiLi4vLi4vdXRpbHMvcGVybWFsaW5rcy9QZXJtYWxpbmtzXCI7XG5pbXBvcnQge01hdHJpeEV2ZW50fSBmcm9tIFwibWF0cml4LWpzLXNkay9zcmMvbW9kZWxzL2V2ZW50XCI7XG5cbi8vIFRPRE86IFB1cmdlIHRoaXMgZnJvbSB0aGUgdW5pdmVyc2VcblxuZXhwb3J0IGNsYXNzIFN0b3BHYXBXaWRnZXREcml2ZXIgZXh0ZW5kcyBXaWRnZXREcml2ZXIge1xuICAgIHByaXZhdGUgYWxsb3dlZENhcGFiaWxpdGllczogU2V0PENhcGFiaWxpdHk+O1xuXG4gICAgLy8gVE9ETzogUmVmYWN0b3Igd2lkZ2V0S2luZCBpbnRvIHRoZSBXaWRnZXQgY2xhc3NcbiAgICBjb25zdHJ1Y3RvcihcbiAgICAgICAgYWxsb3dlZENhcGFiaWxpdGllczogQ2FwYWJpbGl0eVtdLFxuICAgICAgICBwcml2YXRlIGZvcldpZGdldDogV2lkZ2V0LFxuICAgICAgICBwcml2YXRlIGZvcldpZGdldEtpbmQ6IFdpZGdldEtpbmQsXG4gICAgICAgIHByaXZhdGUgaW5Sb29tSWQ/OiBzdHJpbmcsXG4gICAgKSB7XG4gICAgICAgIHN1cGVyKCk7XG5cbiAgICAgICAgLy8gQWx3YXlzIGFsbG93IHNjcmVlbnNob3RzIHRvIGJlIHRha2VuIGJlY2F1c2UgaXQncyBhIGNsaWVudC1pbmR1Y2VkIGZsb3cuIFRoZSB3aWRnZXQgY2FuJ3RcbiAgICAgICAgLy8gc3BldyBzY3JlZW5zaG90cyBhdCB1cyBhbmQgY2FuJ3QgcmVxdWVzdCBzY3JlZW5zaG90cyBvZiB1cywgc28gaXQncyB1cCB0byB1cyB0byBwcm92aWRlIHRoZVxuICAgICAgICAvLyBidXR0b24gaWYgdGhlIHdpZGdldCBzYXlzIGl0IHN1cHBvcnRzIHNjcmVlbnNob3RzLlxuICAgICAgICB0aGlzLmFsbG93ZWRDYXBhYmlsaXRpZXMgPSBuZXcgU2V0KFsuLi5hbGxvd2VkQ2FwYWJpbGl0aWVzLCBNYXRyaXhDYXBhYmlsaXRpZXMuU2NyZWVuc2hvdHNdKTtcblxuICAgICAgICAvLyBHcmFudCB0aGUgcGVybWlzc2lvbnMgdGhhdCBhcmUgc3BlY2lmaWMgdG8gZ2l2ZW4gd2lkZ2V0IHR5cGVzXG4gICAgICAgIGlmIChXaWRnZXRUeXBlLkpJVFNJLm1hdGNoZXModGhpcy5mb3JXaWRnZXQudHlwZSkgJiYgZm9yV2lkZ2V0S2luZCA9PT0gV2lkZ2V0S2luZC5Sb29tKSB7XG4gICAgICAgICAgICB0aGlzLmFsbG93ZWRDYXBhYmlsaXRpZXMuYWRkKE1hdHJpeENhcGFiaWxpdGllcy5BbHdheXNPblNjcmVlbik7XG4gICAgICAgIH0gZWxzZSBpZiAoV2lkZ2V0VHlwZS5TVElDS0VSUElDS0VSLm1hdGNoZXModGhpcy5mb3JXaWRnZXQudHlwZSkgJiYgZm9yV2lkZ2V0S2luZCA9PT0gV2lkZ2V0S2luZC5BY2NvdW50KSB7XG4gICAgICAgICAgICBjb25zdCBzdGlja2VyU2VuZGluZ0NhcCA9IFdpZGdldEV2ZW50Q2FwYWJpbGl0eS5mb3JSb29tRXZlbnQoRXZlbnREaXJlY3Rpb24uU2VuZCwgRXZlbnRUeXBlLlN0aWNrZXIpLnJhdztcbiAgICAgICAgICAgIHRoaXMuYWxsb3dlZENhcGFiaWxpdGllcy5hZGQoTWF0cml4Q2FwYWJpbGl0aWVzLlN0aWNrZXJTZW5kaW5nKTsgLy8gbGVnYWN5IGFzIGZhciBhcyBNU0MyNzYyIGlzIGNvbmNlcm5lZFxuICAgICAgICAgICAgdGhpcy5hbGxvd2VkQ2FwYWJpbGl0aWVzLmFkZChzdGlja2VyU2VuZGluZ0NhcCk7XG5cbiAgICAgICAgICAgIC8vIEF1dG8tYXBwcm92ZSB0aGUgbGVnYWN5IHZpc2liaWxpdHkgY2FwYWJpbGl0eS4gV2Ugc2VuZCBpdCByZWdhcmRsZXNzIG9mIGNhcGFiaWxpdHkuXG4gICAgICAgICAgICAvLyBXaWRnZXRzIGRvbid0IHRlY2huaWNhbGx5IG5lZWQgdG8gcmVxdWVzdCB0aGlzIGNhcGFiaWxpdHksIGJ1dCBTY2FsYXIgc3RpbGwgZG9lcy5cbiAgICAgICAgICAgIHRoaXMuYWxsb3dlZENhcGFiaWxpdGllcy5hZGQoXCJ2aXNpYmlsaXR5XCIpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIHZhbGlkYXRlQ2FwYWJpbGl0aWVzKHJlcXVlc3RlZDogU2V0PENhcGFiaWxpdHk+KTogUHJvbWlzZTxTZXQ8Q2FwYWJpbGl0eT4+IHtcbiAgICAgICAgLy8gQ2hlY2sgdG8gc2VlIGlmIGFueSBjYXBhYmlsaXRpZXMgYXJlbid0IGF1dG9tYXRpY2FsbHkgYWNjZXB0ZWQgKHN1Y2ggYXMgc3RpY2tlciBwaWNrZXJzXG4gICAgICAgIC8vIGFsbG93aW5nIHN0aWNrZXJzIHRvIGJlIHNlbnQpLiBJZiB0aGVyZSBhcmUgZXhjZXNzIGNhcGFiaWxpdGllcyB0byBiZSBhcHByb3ZlZCwgdGhlIHVzZXJcbiAgICAgICAgLy8gd2lsbCBiZSBwcm9tcHRlZCB0byBhY2NlcHQgdGhlbS5cbiAgICAgICAgY29uc3QgZGlmZiA9IGl0ZXJhYmxlRGlmZihyZXF1ZXN0ZWQsIHRoaXMuYWxsb3dlZENhcGFiaWxpdGllcyk7XG4gICAgICAgIGNvbnN0IG1pc3NpbmcgPSBuZXcgU2V0KGRpZmYucmVtb3ZlZCk7IC8vIFwicmVtb3ZlZFwiIGlzIFwiaW4gQSAocmVxdWVzdGVkKSBidXQgbm90IGluIEIgKGFsbG93ZWQpXCJcbiAgICAgICAgY29uc3QgYWxsb3dlZFNvRmFyID0gbmV3IFNldCh0aGlzLmFsbG93ZWRDYXBhYmlsaXRpZXMpO1xuICAgICAgICBnZXRSZW1lbWJlcmVkQ2FwYWJpbGl0aWVzRm9yV2lkZ2V0KHRoaXMuZm9yV2lkZ2V0KS5mb3JFYWNoKGNhcCA9PiB7XG4gICAgICAgICAgICBhbGxvd2VkU29GYXIuYWRkKGNhcCk7XG4gICAgICAgICAgICBtaXNzaW5nLmRlbGV0ZShjYXApO1xuICAgICAgICB9KTtcbiAgICAgICAgaWYgKFdpZGdldFBlcm1pc3Npb25DdXN0b21pc2F0aW9ucy5wcmVhcHByb3ZlQ2FwYWJpbGl0aWVzKSB7XG4gICAgICAgICAgICBjb25zdCBhcHByb3ZlZCA9IGF3YWl0IFdpZGdldFBlcm1pc3Npb25DdXN0b21pc2F0aW9ucy5wcmVhcHByb3ZlQ2FwYWJpbGl0aWVzKHRoaXMuZm9yV2lkZ2V0LCByZXF1ZXN0ZWQpO1xuICAgICAgICAgICAgaWYgKGFwcHJvdmVkKSB7XG4gICAgICAgICAgICAgICAgYXBwcm92ZWQuZm9yRWFjaChjYXAgPT4ge1xuICAgICAgICAgICAgICAgICAgICBhbGxvd2VkU29GYXIuYWRkKGNhcCk7XG4gICAgICAgICAgICAgICAgICAgIG1pc3NpbmcuZGVsZXRlKGNhcCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gVE9ETzogRG8gc29tZXRoaW5nIHdoZW4gdGhlIHdpZGdldCByZXF1ZXN0cyBuZXcgY2FwYWJpbGl0aWVzIG5vdCB5ZXQgYXNrZWQgZm9yXG4gICAgICAgIGlmIChtaXNzaW5nLnNpemUgPiAwKSB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGNvbnN0IFtyZXN1bHRdID0gYXdhaXQgTW9kYWwuY3JlYXRlVHJhY2tlZERpYWxvZyhcbiAgICAgICAgICAgICAgICAgICAgJ0FwcHJvdmUgV2lkZ2V0IENhcHMnLCAnJyxcbiAgICAgICAgICAgICAgICAgICAgV2lkZ2V0Q2FwYWJpbGl0aWVzUHJvbXB0RGlhbG9nLFxuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXF1ZXN0ZWRDYXBhYmlsaXRpZXM6IG1pc3NpbmcsXG4gICAgICAgICAgICAgICAgICAgICAgICB3aWRnZXQ6IHRoaXMuZm9yV2lkZ2V0LFxuICAgICAgICAgICAgICAgICAgICAgICAgd2lkZ2V0S2luZDogdGhpcy5mb3JXaWRnZXRLaW5kLFxuICAgICAgICAgICAgICAgICAgICB9KS5maW5pc2hlZDtcbiAgICAgICAgICAgICAgICAocmVzdWx0LmFwcHJvdmVkIHx8IFtdKS5mb3JFYWNoKGNhcCA9PiBhbGxvd2VkU29GYXIuYWRkKGNhcCkpO1xuICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJOb24tZmF0YWwgZXJyb3IgZ2V0dGluZyBjYXBhYmlsaXRpZXM6IFwiLCBlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBuZXcgU2V0KGl0ZXJhYmxlVW5pb24oYWxsb3dlZFNvRmFyLCByZXF1ZXN0ZWQpKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgc2VuZEV2ZW50KGV2ZW50VHlwZTogc3RyaW5nLCBjb250ZW50OiBhbnksIHN0YXRlS2V5OiBzdHJpbmcgPSBudWxsKTogUHJvbWlzZTxJU2VuZEV2ZW50RGV0YWlscz4ge1xuICAgICAgICBjb25zdCBjbGllbnQgPSBNYXRyaXhDbGllbnRQZWcuZ2V0KCk7XG4gICAgICAgIGNvbnN0IHJvb21JZCA9IEFjdGl2ZVJvb21PYnNlcnZlci5hY3RpdmVSb29tSWQ7XG5cbiAgICAgICAgaWYgKCFjbGllbnQgfHwgIXJvb21JZCkgdGhyb3cgbmV3IEVycm9yKFwiTm90IGluIGEgcm9vbSBvciBub3QgYXR0YWNoZWQgdG8gYSBjbGllbnRcIik7XG5cbiAgICAgICAgbGV0IHI6IHsgZXZlbnRfaWQ6IHN0cmluZyB9ID0gbnVsbDsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBjYW1lbGNhc2VcbiAgICAgICAgaWYgKHN0YXRlS2V5ICE9PSBudWxsKSB7XG4gICAgICAgICAgICAvLyBzdGF0ZSBldmVudFxuICAgICAgICAgICAgciA9IGF3YWl0IGNsaWVudC5zZW5kU3RhdGVFdmVudChyb29tSWQsIGV2ZW50VHlwZSwgY29udGVudCwgc3RhdGVLZXkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gbWVzc2FnZSBldmVudFxuICAgICAgICAgICAgciA9IGF3YWl0IGNsaWVudC5zZW5kRXZlbnQocm9vbUlkLCBldmVudFR5cGUsIGNvbnRlbnQpO1xuXG4gICAgICAgICAgICBpZiAoZXZlbnRUeXBlID09PSBFdmVudFR5cGUuUm9vbU1lc3NhZ2UpIHtcbiAgICAgICAgICAgICAgICBDSEFUX0VGRkVDVFMuZm9yRWFjaCgoZWZmZWN0KSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjb250YWluc0Vtb2ppKGNvbnRlbnQsIGVmZmVjdC5lbW9qaXMpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkaXMuZGlzcGF0Y2goe2FjdGlvbjogYGVmZmVjdHMuJHtlZmZlY3QuY29tbWFuZH1gfSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB7cm9vbUlkLCBldmVudElkOiByLmV2ZW50X2lkfTtcbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgcmVhZFJvb21FdmVudHMoZXZlbnRUeXBlOiBzdHJpbmcsIG1zZ3R5cGU6IHN0cmluZyB8IHVuZGVmaW5lZCwgbGltaXQ6IG51bWJlcik6IFByb21pc2U8TWF0cml4RXZlbnRbXT4ge1xuICAgICAgICBsaW1pdCA9IGxpbWl0ID4gMCA/IE1hdGgubWluKGxpbWl0LCAyNSkgOiAyNTsgLy8gYXJiaXRyYXJ5IGNob2ljZVxuXG4gICAgICAgIGNvbnN0IGNsaWVudCA9IE1hdHJpeENsaWVudFBlZy5nZXQoKTtcbiAgICAgICAgY29uc3Qgcm9vbUlkID0gQWN0aXZlUm9vbU9ic2VydmVyLmFjdGl2ZVJvb21JZDtcbiAgICAgICAgY29uc3Qgcm9vbSA9IGNsaWVudC5nZXRSb29tKHJvb21JZCk7XG4gICAgICAgIGlmICghY2xpZW50IHx8ICFyb29tSWQgfHwgIXJvb20pIHRocm93IG5ldyBFcnJvcihcIk5vdCBpbiBhIHJvb20gb3Igbm90IGF0dGFjaGVkIHRvIGEgY2xpZW50XCIpO1xuXG4gICAgICAgIGNvbnN0IHJlc3VsdHM6IE1hdHJpeEV2ZW50W10gPSBbXTtcbiAgICAgICAgY29uc3QgZXZlbnRzID0gcm9vbS5nZXRMaXZlVGltZWxpbmUoKS5nZXRFdmVudHMoKTsgLy8gdGltZWxpbmVzIGFyZSBtb3N0IHJlY2VudCBsYXN0XG4gICAgICAgIGZvciAobGV0IGkgPSBldmVudHMubGVuZ3RoIC0gMTsgaSA+IDA7IGktLSkge1xuICAgICAgICAgICAgaWYgKHJlc3VsdHMubGVuZ3RoID49IGxpbWl0KSBicmVhaztcblxuICAgICAgICAgICAgY29uc3QgZXYgPSBldmVudHNbaV07XG4gICAgICAgICAgICBpZiAoZXYuZ2V0VHlwZSgpICE9PSBldmVudFR5cGUpIGNvbnRpbnVlO1xuICAgICAgICAgICAgaWYgKGV2ZW50VHlwZSA9PT0gRXZlbnRUeXBlLlJvb21NZXNzYWdlICYmIG1zZ3R5cGUgJiYgbXNndHlwZSAhPT0gZXYuZ2V0Q29udGVudCgpWydtc2d0eXBlJ10pIGNvbnRpbnVlO1xuICAgICAgICAgICAgcmVzdWx0cy5wdXNoKGV2KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByZXN1bHRzLm1hcChlID0+IGUuZXZlbnQpO1xuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyByZWFkU3RhdGVFdmVudHMoXG4gICAgICAgIGV2ZW50VHlwZTogc3RyaW5nLCBzdGF0ZUtleTogc3RyaW5nIHwgdW5kZWZpbmVkLCBsaW1pdDogbnVtYmVyLFxuICAgICk6IFByb21pc2U8TWF0cml4RXZlbnRbXT4ge1xuICAgICAgICBsaW1pdCA9IGxpbWl0ID4gMCA/IE1hdGgubWluKGxpbWl0LCAxMDApIDogMTAwOyAvLyBhcmJpdHJhcnkgY2hvaWNlXG5cbiAgICAgICAgY29uc3QgY2xpZW50ID0gTWF0cml4Q2xpZW50UGVnLmdldCgpO1xuICAgICAgICBjb25zdCByb29tSWQgPSBBY3RpdmVSb29tT2JzZXJ2ZXIuYWN0aXZlUm9vbUlkO1xuICAgICAgICBjb25zdCByb29tID0gY2xpZW50LmdldFJvb20ocm9vbUlkKTtcbiAgICAgICAgaWYgKCFjbGllbnQgfHwgIXJvb21JZCB8fCAhcm9vbSkgdGhyb3cgbmV3IEVycm9yKFwiTm90IGluIGEgcm9vbSBvciBub3QgYXR0YWNoZWQgdG8gYSBjbGllbnRcIik7XG5cbiAgICAgICAgY29uc3QgcmVzdWx0czogTWF0cml4RXZlbnRbXSA9IFtdO1xuICAgICAgICBjb25zdCBzdGF0ZSA9IHJvb20uY3VycmVudFN0YXRlLmV2ZW50cy5nZXQoZXZlbnRUeXBlKTtcbiAgICAgICAgaWYgKHN0YXRlKSB7XG4gICAgICAgICAgICBpZiAoc3RhdGVLZXkgPT09IFwiXCIgfHwgISFzdGF0ZUtleSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGZvcktleSA9IHN0YXRlLmdldChzdGF0ZUtleSk7XG4gICAgICAgICAgICAgICAgaWYgKGZvcktleSkgcmVzdWx0cy5wdXNoKGZvcktleSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlc3VsdHMucHVzaCguLi5BcnJheS5mcm9tKHN0YXRlLnZhbHVlcygpKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzdWx0cy5zbGljZSgwLCBsaW1pdCkubWFwKGUgPT4gZS5ldmVudCk7XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIGFza09wZW5JRChvYnNlcnZlcjogU2ltcGxlT2JzZXJ2YWJsZTxJT3BlbklEVXBkYXRlPikge1xuICAgICAgICBjb25zdCBvaWRjU3RhdGUgPSBXaWRnZXRQZXJtaXNzaW9uU3RvcmUuaW5zdGFuY2UuZ2V0T0lEQ1N0YXRlKFxuICAgICAgICAgICAgdGhpcy5mb3JXaWRnZXQsIHRoaXMuZm9yV2lkZ2V0S2luZCwgdGhpcy5pblJvb21JZCxcbiAgICAgICAgKTtcblxuICAgICAgICBjb25zdCBnZXRUb2tlbiA9ICgpOiBQcm9taXNlPElPcGVuSURDcmVkZW50aWFscz4gPT4ge1xuICAgICAgICAgICAgcmV0dXJuIE1hdHJpeENsaWVudFBlZy5nZXQoKS5nZXRPcGVuSWRUb2tlbigpO1xuICAgICAgICB9O1xuXG4gICAgICAgIGlmIChvaWRjU3RhdGUgPT09IE9JRENTdGF0ZS5EZW5pZWQpIHtcbiAgICAgICAgICAgIHJldHVybiBvYnNlcnZlci51cGRhdGUoe3N0YXRlOiBPcGVuSURSZXF1ZXN0U3RhdGUuQmxvY2tlZH0pO1xuICAgICAgICB9XG4gICAgICAgIGlmIChvaWRjU3RhdGUgPT09IE9JRENTdGF0ZS5BbGxvd2VkKSB7XG4gICAgICAgICAgICByZXR1cm4gb2JzZXJ2ZXIudXBkYXRlKHtzdGF0ZTogT3BlbklEUmVxdWVzdFN0YXRlLkFsbG93ZWQsIHRva2VuOiBhd2FpdCBnZXRUb2tlbigpfSk7XG4gICAgICAgIH1cblxuICAgICAgICBvYnNlcnZlci51cGRhdGUoe3N0YXRlOiBPcGVuSURSZXF1ZXN0U3RhdGUuUGVuZGluZ1VzZXJDb25maXJtYXRpb259KTtcblxuICAgICAgICBNb2RhbC5jcmVhdGVUcmFja2VkRGlhbG9nKFwiT3BlbklEIHdpZGdldCBwZXJtaXNzaW9uc1wiLCAnJywgV2lkZ2V0T3BlbklEUGVybWlzc2lvbnNEaWFsb2csIHtcbiAgICAgICAgICAgIHdpZGdldDogdGhpcy5mb3JXaWRnZXQsXG4gICAgICAgICAgICB3aWRnZXRLaW5kOiB0aGlzLmZvcldpZGdldEtpbmQsXG4gICAgICAgICAgICBpblJvb21JZDogdGhpcy5pblJvb21JZCxcblxuICAgICAgICAgICAgb25GaW5pc2hlZDogYXN5bmMgKGNvbmZpcm0pID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoIWNvbmZpcm0pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG9ic2VydmVyLnVwZGF0ZSh7c3RhdGU6IE9wZW5JRFJlcXVlc3RTdGF0ZS5CbG9ja2VkfSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG9ic2VydmVyLnVwZGF0ZSh7c3RhdGU6IE9wZW5JRFJlcXVlc3RTdGF0ZS5BbGxvd2VkLCB0b2tlbjogYXdhaXQgZ2V0VG9rZW4oKX0pO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIG5hdmlnYXRlKHVyaTogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGNvbnN0IGxvY2FsVXJpID0gdHJ5VHJhbnNmb3JtUGVybWFsaW5rVG9Mb2NhbEhyZWYodXJpKTtcbiAgICAgICAgaWYgKCFsb2NhbFVyaSB8fCBsb2NhbFVyaSA9PT0gdXJpKSB7IC8vIHBhcnNlIGZhaWx1cmUgY2FuIGxlYWQgdG8gYW4gdW5tb2RpZmllZCBVUkxcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkZhaWxlZCB0byB0cmFuc2Zvcm0gVVJJXCIpO1xuICAgICAgICB9XG4gICAgICAgIHdpbmRvdy5sb2NhdGlvbi5oYXNoID0gbG9jYWxVcmk7IC8vIGl0J2xsIGp1c3QgYmUgYSBmcmFnbWVudFxuICAgIH1cbn1cbiJdfQ==