UNPKG

@jsprismarine/prismarine

Version:

Dedicated Minecraft Bedrock Edition server written in TypeScript

315 lines (308 loc) • 31.8 kB
'use strict'; Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); const fs = require('node:fs'); const confbox = require('confbox'); const errors = require('@jsprismarine/errors'); require('@jsprismarine/jsbinaryutils'); require('node:assert'); const utils_cwd = require('../utils/cwd.cjs.cjs'); require('../block/BlockToolType.cjs.cjs'); require('@jsprismarine/bedrock-data'); require('@jsprismarine/nbt'); require('zlib'); require('@jsprismarine/math'); require('@jsprismarine/minecraft'); require('../network/packet/AddActorPacket.cjs.cjs'); require('../network/packet/MoveActorAbsolutePacket.cjs.cjs'); require('../network/packet/RemoveActorPacket.cjs.cjs'); require('node:crypto'); require('../network/packet/ActorFallPacket.cjs.cjs'); require('../network/packet/AddItemActorPacket.cjs.cjs'); require('../network/packet/AddPlayerPacket.cjs.cjs'); require('../network/packet/AnimatePacket.cjs.cjs'); require('../network/packet/AvailableActorIdentifiersPacket.cjs.cjs'); require('../network/packet/AvailableCommandsPacket.cjs.cjs'); require('../network/CompressionProvider.cjs.cjs'); require('../network/packet/NetworkSettingsPacket.cjs.cjs'); require('../network/packet/BiomeDefinitionListPacket.cjs.cjs'); require('../network/packet/ChangeDimensionPacket.cjs.cjs'); require('../network/packet/ChunkRadiusUpdatedPacket.cjs.cjs'); require('../network/packet/CommandRequestPacket.cjs.cjs'); require('../network/packet/ContainerClosePacket.cjs.cjs'); require('../network/packet/ContainerOpenPacket.cjs.cjs'); require('../network/packet/CreativeContentPacket.cjs.cjs'); require('../network/packet/DisconnectPacket.cjs.cjs'); require('../network/packet/EmoteListPacket.cjs.cjs'); require('../network/packet/InteractPacket.cjs.cjs'); require('../network/packet/InventoryContentPacket.cjs.cjs'); require('../network/packet/InventoryTransactionPacket.cjs.cjs'); require('../network/packet/ItemComponentPacket.cjs.cjs'); require('../network/packet/ItemStackRequestPacket.cjs.cjs'); require('../network/packet/ItemStackResponsePacket.cjs.cjs'); require('../network/packet/LevelChunkPacket.cjs.cjs'); require('../network/packet/LevelSoundEventPacket.cjs.cjs'); require('../network/packet/LoginPacket.cjs.cjs'); require('../network/packet/MobEquipmentPacket.cjs.cjs'); require('../network/packet/MovePlayerPacket.cjs.cjs'); require('../network/packet/NetworkChunkPublisherUpdatePacket.cjs.cjs'); require('../network/packet/OnScreenTextureAnimationPacket.cjs.cjs'); require('../network/packet/PacketViolationWarningPacket.cjs.cjs'); require('../network/packet/PlaySoundPacket.cjs.cjs'); require('../network/packet/PlayStatusPacket.cjs.cjs'); require('../network/packet/PlayerActionPacket.cjs.cjs'); require('../network/packet/PlayerListPacket.cjs.cjs'); require('../network/packet/PlayerSkinPacket.cjs.cjs'); require('../network/packet/RequestChunkRadiusPacket.cjs.cjs'); require('../network/packet/RequestNetworkSettingsPacket.cjs.cjs'); require('../network/packet/ResourcePackResponsePacket.cjs.cjs'); require('../network/packet/ResourcePackStackPacket.cjs.cjs'); require('../network/packet/ResourcePacksInfoPacket.cjs.cjs'); require('../network/packet/ServerSettingsRequestPacket.cjs.cjs'); require('../network/packet/SetActorDataPacket.cjs.cjs'); require('../network/packet/SetDefaultGametypePacket.cjs.cjs'); require('../network/packet/SetHealthPacket.cjs.cjs'); require('../network/packet/SetLocalPlayerAsInitializedPacket.cjs.cjs'); require('../network/packet/SetPlayerGametypePacket.cjs.cjs'); require('../network/packet/SetTimePacket.cjs.cjs'); require('../network/packet/ShowProfilePacket.cjs.cjs'); require('../network/packet/StartGamePacket.cjs.cjs'); require('../network/packet/TextPacket.cjs.cjs'); require('../network/packet/TickSyncPacket.cjs.cjs'); require('../network/packet/TransferPacket.cjs.cjs'); require('../network/packet/UpdateAdventureSettingsPacket.cjs.cjs'); require('../network/packet/UpdateAttributesPacket.cjs.cjs'); require('../network/packet/UpdateBlockPacket.cjs.cjs'); require('../network/packet/WorldEventPacket.cjs.cjs'); require('node:path'); require('@jsprismarine/brigadier'); require('../config/Config.cjs.cjs'); const events_player_PlayerToggleOperatorEvent = require('../events/player/PlayerToggleOperatorEvent.cjs.cjs'); require('../network/handler/AnimateHandler.cjs.cjs'); require('../network/handler/CommandRequestHandler.cjs.cjs'); require('../network/handler/ContainerCloseHandler.cjs.cjs'); require('../network/handler/EmoteListHandler.cjs.cjs'); require('../network/handler/InteractHandler.cjs.cjs'); require('../network/handler/InventoryTransactionHandler.cjs.cjs'); require('../network/handler/LevelSoundEventHandler.cjs.cjs'); require('../network/handler/LoginHandler.cjs.cjs'); require('../network/handler/MobEquipmentHandler.cjs.cjs'); require('../network/handler/MovePlayerHandler.cjs.cjs'); require('../network/handler/PacketViolationWarningHandler.cjs.cjs'); require('../network/handler/PlayerActionHandler.cjs.cjs'); require('../network/handler/RequestChunkRadiusHandler.cjs.cjs'); require('../network/handler/RequestNetworkSettingsHandler.cjs.cjs'); require('../network/handler/ResourcePackResponseHandler.cjs.cjs'); require('../network/handler/ServerSettingsRequestHandler.cjs.cjs'); require('../network/handler/SetDefaultGametypeHandler.cjs.cjs'); require('../network/handler/SetLocalPlayerAsInitializedHandler.cjs.cjs'); require('../network/handler/SetPlayerGametypeHandler.cjs.cjs'); require('../network/handler/TextHandler.cjs.cjs'); require('../network/handler/TickSyncHandler.cjs.cjs'); require('node:process'); require('node:readline'); require('heap'); require('../network/packet/UpdateAbilitiesPacket.cjs.cjs'); require('@jsprismarine/raknet'); require('evt'); require('assert'); const _interopDefault = e => e && e.__esModule ? e : { default: e }; const fs__default = /*#__PURE__*/_interopDefault(fs); const PERMISSION_FILE_NAME = "permissions.json"; const OPS_FILE_NAME = "ops.json"; class PermissionManager { server; ops = /* @__PURE__ */ new Set(); permissions = /* @__PURE__ */ new Map(); defaultPermissions = []; defaultOperatorPermissions = []; /** * Create a new permission manager. * @param {Server} server - The server instance. */ constructor(server) { this.server = server; } /** * Enable the manager and load all permissions. * @returns {Promise<void>} A promise that resolves when the manager is enabled. * @group Lifecycle */ async enable() { await this.parseOps(); await this.parsePermissions(); } /** * Signifies that the manager is being disabled and all permissions should be unloaded. * @returns {Promise<void>} A promise that resolves when the manager is disabled. * @group Lifecycle */ async disable() { this.ops.clear(); this.permissions.clear(); this.defaultPermissions = []; } /** * Get the default permissions. * @returns {string[]} The default permissions. */ getDefaultPermissions() { return this.defaultPermissions; } /** * Get a player's permissions. * @param {Player} player - The player to get permissions for. * @returns {Promise<string[]>} A promise that resolves with the player's permissions. */ async getPermissions(player) { return [ ...this.defaultPermissions, ...this.permissions.get(player.getName()) ?? [], ...player.isOp() ? this.defaultOperatorPermissions : [] ]; } /** * Set a player's permissions. * * @remarks * This will not be saved to the permissions.json file. * * @param {Player} player - The player to set permissions for. * @param {string[]} [permissions=[]] - The permissions to set. */ setPermissions(player, permissions = []) { this.permissions.set(player.getName(), permissions); } async parsePermissions() { try { if (!fs__default.default.existsSync(utils_cwd.withCwd(PERMISSION_FILE_NAME))) { this.server.getLogger().warn(`Failed to load permissions list!`); fs__default.default.writeFileSync( // FIXME: This overwrites comments in the file. utils_cwd.withCwd(PERMISSION_FILE_NAME), JSON.stringify( { defaultPermissions: [ "minecraft.command.help", "minecraft.command.list", "minecraft.command.me", "jsprismarine.command.plugins", "jsprismarine.command.version", "jsprismarine.command.tps" ], defaultOperatorPermissions: ["*"], players: [ { name: "filfat", permissions: ["*"] } ] }, null, 4 ) ); } const permissionsObject = confbox.parseJSON5((await fs__default.default.promises.readFile(utils_cwd.withCwd(PERMISSION_FILE_NAME))).toString()); this.defaultPermissions = permissionsObject.defaultPermissions || []; this.defaultOperatorPermissions = permissionsObject.defaultOperatorPermissions || ["*"]; permissionsObject.players?.map( (player) => this.permissions.set(player.name, player.permissions.length <= 0 ? [] : player.permissions) ); } catch (error) { this.server.getLogger().error(error); throw new Error(`Invalid ${PERMISSION_FILE_NAME} file.`); } } async parseOps() { try { if (!fs__default.default.existsSync(utils_cwd.withCwd(OPS_FILE_NAME))) { this.server.getLogger().warn(`Failed to load operators list!`); fs__default.default.writeFileSync(utils_cwd.withCwd(OPS_FILE_NAME), "[]"); } const ops = confbox.parseJSON5((await fs__default.default.promises.readFile(utils_cwd.withCwd(OPS_FILE_NAME))).toString()); ops.map((op) => this.ops.add(op.name)); } catch (error) { this.server.getLogger().error(error); throw new Error(`Invalid ${OPS_FILE_NAME} file.`); } } /** * Set a player as an operator. * * @param {string} username - The player to set as an operator. * @param {boolean} op - Whether the player should be an operator. * @returns {Promise<boolean>} A promise that resolves with a boolean indicating whether the operation was successful. */ async setOp(username, op) { const target = this.server.getSessionManager().getPlayerByExactName(username); if (!target) throw new errors.PlayerNotFoundError(username); const event = new events_player_PlayerToggleOperatorEvent.default(target, op); this.server.post(["playerToggleOperator", event]); if (event.isCancelled()) return false; await target.getNetworkSession().sendAvailableCommands(); if (op) this.ops.add(username); else this.ops.delete(username); try { await fs__default.default.promises.writeFile( // FIXME: This overwrites comments in the file. utils_cwd.withCwd(OPS_FILE_NAME), JSON.stringify( Array.from(this.ops.values()).map((name) => ({ name, level: 4 })), null, 4 ) ); await target.sendSettings(); return true; } catch { return false; } } /** * Check if a player is an operator. * * @param {string} username - The player to check. * @returns {boolean} Whether the player is an operator. */ isOp(username) { return this.ops.has(username); } /** * Check if a player can execute a command. * * @param {Player} executer - The player to check. * @returns {object} An object with an execute method that takes a permission string and returns whether the player can execute the command. */ can(executer) { const execute = (permission) => { if (!executer) throw new Error(`Executer can't be undefined or null`); if (!permission) return true; if (executer.isConsole()) return true; if (executer.isOp()) return true; if (executer.getPermissions().includes(permission)) return true; if (executer.getPermissions().includes("*")) return true; const split = permission.split("."); let scope = ""; for (const action of split) { if (scope) scope = `${scope}.${action}`; else scope = action; if (executer.getPermissions().includes(scope)) return true; if (executer.getPermissions().includes(`${scope}.*`)) return true; } return false; }; return { execute, not: () => { return { execute: (permission) => !execute(permission) }; } }; } } exports.PermissionManager = PermissionManager; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUGVybWlzc2lvbk1hbmFnZXIuY2pzLmNqcyIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3Blcm1pc3Npb24vUGVybWlzc2lvbk1hbmFnZXIudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGZzIGZyb20gJ25vZGU6ZnMnO1xuXG5pbXBvcnQgeyBwYXJzZUpTT041IH0gZnJvbSAnY29uZmJveCc7XG5cbmltcG9ydCB7IFBsYXllck5vdEZvdW5kRXJyb3IgfSBmcm9tICdAanNwcmlzbWFyaW5lL2Vycm9ycyc7XG5pbXBvcnQgdHlwZSB7IFBsYXllciwgU2VydmVyLCBTZXJ2aWNlIH0gZnJvbSAnLi4vJztcbmltcG9ydCB7IHdpdGhDd2QgfSBmcm9tICcuLi8nO1xuaW1wb3J0IHBsYXllclRvZ2dsZU9wZXJhdG9yRXZlbnQgZnJvbSAnLi4vZXZlbnRzL3BsYXllci9QbGF5ZXJUb2dnbGVPcGVyYXRvckV2ZW50JztcblxuaW50ZXJmYWNlIE9wVHlwZSB7XG4gICAgbmFtZTogc3RyaW5nO1xufVxuXG5jb25zdCBQRVJNSVNTSU9OX0ZJTEVfTkFNRSA9ICdwZXJtaXNzaW9ucy5qc29uJztcbmNvbnN0IE9QU19GSUxFX05BTUUgPSAnb3BzLmpzb24nO1xuXG4vKipcbiAqIFBlcm1pc3Npb24gbWFuYWdlci5cbiAqL1xuZXhwb3J0IGNsYXNzIFBlcm1pc3Npb25NYW5hZ2VyIGltcGxlbWVudHMgU2VydmljZSB7XG4gICAgcHJpdmF0ZSByZWFkb25seSBzZXJ2ZXI6IFNlcnZlcjtcbiAgICBwcml2YXRlIHJlYWRvbmx5IG9wczogU2V0PHN0cmluZz4gPSBuZXcgU2V0KCk7XG4gICAgcHJpdmF0ZSByZWFkb25seSBwZXJtaXNzaW9uczogTWFwPHN0cmluZywgc3RyaW5nW10+ID0gbmV3IE1hcCgpO1xuICAgIHByaXZhdGUgZGVmYXVsdFBlcm1pc3Npb25zOiBzdHJpbmdbXSA9IFtdO1xuICAgIHByaXZhdGUgZGVmYXVsdE9wZXJhdG9yUGVybWlzc2lvbnM6IHN0cmluZ1tdID0gW107XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGUgYSBuZXcgcGVybWlzc2lvbiBtYW5hZ2VyLlxuICAgICAqIEBwYXJhbSB7U2VydmVyfSBzZXJ2ZXIgLSBUaGUgc2VydmVyIGluc3RhbmNlLlxuICAgICAqL1xuICAgIHB1YmxpYyBjb25zdHJ1Y3RvcihzZXJ2ZXI6IFNlcnZlcikge1xuICAgICAgICB0aGlzLnNlcnZlciA9IHNlcnZlcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBFbmFibGUgdGhlIG1hbmFnZXIgYW5kIGxvYWQgYWxsIHBlcm1pc3Npb25zLlxuICAgICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIHRoZSBtYW5hZ2VyIGlzIGVuYWJsZWQuXG4gICAgICogQGdyb3VwIExpZmVjeWNsZVxuICAgICAqL1xuICAgIHB1YmxpYyBhc3luYyBlbmFibGUoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGF3YWl0IHRoaXMucGFyc2VPcHMoKTtcbiAgICAgICAgYXdhaXQgdGhpcy5wYXJzZVBlcm1pc3Npb25zKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2lnbmlmaWVzIHRoYXQgdGhlIG1hbmFnZXIgaXMgYmVpbmcgZGlzYWJsZWQgYW5kIGFsbCBwZXJtaXNzaW9ucyBzaG91bGQgYmUgdW5sb2FkZWQuXG4gICAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gdGhlIG1hbmFnZXIgaXMgZGlzYWJsZWQuXG4gICAgICogQGdyb3VwIExpZmVjeWNsZVxuICAgICAqL1xuICAgIHB1YmxpYyBhc3luYyBkaXNhYmxlKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICB0aGlzLm9wcy5jbGVhcigpO1xuICAgICAgICB0aGlzLnBlcm1pc3Npb25zLmNsZWFyKCk7XG4gICAgICAgIHRoaXMuZGVmYXVsdFBlcm1pc3Npb25zID0gW107XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0IHRoZSBkZWZhdWx0IHBlcm1pc3Npb25zLlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmdbXX0gVGhlIGRlZmF1bHQgcGVybWlzc2lvbnMuXG4gICAgICovXG4gICAgcHVibGljIGdldERlZmF1bHRQZXJtaXNzaW9ucygpOiBzdHJpbmdbXSB7XG4gICAgICAgIHJldHVybiB0aGlzLmRlZmF1bHRQZXJtaXNzaW9ucztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgYSBwbGF5ZXIncyBwZXJtaXNzaW9ucy5cbiAgICAgKiBAcGFyYW0ge1BsYXllcn0gcGxheWVyIC0gVGhlIHBsYXllciB0byBnZXQgcGVybWlzc2lvbnMgZm9yLlxuICAgICAqIEByZXR1cm5zIHtQcm9taXNlPHN0cmluZ1tdPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2l0aCB0aGUgcGxheWVyJ3MgcGVybWlzc2lvbnMuXG4gICAgICovXG4gICAgcHVibGljIGFzeW5jIGdldFBlcm1pc3Npb25zKHBsYXllcjogUGxheWVyKTogUHJvbWlzZTxzdHJpbmdbXT4ge1xuICAgICAgICByZXR1cm4gW1xuICAgICAgICAgICAgLi4udGhpcy5kZWZhdWx0UGVybWlzc2lvbnMsXG4gICAgICAgICAgICAuLi4odGhpcy5wZXJtaXNzaW9ucy5nZXQocGxheWVyLmdldE5hbWUoKSkgPz8gW10pLFxuICAgICAgICAgICAgLi4uKHBsYXllci5pc09wKCkgPyB0aGlzLmRlZmF1bHRPcGVyYXRvclBlcm1pc3Npb25zIDogW10pXG4gICAgICAgIF07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0IGEgcGxheWVyJ3MgcGVybWlzc2lvbnMuXG4gICAgICpcbiAgICAgKiBAcmVtYXJrc1xuICAgICAqIFRoaXMgd2lsbCBub3QgYmUgc2F2ZWQgdG8gdGhlIHBlcm1pc3Npb25zLmpzb24gZmlsZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7UGxheWVyfSBwbGF5ZXIgLSBUaGUgcGxheWVyIHRvIHNldCBwZXJtaXNzaW9ucyBmb3IuXG4gICAgICogQHBhcmFtIHtzdHJpbmdbXX0gW3Blcm1pc3Npb25zPVtdXSAtIFRoZSBwZXJtaXNzaW9ucyB0byBzZXQuXG4gICAgICovXG4gICAgcHVibGljIHNldFBlcm1pc3Npb25zKHBsYXllcjogUGxheWVyLCBwZXJtaXNzaW9uczogc3RyaW5nW10gPSBbXSkge1xuICAgICAgICB0aGlzLnBlcm1pc3Npb25zLnNldChwbGF5ZXIuZ2V0TmFtZSgpLCBwZXJtaXNzaW9ucyk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBwYXJzZVBlcm1pc3Npb25zKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgaWYgKCFmcy5leGlzdHNTeW5jKHdpdGhDd2QoUEVSTUlTU0lPTl9GSUxFX05BTUUpKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuc2VydmVyLmdldExvZ2dlcigpLndhcm4oYEZhaWxlZCB0byBsb2FkIHBlcm1pc3Npb25zIGxpc3QhYCk7XG4gICAgICAgICAgICAgICAgZnMud3JpdGVGaWxlU3luYyhcbiAgICAgICAgICAgICAgICAgICAgLy8gRklYTUU6IFRoaXMgb3ZlcndyaXRlcyBjb21tZW50cyBpbiB0aGUgZmlsZS5cbiAgICAgICAgICAgICAgICAgICAgd2l0aEN3ZChQRVJNSVNTSU9OX0ZJTEVfTkFNRSksXG4gICAgICAgICAgICAgICAgICAgIEpTT04uc3RyaW5naWZ5KFxuICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlZmF1bHRQZXJtaXNzaW9uczogW1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnbWluZWNyYWZ0LmNvbW1hbmQuaGVscCcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdtaW5lY3JhZnQuY29tbWFuZC5saXN0JyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ21pbmVjcmFmdC5jb21tYW5kLm1lJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2pzcHJpc21hcmluZS5jb21tYW5kLnBsdWdpbnMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnanNwcmlzbWFyaW5lLmNvbW1hbmQudmVyc2lvbicsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdqc3ByaXNtYXJpbmUuY29tbWFuZC50cHMnXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWZhdWx0T3BlcmF0b3JQZXJtaXNzaW9uczogWycqJ10sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGxheWVyczogW1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lOiAnZmlsZmF0JyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBlcm1pc3Npb25zOiBbJyonXVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXVxuICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgIG51bGwsXG4gICAgICAgICAgICAgICAgICAgICAgICA0XG4gICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjb25zdCBwZXJtaXNzaW9uc09iamVjdDogUGFydGlhbDx7XG4gICAgICAgICAgICAgICAgZGVmYXVsdFBlcm1pc3Npb25zOiBzdHJpbmdbXTtcbiAgICAgICAgICAgICAgICBkZWZhdWx0T3BlcmF0b3JQZXJtaXNzaW9uczogc3RyaW5nW107XG4gICAgICAgICAgICAgICAgcGxheWVyczogQXJyYXk8e1xuICAgICAgICAgICAgICAgICAgICBuYW1lOiBzdHJpbmc7XG4gICAgICAgICAgICAgICAgICAgIHBlcm1pc3Npb25zOiBzdHJpbmdbXTtcbiAgICAgICAgICAgICAgICB9PjtcbiAgICAgICAgICAgIH0+ID0gcGFyc2VKU09ONSgoYXdhaXQgZnMucHJvbWlzZXMucmVhZEZpbGUod2l0aEN3ZChQRVJNSVNTSU9OX0ZJTEVfTkFNRSkpKS50b1N0cmluZygpKTtcblxuICAgICAgICAgICAgdGhpcy5kZWZhdWx0UGVybWlzc2lvbnMgPSBwZXJtaXNzaW9uc09iamVjdC5kZWZhdWx0UGVybWlzc2lvbnMgfHwgW107XG4gICAgICAgICAgICB0aGlzLmRlZmF1bHRPcGVyYXRvclBlcm1pc3Npb25zID0gcGVybWlzc2lvbnNPYmplY3QuZGVmYXVsdE9wZXJhdG9yUGVybWlzc2lvbnMgfHwgWycqJ107XG4gICAgICAgICAgICBwZXJtaXNzaW9uc09iamVjdC5wbGF5ZXJzPy5tYXAoKHBsYXllcikgPT5cbiAgICAgICAgICAgICAgICB0aGlzLnBlcm1pc3Npb25zLnNldChwbGF5ZXIubmFtZSwgcGxheWVyLnBlcm1pc3Npb25zLmxlbmd0aCA8PSAwID8gW10gOiBwbGF5ZXIucGVybWlzc2lvbnMpXG4gICAgICAgICAgICApO1xuICAgICAgICB9IGNhdGNoIChlcnJvcjogdW5rbm93bikge1xuICAgICAgICAgICAgdGhpcy5zZXJ2ZXIuZ2V0TG9nZ2VyKCkuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkICR7UEVSTUlTU0lPTl9GSUxFX05BTUV9IGZpbGUuYCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIHBhcnNlT3BzKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgaWYgKCFmcy5leGlzdHNTeW5jKHdpdGhDd2QoT1BTX0ZJTEVfTkFNRSkpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXJ2ZXIuZ2V0TG9nZ2VyKCkud2FybihgRmFpbGVkIHRvIGxvYWQgb3BlcmF0b3JzIGxpc3QhYCk7XG4gICAgICAgICAgICAgICAgZnMud3JpdGVGaWxlU3luYyh3aXRoQ3dkKE9QU19GSUxFX05BTUUpLCAnW10nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IG9wczogT3BUeXBlW10gPSBwYXJzZUpTT041KChhd2FpdCBmcy5wcm9taXNlcy5yZWFkRmlsZSh3aXRoQ3dkKE9QU19GSUxFX05BTUUpKSkudG9TdHJpbmcoKSk7XG5cbiAgICAgICAgICAgIG9wcy5tYXAoKG9wKSA9PiB0aGlzLm9wcy5hZGQob3AubmFtZSkpO1xuICAgICAgICB9IGNhdGNoIChlcnJvcjogdW5rbm93bikge1xuICAgICAgICAgICAgdGhpcy5zZXJ2ZXIuZ2V0TG9nZ2VyKCkuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkICR7T1BTX0ZJTEVfTkFNRX0gZmlsZS5gKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldCBhIHBsYXllciBhcyBhbiBvcGVyYXRvci5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSB1c2VybmFtZSAtIFRoZSBwbGF5ZXIgdG8gc2V0IGFzIGFuIG9wZXJhdG9yLlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gb3AgLSBXaGV0aGVyIHRoZSBwbGF5ZXIgc2hvdWxkIGJlIGFuIG9wZXJhdG9yLlxuICAgICAqIEByZXR1cm5zIHtQcm9taXNlPGJvb2xlYW4+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIGEgYm9vbGVhbiBpbmRpY2F0aW5nIHdoZXRoZXIgdGhlIG9wZXJhdGlvbiB3YXMgc3VjY2Vzc2Z1bC5cbiAgICAgKi9cbiAgICBwdWJsaWMgYXN5bmMgc2V0T3AodXNlcm5hbWU6IHN0cmluZywgb3A6IGJvb2xlYW4pOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAgICAgY29uc3QgdGFyZ2V0ID0gdGhpcy5zZXJ2ZXIuZ2V0U2Vzc2lvbk1hbmFnZXIoKS5nZXRQbGF5ZXJCeUV4YWN0TmFtZSh1c2VybmFtZSk7IC8vIFRPRE86IGJ5IG5hbWUgbm90IGV4YWN0XG4gICAgICAgIGlmICghdGFyZ2V0KSB0aHJvdyBuZXcgUGxheWVyTm90Rm91bmRFcnJvcih1c2VybmFtZSk7XG4gICAgICAgIGNvbnN0IGV2ZW50ID0gbmV3IHBsYXllclRvZ2dsZU9wZXJhdG9yRXZlbnQodGFyZ2V0LCBvcCk7XG4gICAgICAgIHRoaXMuc2VydmVyLnBvc3QoWydwbGF5ZXJUb2dnbGVPcGVyYXRvcicsIGV2ZW50XSk7XG4gICAgICAgIGlmIChldmVudC5pc0NhbmNlbGxlZCgpKSByZXR1cm4gZmFsc2U7XG5cbiAgICAgICAgYXdhaXQgdGFyZ2V0LmdldE5ldHdvcmtTZXNzaW9uKCkuc2VuZEF2YWlsYWJsZUNvbW1hbmRzKCk7XG5cbiAgICAgICAgaWYgKG9wKSB0aGlzLm9wcy5hZGQodXNlcm5hbWUpO1xuICAgICAgICBlbHNlIHRoaXMub3BzLmRlbGV0ZSh1c2VybmFtZSk7XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGF3YWl0IGZzLnByb21pc2VzLndyaXRlRmlsZShcbiAgICAgICAgICAgICAgICAvLyBGSVhNRTogVGhpcyBvdmVyd3JpdGVzIGNvbW1lbnRzIGluIHRoZSBmaWxlLlxuICAgICAgICAgICAgICAgIHdpdGhDd2QoT1BTX0ZJTEVfTkFNRSksXG4gICAgICAgICAgICAgICAgSlNPTi5zdHJpbmdpZnkoXG4gICAgICAgICAgICAgICAgICAgIEFycmF5LmZyb20odGhpcy5vcHMudmFsdWVzKCkpLm1hcCgobmFtZSkgPT4gKHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXZlbDogNFxuICAgICAgICAgICAgICAgICAgICB9KSksXG4gICAgICAgICAgICAgICAgICAgIG51bGwsXG4gICAgICAgICAgICAgICAgICAgIDRcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICApO1xuXG4gICAgICAgICAgICBhd2FpdCB0YXJnZXQuc2VuZFNldHRpbmdzKCk7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVjayBpZiBhIHBsYXllciBpcyBhbiBvcGVyYXRvci5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSB1c2VybmFtZSAtIFRoZSBwbGF5ZXIgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFdoZXRoZXIgdGhlIHBsYXllciBpcyBhbiBvcGVyYXRvci5cbiAgICAgKi9cbiAgICBwdWJsaWMgaXNPcCh1c2VybmFtZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLm9wcy5oYXModXNlcm5hbWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrIGlmIGEgcGxheWVyIGNhbiBleGVjdXRlIGEgY29tbWFuZC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7UGxheWVyfSBleGVjdXRlciAtIFRoZSBwbGF5ZXIgdG8gY2hlY2suXG4gICAgICogQHJldHVybnMge29iamVjdH0gQW4gb2JqZWN0IHdpdGggYW4gZXhlY3V0ZSBtZXRob2QgdGhhdCB0YWtlcyBhIHBlcm1pc3Npb24gc3RyaW5nIGFuZCByZXR1cm5zIHdoZXRoZXIgdGhlIHBsYXllciBjYW4gZXhlY3V0ZSB0aGUgY29tbWFuZC5cbiAgICAgKi9cbiAgICBwdWJsaWMgY2FuKGV4ZWN1dGVyPzogUGxheWVyKSB7XG4gICAgICAgIGNvbnN0IGV4ZWN1dGUgPSAocGVybWlzc2lvbj86IHN0cmluZykgPT4ge1xuICAgICAgICAgICAgaWYgKCFleGVjdXRlcikgdGhyb3cgbmV3IEVycm9yKGBFeGVjdXRlciBjYW4ndCBiZSB1bmRlZmluZWQgb3IgbnVsbGApO1xuXG4gICAgICAgICAgICBpZiAoIXBlcm1pc3Npb24pIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgaWYgKGV4ZWN1dGVyLmlzQ29uc29sZSgpKSByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIGlmIChleGVjdXRlci5pc09wKCkpIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgaWYgKGV4ZWN1dGVyLmdldFBlcm1pc3Npb25zKCkuaW5jbHVkZXMocGVybWlzc2lvbikpIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgaWYgKGV4ZWN1dGVyLmdldFBlcm1pc3Npb25zKCkuaW5jbHVkZXMoJyonKSkgcmV0dXJuIHRydWU7XG5cbiAgICAgICAgICAgIGNvbnN0IHNwbGl0ID0gcGVybWlzc2lvbi5zcGxpdCgnLicpO1xuICAgICAgICAgICAgbGV0IHNjb3BlID0gJyc7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IGFjdGlvbiBvZiBzcGxpdCkge1xuICAgICAgICAgICAgICAgIGlmIChzY29wZSkgc2NvcGUgPSBgJHtzY29wZX0uJHthY3Rpb259YDtcbiAgICAgICAgICAgICAgICBlbHNlIHNjb3BlID0gYWN0aW9uO1xuXG4gICAgICAgICAgICAgICAgaWYgKGV4ZWN1dGVyLmdldFBlcm1pc3Npb25zKCkuaW5jbHVkZXMoc2NvcGUpKSByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICBpZiAoZXhlY3V0ZXIuZ2V0UGVybWlzc2lvbnMoKS5pbmNsdWRlcyhgJHtzY29wZX0uKmApKSByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9O1xuXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBleGVjdXRlLFxuICAgICAgICAgICAgbm90OiAoKSA9PiB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgZXhlY3V0ZTogKHBlcm1pc3Npb24/OiBzdHJpbmcpID0+ICFleGVjdXRlKHBlcm1pc3Npb24pXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICB9XG59XG4iXSwibmFtZXMiOlsiZnMiLCJ3aXRoQ3dkIiwicGFyc2VKU09ONSIsIlBsYXllck5vdEZvdW5kRXJyb3IiLCJwbGF5ZXJUb2dnbGVPcGVyYXRvckV2ZW50Il0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFhQSxNQUFNLG9CQUF1QixHQUFBLGtCQUFBO0FBQzdCLE1BQU0sYUFBZ0IsR0FBQSxVQUFBO0FBS2YsTUFBTSxpQkFBcUMsQ0FBQTtBQUFBLEVBQzdCLE1BQUE7QUFBQSxFQUNBLEdBQUEsdUJBQXVCLEdBQUksRUFBQTtBQUFBLEVBQzNCLFdBQUEsdUJBQXlDLEdBQUksRUFBQTtBQUFBLEVBQ3RELHFCQUErQixFQUFDO0FBQUEsRUFDaEMsNkJBQXVDLEVBQUM7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLEVBTXpDLFlBQVksTUFBZ0IsRUFBQTtBQUMvQixJQUFBLElBQUEsQ0FBSyxNQUFTLEdBQUEsTUFBQTtBQUFBO0FBQ2xCO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxFQU9BLE1BQWEsTUFBd0IsR0FBQTtBQUNqQyxJQUFBLE1BQU0sS0FBSyxRQUFTLEVBQUE7QUFDcEIsSUFBQSxNQUFNLEtBQUssZ0JBQWlCLEVBQUE7QUFBQTtBQUNoQztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUFPQSxNQUFhLE9BQXlCLEdBQUE7QUFDbEMsSUFBQSxJQUFBLENBQUssSUFBSSxLQUFNLEVBQUE7QUFDZixJQUFBLElBQUEsQ0FBSyxZQUFZLEtBQU0sRUFBQTtBQUN2QixJQUFBLElBQUEsQ0FBSyxxQkFBcUIsRUFBQztBQUFBO0FBQy9CO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUFNTyxxQkFBa0MsR0FBQTtBQUNyQyxJQUFBLE9BQU8sSUFBSyxDQUFBLGtCQUFBO0FBQUE7QUFDaEI7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLEVBT0EsTUFBYSxlQUFlLE1BQW1DLEVBQUE7QUFDM0QsSUFBTyxPQUFBO0FBQUEsTUFDSCxHQUFHLElBQUssQ0FBQSxrQkFBQTtBQUFBLE1BQ1IsR0FBSSxLQUFLLFdBQVksQ0FBQSxHQUFBLENBQUksT0FBTyxPQUFRLEVBQUMsS0FBSyxFQUFDO0FBQUEsTUFDL0MsR0FBSSxNQUFPLENBQUEsSUFBQSxFQUFTLEdBQUEsSUFBQSxDQUFLLDZCQUE2QjtBQUFDLEtBQzNEO0FBQUE7QUFDSjtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxFQVdPLGNBQWUsQ0FBQSxNQUFBLEVBQWdCLFdBQXdCLEdBQUEsRUFBSSxFQUFBO0FBQzlELElBQUEsSUFBQSxDQUFLLFdBQVksQ0FBQSxHQUFBLENBQUksTUFBTyxDQUFBLE9BQUEsSUFBVyxXQUFXLENBQUE7QUFBQTtBQUN0RCxFQUVBLE1BQWMsZ0JBQWtDLEdBQUE7QUFDNUMsSUFBSSxJQUFBO0FBQ0EsTUFBQSxJQUFJLENBQUNBLG1CQUFHLENBQUEsVUFBQSxDQUFXQyxpQkFBUSxDQUFBLG9CQUFvQixDQUFDLENBQUcsRUFBQTtBQUMvQyxRQUFBLElBQUEsQ0FBSyxNQUFPLENBQUEsU0FBQSxFQUFZLENBQUEsSUFBQSxDQUFLLENBQWtDLGdDQUFBLENBQUEsQ0FBQTtBQUMvRCxRQUFHRCxtQkFBQSxDQUFBLGFBQUE7QUFBQTtBQUFBLFVBRUNDLGtCQUFRLG9CQUFvQixDQUFBO0FBQUEsVUFDNUIsSUFBSyxDQUFBLFNBQUE7QUFBQSxZQUNEO0FBQUEsY0FDSSxrQkFBb0IsRUFBQTtBQUFBLGdCQUNoQix3QkFBQTtBQUFBLGdCQUNBLHdCQUFBO0FBQUEsZ0JBQ0Esc0JBQUE7QUFBQSxnQkFDQSw4QkFBQTtBQUFBLGdCQUNBLDhCQUFBO0FBQUEsZ0JBQ0E7QUFBQSxlQUNKO0FBQUEsY0FDQSwwQkFBQSxFQUE0QixDQUFDLEdBQUcsQ0FBQTtBQUFBLGNBQ2hDLE9BQVMsRUFBQTtBQUFBLGdCQUNMO0FBQUEsa0JBQ0ksSUFBTSxFQUFBLFFBQUE7QUFBQSxrQkFDTixXQUFBLEVBQWEsQ0FBQyxHQUFHO0FBQUE7QUFDckI7QUFDSixhQUNKO0FBQUEsWUFDQSxJQUFBO0FBQUEsWUFDQTtBQUFBO0FBQ0osU0FDSjtBQUFBO0FBR0osTUFBTSxNQUFBLGlCQUFBLEdBT0RDLGtCQUFZLENBQUEsQ0FBQSxNQUFNRixtQkFBRyxDQUFBLFFBQUEsQ0FBUyxRQUFTLENBQUFDLGlCQUFBLENBQVEsb0JBQW9CLENBQUMsQ0FBRyxFQUFBLFFBQUEsRUFBVSxDQUFBO0FBRXRGLE1BQUssSUFBQSxDQUFBLGtCQUFBLEdBQXFCLGlCQUFrQixDQUFBLGtCQUFBLElBQXNCLEVBQUM7QUFDbkUsTUFBQSxJQUFBLENBQUssMEJBQTZCLEdBQUEsaUJBQUEsQ0FBa0IsMEJBQThCLElBQUEsQ0FBQyxHQUFHLENBQUE7QUFDdEYsTUFBQSxpQkFBQSxDQUFrQixPQUFTLEVBQUEsR0FBQTtBQUFBLFFBQUksQ0FBQyxNQUFBLEtBQzVCLElBQUssQ0FBQSxXQUFBLENBQVksSUFBSSxNQUFPLENBQUEsSUFBQSxFQUFNLE1BQU8sQ0FBQSxXQUFBLENBQVksTUFBVSxJQUFBLENBQUEsR0FBSSxFQUFDLEdBQUksT0FBTyxXQUFXO0FBQUEsT0FDOUY7QUFBQSxhQUNLLEtBQWdCLEVBQUE7QUFDckIsTUFBQSxJQUFBLENBQUssTUFBTyxDQUFBLFNBQUEsRUFBWSxDQUFBLEtBQUEsQ0FBTSxLQUFLLENBQUE7QUFDbkMsTUFBQSxNQUFNLElBQUksS0FBQSxDQUFNLENBQVcsUUFBQSxFQUFBLG9CQUFvQixDQUFRLE1BQUEsQ0FBQSxDQUFBO0FBQUE7QUFDM0Q7QUFDSixFQUVBLE1BQWMsUUFBMEIsR0FBQTtBQUNwQyxJQUFJLElBQUE7QUFDQSxNQUFBLElBQUksQ0FBQ0QsbUJBQUcsQ0FBQSxVQUFBLENBQVdDLGlCQUFRLENBQUEsYUFBYSxDQUFDLENBQUcsRUFBQTtBQUN4QyxRQUFBLElBQUEsQ0FBSyxNQUFPLENBQUEsU0FBQSxFQUFZLENBQUEsSUFBQSxDQUFLLENBQWdDLDhCQUFBLENBQUEsQ0FBQTtBQUM3RCxRQUFBRCxtQkFBQSxDQUFHLGFBQWMsQ0FBQUMsaUJBQUEsQ0FBUSxhQUFhLENBQUEsRUFBRyxJQUFJLENBQUE7QUFBQTtBQUVqRCxNQUFNLE1BQUEsR0FBQSxHQUFnQkMsa0JBQVksQ0FBQSxDQUFBLE1BQU1GLG1CQUFHLENBQUEsUUFBQSxDQUFTLFFBQVMsQ0FBQUMsaUJBQUEsQ0FBUSxhQUFhLENBQUMsQ0FBRyxFQUFBLFFBQUEsRUFBVSxDQUFBO0FBRWhHLE1BQUksR0FBQSxDQUFBLEdBQUEsQ0FBSSxDQUFDLEVBQU8sS0FBQSxJQUFBLENBQUssSUFBSSxHQUFJLENBQUEsRUFBQSxDQUFHLElBQUksQ0FBQyxDQUFBO0FBQUEsYUFDaEMsS0FBZ0IsRUFBQTtBQUNyQixNQUFBLElBQUEsQ0FBSyxNQUFPLENBQUEsU0FBQSxFQUFZLENBQUEsS0FBQSxDQUFNLEtBQUssQ0FBQTtBQUNuQyxNQUFBLE1BQU0sSUFBSSxLQUFBLENBQU0sQ0FBVyxRQUFBLEVBQUEsYUFBYSxDQUFRLE1BQUEsQ0FBQSxDQUFBO0FBQUE7QUFDcEQ7QUFDSjtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLEVBU0EsTUFBYSxLQUFNLENBQUEsUUFBQSxFQUFrQixFQUErQixFQUFBO0FBQ2hFLElBQUEsTUFBTSxTQUFTLElBQUssQ0FBQSxNQUFBLENBQU8saUJBQWtCLEVBQUEsQ0FBRSxxQkFBcUIsUUFBUSxDQUFBO0FBQzVFLElBQUEsSUFBSSxDQUFDLE1BQUEsRUFBYyxNQUFBLElBQUlFLDJCQUFvQixRQUFRLENBQUE7QUFDbkQsSUFBQSxNQUFNLEtBQVEsR0FBQSxJQUFJQywrQ0FBMEIsQ0FBQSxNQUFBLEVBQVEsRUFBRSxDQUFBO0FBQ3RELElBQUEsSUFBQSxDQUFLLE1BQU8sQ0FBQSxJQUFBLENBQUssQ0FBQyxzQkFBQSxFQUF3QixLQUFLLENBQUMsQ0FBQTtBQUNoRCxJQUFJLElBQUEsS0FBQSxDQUFNLFdBQVksRUFBQSxFQUFVLE9BQUEsS0FBQTtBQUVoQyxJQUFNLE1BQUEsTUFBQSxDQUFPLGlCQUFrQixFQUFBLENBQUUscUJBQXNCLEVBQUE7QUFFdkQsSUFBQSxJQUFJLEVBQUksRUFBQSxJQUFBLENBQUssR0FBSSxDQUFBLEdBQUEsQ0FBSSxRQUFRLENBQUE7QUFBQSxTQUN4QixJQUFBLENBQUssR0FBSSxDQUFBLE1BQUEsQ0FBTyxRQUFRLENBQUE7QUFFN0IsSUFBSSxJQUFBO0FBQ0EsTUFBQSxNQUFNSixvQkFBRyxRQUFTLENBQUEsU0FBQTtBQUFBO0FBQUEsUUFFZEMsa0JBQVEsYUFBYSxDQUFBO0FBQUEsUUFDckIsSUFBSyxDQUFBLFNBQUE7QUFBQSxVQUNELEtBQUEsQ0FBTSxLQUFLLElBQUssQ0FBQSxHQUFBLENBQUksUUFBUSxDQUFBLENBQUUsR0FBSSxDQUFBLENBQUMsSUFBVSxNQUFBO0FBQUEsWUFDekMsSUFBQTtBQUFBLFlBQ0EsS0FBTyxFQUFBO0FBQUEsV0FDVCxDQUFBLENBQUE7QUFBQSxVQUNGLElBQUE7QUFBQSxVQUNBO0FBQUE7QUFDSixPQUNKO0FBRUEsTUFBQSxNQUFNLE9BQU8sWUFBYSxFQUFBO0FBQzFCLE1BQU8sT0FBQSxJQUFBO0FBQUEsS0FDSCxDQUFBLE1BQUE7QUFDSixNQUFPLE9BQUEsS0FBQTtBQUFBO0FBQ1g7QUFDSjtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxFQVFPLEtBQUssUUFBMkIsRUFBQTtBQUNuQyxJQUFPLE9BQUEsSUFBQSxDQUFLLEdBQUksQ0FBQSxHQUFBLENBQUksUUFBUSxDQUFBO0FBQUE7QUFDaEM7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUFRTyxJQUFJLFFBQW1CLEVBQUE7QUFDMUIsSUFBTSxNQUFBLE9BQUEsR0FBVSxDQUFDLFVBQXdCLEtBQUE7QUFDckMsTUFBQSxJQUFJLENBQUMsUUFBQSxFQUFnQixNQUFBLElBQUksTUFBTSxDQUFxQyxtQ0FBQSxDQUFBLENBQUE7QUFFcEUsTUFBSSxJQUFBLENBQUMsWUFBbUIsT0FBQSxJQUFBO0FBQ3hCLE1BQUksSUFBQSxRQUFBLENBQVMsU0FBVSxFQUFBLEVBQVUsT0FBQSxJQUFBO0FBQ2pDLE1BQUksSUFBQSxRQUFBLENBQVMsSUFBSyxFQUFBLEVBQVUsT0FBQSxJQUFBO0FBQzVCLE1BQUEsSUFBSSxTQUFTLGNBQWUsRUFBQSxDQUFFLFFBQVMsQ0FBQSxVQUFVLEdBQVUsT0FBQSxJQUFBO0FBQzNELE1BQUEsSUFBSSxTQUFTLGNBQWUsRUFBQSxDQUFFLFFBQVMsQ0FBQSxHQUFHLEdBQVUsT0FBQSxJQUFBO0FBRXBELE1BQU0sTUFBQSxLQUFBLEdBQVEsVUFBVyxDQUFBLEtBQUEsQ0FBTSxHQUFHLENBQUE7QUFDbEMsTUFBQSxJQUFJLEtBQVEsR0FBQSxFQUFBO0FBQ1osTUFBQSxLQUFBLE1BQVcsVUFBVSxLQUFPLEVBQUE7QUFDeEIsUUFBQSxJQUFJLEtBQU8sRUFBQSxLQUFBLEdBQVEsQ0FBRyxFQUFBLEtBQUssSUFBSSxNQUFNLENBQUEsQ0FBQTtBQUFBLGFBQ3hCLEtBQUEsR0FBQSxNQUFBO0FBRWIsUUFBQSxJQUFJLFNBQVMsY0FBZSxFQUFBLENBQUUsUUFBUyxDQUFBLEtBQUssR0FBVSxPQUFBLElBQUE7QUFDdEQsUUFBSSxJQUFBLFFBQUEsQ0FBUyxnQkFBaUIsQ0FBQSxRQUFBLENBQVMsR0FBRyxLQUFLLENBQUEsRUFBQSxDQUFJLEdBQVUsT0FBQSxJQUFBO0FBQUE7QUFHakUsTUFBTyxPQUFBLEtBQUE7QUFBQSxLQUNYO0FBRUEsSUFBTyxPQUFBO0FBQUEsTUFDSCxPQUFBO0FBQUEsTUFDQSxLQUFLLE1BQU07QUFDUCxRQUFPLE9BQUE7QUFBQSxVQUNILE9BQVMsRUFBQSxDQUFDLFVBQXdCLEtBQUEsQ0FBQyxRQUFRLFVBQVU7QUFBQSxTQUN6RDtBQUFBO0FBQ0osS0FDSjtBQUFBO0FBRVI7Ozs7In0=