/* THIS IS A GENERATED/BUNDLED FILE BY ESBUILD if you want to view the source, please visit the github repository of this plugin */ var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __esm = (fn, res) => function __init() { return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res; }; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/modals/ConfirmModal.ts var ConfirmModal_exports = {}; __export(ConfirmModal_exports, { ConfirmModal: () => ConfirmModal, openConfirmModal: () => openConfirmModal }); function openConfirmModal(app, title, message, confirmText = "Confirm", cancelText = "Cancel") { const modal = new ConfirmModal(app, title, message, confirmText, cancelText); return modal.openAndAwaitResult(); } var import_obsidian14, ConfirmModal; var init_ConfirmModal = __esm({ "src/modals/ConfirmModal.ts"() { import_obsidian14 = require("obsidian"); ConfirmModal = class extends import_obsidian14.Modal { constructor(app, title, message, confirmText = "Confirm", cancelText = "Cancel") { super(app); this.title = title; this.message = message; this.confirmText = confirmText; this.cancelText = cancelText; } onOpen() { const { contentEl, titleEl } = this; titleEl.setText(this.title); const messageEl = contentEl.createDiv({ cls: "image-manager-confirm-message" }); messageEl.createEl("p", { text: this.message }); const buttonContainer = contentEl.createDiv({ cls: "image-manager-confirm-buttons" }); buttonContainer.createEl("button", { text: this.confirmText, cls: "mod-cta" }).addEventListener("click", () => { this.resolve({ confirmed: true }); this.close(); }); buttonContainer.createEl("button", { text: this.cancelText }).addEventListener("click", () => { this.resolve({ confirmed: false }); this.close(); }); setTimeout(() => { const confirmButton = buttonContainer.querySelector(".mod-cta"); confirmButton == null ? void 0 : confirmButton.focus(); }, 50); } onClose() { const { contentEl } = this; contentEl.empty(); } openAndAwaitResult() { return new Promise((resolve) => { this.resolve = resolve; this.open(); }); } }; } }); // src/main.ts var main_exports = {}; __export(main_exports, { default: () => ImageManagerPlugin }); module.exports = __toCommonJS(main_exports); var import_obsidian15 = require("obsidian"); // src/settings.ts var import_obsidian = require("obsidian"); // src/types.ts var DEFAULT_BANNER_DEVICE_SETTINGS = { ["desktop" /* Desktop */]: { enabled: true, height: 240, viewOffset: 0, noteOffset: -32, bannerRadiusEnabled: false, borderRadius: [8, 8, 8, 8], padding: 8, fade: true, animation: false, iconEnabled: false, iconSize: 96, iconRadius: 8, iconBackground: true, iconBorder: 2, iconFrame: true, iconAlignmentH: "flex-start", iconAlignmentV: "flex-end", iconOffsetX: 0, iconOffsetY: -24 }, ["tablet" /* Tablet */]: { enabled: true, height: 190, viewOffset: 0, noteOffset: -32, bannerRadiusEnabled: false, borderRadius: [8, 8, 8, 8], padding: 8, fade: true, animation: false, iconEnabled: false, iconSize: 96, iconRadius: 8, iconBackground: true, iconBorder: 2, iconFrame: true, iconAlignmentH: "flex-start", iconAlignmentV: "flex-end", iconOffsetX: 0, iconOffsetY: -24 }, ["phone" /* Phone */]: { enabled: true, height: 160, viewOffset: 0, noteOffset: -32, bannerRadiusEnabled: false, borderRadius: [8, 8, 8, 8], padding: 8, fade: true, animation: false, iconEnabled: false, iconSize: 56, iconRadius: 8, iconBackground: true, iconBorder: 2, iconFrame: true, iconAlignmentH: "flex-start", iconAlignmentV: "flex-end", iconOffsetX: 0, iconOffsetY: -24 } }; var DEFAULT_BANNER_SETTINGS = { properties: { imageProperty: "banner", iconProperty: "icon", hidePropertyEnabled: false, hideProperty: "" }, desktop: { ...DEFAULT_BANNER_DEVICE_SETTINGS["desktop" /* Desktop */] }, tablet: { ...DEFAULT_BANNER_DEVICE_SETTINGS["tablet" /* Tablet */] }, phone: { ...DEFAULT_BANNER_DEVICE_SETTINGS["phone" /* Phone */] } }; var DEFAULT_SETTINGS = { // General Settings enableRenameOnPaste: true, enableRenameOnDrop: true, imageNameTemplate: "", attachmentLocation: "obsidian" /* ObsidianDefault */, customAttachmentPath: "./assets", // Image Services defaultProvider: "unsplash" /* Unsplash */, unsplashProxyServer: "", pexelsApiKey: "", pexelsApiKeySecretId: "", pixabayApiKey: "", pixabayApiKeySecretId: "", defaultOrientation: "any" /* Any */, defaultImageSize: "large" /* Large */, // Property Insertion enablePropertyPaste: true, propertyLinkFormat: "obsidian" /* ObsidianDefault */, customPropertyLinkFormat: "{image-url}", defaultPropertyName: "banner", defaultIconPropertyName: "icon", altTextProperty: "", // Conversion autoConvertRemoteImages: false, convertOnNoteOpen: false, convertOnNoteSave: false, processBackgroundChanges: true, // Rename Options showRenameDialog: true, autoRename: false, dupNumberDelimiter: "-", dupNumberAtStart: false, disableRenameNotice: false, enableDescriptiveImages: false, // Image Insertion Options (remote image attribution options) insertSize: "", // Empty = no size specified insertReferral: true, // Default to true (attribution) insertBackLink: false, // Default to false appendReferral: false, // Default to false // Banner Settings banner: { ...DEFAULT_BANNER_SETTINGS }, // Advanced supportedExtensions: ["md", "mdx"], debugMode: false }; // src/settings.ts var ImageManagerSettingTab = class extends import_obsidian.PluginSettingTab { constructor(app, plugin) { super(app, plugin); this.icon = "lucide-image-down"; this.plugin = plugin; } display() { const { containerEl } = this; containerEl.empty(); this.renderGeneralSettings(containerEl); this.renderImageServicesSettings(containerEl); this.renderPropertySettings(containerEl); this.renderConversionSettings(containerEl); this.renderRenameSettings(containerEl); this.renderBannerSettings(containerEl); this.renderAdvancedSettings(containerEl); } renderGeneralSettings(containerEl) { const group = new import_obsidian.SettingGroup(containerEl); group.addSetting((setting) => { setting.setName("Image name template").setDesc("Template for generated image names. Variables: {{fileName}}, {{dirName}}, {{DATE:YYYY-MM-DD}}, {{TIME:HH-mm-ss}}").addText((text) => { text.setPlaceholder("{{fileName}}").setValue(this.plugin.settings.imageNameTemplate).onChange(async (value) => { this.plugin.settings.imageNameTemplate = value; await this.plugin.saveSettings(); }); }); }); group.addSetting((setting) => { setting.setName("Attachment location").setDesc("Where to save inserted images").addDropdown((dropdown) => { dropdown.addOption("obsidian" /* ObsidianDefault */, "Use Obsidian's settings").addOption("same" /* SameFolder */, "Same folder as note").addOption("subfolder" /* Subfolder */, "Subfolder (configure below)").addOption("vault" /* VaultFolder */, "Vault folder (configure below)").setValue(this.plugin.settings.attachmentLocation).onChange(async (value) => { this.plugin.settings.attachmentLocation = value; await this.plugin.saveSettings(); const scrollContainer = containerEl.closest(".vertical-tab-content") || containerEl.closest(".settings-content") || containerEl.parentElement; const scrollTop = (scrollContainer == null ? void 0 : scrollContainer.scrollTop) || 0; this.display(); requestAnimationFrame(() => { if (scrollContainer) { scrollContainer.scrollTop = scrollTop; } }); }); }); }); if (this.plugin.settings.attachmentLocation !== "obsidian" /* ObsidianDefault */ && this.plugin.settings.attachmentLocation !== "same" /* SameFolder */) { group.addSetting((setting) => { setting.setName("Custom attachment path").setDesc('Path for attachments. Use "./" for relative to note, or "/" for vault root.').addText((text) => { text.setPlaceholder("./assets").setValue(this.plugin.settings.customAttachmentPath).onChange(async (value) => { this.plugin.settings.customAttachmentPath = value; await this.plugin.saveSettings(); }); }); }); } } renderImageServicesSettings(containerEl) { const group = new import_obsidian.SettingGroup(containerEl).setHeading("Image services"); group.addSetting((setting) => { setting.setName("Default provider").setDesc("Default image provider for search").addDropdown((dropdown) => { dropdown.addOption("unsplash" /* Unsplash */, "Unsplash").addOption("pexels" /* Pexels */, "Pexels").addOption("pixabay" /* Pixabay */, "Pixabay").addOption("local" /* Local */, "Local files").setValue(this.plugin.settings.defaultProvider).onChange(async (value) => { this.plugin.settings.defaultProvider = value; await this.plugin.saveSettings(); }); }); }); group.addSetting((setting) => { setting.setName("Default orientation").setDesc("Filter images by orientation").addDropdown((dropdown) => { dropdown.addOption("any" /* Any */, "Any").addOption("landscape" /* Landscape */, "Landscape").addOption("portrait" /* Portrait */, "Portrait").addOption("square" /* Square */, "Square").setValue(this.plugin.settings.defaultOrientation).onChange(async (value) => { this.plugin.settings.defaultOrientation = value; await this.plugin.saveSettings(); }); }); }); group.addSetting((setting) => { setting.setName("Default image size").setDesc("Preferred size when downloading images").addDropdown((dropdown) => { dropdown.addOption("original" /* Original */, "Original").addOption("large" /* Large */, "Large").addOption("medium" /* Medium */, "Medium").addOption("small" /* Small */, "Small").setValue(this.plugin.settings.defaultImageSize).onChange(async (value) => { this.plugin.settings.defaultImageSize = value; await this.plugin.saveSettings(); }); }); }); group.addSetting((setting) => { setting.setName("Unsplash proxy server").setDesc("Optional proxy server (leave empty to use built-in)").addText((text) => { text.setPlaceholder("https://your-proxy.com/").setValue(this.plugin.settings.unsplashProxyServer).onChange(async (value) => { this.plugin.settings.unsplashProxyServer = value; await this.plugin.saveSettings(); }); }); }); group.addSetting((setting) => { setting.setName("Pexels API key"); if ((0, import_obsidian.requireApiVersion)("1.11.4")) { setting.setDesc("Choose a secret that contains your Pexels API key.").addComponent((el) => { const obsidian = require("obsidian"); const SecretComponent = obsidian.SecretComponent; const component = new SecretComponent(this.app, el); component.setValue(this.plugin.settings.pexelsApiKeySecretId); component.onChange((value) => { void (async () => { this.plugin.settings.pexelsApiKeySecretId = value; await this.plugin.saveSettings(); })(); }); return component; }); } else { setting.setDesc("Get your API key from https://www.pexels.com/api/new/").addText((text) => { text.setPlaceholder("Pexels API key").setValue(this.plugin.settings.pexelsApiKey).onChange(async (value) => { this.plugin.settings.pexelsApiKey = value; await this.plugin.saveSettings(); }); }); } }); group.addSetting((setting) => { setting.setName("Pixabay API key"); if ((0, import_obsidian.requireApiVersion)("1.11.4")) { setting.setDesc("Choose a secret that contains your Pixabay API key.").addComponent((el) => { const obsidian = require("obsidian"); const SecretComponent = obsidian.SecretComponent; const component = new SecretComponent(this.app, el); component.setValue(this.plugin.settings.pixabayApiKeySecretId); component.onChange((value) => { void (async () => { this.plugin.settings.pixabayApiKeySecretId = value; await this.plugin.saveSettings(); })(); }); return component; }); } else { setting.setDesc("Get your API key from https://pixabay.com/api/docs/").addText((text) => { text.setPlaceholder("Pixabay API key").setValue(this.plugin.settings.pixabayApiKey).onChange(async (value) => { this.plugin.settings.pixabayApiKey = value; await this.plugin.saveSettings(); }); }); } }); group.addSetting((setting) => { setting.setName("Insert size").setDesc('Set the size of the image when inserting. Format could be only the width "200" or the width and height "200x100". Leave empty for no size.').addText((text) => { text.setPlaceholder("200 or 200x100").setValue(this.plugin.settings.insertSize).onChange(async (value) => { this.plugin.settings.insertSize = value; await this.plugin.saveSettings(); }); }); }); group.addSetting((setting) => { setting.setName("Insert referral").setDesc("Insert the reference text").addToggle((toggle) => { toggle.setValue(this.plugin.settings.insertReferral).onChange(async (value) => { this.plugin.settings.insertReferral = value; await this.plugin.saveSettings(); }); }); }); group.addSetting((setting) => { setting.setName("Insert backlink").setDesc("Insert a backlink in front of the reference text").addToggle((toggle) => { toggle.setValue(this.plugin.settings.insertBackLink).onChange(async (value) => { this.plugin.settings.insertBackLink = value; await this.plugin.saveSettings(); }); }); }); } renderPropertySettings(containerEl) { const group = new import_obsidian.SettingGroup(containerEl).setHeading("Property insertion"); group.addSetting((setting) => { setting.setName("Enable paste into properties").setDesc("Allow pasting images directly into properties").addToggle((toggle) => { toggle.setValue(this.plugin.settings.enablePropertyPaste).onChange(async (value) => { this.plugin.settings.enablePropertyPaste = value; await this.plugin.saveSettings(); }); }); }); group.addSetting((setting) => { setting.setName("Property link format").setDesc("How to format the image link in properties").addDropdown((dropdown) => { dropdown.addOption("obsidian" /* ObsidianDefault */, "Use Obsidian's settings").addOption("path" /* Path */, "Plain path (path/to/image.jpg)").addOption("relative" /* RelativePath */, "Relative path (./image.jpg)").addOption("wikilink" /* Wikilink */, "Wikilink ([[path/to/image.jpg]])").addOption("markdown" /* Markdown */, "Markdown (![](path/to/image.jpg))").addOption("custom" /* Custom */, "Custom format").setValue(this.plugin.settings.propertyLinkFormat).onChange(async (value) => { this.plugin.settings.propertyLinkFormat = value; await this.plugin.saveSettings(); const scrollContainer = containerEl.closest(".vertical-tab-content") || containerEl.closest(".settings-content") || containerEl.parentElement; const scrollTop = (scrollContainer == null ? void 0 : scrollContainer.scrollTop) || 0; this.display(); requestAnimationFrame(() => { if (scrollContainer) { scrollContainer.scrollTop = scrollTop; } }); }); }); }); if (this.plugin.settings.propertyLinkFormat === "custom" /* Custom */) { group.addSetting((setting) => { setting.setName("Custom format template").setDesc("Use {image-url} as placeholder for the image path").addText((text) => { text.setPlaceholder("{image-url}").setValue(this.plugin.settings.customPropertyLinkFormat).onChange(async (value) => { this.plugin.settings.customPropertyLinkFormat = value; await this.plugin.saveSettings(); }); }); }); } group.addSetting((setting) => { setting.setName("Default property name").setDesc("Default property name when inserting to properties via command").addText((text) => { text.setPlaceholder("Banner").setValue(this.plugin.settings.defaultPropertyName).onChange(async (value) => { this.plugin.settings.defaultPropertyName = value; await this.plugin.saveSettings(); }); }); }); group.addSetting((setting) => { setting.setName("Default icon property name").setDesc("Default property name when inserting to icon property via command").addText((text) => { text.setPlaceholder("Icon").setValue(this.plugin.settings.defaultIconPropertyName).onChange(async (value) => { this.plugin.settings.defaultIconPropertyName = value; await this.plugin.saveSettings(); }); }); }); group.addSetting((setting) => { setting.setName("Alt text property name").setDesc('Property name to use for image alt text (description) when inserting to properties. If "Descriptive images" is enabled, this will be filled with the description you provide. If disabled, it will be filled with the search term for external images.').addText((text) => { text.setPlaceholder("alt").setValue(this.plugin.settings.altTextProperty).onChange(async (value) => { this.plugin.settings.altTextProperty = value; await this.plugin.saveSettings(); }); }); }); } renderConversionSettings(containerEl) { const group = new import_obsidian.SettingGroup(containerEl).setHeading("Remote image conversion"); group.addSetting((setting) => { setting.setName("Auto-convert remote images").setDesc("Automatically download and replace remote image urls with local files").addToggle((toggle) => { toggle.setValue(this.plugin.settings.autoConvertRemoteImages).onChange(async (value) => { this.plugin.settings.autoConvertRemoteImages = value; await this.plugin.saveSettings(); const scrollContainer = containerEl.closest(".vertical-tab-content") || containerEl.closest(".settings-content") || containerEl.parentElement; const scrollTop = (scrollContainer == null ? void 0 : scrollContainer.scrollTop) || 0; this.display(); requestAnimationFrame(() => { if (scrollContainer) { scrollContainer.scrollTop = scrollTop; } }); }); }); }); if (this.plugin.settings.autoConvertRemoteImages) { group.addSetting((setting) => { setting.setName("Convert on note open").setDesc("Process remote images when opening a note").addToggle((toggle) => { toggle.setValue(this.plugin.settings.convertOnNoteOpen).onChange(async (value) => { this.plugin.settings.convertOnNoteOpen = value; await this.plugin.saveSettings(); }); }); }); group.addSetting((setting) => { setting.setName("Convert on note save").setDesc("Process remote images when saving a note").addToggle((toggle) => { toggle.setValue(this.plugin.settings.convertOnNoteSave).onChange(async (value) => { this.plugin.settings.convertOnNoteSave = value; await this.plugin.saveSettings(); }); }); }); } } renderRenameSettings(containerEl) { const group = new import_obsidian.SettingGroup(containerEl).setHeading("Rename options"); group.addSetting((setting) => { setting.setName("Show image rename dialog automatically").setDesc("Handle and rename images when they are added to the vault via paste or drag and drop").addToggle((toggle) => { toggle.setValue(this.plugin.settings.showRenameDialog).onChange(async (value) => { this.plugin.settings.showRenameDialog = value; await this.plugin.saveSettings(); this.refreshWithScrollPreserve(containerEl); }); }); }); if (this.plugin.settings.showRenameDialog) { group.addSetting((setting) => { setting.setName("Rename on paste").setDesc("Handle and rename images when pasting into the editor").addToggle((toggle) => { toggle.setValue(this.plugin.settings.enableRenameOnPaste).onChange(async (value) => { this.plugin.settings.enableRenameOnPaste = value; await this.plugin.saveSettings(); }); }); }); group.addSetting((setting) => { setting.setName("Rename on drag and drop").setDesc("Handle and rename images when dropping into the editor").addToggle((toggle) => { toggle.setValue(this.plugin.settings.enableRenameOnDrop).onChange(async (value) => { this.plugin.settings.enableRenameOnDrop = value; await this.plugin.saveSettings(); }); }); }); } group.addSetting((setting) => { setting.setName("Process background file changes").setDesc("Automatically convert and rename remote images when files are changed in the background (by Git or other plugins). Warning: Turning this on may cause the rename modal to appear for images you've already processed on other devices during a sync.").addToggle((toggle) => { toggle.setValue(this.plugin.settings.processBackgroundChanges).onChange(async (value) => { this.plugin.settings.processBackgroundChanges = value; await this.plugin.saveSettings(); }); }); }); group.addSetting((setting) => { setting.setName("Descriptive images").setDesc("Ask for image description, use as display text and kebab-case for file name (applies to note body insertions only, not properties)").addToggle((toggle) => { toggle.setValue(this.plugin.settings.enableDescriptiveImages).onChange(async (value) => { this.plugin.settings.enableDescriptiveImages = value; await this.plugin.saveSettings(); }); }); }); group.addSetting((setting) => { setting.setName("Auto rename").setDesc("Automatically rename without showing dialog (uses template)").addToggle((toggle) => { toggle.setValue(this.plugin.settings.autoRename).onChange(async (value) => { this.plugin.settings.autoRename = value; await this.plugin.saveSettings(); }); }); }); group.addSetting((setting) => { setting.setName("Duplicate number delimiter").setDesc('Character(s) between name and number for duplicates (e.g., "-" gives "image-1")').addText((text) => { text.setPlaceholder("-").setValue(this.plugin.settings.dupNumberDelimiter).onChange(async (value) => { this.plugin.settings.dupNumberDelimiter = value; await this.plugin.saveSettings(); }); }); }); group.addSetting((setting) => { setting.setName("Duplicate number at start").setDesc('Put the duplicate number at the start ("1-image" instead of "image-1")').addToggle((toggle) => { toggle.setValue(this.plugin.settings.dupNumberAtStart).onChange(async (value) => { this.plugin.settings.dupNumberAtStart = value; await this.plugin.saveSettings(); }); }); }); group.addSetting((setting) => { setting.setName("Disable rename notice").setDesc("Do not show a notice after renaming an image").addToggle((toggle) => { toggle.setValue(this.plugin.settings.disableRenameNotice).onChange(async (value) => { this.plugin.settings.disableRenameNotice = value; await this.plugin.saveSettings(); }); }); }); } /** * Get the current device type */ getCurrentDevice() { if (import_obsidian.Platform.isPhone) { return "phone" /* Phone */; } if (import_obsidian.Platform.isTablet) { return "tablet" /* Tablet */; } return "desktop" /* Desktop */; } /** * Helper to preserve scroll position when re-rendering settings */ refreshWithScrollPreserve(containerEl) { const scrollContainer = containerEl.closest(".vertical-tab-content") || containerEl.closest(".settings-content") || containerEl.parentElement; const scrollTop = (scrollContainer == null ? void 0 : scrollContainer.scrollTop) || 0; this.display(); requestAnimationFrame(() => { if (scrollContainer) { scrollContainer.scrollTop = scrollTop; } }); } renderBannerSettings(containerEl) { const group = new import_obsidian.SettingGroup(containerEl).setHeading("Banner images"); const currentDevice = this.getCurrentDevice(); const deviceSettings = this.plugin.settings.banner[currentDevice]; const defaultDeviceSettings = DEFAULT_BANNER_DEVICE_SETTINGS[currentDevice]; const propertySettings = this.plugin.settings.banner.properties; group.addSetting((setting) => { setting.setName("Show banner").setDesc(`Enable or disable banners on your ${currentDevice} device`).addToggle((toggle) => { toggle.setValue(deviceSettings.enabled).onChange(async (value) => { this.plugin.settings.banner[currentDevice].enabled = value; await this.plugin.saveSettings(); this.refreshWithScrollPreserve(containerEl); }); }); }); if (!deviceSettings.enabled) { return; } group.addSetting((setting) => { setting.setName("Height").setDesc(`Height of the banner on your ${currentDevice} device (in pixels)`).addText((text) => { text.setPlaceholder(String(defaultDeviceSettings.height)).setValue(String(deviceSettings.height)).onChange(async (value) => { const num = parseInt(value, 10); if (!isNaN(num) && num > 0) { this.plugin.settings.banner[currentDevice].height = num; await this.plugin.saveSettings(); } }); }); }); group.addSetting((setting) => { setting.setName("Padding").setDesc("Padding of the banner from the edges of the note (in pixels)").addText((text) => { text.setPlaceholder(String(defaultDeviceSettings.padding)).setValue(String(deviceSettings.padding)).onChange(async (value) => { const num = parseInt(value, 10); if (!isNaN(num) && num >= 0) { this.plugin.settings.banner[currentDevice].padding = num; await this.plugin.saveSettings(); } }); }); }); group.addSetting((setting) => { setting.setName("Note offset").setDesc("Move the position of the note content (in pixels)").addText((text) => { text.setPlaceholder(String(defaultDeviceSettings.noteOffset)).setValue(String(deviceSettings.noteOffset)).onChange(async (value) => { const num = parseInt(value, 10); if (!isNaN(num)) { this.plugin.settings.banner[currentDevice].noteOffset = num; await this.plugin.saveSettings(); } }); }); }); group.addSetting((setting) => { setting.setName("View offset").setDesc("Move the position of the view content (in pixels)").addText((text) => { text.setPlaceholder(String(defaultDeviceSettings.viewOffset)).setValue(String(deviceSettings.viewOffset)).onChange(async (value) => { const num = parseInt(value, 10); if (!isNaN(num)) { this.plugin.settings.banner[currentDevice].viewOffset = num; await this.plugin.saveSettings(); } }); }); }); group.addSetting((setting) => { setting.setName("Fade").setDesc("Fade the image out towards the content").addToggle((toggle) => { toggle.setValue(deviceSettings.fade).onChange(async (value) => { this.plugin.settings.banner[currentDevice].fade = value; await this.plugin.saveSettings(); }); }); }); group.addSetting((setting) => { setting.setName("Rounded corners").setDesc("Enable rounded corners for the banner").addToggle((toggle) => { toggle.setValue(deviceSettings.bannerRadiusEnabled).onChange(async (value) => { this.plugin.settings.banner[currentDevice].bannerRadiusEnabled = value; await this.plugin.saveSettings(); }); }); }); group.addSetting((setting) => { setting.setName("Animation").setDesc("Enable banner animation when opening files").addToggle((toggle) => { toggle.setValue(deviceSettings.animation).onChange(async (value) => { this.plugin.settings.banner[currentDevice].animation = value; await this.plugin.saveSettings(); }); }); }); group.addSetting((setting) => { setting.setName("Banner property").setDesc("Name of the banner property this plugin will look for in the properties").addText((text) => { text.setPlaceholder("Banner").setValue(propertySettings.imageProperty).onChange(async (value) => { this.plugin.settings.banner.properties.imageProperty = value || "banner"; await this.plugin.saveSettings(); }); }); }); group.addSetting((setting) => { setting.setName("Icon property").setDesc("Name of the icon property this plugin will look for in the properties").addText((text) => { text.setPlaceholder("Icon").setValue(propertySettings.iconProperty).onChange(async (value) => { this.plugin.settings.banner.properties.iconProperty = value || "icon"; await this.plugin.saveSettings(); }); }); }); group.addSetting((setting) => { setting.setName("Enable per-note banner hiding").setDesc("Allow disabling banners on a per-note basis using a properties field").addToggle((toggle) => { toggle.setValue(propertySettings.hidePropertyEnabled).onChange(async (value) => { this.plugin.settings.banner.properties.hidePropertyEnabled = value; await this.plugin.saveSettings(); this.refreshWithScrollPreserve(containerEl); }); }); }); if (propertySettings.hidePropertyEnabled) { group.addSetting((setting) => { setting.setName("Hide banner property").setDesc("Name of the property that, when set to true, will hide the banner for that note").addText((text) => { text.setPlaceholder("hideBanner").setValue(propertySettings.hideProperty).onChange(async (value) => { this.plugin.settings.banner.properties.hideProperty = value || ""; await this.plugin.saveSettings(); }); }); }); } group.addSetting((setting) => { setting.setName("Show icon").setDesc("Enable or disable the icon").addToggle((toggle) => { toggle.setValue(deviceSettings.iconEnabled).onChange(async (value) => { this.plugin.settings.banner[currentDevice].iconEnabled = value; await this.plugin.saveSettings(); this.refreshWithScrollPreserve(containerEl); }); }); }); if (deviceSettings.iconEnabled) { group.addSetting((setting) => { setting.setName("Icon size").setDesc("Size of the icon (in pixels)").addText((text) => { text.setPlaceholder(String(defaultDeviceSettings.iconSize)).setValue(String(deviceSettings.iconSize)).onChange(async (value) => { const num = parseInt(value, 10); if (!isNaN(num) && num > 0) { this.plugin.settings.banner[currentDevice].iconSize = num; await this.plugin.saveSettings(); } }); }); }); group.addSetting((setting) => { setting.setName("Icon background").setDesc("Enable or disable the icon background").addToggle((toggle) => { toggle.setValue(deviceSettings.iconBackground).onChange(async (value) => { this.plugin.settings.banner[currentDevice].iconBackground = value; await this.plugin.saveSettings(); }); }); }); group.addSetting((setting) => { setting.setName("Icon frame").setDesc("Show the border/background frame around the icon (disable to display just the icon graphic)").addToggle((toggle) => { toggle.setValue(deviceSettings.iconFrame).onChange(async (value) => { this.plugin.settings.banner[currentDevice].iconFrame = value; await this.plugin.saveSettings(); }); }); }); group.addSetting((setting) => { setting.setName("Icon border size").setDesc("Size of the icon border (in pixels)").addText((text) => { text.setPlaceholder(String(defaultDeviceSettings.iconBorder)).setValue(String(deviceSettings.iconBorder)).onChange(async (value) => { const num = parseInt(value, 10); if (!isNaN(num) && num >= 0) { this.plugin.settings.banner[currentDevice].iconBorder = num; await this.plugin.saveSettings(); } }); }); }); group.addSetting((setting) => { setting.setName("Icon border radius").setDesc("Size of the icon border radius (in pixels)").addText((text) => { text.setPlaceholder(String(defaultDeviceSettings.iconRadius)).setValue(String(deviceSettings.iconRadius)).onChange(async (value) => { const num = parseInt(value, 10); if (!isNaN(num) && num >= 0) { this.plugin.settings.banner[currentDevice].iconRadius = num; await this.plugin.saveSettings(); } }); }); }); group.addSetting((setting) => { setting.setName("Icon alignment - horizontal").setDesc("Horizontal alignment of the icon").addDropdown((dropdown) => { dropdown.addOption("flex-start", "Left").addOption("center", "Center").addOption("flex-end", "Right").setValue(deviceSettings.iconAlignmentH).onChange(async (value) => { this.plugin.settings.banner[currentDevice].iconAlignmentH = value; await this.plugin.saveSettings(); }); }); }); group.addSetting((setting) => { setting.setName("Icon alignment - vertical").setDesc("Vertical alignment of the icon").addDropdown((dropdown) => { dropdown.addOption("flex-start", "Top").addOption("center", "Center").addOption("flex-end", "Bottom").setValue(deviceSettings.iconAlignmentV).onChange(async (value) => { this.plugin.settings.banner[currentDevice].iconAlignmentV = value; await this.plugin.saveSettings(); }); }); }); } } renderAdvancedSettings(containerEl) { const group = new import_obsidian.SettingGroup(containerEl).setHeading("Advanced"); group.addSetting((setting) => { setting.setName("Supported file extensions").setDesc("File extensions to process (comma-separated)").addText((text) => { const currentValue = this.plugin.settings.supportedExtensions.length > 0 ? this.plugin.settings.supportedExtensions.join(", ") : ""; text.setPlaceholder("File extensions").setValue(currentValue).onChange(async (value) => { const extensions = value.split(",").map((ext) => ext.trim().toLowerCase()).filter((ext) => ext.length > 0); this.plugin.settings.supportedExtensions = extensions.length > 0 ? extensions : ["md"]; await this.plugin.saveSettings(); }); }); }); group.addSetting((setting) => { setting.setName("Debug mode").setDesc("Enable debug logging to console").addToggle((toggle) => { toggle.setValue(this.plugin.settings.debugMode).onChange(async (value) => { this.plugin.settings.debugMode = value; await this.plugin.saveSettings(); }); }); }); } }; // src/services/StorageManager.ts var import_obsidian2 = require("obsidian"); var StorageManager = class { constructor(app, settings, observable) { this.app = app; this.settings = settings; observable == null ? void 0 : observable.subscribe((newSettings) => { this.updateSettings(newSettings); }); } /** * Update settings reference */ updateSettings(settings) { this.settings = settings; } /** * Get the attachment folder path for a given note */ getAttachmentFolder(noteFile) { var _a, _b; const notePath = (_b = (_a = noteFile.parent) == null ? void 0 : _a.path) != null ? _b : ""; switch (this.settings.attachmentLocation) { case "same" /* SameFolder */: return notePath; case "subfolder" /* Subfolder */: return (0, import_obsidian2.normalizePath)(this.joinPaths(notePath, this.settings.customAttachmentPath)); case "vault" /* VaultFolder */: return (0, import_obsidian2.normalizePath)(this.settings.customAttachmentPath); case "obsidian" /* ObsidianDefault */: default: return this.getObsidianAttachmentFolder(noteFile); } } /** * Get Obsidian's configured attachment folder */ getObsidianAttachmentFolder(noteFile) { var _a, _b, _c; const vaultConfig = this.app.vault.config; const attachmentFolderPath = (_a = vaultConfig == null ? void 0 : vaultConfig.attachmentFolderPath) != null ? _a : "/"; const notePath = (_c = (_b = noteFile.parent) == null ? void 0 : _b.path) != null ? _c : ""; if (attachmentFolderPath === "/") { return ""; } else if (attachmentFolderPath === "./") { return notePath; } else if (attachmentFolderPath.startsWith("./")) { const relativePath = attachmentFolderPath.slice(2); return (0, import_obsidian2.normalizePath)(this.joinPaths(notePath, relativePath)); } else { return (0, import_obsidian2.normalizePath)(attachmentFolderPath); } } /** * Join path segments */ joinPaths(...parts) { return parts.filter((p) => p).join("/"); } /** * Ensure a folder exists, creating it if necessary */ async ensureFolderExists(folderPath) { if (!folderPath) return; const normalizedPath = (0, import_obsidian2.normalizePath)(folderPath); const folder = this.app.vault.getAbstractFileByPath(normalizedPath); if (!folder) { await this.app.vault.createFolder(normalizedPath); } else if (!(folder instanceof import_obsidian2.TFolder)) { throw new Error(`Path exists but is not a folder: ${normalizedPath}`); } } /** * Generate a unique file path for an image */ async getAvailablePath(baseName, extension, noteFile) { const folder = this.getAttachmentFolder(noteFile); await this.ensureFolderExists(folder); const sanitizedName = this.sanitizeFileName(baseName); let fileName = `${sanitizedName}.${extension}`; let filePath = folder ? (0, import_obsidian2.normalizePath)(this.joinPaths(folder, fileName)) : (0, import_obsidian2.normalizePath)(fileName); let counter = 1; while (this.app.vault.getAbstractFileByPath(filePath)) { if (this.settings.dupNumberAtStart) { fileName = `${counter}${this.settings.dupNumberDelimiter}${sanitizedName}.${extension}`; } else { fileName = `${sanitizedName}${this.settings.dupNumberDelimiter}${counter}.${extension}`; } filePath = folder ? (0, import_obsidian2.normalizePath)(this.joinPaths(folder, fileName)) : (0, import_obsidian2.normalizePath)(fileName); counter++; } return filePath; } /** * Save binary data as a file */ async saveFile(data, filePath) { const normalizedPath = (0, import_obsidian2.normalizePath)(filePath); const lastSlash = normalizedPath.lastIndexOf("/"); const parentPath = lastSlash > 0 ? normalizedPath.slice(0, lastSlash) : ""; if (parentPath) { await this.ensureFolderExists(parentPath); } return await this.app.vault.createBinary(normalizedPath, data); } /** * Generate markdown image link for a file * Ensures the link includes '!' for images * @param displayText Optional display text to add after the link (e.g., ![[image.jpg|display text]]) * @param insertSize Optional size to add (e.g., "200" or "200x100") */ generateMarkdownLink(file, sourcePath, displayText, insertSize) { const link = this.app.fileManager.generateMarkdownLink(file, sourcePath); let imageLink = link; if (this.isImageFile(file) && !link.startsWith("!")) { imageLink = `!${link}`; } if (this.settings.debugMode) { console.debug("[Image Manager] generateMarkdownLink", { originalLink: link, imageLink, insertSize, displayText, hasSize: !!(insertSize && insertSize.trim()) }); } if (imageLink.startsWith("![") && imageLink.includes("](")) { if (insertSize && insertSize.trim()) { const sizePart = `|${insertSize}`; if (displayText && displayText.trim()) { imageLink = imageLink.replace(/^!\[([^\]]*)\]/, `![${displayText}${sizePart}]`); } else { const altMatch = imageLink.match(/^!\[([^\]]*)\]/); if (altMatch) { const alt = altMatch[1] || ""; imageLink = imageLink.replace(/^!\[([^\]]*)\]/, `![${alt}${sizePart}]`); } } } else if (displayText && displayText.trim()) { imageLink = imageLink.replace(/^!\[([^\]]*)\]/, `![${displayText}]`); } } else if (imageLink.startsWith("![") && imageLink.includes("]]")) { const parts = []; if (insertSize && insertSize.trim()) { parts.push(insertSize); } if (displayText && displayText.trim()) { parts.push(displayText); } if (parts.length > 0) { imageLink = imageLink.replace(/\]\]$/, `|${parts.join("|")}]]`); } } if (this.settings.debugMode) { console.debug("[Image Manager] generateMarkdownLink result", { finalLink: imageLink }); } return imageLink; } /** * Get relative path from source file to target file */ getRelativePath(from, to) { var _a, _b, _c, _d; const fromDir = (_b = (_a = from.parent) == null ? void 0 : _a.path) != null ? _b : ""; const toPath = to.path; if (!fromDir) { return toPath; } const toDir = (_d = (_c = to.parent) == null ? void 0 : _c.path) != null ? _d : ""; if (fromDir === toDir) { return to.name; } return toPath; } /** * Sanitize a file name */ sanitizeFileName(name) { return name.replace(/[\\/:*?"<>|]/g, "-").replace(/\s+/g, "-").replace(/^\.+/, "").replace(/\.+$/, "").trim(); } /** * Get file extension from MIME type */ getExtensionFromMimeType(mimeType) { var _a; const mimeToExt = { "image/jpeg": "jpg", "image/jpg": "jpg", "image/png": "png", "image/gif": "gif", "image/webp": "webp", "image/svg+xml": "svg", "image/bmp": "bmp", "image/tiff": "tiff", "image/avif": "avif" }; return (_a = mimeToExt[mimeType]) != null ? _a : "png"; } /** * Check if a file is an image based on extension */ isImageFile(file) { const imageExtensions = ["jpg", "jpeg", "png", "gif", "webp", "svg", "bmp", "tiff", "avif"]; return imageExtensions.includes(file.extension.toLowerCase()); } /** * Check if a URL points to an external image */ isExternalImageUrl(url) { try { const parsed = new URL(url); if (!["http:", "https:"].includes(parsed.protocol)) { return false; } const pathname = parsed.pathname.toLowerCase(); const imageExtensions = [".jpg", ".jpeg", ".png", ".gif", ".webp", ".svg", ".bmp", ".tiff", ".avif"]; if (imageExtensions.some((ext) => pathname.endsWith(ext))) { return true; } const imageHosts = [ "images.unsplash.com", "images.pexels.com", "pixabay.com", "i.imgur.com", "cdn.discordapp.com" ]; return imageHosts.some((host) => parsed.hostname.includes(host)); } catch (e) { return false; } } }; // src/services/ImageProcessor.ts var import_obsidian5 = require("obsidian"); // src/utils/template.ts function renderTemplate(template, variables, frontmatter) { var _a, _b; let result = template; result = result.replace(/\{\{fileName\}\}/g, variables.fileName); result = result.replace(/\{\{dirName\}\}/g, variables.dirName); result = result.replace(/\{\{imageNameKey\}\}/g, (_a = variables.imageNameKey) != null ? _a : ""); result = result.replace(/\{\{firstHeading\}\}/g, (_b = variables.firstHeading) != null ? _b : ""); result = result.replace(/\{\{DATE:([^}]+)\}\}/g, (_, format) => { return formatDate(/* @__PURE__ */ new Date(), format); }); result = result.replace(/\{\{TIME:([^}]+)\}\}/g, (_, format) => { return formatTime(/* @__PURE__ */ new Date(), format); }); if (frontmatter) { result = result.replace(/\{\{fm:([^}]+)\}\}/g, (_, key) => { const value = frontmatter[key.trim()]; if (value == null) return ""; if (typeof value === "string") return value; if (typeof value === "number" || typeof value === "boolean") return String(value); return ""; }); } return result; } function formatDate(date, format) { const year = date.getFullYear(); const month = date.getMonth() + 1; const day = date.getDate(); return format.replace("YYYY", String(year)).replace("YY", String(year).slice(-2)).replace("MM", String(month).padStart(2, "0")).replace("DD", String(day).padStart(2, "0")).replace("M", String(month)).replace("D", String(day)); } function formatTime(date, format) { const hours = date.getHours(); const minutes = date.getMinutes(); const seconds = date.getSeconds(); return format.replace("HH", String(hours).padStart(2, "0")).replace("mm", String(minutes).padStart(2, "0")).replace("ss", String(seconds).padStart(2, "0")).replace("H", String(hours)).replace("m", String(minutes)).replace("s", String(seconds)); } function buildTemplateVariables(app, activeFile) { var _a, _b; const cache = app.metadataCache.getFileCache(activeFile); const frontmatter = cache == null ? void 0 : cache.frontmatter; let firstHeading = ""; if (cache == null ? void 0 : cache.headings) { for (const heading of cache.headings) { if (heading.level === 1) { firstHeading = heading.heading; break; } } } return { fileName: activeFile.basename, dirName: (_b = (_a = activeFile.parent) == null ? void 0 : _a.name) != null ? _b : "", imageNameKey: frontmatter == null ? void 0 : frontmatter.imageNameKey, firstHeading, date: formatDate(/* @__PURE__ */ new Date(), "YYYY-MM-DD"), time: formatTime(/* @__PURE__ */ new Date(), "HH-mm-ss") }; } function isTemplateMeaningful(result, delimiter) { const meaninglessRegex = new RegExp(`[${escapeRegExp(delimiter)}\\s]`, "gm"); return result.replace(meaninglessRegex, "") !== ""; } function escapeRegExp(string) { return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } // src/modals/RenameModal.ts var import_obsidian3 = require("obsidian"); var RenameModal = class extends import_obsidian3.Modal { constructor(app, imageFile, suggestedName, onSubmit) { super(app); this.nameInput = null; this.previewEl = null; this.errorEl = null; this.imageFile = imageFile; this.suggestedName = suggestedName; this.currentName = suggestedName; this.onSubmit = onSubmit; } onOpen() { const { contentEl, titleEl } = this; this.containerEl.addClass("image-manager-rename-modal"); titleEl.setText("Rename image"); this.renderImagePreview(contentEl); this.renderFileInfo(contentEl); this.renderNameInput(contentEl); this.errorEl = contentEl.createDiv({ cls: "image-manager-error image-manager-error-hidden" }); this.renderButtons(contentEl); setTimeout(() => { if (this.nameInput) { this.nameInput.focus(); this.nameInput.select(); } }, 50); } renderImagePreview(containerEl) { const previewContainer = containerEl.createDiv({ cls: "image-manager-preview" }); const img = previewContainer.createEl("img", { attr: { src: this.app.vault.getResourcePath(this.imageFile), alt: this.imageFile.name } }); img.addClass("image-manager-preview-img"); } renderFileInfo(containerEl) { const infoContainer = containerEl.createDiv({ cls: "image-manager-info" }); const infoList = infoContainer.createEl("ul"); const originalItem = infoList.createEl("li"); originalItem.createEl("strong", { text: "Original: " }); originalItem.createEl("span", { text: this.imageFile.path }); const newItem = infoList.createEl("li"); newItem.createEl("strong", { text: "New path: " }); this.previewEl = newItem.createEl("span", { text: this.getNewPath(this.currentName) }); } renderNameInput(containerEl) { new import_obsidian3.Setting(containerEl).setName("New name").setDesc("Enter a new name for the image (without extension)").addText((text) => { this.nameInput = text.inputEl; text.setPlaceholder("Enter name").setValue(this.currentName).onChange((value) => { this.currentName = this.sanitizeName(value); this.updatePreview(); }); text.inputEl.addEventListener("keydown", (e) => { if (e.key === "Enter" && !e.isComposing) { e.preventDefault(); this.submit(); } }); }); } renderButtons(containerEl) { new import_obsidian3.Setting(containerEl).addButton((btn) => { btn.setButtonText("Rename").setCta().onClick(() => this.submit()); }).addButton((btn) => { btn.setButtonText("Skip").onClick(() => this.cancel()); }); } getNewPath(name) { var _a, _b; const folder = (_b = (_a = this.imageFile.parent) == null ? void 0 : _a.path) != null ? _b : ""; const extension = this.imageFile.extension; const fileName = `${name}.${extension}`; return folder ? `${folder}/${fileName}` : fileName; } updatePreview() { if (this.previewEl) { this.previewEl.setText(this.getNewPath(this.currentName)); } } sanitizeName(name) { return name.replace(/[\\/:*?"<>|]/g, "-").replace(/\s+/g, "-").trim(); } showError(message) { if (this.errorEl) { this.errorEl.setText(message); this.errorEl.addClass("image-manager-error-visible"); this.errorEl.removeClass("image-manager-error-hidden"); } } hideError() { if (this.errorEl) { this.errorEl.addClass("image-manager-error-hidden"); this.errorEl.removeClass("image-manager-error-visible"); } } submit() { this.hideError(); if (!this.currentName || this.currentName.trim() === "") { this.showError("Name cannot be empty"); return; } this.onSubmit({ newName: this.currentName, cancelled: false }); this.close(); } cancel() { this.onSubmit({ newName: "", cancelled: true }); this.close(); } onClose() { const { contentEl } = this; contentEl.empty(); } }; function openRenameModal(app, imageFile, suggestedName) { return new Promise((resolve) => { const modal = new RenameModal(app, imageFile, suggestedName, resolve); modal.open(); }); } // src/modals/DescriptiveImageModal.ts var import_obsidian4 = require("obsidian"); // src/utils/kebab-case.ts function toKebabCase(str) { return str.toLowerCase().replace(/[<>:"/\\|?*]/g, "").replace(/['"]/g, "").replace(/[^\w\s-]/g, "").trim().replace(/\s+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, ""); } // src/modals/DescriptiveImageModal.ts var DescriptiveImageModal = class extends import_obsidian4.Modal { constructor(app, imageFile, onSubmit, suggestedDescription) { super(app); this.description = ""; this.descriptionInput = null; this.previewEl = null; this.fileNamePreviewEl = null; this.errorEl = null; this.imageFile = imageFile; this.onSubmit = onSubmit; this.description = suggestedDescription != null ? suggestedDescription : ""; } onOpen() { const { contentEl, titleEl } = this; this.containerEl.addClass("image-manager-rename-modal"); titleEl.setText("Describe image"); this.renderImagePreview(contentEl); new import_obsidian4.Setting(contentEl).setName("Image description").setDesc("Describe this image. This will be used as display text and for the file name.").addText((text) => { this.descriptionInput = text.inputEl; text.setPlaceholder("A beautiful sunset over mountains").setValue(this.description).onChange((value) => { this.description = value; this.updatePreview(); }); text.inputEl.addEventListener("keydown", (e) => { if (e.key === "Enter" && !e.isComposing) { e.preventDefault(); this.submit(); } }); }); const previewContainer = contentEl.createDiv({ cls: "image-manager-info" }); previewContainer.createEl("p", { text: "Preview:" }); const fileNamePreview = previewContainer.createEl("p"); fileNamePreview.createEl("strong", { text: "Filename: " }); this.fileNamePreviewEl = fileNamePreview.createEl("span"); const linkPreview = previewContainer.createEl("p"); linkPreview.createEl("strong", { text: "Link: " }); this.previewEl = linkPreview.createEl("span", { cls: "code" }); this.errorEl = contentEl.createDiv({ cls: "image-manager-error image-manager-error-hidden" }); new import_obsidian4.Setting(contentEl).addButton((btn) => { btn.setButtonText("Insert").setCta().onClick(() => this.submit()); }).addButton((btn) => { btn.setButtonText("Cancel").onClick(() => this.cancel()); }); if (this.description) { this.updatePreview(); } setTimeout(() => { if (this.descriptionInput) { this.descriptionInput.focus(); } }, 50); } renderImagePreview(containerEl) { const previewContainer = containerEl.createDiv({ cls: "image-manager-preview" }); const img = previewContainer.createEl("img", { attr: { src: this.app.vault.getResourcePath(this.imageFile), alt: this.imageFile.name } }); img.addClass("image-manager-preview-img"); } updatePreview() { if (!this.description || this.description.trim() === "") { if (this.fileNamePreviewEl) { this.fileNamePreviewEl.setText("(enter description)"); } if (this.previewEl) { this.previewEl.setText("(enter description)"); } return; } const kebabName = toKebabCase(this.description); const extension = this.imageFile.extension; const fileName = `${kebabName}.${extension}`; const displayText = this.description.trim(); if (this.fileNamePreviewEl) { this.fileNamePreviewEl.setText(fileName); } if (this.previewEl) { this.previewEl.setText(`![[${fileName}|${displayText}]]`); } } showError(message) { if (this.errorEl) { this.errorEl.setText(message); this.errorEl.addClass("image-manager-error-visible"); this.errorEl.removeClass("image-manager-error-hidden"); } } hideError() { if (this.errorEl) { this.errorEl.addClass("image-manager-error-hidden"); this.errorEl.removeClass("image-manager-error-visible"); } } submit() { this.hideError(); if (!this.description || this.description.trim() === "") { this.showError("Description cannot be empty"); return; } const kebabName = toKebabCase(this.description); if (!kebabName || kebabName === "") { this.showError("Description must contain valid characters"); return; } this.onSubmit({ description: this.description.trim(), fileName: kebabName, cancelled: false }); this.close(); } cancel() { this.onSubmit({ description: "", fileName: "", cancelled: true }); this.close(); } onClose() { const { contentEl } = this; contentEl.empty(); } }; function openDescriptiveImageModal(app, imageFile, suggestedDescription) { return new Promise((resolve) => { const modal = new DescriptiveImageModal(app, imageFile, resolve, suggestedDescription); modal.open(); }); } // src/services/ImageProcessor.ts var ImageProcessor = class { constructor(app, settings, storageManager, observable) { this.app = app; this.settings = settings; this.storageManager = storageManager; observable == null ? void 0 : observable.subscribe((newSettings) => { this.updateSettings(newSettings); }); } /** * Update settings reference */ updateSettings(settings) { this.settings = settings; this.storageManager.updateSettings(settings); } /** * Process a pasted/dropped image file * This is called from our event handlers (user-initiated action) * @param isPropertyInsertion - If true, skip descriptive images (only applies to note body) */ async processImageFile(file, activeFile, showRenameModal = true, isPropertyInsertion = false) { try { const arrayBuffer = await file.arrayBuffer(); const extension = this.getExtension(file); const suggestedName = this.generateNameWithSuffix(activeFile); let finalName = suggestedName; if (showRenameModal && !this.settings.autoRename) { const tempPath = await this.storageManager.getAvailablePath( `temp-${Date.now()}`, extension, activeFile ); const tempFile = await this.storageManager.saveFile(arrayBuffer, tempPath); let finalName2; let displayText; if (this.settings.enableDescriptiveImages) { const descResult = await openDescriptiveImageModal(this.app, tempFile, suggestedName); if (descResult.cancelled) { await this.app.fileManager.trashFile(tempFile); return { file: null, path: "", linkText: "", success: false, error: "Cancelled by user" }; } finalName2 = descResult.fileName; displayText = descResult.description; } else { const result = await openRenameModal(this.app, tempFile, suggestedName); if (result.cancelled) { await this.app.fileManager.trashFile(tempFile); return { file: null, path: "", linkText: "", success: false, error: "Cancelled by user" }; } finalName2 = result.newName; } const finalPath = await this.getDeduplicatedPath(finalName2, extension, activeFile); await this.app.fileManager.renameFile(tempFile, finalPath); const abstractFile = this.app.vault.getAbstractFileByPath(finalPath); if (!(abstractFile instanceof import_obsidian5.TFile)) { throw new Error("Renamed file not found"); } const renamedFile = abstractFile; const linkText = this.storageManager.generateMarkdownLink( renamedFile, activeFile.path, displayText, this.settings.insertSize ); if (!this.settings.disableRenameNotice) { new import_obsidian5.Notice(`Image saved as: ${renamedFile.name}`); } return { file: renamedFile, path: finalPath, linkText, description: displayText, success: true }; } else { const finalPath = await this.getDeduplicatedPath(finalName, extension, activeFile); const savedFile = await this.storageManager.saveFile(arrayBuffer, finalPath); const linkText = this.storageManager.generateMarkdownLink( savedFile, activeFile.path, void 0, this.settings.insertSize ); if (!this.settings.disableRenameNotice) { new import_obsidian5.Notice(`Image saved as: ${savedFile.name}`); } return { file: savedFile, path: finalPath, linkText, description: void 0, success: true }; } } catch (error) { console.error("Error processing image:", error); return { file: null, path: "", linkText: "", success: false, error: error instanceof Error ? error.message : String(error) }; } } /** * Process an image from a URL (download and save locally) * @param isPropertyInsertion - If true, skip descriptive images (only applies to note body) * @param suggestedNameOverride - Optional override for suggested name (e.g., from search term) */ async processImageUrl(url, activeFile, showRenameModal = true, isPropertyInsertion = false, suggestedNameOverride) { var _a; try { const response = await (0, import_obsidian5.requestUrl)({ url }); if (response.status >= 400) { throw new Error(`Failed to download image: ${response.status}`); } const arrayBuffer = response.arrayBuffer; const contentType = (_a = response.headers["content-type"]) != null ? _a : "image/png"; const extension = this.storageManager.getExtensionFromMimeType(contentType); const suggestedName = this.generateNameWithSuffix(activeFile, suggestedNameOverride); let finalName = suggestedName; if (showRenameModal && !this.settings.autoRename) { const tempPath = await this.storageManager.getAvailablePath( `temp-${Date.now()}`, extension, activeFile ); const tempFile = await this.storageManager.saveFile(arrayBuffer, tempPath); let finalName2; let displayText; const shouldShowDescriptive = this.settings.enableDescriptiveImages && (!isPropertyInsertion || this.settings.altTextProperty !== ""); if (shouldShowDescriptive) { const descResult = await openDescriptiveImageModal(this.app, tempFile, suggestedName); if (descResult.cancelled) { await this.app.fileManager.trashFile(tempFile); return { file: null, path: "", linkText: "", success: false, error: "Cancelled by user" }; } finalName2 = descResult.fileName; displayText = descResult.description; } else { const result = await openRenameModal(this.app, tempFile, suggestedName); if (result.cancelled) { await this.app.fileManager.trashFile(tempFile); return { file: null, path: "", linkText: "", success: false, error: "Cancelled by user" }; } finalName2 = result.newName; } const finalPath = await this.getDeduplicatedPath(finalName2, extension, activeFile); await this.app.fileManager.renameFile(tempFile, finalPath); const abstractFile = this.app.vault.getAbstractFileByPath(finalPath); if (!(abstractFile instanceof import_obsidian5.TFile)) { throw new Error("Renamed file not found"); } const renamedFile = abstractFile; const linkText = this.storageManager.generateMarkdownLink( renamedFile, activeFile.path, displayText, this.settings.insertSize ); if (!this.settings.disableRenameNotice) { new import_obsidian5.Notice(`Image downloaded and saved as: ${renamedFile.name}`); } return { file: renamedFile, path: finalPath, linkText, description: displayText, success: true }; } else { const finalPath = await this.getDeduplicatedPath(finalName, extension, activeFile); const savedFile = await this.storageManager.saveFile(arrayBuffer, finalPath); const linkText = this.storageManager.generateMarkdownLink( savedFile, activeFile.path, void 0, this.settings.insertSize ); if (!this.settings.disableRenameNotice) { new import_obsidian5.Notice(`Image downloaded and saved as: ${savedFile.name}`); } return { file: savedFile, path: finalPath, linkText, description: isPropertyInsertion ? suggestedNameOverride : void 0, success: true }; } } catch (error) { console.error("Error processing image URL:", error); return { file: null, path: "", linkText: "", success: false, error: error instanceof Error ? error.message : String(error) }; } } /** * Generate a suggested name based on the template and optional suffix */ generateNameWithSuffix(activeFile, suffix) { const variables = buildTemplateVariables(this.app, activeFile); const rendered = renderTemplate(this.settings.imageNameTemplate, variables); const isMeaningful = isTemplateMeaningful(rendered, this.settings.dupNumberDelimiter); const base = isMeaningful ? rendered : ""; if (base && suffix) { return `${base} - ${suffix}`; } else if (base) { return `${base} - `; } else if (suffix) { return suffix; } return ""; } /** * Generate a suggested name based on the template */ generateSuggestedName(activeFile) { return this.generateNameWithSuffix(activeFile); } /** * Get a deduplicated file path */ async getDeduplicatedPath(baseName, extension, activeFile) { return await this.storageManager.getAvailablePath(baseName, extension, activeFile); } /** * Get file extension from File object */ getExtension(file) { var _a; const nameParts = file.name.split("."); if (nameParts.length > 1) { const nameExt = (_a = nameParts[nameParts.length - 1]) == null ? void 0 : _a.toLowerCase(); if (nameExt) { return nameExt; } } return this.storageManager.getExtensionFromMimeType(file.type); } /** * Insert link text at cursor position */ insertLinkAtCursor(linkText) { const view = this.app.workspace.getActiveViewOfType(import_obsidian5.MarkdownView); if (view == null ? void 0 : view.editor) { view.editor.replaceSelection(linkText); } } /** * Get the active markdown file */ getActiveFile() { var _a; const view = this.app.workspace.getActiveViewOfType(import_obsidian5.MarkdownView); return (_a = view == null ? void 0 : view.file) != null ? _a : null; } /** * Rename an existing image file with optional rename modal * Used by LocalConversionService to rename converted images */ async renameImageFile(imageFile, suggestedName, activeFile) { try { const extension = imageFile.extension; let finalName = suggestedName; let displayText = ""; if (this.settings.enableDescriptiveImages) { const descResult = await openDescriptiveImageModal(this.app, imageFile, suggestedName); if (descResult.cancelled) { return null; } displayText = descResult.description; finalName = descResult.fileName; } else if (!this.settings.autoRename) { const result = await openRenameModal( this.app, imageFile, finalName ); if (result.cancelled) { return null; } finalName = result.newName; } const finalPath = await this.getDeduplicatedPath(finalName, extension, activeFile); await this.app.fileManager.renameFile(imageFile, finalPath); const abstractFile = this.app.vault.getAbstractFileByPath(finalPath); if (!(abstractFile instanceof import_obsidian5.TFile)) { throw new Error("Renamed file not found"); } const renamedFile = abstractFile; const linkText = this.storageManager.generateMarkdownLink( renamedFile, activeFile.path, displayText, this.settings.insertSize ); return { file: renamedFile, path: finalPath, linkText, success: true }; } catch (error) { console.error("Error renaming image file:", error); return { file: null, path: "", linkText: "", success: false, error: error instanceof Error ? error.message : String(error) }; } } /** * Debug logging */ log(...args) { if (this.settings.debugMode) { console.debug("[Image Manager]", ...args); } } }; // src/services/PropertyHandler.ts var import_obsidian7 = require("obsidian"); // src/utils/mdx-frontmatter.ts var import_obsidian6 = require("obsidian"); function isMdxFile(file) { return file.extension === "mdx"; } function isMarkdownFile(file) { return file.extension === "md" || file.extension === "mdx"; } function parseMdxFrontmatter(content) { var _a; const frontmatterRegex = /^---\r?\n([\s\S]*?)\r?\n---\r?\n/; const match = content.match(frontmatterRegex); if (!match) { return { frontmatter: {}, body: content }; } const frontmatterText = (_a = match[1]) != null ? _a : ""; const bodyContent = content.slice(match[0].length); try { const parsed = (0, import_obsidian6.parseYaml)(frontmatterText); const frontmatter = parsed && typeof parsed === "object" ? parsed : {}; return { frontmatter, body: bodyContent }; } catch (e) { console.error("Error parsing MDX properties:", e); return { frontmatter: {}, body: bodyContent }; } } async function readMdxFrontmatter(app, file) { if (!isMdxFile(file)) { return null; } try { const content = await app.vault.read(file); const parsed = parseMdxFrontmatter(content); return parsed ? parsed.frontmatter : null; } catch (e) { console.error(`Error reading MDX properties from ${file.path}:`, e); return null; } } async function processMdxFrontMatter(app, file, callback) { if (!isMdxFile(file)) { throw new Error(`File ${file.path} is not an MDX file`); } try { const content = await app.vault.read(file); const parsed = parseMdxFrontmatter(content); if (!parsed) { throw new Error("Failed to parse existing frontmatter"); } const frontmatter = { ...parsed.frontmatter }; callback(frontmatter); const newFrontmatterText = (0, import_obsidian6.stringifyYaml)(frontmatter).trim(); const newContent = `--- ${newFrontmatterText} --- ${parsed.body}`; await app.vault.modify(file, newContent); } catch (e) { console.error(`Error processing MDX properties for ${file.path}:`, e); throw e; } } async function getFrontmatter(app, file) { var _a; if (isMdxFile(file)) { return await readMdxFrontmatter(app, file); } const cache = app.metadataCache.getFileCache(file); return (_a = cache == null ? void 0 : cache.frontmatter) != null ? _a : null; } // src/services/PropertyHandler.ts var PropertyHandler = class { constructor(app, settings, storageManager, imageProcessor, remoteService, observable) { this.app = app; this.settings = settings; this.storageManager = storageManager; this.imageProcessor = imageProcessor; this.remoteService = remoteService; observable == null ? void 0 : observable.subscribe((newSettings) => { this.updateSettings(newSettings); }); } /** * Update settings reference */ updateSettings(settings) { var _a; this.settings = settings; (_a = this.imageProcessor) == null ? void 0 : _a.updateSettings(settings); } /** * Set an image property value in frontmatter */ async setPropertyValue(noteFile, propertyName, imageFile, altText) { const linkValue = this.formatPropertyLink(imageFile, noteFile); try { if (isMdxFile(noteFile)) { await this.setMdxProperty(noteFile, propertyName, linkValue, altText); } else { await this.setMdProperty(noteFile, propertyName, linkValue, altText); } new import_obsidian7.Notice(`Image added to property: ${propertyName}`); } catch (error) { console.error("Failed to update property:", error); new import_obsidian7.Notice(`Failed to update property: ${error instanceof Error ? error.message : String(error)}`); throw error; } } /** * Set property in MD file using Obsidian's API */ async setMdProperty(file, propertyName, value, altText) { await this.app.fileManager.processFrontMatter(file, (frontmatter) => { frontmatter[propertyName] = value; if (altText && this.settings.altTextProperty) { frontmatter[this.settings.altTextProperty] = altText; } }); } /** * Set property in MDX file using custom handler */ async setMdxProperty(file, propertyName, value, altText) { await processMdxFrontMatter(this.app, file, (frontmatter) => { frontmatter[propertyName] = value; if (altText && this.settings.altTextProperty) { frontmatter[this.settings.altTextProperty] = altText; } }); } /** * Format the image link according to settings * Public method so PasteHandler can get the formatted value for UI updates */ formatPropertyLink(imageFile, noteFile) { if (this.settings.propertyLinkFormat === "obsidian" /* ObsidianDefault */) { const generatedLink = this.app.fileManager.generateMarkdownLink(imageFile, noteFile.path); if (generatedLink.startsWith("![") && generatedLink.includes("]]")) { return generatedLink.substring(1); } else if (generatedLink.startsWith("![") && generatedLink.includes("](")) { const match = generatedLink.match(/!\[.*?\]\((.*?)\)/); return match && match[1] ? match[1] : generatedLink; } else if (generatedLink.startsWith("[[") && generatedLink.endsWith("]]")) { return generatedLink; } else if (generatedLink.includes("](")) { const match = generatedLink.match(/\[.*?\]\((.*?)\)/); return match && match[1] ? match[1] : generatedLink; } return generatedLink; } let pathToUse; switch (this.settings.propertyLinkFormat) { case "relative" /* RelativePath */: pathToUse = `./${imageFile.name}`; break; case "custom" /* Custom */: pathToUse = imageFile.name; break; case "path" /* Path */: default: pathToUse = this.getRelativePath(noteFile, imageFile); break; } switch (this.settings.propertyLinkFormat) { case "wikilink" /* Wikilink */: return `[[${pathToUse}]]`; case "markdown" /* Markdown */: return `![](${encodeURI(pathToUse)})`; case "custom" /* Custom */: return this.settings.customPropertyLinkFormat.replace( /\{image-url\}/gi, pathToUse ); case "relative" /* RelativePath */: case "path" /* Path */: default: return pathToUse; } } /** * Get relative path from note to image */ getRelativePath(fromFile, toFile) { var _a; const vaultConfig = this.app.vault.config; const useMarkdownLinks = (_a = vaultConfig == null ? void 0 : vaultConfig.useMarkdownLinks) != null ? _a : false; const useWikilinks = !useMarkdownLinks; if (useWikilinks && this.settings.propertyLinkFormat === "wikilink" /* Wikilink */) { return toFile.name; } return this.storageManager.getRelativePath(fromFile, toFile); } /** * Get the current value of a property */ getPropertyValue(file, propertyName) { var _a; const cache = this.app.metadataCache.getFileCache(file); return (_a = cache == null ? void 0 : cache.frontmatter) == null ? void 0 : _a[propertyName]; } /** * Check if a property exists in frontmatter */ hasProperty(file, propertyName) { var _a; const cache = this.app.metadataCache.getFileCache(file); return ((_a = cache == null ? void 0 : cache.frontmatter) == null ? void 0 : _a[propertyName]) !== void 0; } /** * Insert an image from a URL into a property * Downloads the image, saves it locally, and sets the property * @param remoteImage Optional RemoteImage object for generating referral text * @param suggestedNameOverride Optional override for suggested name (e.g., from search term) */ async insertImageFromUrl(imageUrl, noteFile, propertyName, remoteImage, suggestedNameOverride) { const result = await this.imageProcessor.processImageUrl( imageUrl, noteFile, true, // Show rename modal if enabled true, // isPropertyInsertion - skip descriptive images suggestedNameOverride // Pass search term as suggested name ); if (!result.success || !result.file) { throw new Error(result.error || "Failed to process image"); } await this.setPropertyValue(noteFile, propertyName, result.file, result.description); if (this.settings.appendReferral && remoteImage && this.remoteService) { const referralText = this.remoteService.generateReferralText(remoteImage); if (referralText) { const content = await this.app.vault.read(noteFile); const updatedContent = content + referralText; await this.app.vault.modify(noteFile, updatedContent); } } } }; // src/services/PasteHandler.ts var import_obsidian8 = require("obsidian"); var PasteHandler = class { constructor(app, settings, imageProcessor, propertyHandler, observable) { this.app = app; this.settings = settings; this.imageProcessor = imageProcessor; this.propertyHandler = propertyHandler; observable == null ? void 0 : observable.subscribe((newSettings) => { this.updateSettings(newSettings); }); } /** * Update settings reference */ updateSettings(settings) { this.settings = settings; } /** * Handle editor paste event * This is registered via workspace.on('editor-paste') */ async handleEditorPaste(evt, editor, view) { var _a; if (!this.settings.showRenameDialog || !this.settings.enableRenameOnPaste) { return false; } const activeEl = document.activeElement; if (activeEl && this.isFrontmatterField(activeEl)) { return false; } const files = (_a = evt.clipboardData) == null ? void 0 : _a.files; if (!files || files.length === 0) { return false; } const imageFiles = []; for (let i = 0; i < files.length; i++) { const file = files.item(i); if (file && file.type.startsWith("image/")) { imageFiles.push(file); } } if (imageFiles.length === 0) { return false; } evt.preventDefault(); const activeFile = view.file; if (!activeFile) { new import_obsidian8.Notice("No active file"); return true; } for (let i = 0; i < imageFiles.length; i++) { const imageFile = imageFiles[i]; if (!imageFile) continue; const result = await this.imageProcessor.processImageFile( imageFile, activeFile, true // Show rename modal ); if (result.success && result.linkText) { editor.replaceSelection(result.linkText); } } return true; } /** * Handle paste into frontmatter property * This is registered via document paste event with property detection */ async handlePropertyPaste(evt) { var _a; if (!this.settings.showRenameDialog || !this.settings.enablePropertyPaste) { return false; } const activeEl = document.activeElement; if (!activeEl) { return false; } if (!this.isFrontmatterField(activeEl)) { return false; } if (this.settings.debugMode) { console.debug("[Image Manager] Property paste detected", { activeElement: activeEl.tagName, classes: activeEl.className, propertyName: this.getPropertyName(activeEl) }); } const files = (_a = evt.clipboardData) == null ? void 0 : _a.files; if (!files || files.length === 0) { return false; } let imageFile = null; for (let i = 0; i < files.length; i++) { const f = files.item(i); if (f && f.type.startsWith("image/")) { imageFile = f; break; } } if (!imageFile) { return false; } const currentEl = document.activeElement; if (!currentEl || !this.isFrontmatterField(currentEl)) { return false; } const activeFile = this.app.workspace.getActiveFile(); if (!activeFile) { return false; } evt.preventDefault(); evt.stopPropagation(); evt.stopImmediatePropagation(); const propertyName = this.getPropertyName(currentEl); if (!propertyName) { new import_obsidian8.Notice("Could not determine property name"); return true; } const result = await this.imageProcessor.processImageFile( imageFile, activeFile, true, // Show rename modal for property paste true // isPropertyInsertion - skip descriptive images ); if (result.success && result.file) { const linkValue = this.propertyHandler.formatPropertyLink(result.file, activeFile); await this.propertyHandler.setPropertyValue( activeFile, propertyName, result.file, result.description ); await new Promise((resolve) => setTimeout(resolve, 300)); const propertyEl = document.querySelector( `.metadata-property[data-property-key="${propertyName}"]` ); if (this.settings.debugMode) { console.debug("[Image Manager] Updating property UI", { propertyName, linkValue, propertyElFound: !!propertyEl }); } const inputEl = propertyEl == null ? void 0 : propertyEl.querySelector( ".metadata-input-longtext, .metadata-input-text, input.metadata-input, textarea.metadata-input" ); if (inputEl) { if (this.settings.debugMode) { const currentValue = inputEl instanceof HTMLInputElement || inputEl instanceof HTMLTextAreaElement ? inputEl.value : inputEl.textContent || inputEl.innerText; console.debug("[Image Manager] Found input field, updating value", { elementType: inputEl.tagName, currentValue, newValue: linkValue }); } if (inputEl instanceof HTMLInputElement || inputEl instanceof HTMLTextAreaElement) { inputEl.value = linkValue; } else { inputEl.textContent = linkValue; inputEl.innerText = linkValue; } const inputEvent = new Event("input", { bubbles: true, cancelable: true }); const changeEvent = new Event("change", { bubbles: true, cancelable: true }); const blurEvent = new Event("blur", { bubbles: true, cancelable: true }); inputEl.dispatchEvent(inputEvent); setTimeout(() => { inputEl.dispatchEvent(changeEvent); if (inputEl instanceof HTMLElement) { inputEl.focus(); setTimeout(() => { inputEl.blur(); inputEl.dispatchEvent(blurEvent); setTimeout(() => { const view = this.app.workspace.getActiveViewOfType(import_obsidian8.MarkdownView); if (view == null ? void 0 : view.editor) { view.editor.focus(); } }, 50); }, 50); } }, 50); } else { const view = this.app.workspace.getActiveViewOfType(import_obsidian8.MarkdownView); if (view == null ? void 0 : view.editor) { view.editor.focus(); } } } return true; } /** * Check if an element is a supported frontmatter field * Works for both MD and MDX files */ isFrontmatterField(element) { const propertyEl = element.closest(".metadata-property"); if (!propertyEl) { return false; } return element.matches(".metadata-input-longtext") || element.matches(".metadata-input-text") || element.matches("input.metadata-input") || element.matches("textarea.metadata-input") || // Also check if the element itself is an input/textarea/div inside a property (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement || element instanceof HTMLDivElement && element.classList.contains("metadata-input-longtext")) && propertyEl !== null; } /** * Get the property name from a frontmatter field element */ getPropertyName(element) { var _a; const propertyEl = element.closest(".metadata-property"); return (_a = propertyEl == null ? void 0 : propertyEl.getAttribute("data-property-key")) != null ? _a : null; } }; var DropHandler = class { constructor(app, settings, imageProcessor, observable) { this.app = app; this.settings = settings; this.imageProcessor = imageProcessor; observable == null ? void 0 : observable.subscribe((newSettings) => { this.updateSettings(newSettings); }); } /** * Update settings reference */ updateSettings(settings) { this.settings = settings; } /** * Handle editor drop event */ async handleEditorDrop(evt, editor, view) { var _a; if (!this.settings.showRenameDialog || !this.settings.enableRenameOnDrop) { return false; } const files = (_a = evt.dataTransfer) == null ? void 0 : _a.files; if (!files || files.length === 0) { return false; } const imageFiles = []; for (let i = 0; i < files.length; i++) { const f = files.item(i); if (f && f.type.startsWith("image/")) { imageFiles.push(f); } } if (imageFiles.length === 0) { return false; } evt.preventDefault(); const activeFile = view.file; if (!activeFile) { new import_obsidian8.Notice("No active file"); return true; } for (let i = 0; i < imageFiles.length; i++) { const imageFile = imageFiles[i]; if (!imageFile) continue; const result = await this.imageProcessor.processImageFile( imageFile, activeFile, true ); if (result.success && result.linkText) { editor.replaceSelection(result.linkText); } } return true; } }; // src/services/RemoteImageService.ts var import_obsidian9 = require("obsidian"); var UNSPLASH_PROXY = "https://insert-unsplash-image.cloudy9101.com/"; var RemoteImageService = class { constructor(app, settings, observable) { this.app = app; this.settings = settings; observable == null ? void 0 : observable.subscribe((newSettings) => { this.updateSettings(newSettings); }); } /** * Update settings reference */ updateSettings(settings) { this.settings = settings; } /** * Search for images from the specified provider */ async search(query, provider, page = 1) { const targetProvider = provider != null ? provider : this.settings.defaultProvider; switch (targetProvider) { case "unsplash" /* Unsplash */: return await this.searchUnsplash(query, page); case "pexels" /* Pexels */: return await this.searchPexels(query, page); case "pixabay" /* Pixabay */: return await this.searchPixabay(query, page); default: throw new Error(`Unsupported provider: ${targetProvider}`); } } /** * Search Unsplash */ async searchUnsplash(query, page) { var _a; let proxyUrl = this.settings.unsplashProxyServer || UNSPLASH_PROXY; if (!proxyUrl.endsWith("/")) { proxyUrl += "/"; } const orientation = this.mapOrientation(this.settings.defaultOrientation); const url = new URL("/search/photos", proxyUrl); url.searchParams.set("query", query); url.searchParams.set("page", String(page)); url.searchParams.set("per_page", "20"); if (orientation) { url.searchParams.set("orientation", orientation); } const response = await (0, import_obsidian9.requestUrl)({ url: url.toString() }); if (response.status >= 400) { console.error("Unsplash API error:", response.status, response.text); throw new Error(`Unsplash search failed: ${response.status} - ${response.text}`); } const data = response.json; if (!data || !data.results) { console.error("Invalid Unsplash response:", data); throw new Error("Invalid response from Unsplash API"); } const results = (_a = data.results) != null ? _a : []; return results.map((photo) => this.mapUnsplashPhoto(photo)); } /** * Get Pexels API key from SecretStorage or fall back to plaintext */ getPexelsApiKey() { if ((0, import_obsidian9.requireApiVersion)("1.11.4") && this.settings.pexelsApiKeySecretId) { const secretStorage = this.app.secretStorage; if (secretStorage) { const secret = secretStorage.getSecret(this.settings.pexelsApiKeySecretId); if (secret) { return secret; } } } return this.settings.pexelsApiKey || null; } /** * Get Pixabay API key from SecretStorage or fall back to plaintext */ getPixabayApiKey() { if ((0, import_obsidian9.requireApiVersion)("1.11.4") && this.settings.pixabayApiKeySecretId) { const secretStorage = this.app.secretStorage; if (secretStorage) { const secret = secretStorage.getSecret(this.settings.pixabayApiKeySecretId); if (secret) { return secret; } } } return this.settings.pixabayApiKey || null; } /** * Search Pexels */ async searchPexels(query, page) { var _a; const apiKey = this.getPexelsApiKey(); if (!apiKey) { const errorMsg = (0, import_obsidian9.requireApiVersion)("1.11.4") ? "Pexels API key is required. Please configure it in settings (use SecretStorage on Obsidian 1.11.4+ or enter plaintext on older versions)." : "Pexels API key is required. Please configure it in settings."; throw new Error(errorMsg); } const orientation = this.mapOrientation(this.settings.defaultOrientation); const params = new URLSearchParams({ query, page: String(page), per_page: "20" }); if (orientation) { params.set("orientation", orientation); } const url = `https://api.pexels.com/v1/search?${params.toString()}`; const response = await (0, import_obsidian9.requestUrl)({ url, headers: { Authorization: apiKey } }); if (response.status >= 400) { throw new Error(`Pexels search failed: ${response.status}`); } const data = response.json; const photos = (_a = data.photos) != null ? _a : []; return photos.map((photo) => this.mapPexelsPhoto(photo)); } /** * Search Pixabay */ async searchPixabay(query, page) { var _a; const apiKey = this.getPixabayApiKey(); if (!apiKey) { const errorMsg = (0, import_obsidian9.requireApiVersion)("1.11.4") ? "Pixabay API key is required. Please configure it in settings (use SecretStorage on Obsidian 1.11.4+ or enter plaintext on older versions)." : "Pixabay API key is required. Please configure it in settings."; throw new Error(errorMsg); } const orientation = this.mapPixabayOrientation(this.settings.defaultOrientation); const params = new URLSearchParams({ key: apiKey, q: query, page: String(page), per_page: "20", image_type: "photo" }); if (orientation) { params.set("orientation", orientation); } const url = `https://pixabay.com/api/?${params.toString()}`; const response = await (0, import_obsidian9.requestUrl)({ url }); if (response.status >= 400) { throw new Error(`Pixabay search failed: ${response.status}`); } const data = response.json; const hits = (_a = data.hits) != null ? _a : []; return hits.map((hit) => this.mapPixabayHit(hit)); } /** * Get the download URL for an image based on size preference */ getDownloadUrl(image, size) { const targetSize = size != null ? size : this.settings.defaultImageSize; switch (targetSize) { case "original" /* Original */: return image.fullUrl; case "large" /* Large */: return image.regularUrl; case "medium" /* Medium */: return image.regularUrl; case "small" /* Small */: return image.thumbnailUrl; default: return image.regularUrl; } } /** * Download an image and return the binary data */ async downloadImage(image) { const url = this.getDownloadUrl(image); const response = await (0, import_obsidian9.requestUrl)({ url }); if (response.status >= 400) { throw new Error(`Failed to download image: ${response.status}`); } return response.arrayBuffer; } /** * Generate referral text for an image (attribution) */ generateReferralText(image) { if (!this.settings.insertReferral) { return ""; } const backlink = this.settings.insertBackLink && image.pageUrl ? `[Backlink](${image.pageUrl}) | ` : ""; let referral = ""; switch (image.provider) { case "unsplash" /* Unsplash */: if (image.author && image.authorUrl) { const utm = "utm_source=Obsidian%20Image%20Manager&utm_medium=referral"; referral = ` *${backlink}Photo by [${image.author}](${image.authorUrl}) on [Unsplash](https://unsplash.com/?${utm})* `; } break; case "pexels" /* Pexels */: if (image.author && image.authorUrl) { referral = ` *${backlink}Photo by [${image.author}](${image.authorUrl}) on [Pexels](https://www.pexels.com/)* `; } break; case "pixabay" /* Pixabay */: if (image.author && image.authorUrl) { referral = ` *${backlink}Image by [${image.author}](${image.authorUrl}) on [Pixabay](https://pixabay.com/)* `; } break; } return referral; } /** * Map orientation setting to API parameter */ mapOrientation(orientation) { switch (orientation) { case "landscape" /* Landscape */: return "landscape"; case "portrait" /* Portrait */: return "portrait"; case "square" /* Square */: return "squarish"; default: return null; } } /** * Map orientation for Pixabay (different values) */ mapPixabayOrientation(orientation) { switch (orientation) { case "landscape" /* Landscape */: return "horizontal"; case "portrait" /* Portrait */: return "vertical"; default: return null; } } /** * Map Unsplash photo to RemoteImage */ mapUnsplashPhoto(photo) { var _a, _b; return { id: photo.id, provider: "unsplash" /* Unsplash */, thumbnailUrl: photo.urls.thumb, regularUrl: photo.urls.regular, fullUrl: photo.urls.full, downloadUrl: photo.links.download_location || photo.links.download, width: photo.width, height: photo.height, description: (_b = (_a = photo.description) != null ? _a : photo.alt_description) != null ? _b : "", author: photo.user.name, authorUrl: photo.user.links.html, pageUrl: photo.links.html }; } /** * Map Pexels photo to RemoteImage */ mapPexelsPhoto(photo) { var _a; return { id: String(photo.id), provider: "pexels" /* Pexels */, thumbnailUrl: photo.src.tiny, regularUrl: photo.src.large, fullUrl: photo.src.original, downloadUrl: photo.src.original, width: photo.width, height: photo.height, description: (_a = photo.alt) != null ? _a : "", author: photo.photographer, authorUrl: photo.photographer_url, pageUrl: photo.url }; } /** * Map Pixabay hit to RemoteImage */ mapPixabayHit(hit) { return { id: String(hit.id), provider: "pixabay" /* Pixabay */, thumbnailUrl: hit.previewURL, regularUrl: hit.webformatURL, fullUrl: hit.largeImageURL, downloadUrl: hit.largeImageURL, width: hit.imageWidth, height: hit.imageHeight, description: hit.tags, author: hit.user, authorUrl: `https://pixabay.com/users/${hit.user}-${hit.user_id}/`, pageUrl: hit.pageURL }; } }; // src/services/LocalConversionService.ts var import_obsidian10 = require("obsidian"); var MARKDOWN_IMAGE_REGEX = /!\[([^\]]*)\]\((https?:\/\/[^\s)]+)\)/g; var HTML_IMAGE_REGEX = /]+src=["'](https?:\/\/[^"']+)["'][^>]*>/g; var LocalConversionService = class { constructor(app, settings, storageManager, imageProcessor, observable) { this.app = app; this.settings = settings; this.storageManager = storageManager; this.imageProcessor = imageProcessor; observable == null ? void 0 : observable.subscribe((newSettings) => { this.updateSettings(newSettings); }); } /** * Update settings reference */ updateSettings(settings) { var _a; this.settings = settings; (_a = this.imageProcessor) == null ? void 0 : _a.updateSettings(settings); } /** * Process a file to convert all remote images to local * @param file - The file to process * @param isBackground - If true, skip conversion if user interaction (modal) would be required */ async processFile(file, isBackground = false) { if (!isMarkdownFile(file)) { return 0; } const content = await this.app.vault.read(file); const { newContent, count } = await this.processContent(content, file, isBackground); if (count > 0) { await this.app.vault.modify(file, newContent); } return count; } /** * Process content and replace remote images with local */ async processContent(content, sourceFile, isBackground = false) { let newContent = content; let count = 0; const externalImages = await this.findExternalImages(content, sourceFile); for (const image of externalImages) { try { if (isBackground && !this.settings.autoRename) { continue; } const tempPath = await this.downloadAndSave(image.url, sourceFile); if (!tempPath) { continue; } const tempFile = this.app.vault.getAbstractFileByPath(tempPath); if (!(tempFile instanceof import_obsidian10.TFile)) { continue; } let finalFile = tempFile; const suggestedName = image.alt ? this.storageManager.sanitizeFileName(image.alt) : tempFile.basename; const result = await this.imageProcessor.renameImageFile( tempFile, suggestedName, sourceFile ); if (result && result.file) { finalFile = result.file; } else { await this.app.fileManager.trashFile(tempFile); continue; } newContent = newContent.replace(image.fullMatch, image.replacement(finalFile.path)); count++; } catch (error) { console.error(`Failed to convert image: ${image.url}`, error); } } return { newContent, count }; } /** * Check if a position in content is inside a code block */ isInsideCodeBlock(content, position) { const fencedCodeBlockRegex = /```[\s\S]*?```/g; let match; while ((match = fencedCodeBlockRegex.exec(content)) !== null) { const start = match.index; const end = start + match[0].length; if (position >= start && position < end) { return true; } } const fencedPositions = Array.from({ length: content.length }, () => false); const fencedRegex = /```[\s\S]*?```/g; while ((match = fencedRegex.exec(content)) !== null) { for (let i = match.index; i < match.index + match[0].length; i++) { fencedPositions[i] = true; } } const inlineCodeRegex = /`[^`\n]+`/g; while ((match = inlineCodeRegex.exec(content)) !== null) { if (fencedPositions[match.index]) { continue; } const start = match.index; const end = start + match[0].length; if (position >= start && position < end) { return true; } } return false; } /** * Find all external images in content * Verifies each URL with HEAD request to ensure it actually serves an image */ async findExternalImages(content, sourceFile) { var _a; const candidateMatches = []; let match; const mdRegex = new RegExp(MARKDOWN_IMAGE_REGEX.source, "g"); while ((match = mdRegex.exec(content)) !== null) { const matchIndex = match.index; if (this.isInsideCodeBlock(content, matchIndex)) { continue; } const fullMatch = match[0]; const alt = (_a = match[1]) != null ? _a : ""; const url = match[2]; if (url && this.isExternalUrl(url) && this.isImageUrl(url)) { const sourceFileRef = sourceFile; candidateMatches.push({ fullMatch, url, alt, replacement: (localPath) => { const savedFile = this.app.vault.getAbstractFileByPath(localPath); if (savedFile instanceof import_obsidian10.TFile) { const link = this.storageManager.generateMarkdownLink(savedFile, sourceFileRef.path); if (alt && link.startsWith("![") && link.includes("]]")) { return link.replace("]]", `|${alt}]]`); } if (link.startsWith("![") && link.includes("](")) { const pathMatch = link.match(/\]\(([^)]+)\)/); if (pathMatch) { return `![${alt}](${pathMatch[1]})`; } return `![${alt}](${encodeURI(localPath)})`; } return link; } const localFile = this.app.vault.getAbstractFileByPath(localPath); if (localFile instanceof import_obsidian10.TFile) { const relativePath = this.storageManager.getRelativePath(sourceFileRef, localFile); return `![${alt}](${encodeURI(relativePath)})`; } return `![${alt}](${encodeURI(localPath)})`; } }); } } const htmlRegex = new RegExp(HTML_IMAGE_REGEX.source, "g"); while ((match = htmlRegex.exec(content)) !== null) { const matchIndex = match.index; if (this.isInsideCodeBlock(content, matchIndex)) { continue; } const fullMatch = match[0]; const url = match[1]; if (url && this.isExternalUrl(url) && this.isImageUrl(url)) { candidateMatches.push({ fullMatch, url, replacement: (localPath) => `![](${encodeURI(localPath)})` }); } } const verifiedMatches = []; for (const candidate of candidateMatches) { const isImage = await this.verifyImageUrl(candidate.url); if (isImage) { verifiedMatches.push(candidate); } } return verifiedMatches; } /** * Check if a URL is external */ isExternalUrl(url) { try { const parsed = new URL(url); return ["http:", "https:"].includes(parsed.protocol); } catch (e) { return false; } } /** * Check if a URL should be considered for image conversion * Returns false for known non-image embed domains (YouTube, etc.) * This is a preliminary filter - actual image verification happens via HEAD request */ isImageUrl(url) { try { const parsed = new URL(url); const hostname = parsed.hostname.toLowerCase(); const nonImageDomains = [ "youtube.com", "www.youtube.com", "youtu.be", "m.youtube.com", "youtube-nocookie.com", "www.youtube-nocookie.com", "vimeo.com", "www.vimeo.com", "spotify.com", "open.spotify.com", "soundcloud.com", "www.soundcloud.com" ]; if (nonImageDomains.some((domain) => hostname === domain || hostname.endsWith("." + domain))) { return false; } return true; } catch (e) { return false; } } /** * Verify if a URL actually serves an image by checking Content-Type header * Uses HEAD request to avoid downloading non-image content */ async verifyImageUrl(url) { var _a, _b; try { const response = await (0, import_obsidian10.requestUrl)({ url, method: "HEAD" }); const contentType = (_b = (_a = response.headers["content-type"]) == null ? void 0 : _a.toLowerCase()) != null ? _b : ""; return contentType.startsWith("image/"); } catch (e) { return false; } } /** * Download an image and save it locally * Includes Content-Type validation as a safety net */ async downloadAndSave(url, sourceFile) { var _a, _b, _c; try { const response = await (0, import_obsidian10.requestUrl)({ url }); if (response.status >= 400) { throw new Error(`HTTP ${response.status}`); } const contentType = (_a = response.headers["content-type"]) != null ? _a : ""; if (!contentType.toLowerCase().startsWith("image/")) { console.warn(`Skipping ${url}: Content-Type is ${contentType}, not an image`); return null; } const extension = this.storageManager.getExtensionFromMimeType(contentType); const arrayBuffer = response.arrayBuffer; const urlPath = new URL(url).pathname; const urlFileName = (_c = (_b = urlPath.split("/").pop()) == null ? void 0 : _b.split(".")[0]) != null ? _c : "image"; const baseName = this.storageManager.sanitizeFileName(urlFileName); const filePath = await this.storageManager.getAvailablePath(baseName, extension, sourceFile); await this.storageManager.saveFile(arrayBuffer, filePath); return filePath; } catch (error) { console.error(`Failed to download ${url}:`, error); return null; } } /** * Process all files in the vault */ async processAllFiles() { const files = this.app.vault.getMarkdownFiles(); let totalCount = 0; for (const file of files) { if (this.settings.supportedExtensions.includes(file.extension)) { const count = await this.processFile(file); totalCount += count; } } return totalCount; } /** * Register event handlers for automatic conversion */ registerEventHandlers(onNoteOpen, onNoteSave) { } }; // src/services/BannerService.ts var import_obsidian11 = require("obsidian"); var ObsidianModule = __toESM(require("obsidian"), 1); function setCssProperties(element, props) { const obsidian = ObsidianModule; if (typeof obsidian.setCssProperties === "function") { obsidian.setCssProperties(element, props); } else { for (const [key, value] of Object.entries(props)) { element.style.setProperty(key, value); } } } var CSS_CLASSES = { Main: "image-manager-banner", Content: "banner-content", Icon: "banner-icon", Static: "static" }; var PATTERNS = { Wikilink: /^!?\[\[([^\]]+?)(\|([^\]]+?))?\]\]$/, Markdown: /^!?\[([^\]]*)\]\(([^)]+?)\)$/, MarkdownBare: /^!?<([^>]+)>$/, Weblink: /^https?:\/\//i }; var bannerDataStore = /* @__PURE__ */ new Map(); var BannerService = class { constructor(app, settings, observable) { this.app = app; this.settings = settings; observable == null ? void 0 : observable.subscribe((newSettings) => { this.updateSettings(newSettings); this.applySettings(); }); } /** * Update settings reference */ updateSettings(settings) { this.settings = settings; } /** * Get the current device type */ getCurrentDevice() { if (import_obsidian11.Platform.isPhone) { return "phone" /* Phone */; } if (import_obsidian11.Platform.isTablet) { return "tablet" /* Tablet */; } return "desktop" /* Desktop */; } /** * Get device-specific settings */ getDeviceSettings() { const device = this.getCurrentDevice(); return this.settings.banner[device]; } /** * Process all open markdown views */ processAll(force = false) { const deviceSettings = this.getDeviceSettings(); this.app.workspace.iterateRootLeaves((leaf) => { const view = leaf.view; if (view instanceof import_obsidian11.MarkdownView) { if (deviceSettings.enabled) { const file = (view == null ? void 0 : view.file) || null; void this.process(file, view, force); } else { this.remove(view); } } }); } /** * Process a single file/view */ async process(file, view, force = false) { const data = await this.compute(file, view); if (!data) { return; } if (force) { data.needsUpdate = true; } if (!data.image) { this.remove(view, data); return; } if (!data.icon) { data.needsUpdate = true; } const deviceSettings = this.getDeviceSettings(); if (deviceSettings.enabled) { await this.render(data, view, force); } } /** * Compute banner data from frontmatter */ async compute(file, targetView) { var _a; const view = targetView || this.getActiveView(); if (!file || !(view instanceof import_obsidian11.MarkdownView)) { return null; } const deviceSettings = this.getDeviceSettings(); if (!deviceSettings.enabled) { return null; } if (!this.settings.supportedExtensions.includes(file.extension) && file.extension !== "md") { return null; } const leafId = (_a = view == null ? void 0 : view.leaf) == null ? void 0 : _a.id; if (!leafId) { return null; } const oldData = bannerDataStore.get(leafId) || this.createDefaultBannerData(); const newData = this.createDefaultBannerData(view, oldData.viewMode); if (file.extension === "md") { const cache = this.app.metadataCache.getFileCache(file); if ((cache == null ? void 0 : cache.frontmatter) != null) { const propertySettings2 = this.settings.banner.properties; const imageProp2 = propertySettings2.imageProperty; const iconProp2 = propertySettings2.iconProperty; if (propertySettings2.hidePropertyEnabled && propertySettings2.hideProperty) { const hideProp = propertySettings2.hideProperty; const hideValue = cache.frontmatter[hideProp]; if (hideValue === true || hideValue === "true" || hideValue === 1 || hideValue === "1") { return newData; } } const hasBannerProperty = cache.frontmatter[imageProp2] != null; const hasIconProperty = deviceSettings.iconEnabled && cache.frontmatter[iconProp2] != null; if (!hasBannerProperty && !hasIconProperty) { return newData; } } } const frontmatter = await getFrontmatter(this.app, file); if (!frontmatter) { return newData; } const propertySettings = this.settings.banner.properties; if (propertySettings.hidePropertyEnabled && propertySettings.hideProperty) { const hideProp = propertySettings.hideProperty; const hideValue = frontmatter[hideProp]; if (hideValue === true || hideValue === "true" || hideValue === 1 || hideValue === "1") { return newData; } } const imageProp = propertySettings.imageProperty; const iconProp = propertySettings.iconProperty; const imageValue = frontmatter[imageProp]; if (imageValue && typeof imageValue === "string") { newData.image = imageValue; newData.filepath = file.path; if (oldData.filepath !== newData.filepath) { newData.needsUpdate = true; newData.isImageChange = true; } else if (oldData.image !== newData.image) { newData.needsUpdate = true; newData.isImageChange = true; if (await this.isImagePropertiesUpdate(oldData.image, newData.image, view)) { newData.isImagePropsUpdate = true; newData.isImageChange = false; } } } if (deviceSettings.iconEnabled) { const iconValue = frontmatter[iconProp]; if (iconValue && typeof iconValue === "string") { newData.icon = iconValue; if (oldData.icon !== newData.icon) { newData.needsUpdate = true; } } else if (oldData.icon) { newData.icon = null; newData.needsUpdate = true; } } return newData; } /** * Render banner in the view */ async render(data, targetView, force = false) { var _a; const { image, viewMode, lastViewMode } = data; const view = targetView || this.getActiveView(); if (!view || !(view instanceof import_obsidian11.MarkdownView)) { return; } const container = view.containerEl; if (!container) { return; } const containers = container.querySelectorAll( ".cm-scroller, .markdown-reading-view > .markdown-preview-view" ); const bannerMissing = !!image && containers.length > 0 && Array.from(containers).some((c) => !c.querySelector(`.${CSS_CLASSES.Main}`)); if (bannerMissing) { data.needsUpdate = true; data.isImageChange = true; } if (!force && !data.needsUpdate && lastViewMode === viewMode && !bannerMissing) { return; } if (containers.length === 0) { return; } const imageOptions = await this.parseLink(image || "", view); const banners = this.updateBannerElements(data, imageOptions, containers); await this.updateIcons(data, banners, view); if (data.isImageChange) { this.injectBanners(banners, containers); } else { this.replaceBanners(banners); } data.lastViewMode = viewMode; container.dataset.imBanner = ""; const leafId = (_a = view == null ? void 0 : view.leaf) == null ? void 0 : _a.id; if (leafId) { bannerDataStore.set(leafId, data); } } /** * Update banner DOM elements */ updateBannerElements(data, imgOptions, containers) { const { isImageChange, isImagePropsUpdate } = data; const banners = []; containers.forEach((container) => { var _a; let element = container.querySelector(`.${CSS_CLASSES.Main}`); if (!element) { element = document.createElement("div"); element.classList.add(CSS_CLASSES.Main); } let content = element.querySelector(`.${CSS_CLASSES.Content}`); if (!content) { content = document.createElement("div"); content.classList.add(CSS_CLASSES.Content); element.appendChild(content); } banners.push(element); if (isImageChange || isImagePropsUpdate) { if (isImageChange) { element.classList.remove(CSS_CLASSES.Static); (_a = content.firstChild) == null ? void 0 : _a.remove(); } const cssVars = { "--im-banner-img-x": `${imgOptions.x}px`, "--im-banner-img-y": `${imgOptions.y}px`, "--im-banner-size": imgOptions.repeatable ? "auto" : "cover", "--im-banner-repeat": imgOptions.repeatable ? "repeat" : "no-repeat", "--im-banner-url": "none" }; if (imgOptions.type === "video" /* Video */) { const video = document.createElement("video"); video.controls = false; video.autoplay = true; video.muted = true; video.loop = true; video.src = imgOptions.url.replace(/^"|"$/g, ""); content.appendChild(video); } else { cssVars["--im-banner-url"] = `url(${imgOptions.url})`; } setCssProperties(container, cssVars); } }); return banners; } /** * Update icon elements on banners */ async updateIcons(data, banners, view) { var _a; const deviceSettings = this.getDeviceSettings(); let calculatedFontSize = null; for (const banner of banners) { const { icon } = data; let iconContainer = banner.querySelector(`.${CSS_CLASSES.Icon}`); const hasContainer = iconContainer !== null; if (hasContainer) { iconContainer == null ? void 0 : iconContainer.classList.add(CSS_CLASSES.Static); } if (deviceSettings.iconEnabled && icon) { if (!hasContainer) { iconContainer = document.createElement("div"); iconContainer.classList.add(CSS_CLASSES.Icon); const innerDiv = document.createElement("div"); iconContainer.appendChild(innerDiv); banner.prepend(iconContainer); } const iconElement = iconContainer == null ? void 0 : iconContainer.querySelector("div"); if (!iconElement) continue; const iconData = await this.parseIcon(icon, view); let value = ((_a = iconData.value) == null ? void 0 : _a.replace(/([#.:[\\]"])/g, "\\$1")) || ""; iconElement.dataset.type = iconData.type; if (iconData.type === "link" /* Link */) { setCssProperties(iconElement, { "--im-banner-icon-value": `url(${value})` }); } else { calculatedFontSize = calculatedFontSize != null ? calculatedFontSize : this.calculateFontSize(value, deviceSettings.iconSize); setCssProperties(iconElement, { "--im-banner-icon-value": `"${value}"`, "--im-banner-icon-fontsize": calculatedFontSize }); } } else if (hasContainer && iconContainer) { data.icon = null; iconContainer.remove(); } } } /** * Inject banners into containers */ injectBanners(banners, containers) { const deviceSettings = this.getDeviceSettings(); const shouldAnimate = deviceSettings.animation; containers.forEach((container, index) => { const banner = banners[index]; if (banner) { banner.classList.remove(CSS_CLASSES.Static); container.prepend(banner); if (shouldAnimate) { void banner.offsetHeight; requestAnimationFrame(() => { banner.onanimationend = () => { banner.classList.add(CSS_CLASSES.Static); }; }); } else { banner.classList.add(CSS_CLASSES.Static); } } }); } /** * Replace banners (no animation) */ replaceBanners(banners) { banners.forEach((banner) => { banner.classList.add(CSS_CLASSES.Static); }); } /** * Remove banner from view */ remove(view, data) { var _a; const targetView = view || (data == null ? void 0 : data.filepath) ? this.getActiveView() : null; if (!(targetView instanceof import_obsidian11.MarkdownView)) { return; } const container = targetView.containerEl; if (!container) { return; } const targets = container.querySelectorAll(`.${CSS_CLASSES.Main}`); targets.forEach((t) => t.remove()); const leafId = (_a = targetView == null ? void 0 : targetView.leaf) == null ? void 0 : _a.id; if (leafId) { bannerDataStore.delete(leafId); } delete container.dataset.imBanner; } /** * Apply current settings to DOM */ applySettings() { var _a; const deviceSettings = this.getDeviceSettings(); const height = deviceSettings.height; const noteOffset = deviceSettings.noteOffset; const viewOffset = deviceSettings.viewOffset; const radius = deviceSettings.bannerRadiusEnabled ? deviceSettings.borderRadius : [0, 0, 0, 0]; const padding = deviceSettings.padding; const fade = deviceSettings.fade; const cssVars = { "--im-banner-height": `${height}px`, "--im-banner-note-offset": `${noteOffset}px`, "--im-banner-view-offset": `${viewOffset}px`, "--im-banner-radius": `${radius[0]}px ${radius[1]}px ${radius[2]}px ${radius[3]}px`, "--im-banner-padding": `${padding}px`, "--im-banner-mask": fade ? "revert-layer" : "initial", "--im-banner-mask-webkit": fade ? "revert-layer" : "initial" }; if (deviceSettings.iconEnabled) { const iconFrame = (_a = deviceSettings.iconFrame) != null ? _a : true; cssVars["--im-banner-icon-size-w"] = `${deviceSettings.iconSize}px`; cssVars["--im-banner-icon-size-h"] = `${deviceSettings.iconSize}px`; cssVars["--im-banner-icon-radius"] = `${deviceSettings.iconRadius}px`; cssVars["--im-banner-icon-align-h"] = deviceSettings.iconAlignmentH; cssVars["--im-banner-icon-align-v"] = deviceSettings.iconAlignmentV; cssVars["--im-banner-icon-offset-x"] = `${deviceSettings.iconOffsetX}px`; cssVars["--im-banner-icon-offset-y"] = `${deviceSettings.iconOffsetY}px`; cssVars["--im-banner-icon-border"] = iconFrame ? `${deviceSettings.iconBorder}px` : "0px"; cssVars["--im-banner-icon-background"] = iconFrame && deviceSettings.iconBackground ? "revert-layer" : "transparent"; } setCssProperties(document.body, cssVars); this.processAll(true); } /** * Parse image link string into options */ async parseLink(str, view) { var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n; let url = null; let displayText = null; let external = false; let obsidianUrl = false; let options = { x: 0, y: 0, repeatable: false }; const wikilinkMatch = str.match(PATTERNS.Wikilink); if (wikilinkMatch) { url = (_b = (_a = wikilinkMatch[1]) == null ? void 0 : _a.trim()) != null ? _b : null; displayText = (_d = (_c = wikilinkMatch[3]) == null ? void 0 : _c.trim()) != null ? _d : null; } const markdownMatch = str.match(PATTERNS.Markdown); const markdownBareMatch = str.match(PATTERNS.MarkdownBare); if (markdownMatch) { displayText = (_f = (_e = markdownMatch[1]) == null ? void 0 : _e.trim()) != null ? _f : null; url = (_h = (_g = markdownMatch[2]) == null ? void 0 : _g.trim()) != null ? _h : null; } else if (markdownBareMatch) { url = (_j = (_i = markdownBareMatch[1]) == null ? void 0 : _i.trim()) != null ? _j : null; displayText = null; } if (!url) { url = str; displayText = null; } external = PATTERNS.Weblink.test(url); if (this.isObsidianUrl(url)) { const urlStr = url.replace("obsidian://open", ""); const params = new URLSearchParams(urlStr); const file = params.get("file"); if (file) { url = file; obsidianUrl = true; external = false; displayText = null; } } if (url.startsWith("file:")) { url = url.replace(/^file:\/{1,}/, import_obsidian11.Platform.resourcePathPrefix); external = true; } const hashIndex = url.indexOf("#"); if ((external || obsidianUrl) && hashIndex !== -1) { options = this.parseImageProperties(url.substring(hashIndex + 1)); url = url.replace(/#.*/, "").trim(); } if (displayText) { options = this.parseImageProperties(displayText); } if (!external) { const vault = this.app.vault; let file = null; if (url.startsWith("/") && !url.startsWith("//")) { const vaultCms = (_l = (_k = this.app.plugins) == null ? void 0 : _k.plugins) == null ? void 0 : _l["vault-cms"]; const resolved = (_m = vaultCms == null ? void 0 : vaultCms.resolvePublicPath) == null ? void 0 : _m.call(vaultCms, url); if (resolved) { url = resolved; external = true; } } if (!external) { if (view == null ? void 0 : view.file) { const resolvedPath = this.app.metadataCache.getFirstLinkpathDest(url, view.file.path); if (resolvedPath) { file = resolvedPath; } } if (!file) { const files = vault.getFiles().filter((f) => f.path === url || f.name === url); file = files.find((f) => f.path === url) || files.find((f) => f.name === url) || null; } if (file) { url = vault.getResourcePath(file); } } } let type = null; try { const urlObj = new URL(url); const extension = (_n = urlObj.pathname.split(".").pop()) == null ? void 0 : _n.toLowerCase(); const imageExtensions = ["jpg", "jpeg", "png", "gif", "svg", "webp"]; const videoExtensions = ["mp4", "webm", "ogg", "ogv", "mov"]; if (extension && imageExtensions.includes(extension)) { type = "image" /* Image */; } else if (extension && videoExtensions.includes(extension)) { type = "video" /* Video */; } if (!type) { try { const response = await (0, import_obsidian11.requestUrl)({ url, method: "HEAD" }); const contentType = (response == null ? void 0 : response.headers["content-type"]) || null; if (contentType) { if (contentType.includes("image")) { type = "image" /* Image */; } else if (contentType.includes("video")) { type = "video" /* Video */; } } } catch (e) { } } } catch (e) { } return { url: `"${url.trim().replace(/(["\\])/g, "\\$1")}"`, external, type, ...options }; } /** * Parse image properties (offset, repeat) from string */ parseImageProperties(str) { const values = str.toLowerCase(); const repeatable = values.includes("repeat"); const sizes = str.split(/x|,/); const numbers = sizes.filter((v) => !isNaN(parseInt(v.trim(), 10))); let x = 0; let y = 0; const num0 = numbers[0]; const num1 = numbers[1]; if (numbers.length === 2 && num0 && num1) { x = parseInt(num0.trim(), 10); y = parseInt(num1.trim(), 10); } else if (numbers.length === 1 && num0) { y = parseInt(num0.trim(), 10); } return { x, y, repeatable }; } /** * Parse icon property */ async parseIcon(icon, view) { const str = icon || ""; const result = { value: null, type: "text" /* Text */ }; const isExplicitLink = PATTERNS.Wikilink.test(str) || PATTERNS.Markdown.test(str) || PATTERNS.MarkdownBare.test(str) || PATTERNS.Weblink.test(str) || this.isObsidianUrl(str); const imageExtensions = /\.(jpg|jpeg|png|gif|svg|webp|bmp|ico|avif)$/i; const isFilePath = imageExtensions.test(str); if (isExplicitLink || isFilePath) { result.type = "link" /* Link */; const data = await this.parseLink(str, view); result.value = data.url; } else { result.value = str; } return result; } /** * Check if only image properties changed (not the URL) */ async isImagePropertiesUpdate(oldStr, newStr, view) { if (!oldStr || !newStr) { return false; } const oldOpt = await this.parseLink(oldStr, view); const newOpt = await this.parseLink(newStr, view); return oldOpt.url === newOpt.url; } /** * Resolve absolute-from-root image paths (e.g. /images/blog/1.jpg) * Uses the configured project root to find files in the public/ folder. * Returns a file:// URL if found, null otherwise. */ /** * Check if URL is an obsidian:// URL */ isObsidianUrl(url) { return url.startsWith("obsidian://open"); } /** * Calculate font size to fit text in icon * Uses actual DOM measurement for accurate sizing */ calculateFontSize(textContent, iconSize) { const temp = document.createElement("span"); temp.addClass("im-measure-temp"); setCssProperties(temp, { position: "absolute", visibility: "hidden", "white-space": "nowrap", padding: "0", margin: "0", left: "-9999px" }); temp.textContent = textContent.toUpperCase(); document.body.appendChild(temp); const checkWidth = iconSize - 16; let fontSize = iconSize; setCssProperties(temp, { "font-size": `${fontSize}px` }); while (temp.offsetWidth > checkWidth && fontSize > 1) { fontSize -= 1; setCssProperties(temp, { "font-size": `${fontSize}px` }); } document.body.removeChild(temp); return `${fontSize}px`; } /** * Get active markdown view */ getActiveView() { return this.app.workspace.getActiveViewOfType(import_obsidian11.MarkdownView); } /** * Create default banner data object */ createDefaultBannerData(view, lastViewMode) { let viewMode = null; if (view) { const mode = view.getMode(); viewMode = mode === "preview" ? "preview" : "source"; } return { filepath: null, image: null, icon: null, viewMode, lastViewMode: lastViewMode || null, isImagePropsUpdate: false, isImageChange: false, needsUpdate: false }; } /** * Cleanup when plugin unloads */ destroy() { document.querySelectorAll(`.${CSS_CLASSES.Main}`).forEach((el) => el.remove()); bannerDataStore.clear(); } }; // src/modals/FilePickerModal.ts var import_obsidian12 = require("obsidian"); var FilePickerModal = class extends import_obsidian12.Modal { constructor(app, imageProcessor, propertyHandler, insertToProperty = false, propertyName) { super(app); this.imageProcessor = imageProcessor; this.propertyHandler = propertyHandler; this.insertToProperty = insertToProperty; this.propertyName = propertyName; } onOpen() { const { contentEl } = this; const input = contentEl.createEl("input", { type: "file", attr: { accept: "image/*", multiple: "true", style: "display: none;" } }); input.addEventListener("change", () => { void this.handleFileSelection(input); }); input.addEventListener("cancel", () => { this.close(); }); input.click(); } async handleFileSelection(input) { this.close(); const files = input.files; if (!files || files.length === 0) { new import_obsidian12.Notice("No files selected"); return; } const activeFile = this.getActiveFile(); if (!activeFile) { new import_obsidian12.Notice("No active file"); return; } const view = this.app.workspace.getActiveViewOfType(import_obsidian12.MarkdownView); const editor = view == null ? void 0 : view.editor; for (let i = 0; i < files.length; i++) { const file = files.item(i); if (!file || !file.type.startsWith("image/")) { continue; } if (this.insertToProperty) { if (!this.propertyName || this.propertyName.trim() === "") { new import_obsidian12.Notice("Please specify a property name in settings"); return; } const result = await this.imageProcessor.processImageFile( file, activeFile, true, // Show rename modal true // isPropertyInsertion - skip descriptive images ); if (result.success && result.file) { await this.propertyHandler.setPropertyValue( activeFile, this.propertyName, result.file ); } } else { const result = await this.imageProcessor.processImageFile( file, activeFile, true // Show rename modal ); if (result.success && result.linkText && editor) { editor.replaceSelection(result.linkText); } } } new import_obsidian12.Notice(`Added ${files.length} image(s)`); } getActiveFile() { var _a; const view = this.app.workspace.getActiveViewOfType(import_obsidian12.MarkdownView); return (_a = view == null ? void 0 : view.file) != null ? _a : null; } onClose() { const { contentEl } = this; contentEl.empty(); } }; function openFilePicker(app, imageProcessor, propertyHandler, insertToProperty = false, propertyName) { new FilePickerModal(app, imageProcessor, propertyHandler, insertToProperty, propertyName).open(); } // src/modals/RemoteSearchModal.ts var import_obsidian13 = require("obsidian"); var RemoteSearchModal = class extends import_obsidian13.Modal { constructor(app, settings, remoteService, imageProcessor, propertyHandler, options = {}) { super(app); this.container = null; this.queryInput = null; this.providerSelect = null; this.sizeSelect = null; this.scrollArea = null; this.imagesList = null; this.loadingContainer = null; this.currentQuery = ""; this.currentPage = 1; this.currentResults = []; this.isLoading = false; this.selectedImage = 0; this.settings = settings; this.remoteService = remoteService; this.imageProcessor = imageProcessor; this.propertyHandler = propertyHandler; this.options = options; this.currentProvider = settings.defaultProvider; this.containerEl.addClass("image-inserter-container"); } onOpen() { const { contentEl } = this; this.container = contentEl.createDiv({ cls: "container" }); const inputGroup = this.container.createDiv({ cls: "input-group" }); this.queryInput = inputGroup.createEl("input", { type: "text", cls: "query-input", attr: { placeholder: "Search images...", autofocus: "true" } }); this.providerSelect = inputGroup.createEl("select", { cls: "selector" }); this.providerSelect.createEl("option", { text: "Unsplash", value: "unsplash" /* Unsplash */ }); this.providerSelect.createEl("option", { text: "Pexels", value: "pexels" /* Pexels */ }); this.providerSelect.createEl("option", { text: "Pixabay", value: "pixabay" /* Pixabay */ }); this.providerSelect.value = this.currentProvider; this.sizeSelect = inputGroup.createEl("select", { cls: "selector" }); this.sizeSelect.createEl("option", { text: "Original", value: "original" /* Original */ }); this.sizeSelect.createEl("option", { text: "Large", value: "large" /* Large */ }); this.sizeSelect.createEl("option", { text: "Medium", value: "medium" /* Medium */ }); this.sizeSelect.createEl("option", { text: "Small", value: "small" /* Small */ }); this.sizeSelect.value = this.settings.defaultImageSize; this.loadingContainer = this.container.createDiv({ cls: "loading-container" }); const loaderIcon = this.loadingContainer.createDiv({ cls: "loader-icon" }); const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); svg.setAttribute("width", "24"); svg.setAttribute("height", "24"); svg.setAttribute("viewBox", "0 0 24 24"); svg.setAttribute("fill", "none"); svg.setAttribute("stroke", "currentColor"); svg.setAttribute("stroke-width", "2"); svg.setAttribute("stroke-linecap", "round"); svg.setAttribute("stroke-linejoin", "round"); svg.classList.add("lucide", "lucide-loader-circle"); const path = document.createElementNS("http://www.w3.org/2000/svg", "path"); path.setAttribute("d", "M21 12a9 9 0 1 1-6.219-8.56"); svg.appendChild(path); loaderIcon.appendChild(svg); this.showLoading(false); this.scrollArea = this.container.createDiv({ cls: "scroll-area" }); this.imagesList = this.scrollArea.createDiv({ cls: "images-list" }); this.setupEventListeners(); setTimeout(() => { var _a; (_a = this.queryInput) == null ? void 0 : _a.focus(); }, 50); } setupEventListeners() { var _a, _b, _c, _d; const debouncedSearch = (0, import_obsidian13.debounce)((query) => { if (query.trim()) { void this.performSearch(query, true); } else { this.clearResults(); } }, 1e3, true); (_a = this.queryInput) == null ? void 0 : _a.addEventListener("input", (e) => { const query = e.target.value; this.currentQuery = query; this.showLoading(true); debouncedSearch(query); }); (_b = this.queryInput) == null ? void 0 : _b.addEventListener("keydown", (e) => { var _a2; if (e.key === "Enter") { e.preventDefault(); const query = ((_a2 = this.queryInput) == null ? void 0 : _a2.value.trim()) || ""; if (query) { void this.performSearch(query, true); } else if (this.currentResults.length > 0 && this.selectedImage < this.currentResults.length) { const image = this.currentResults[this.selectedImage]; if (image) { void this.insertImage(image); } } } else if (e.ctrlKey && e.key === "n") { e.preventDefault(); if (this.currentResults.length > 0) { this.selectedImage = (this.selectedImage + 1) % this.currentResults.length; this.renderResults(); } } else if (e.ctrlKey && e.key === "p") { e.preventDefault(); if (this.currentResults.length > 0) { this.selectedImage = (this.selectedImage - 1 + this.currentResults.length) % this.currentResults.length; this.renderResults(); } } }); (_c = this.providerSelect) == null ? void 0 : _c.addEventListener("change", (e) => { this.currentProvider = e.target.value; if (this.currentQuery) { this.showLoading(true); void this.performSearch(this.currentQuery, true); } }); (_d = this.sizeSelect) == null ? void 0 : _d.addEventListener("change", (e) => { const size = e.target.value; this.settings.defaultImageSize = size; if (this.currentQuery) { this.showLoading(true); void this.performSearch(this.currentQuery, true); } }); } async performSearch(query, resetPage = false) { if (this.isLoading) return; this.currentQuery = query; if (resetPage) { this.currentPage = 1; } this.isLoading = true; this.showLoading(true); try { this.currentResults = await this.remoteService.search( query, this.currentProvider, this.currentPage ); this.selectedImage = 0; this.renderResults(); } catch (error) { console.error("Search failed:", error); const errorMsg = error instanceof Error ? error.message : "Search failed"; new import_obsidian13.Notice(`Request failed, status ${errorMsg}`); this.renderError(errorMsg); } finally { this.isLoading = false; this.showLoading(false); } } renderResults() { if (!this.imagesList) return; this.imagesList.empty(); if (this.currentResults.length === 0) { const noResult = this.imagesList.createDiv({ cls: "no-result-container" }); noResult.setText("No results found"); return; } for (let i = 0; i < this.currentResults.length; i++) { const image = this.currentResults[i]; if (!image) continue; const result = this.imagesList.createDiv({ cls: `query-result${i === this.selectedImage ? " is-selected" : ""}` }); result.createEl("img", { attr: { src: image.thumbnailUrl, alt: image.description || "Image" } }); result.addEventListener("click", () => { void this.insertImage(image); }); result.addEventListener("mousemove", () => { this.selectedImage = i; this.renderResults(); }); } this.renderPagination(); } renderPagination() { if (!this.scrollArea) return; const existingPagination = this.scrollArea.querySelector(".pagination"); if (existingPagination) { existingPagination.remove(); } const hasMore = this.currentResults.length >= 20; if (hasMore || this.currentPage > 1) { const pagination = this.scrollArea.createDiv({ cls: "pagination" }); if (this.currentPage > 1) { const prevBtn = pagination.createEl("button", { cls: "btn", text: "Previous" }); prevBtn.addEventListener("click", () => { this.currentPage--; this.showLoading(true); void this.performSearch(this.currentQuery); }); } if (hasMore) { const nextBtn = pagination.createEl("button", { cls: "btn", text: "Next" }); nextBtn.addEventListener("click", () => { this.currentPage++; this.showLoading(true); void this.performSearch(this.currentQuery); }); } } } renderError(message) { if (!this.imagesList) return; this.imagesList.empty(); const errorDiv = this.imagesList.createDiv({ cls: "no-result-container error-text" }); errorDiv.setText(`Error: ${message}`); } clearResults() { if (this.imagesList) { this.imagesList.empty(); } this.currentResults = []; } showLoading(show) { if (this.loadingContainer) { this.loadingContainer.style.display = show ? "flex" : "none"; } if (this.scrollArea) { if (show) { this.scrollArea.addClass("loading"); } else { this.scrollArea.removeClass("loading"); } } } async insertImage(image) { this.close(); const activeFile = this.getActiveFile(); if (!activeFile) { new import_obsidian13.Notice("No active file"); return; } try { const downloadUrl = this.remoteService.getDownloadUrl(image, this.settings.defaultImageSize); if (this.options.insertToProperty) { if (!this.options.propertyName || this.options.propertyName.trim() === "") { new import_obsidian13.Notice("Please specify a property name in settings"); return; } await this.propertyHandler.insertImageFromUrl( downloadUrl, activeFile, this.options.propertyName, image, // Pass RemoteImage for referral text generation this.currentQuery // Pass search term as suggested name ); } else { const result = await this.imageProcessor.processImageUrl( downloadUrl, activeFile, true, // Show rename modal false, // Not property insertion this.currentQuery // Pass search term as suggested name ); if (result.success && result.linkText) { const referralText = this.remoteService.generateReferralText(image); const fullText = result.linkText + referralText; const view = this.app.workspace.getActiveViewOfType(import_obsidian13.MarkdownView); if (view == null ? void 0 : view.editor) { view.editor.replaceSelection(fullText); } } } } catch (error) { console.error("Failed to insert image:", error); new import_obsidian13.Notice(`Failed to insert image: ${error instanceof Error ? error.message : String(error)}`); } } getActiveFile() { var _a; const view = this.app.workspace.getActiveViewOfType(import_obsidian13.MarkdownView); return (_a = view == null ? void 0 : view.file) != null ? _a : null; } onClose() { const { contentEl } = this; contentEl.empty(); } }; function openRemoteSearch(app, settings, remoteService, imageProcessor, propertyHandler, options = {}) { new RemoteSearchModal(app, settings, remoteService, imageProcessor, propertyHandler, options).open(); } // src/main.ts var SettingsObservable = class { constructor() { this.observers = []; } subscribe(fn) { this.observers.push(fn); } notify(settings) { this.observers.forEach((fn) => fn(settings)); } }; var ImageManagerPlugin = class extends import_obsidian15.Plugin { constructor() { super(...arguments); // Settings observer for notifying services of changes this.settingsObservable = new SettingsObservable(); } async onload() { await this.loadSettings(); await this.migrateApiKeysToSecrets(); this.initializeServices(); this.registerEventHandlers(); this.registerCommands(); this.addSettingTab(new ImageManagerSettingTab(this.app, this)); this.log("Image Manager plugin loaded"); } onunload() { var _a; (_a = this.bannerService) == null ? void 0 : _a.destroy(); this.log("Image Manager plugin unloaded"); } /** * Migrate API keys from plaintext to SecretStorage (one-time migration for 1.11.4+) * Only runs if Secrets API is available and secret IDs are not already set */ async migrateApiKeysToSecrets() { if (!(0, import_obsidian15.requireApiVersion)("1.11.4")) { return; } let migrated = false; const failures = []; const secretStorage = this.app.secretStorage; if (!secretStorage) { return; } if (!this.settings.pexelsApiKeySecretId && this.settings.pexelsApiKey) { const secretId = "image-manager-pexels-api-key"; try { secretStorage.setSecret(secretId, this.settings.pexelsApiKey); this.settings.pexelsApiKeySecretId = secretId; migrated = true; console.info("[Image Manager] Successfully migrated Pexels API key to SecretStorage"); } catch (error) { console.error("[Image Manager] Failed to migrate Pexels API key to SecretStorage:", error); failures.push("Pexels"); } } if (!this.settings.pixabayApiKeySecretId && this.settings.pixabayApiKey) { const secretId = "image-manager-pixabay-api-key"; try { secretStorage.setSecret(secretId, this.settings.pixabayApiKey); this.settings.pixabayApiKeySecretId = secretId; migrated = true; console.info("[Image Manager] Successfully migrated Pixabay API key to SecretStorage"); } catch (error) { console.error("[Image Manager] Failed to migrate Pixabay API key to SecretStorage:", error); failures.push("Pixabay"); } } if (migrated) { await this.saveSettings(); console.info("[Image Manager] API key migration completed"); } if (failures.length > 0) { new import_obsidian15.Notice( `Image Manager: Failed to migrate ${failures.join(" and ")} API key(s) to secure storage. Please re-enter your API key(s) in settings.`, 1e4 ); } } /** * Initialize all services */ initializeServices() { this.storageManager = new StorageManager(this.app, this.settings, this.settingsObservable); this.remoteService = new RemoteImageService(this.app, this.settings, this.settingsObservable); this.imageProcessor = new ImageProcessor(this.app, this.settings, this.storageManager, this.settingsObservable); this.propertyHandler = new PropertyHandler(this.app, this.settings, this.storageManager, this.imageProcessor, this.remoteService, this.settingsObservable); this.pasteHandler = new PasteHandler( this.app, this.settings, this.imageProcessor, this.propertyHandler, this.settingsObservable ); this.dropHandler = new DropHandler(this.app, this.settings, this.imageProcessor, this.settingsObservable); this.conversionService = new LocalConversionService(this.app, this.settings, this.storageManager, this.imageProcessor, this.settingsObservable); this.bannerService = new BannerService(this.app, this.settings, this.settingsObservable); } /** * Register event handlers */ registerEventHandlers() { this.registerEvent( this.app.workspace.on("editor-paste", (evt, editor, view) => { void this.pasteHandler.handleEditorPaste(evt, editor, view); }) ); this.registerEvent( this.app.workspace.on("editor-drop", (evt, editor, view) => { void this.dropHandler.handleEditorDrop(evt, editor, view); }) ); this.registerDomEvent(document, "paste", (evt) => { const target = evt.target; if (!target || !target.closest(".workspace")) { return; } void this.pasteHandler.handlePropertyPaste(evt); }, { capture: true }); this.registerEvent( this.app.workspace.on("file-open", (file) => { if (!file) { return; } if (this.settings.autoConvertRemoteImages && this.settings.convertOnNoteOpen) { if (this.settings.supportedExtensions.includes(file.extension)) { void (async () => { await new Promise((resolve) => setTimeout(resolve, 500)); const activeFile = this.app.workspace.getActiveFile(); const isActiveFile = activeFile && activeFile.path === file.path; if (isActiveFile || this.settings.processBackgroundChanges) { const count = await this.conversionService.processFile(file, !isActiveFile); if (count > 0) { new import_obsidian15.Notice(`Converted ${count} remote image(s) to local`); } } })(); } } const deviceSettings = this.bannerService.getDeviceSettings(); if (deviceSettings.enabled && (this.settings.supportedExtensions.includes(file.extension) || file.extension === "md")) { const view = this.app.workspace.getActiveViewOfType(import_obsidian15.MarkdownView); if (view instanceof import_obsidian15.MarkdownView) { void this.bannerService.process(file, view); } } }) ); this.registerEvent( this.app.workspace.on("layout-change", () => { const deviceSettings = this.bannerService.getDeviceSettings(); if (!deviceSettings.enabled) { return; } const view = this.app.workspace.getActiveViewOfType(import_obsidian15.MarkdownView); if (view && view.file && (this.settings.supportedExtensions.includes(view.file.extension) || view.file.extension === "md")) { void this.bannerService.process(view.file, view); } }) ); this.registerEvent( this.app.metadataCache.on("changed", (file) => { if (this.settings.autoConvertRemoteImages && this.settings.convertOnNoteSave) { if (this.settings.supportedExtensions.includes(file.extension)) { void (async () => { const activeFile = this.app.workspace.getActiveFile(); const isActiveFile = activeFile && activeFile.path === file.path; if (isActiveFile || this.settings.processBackgroundChanges) { const count = await this.conversionService.processFile(file, !isActiveFile); if (count > 0) { new import_obsidian15.Notice(`Converted ${count} remote image(s) to local`); } } })(); } } const deviceSettings = this.bannerService.getDeviceSettings(); if (!deviceSettings.enabled || !this.settings.supportedExtensions.includes(file.extension) && file.extension !== "md") { return; } this.app.workspace.iterateRootLeaves((leaf) => { const view = leaf.view; if (view instanceof import_obsidian15.MarkdownView && view.file === file) { void this.bannerService.process(file, view); } }); }) ); this.app.workspace.onLayoutReady(() => { this.bannerService.applySettings(); }); } /** * Register commands */ registerCommands() { this.addCommand({ id: "insert-image", name: "Insert local image", editorCallback: (editor, view) => { openFilePicker(this.app, this.imageProcessor, this.propertyHandler); } }); this.addCommand({ id: "search-image", name: "Insert remote image", editorCallback: (editor, view) => { openRemoteSearch( this.app, this.settings, this.remoteService, this.imageProcessor, this.propertyHandler ); } }); this.addCommand({ id: "insert-remote-image-to-property", name: "Insert remote image to property", editorCallback: (editor, view) => { openRemoteSearch( this.app, this.settings, this.remoteService, this.imageProcessor, this.propertyHandler, { insertToProperty: true, propertyName: this.settings.defaultPropertyName } ); } }); this.addCommand({ id: "insert-local-image-to-property", name: "Insert local image to property", editorCallback: (editor, view) => { openFilePicker( this.app, this.imageProcessor, this.propertyHandler, true, // insertToProperty this.settings.defaultPropertyName ); } }); this.addCommand({ id: "insert-remote-image-to-icon-property", name: "Insert remote image to icon property", editorCallback: (editor, view) => { openRemoteSearch( this.app, this.settings, this.remoteService, this.imageProcessor, this.propertyHandler, { insertToProperty: true, propertyName: this.settings.defaultIconPropertyName } ); } }); this.addCommand({ id: "insert-local-image-to-icon-property", name: "Insert local image to icon property", editorCallback: (editor, view) => { openFilePicker( this.app, this.imageProcessor, this.propertyHandler, true, // insertToProperty this.settings.defaultIconPropertyName ); } }); this.addCommand({ id: "convert-remote-images", name: "Convert remote images", editorCallback: async (editor, view) => { const file = view.file; if (!file) { new import_obsidian15.Notice("No active file"); return; } const count = await this.conversionService.processFile(file); if (count > 0) { new import_obsidian15.Notice(`Converted ${count} remote image(s) to local`); } else { new import_obsidian15.Notice("No remote images found"); } } }); this.addCommand({ id: "convert-all-remote-images", name: "Convert all remote images", callback: async () => { const { openConfirmModal: openConfirmModal2 } = await Promise.resolve().then(() => (init_ConfirmModal(), ConfirmModal_exports)); const result = await openConfirmModal2( this.app, "Convert All Remote Images", "This will scan all files in your vault and convert every remote image URL to a local file. This action cannot be undone.\n\nEach image will be downloaded and you'll be prompted to rename them. This may take a while if you have many images.\n\nAre you sure you want to proceed?", "Yes, convert all images", "Cancel" ); if (!result.confirmed) { return; } new import_obsidian15.Notice("Processing all files... This may take a while."); const count = await this.conversionService.processAllFiles(); new import_obsidian15.Notice(`Converted ${count} remote image(s) to local`); } }); } /** * Load settings from storage */ async loadSettings() { const data = await this.loadData(); this.settings = Object.assign({}, DEFAULT_SETTINGS, data != null ? data : {}); } /** * Save settings to storage */ async saveSettings() { await this.saveData(this.settings); this.settingsObservable.notify(this.settings); } /** * Debug logging */ log(...args) { var _a; if ((_a = this.settings) == null ? void 0 : _a.debugMode) { console.debug("[Image Manager]", ...args); } } }; //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsic3JjL21vZGFscy9Db25maXJtTW9kYWwudHMiLCAic3JjL21haW4udHMiLCAic3JjL3NldHRpbmdzLnRzIiwgInNyYy90eXBlcy50cyIsICJzcmMvc2VydmljZXMvU3RvcmFnZU1hbmFnZXIudHMiLCAic3JjL3NlcnZpY2VzL0ltYWdlUHJvY2Vzc29yLnRzIiwgInNyYy91dGlscy90ZW1wbGF0ZS50cyIsICJzcmMvbW9kYWxzL1JlbmFtZU1vZGFsLnRzIiwgInNyYy9tb2RhbHMvRGVzY3JpcHRpdmVJbWFnZU1vZGFsLnRzIiwgInNyYy91dGlscy9rZWJhYi1jYXNlLnRzIiwgInNyYy9zZXJ2aWNlcy9Qcm9wZXJ0eUhhbmRsZXIudHMiLCAic3JjL3V0aWxzL21keC1mcm9udG1hdHRlci50cyIsICJzcmMvc2VydmljZXMvUGFzdGVIYW5kbGVyLnRzIiwgInNyYy9zZXJ2aWNlcy9SZW1vdGVJbWFnZVNlcnZpY2UudHMiLCAic3JjL3NlcnZpY2VzL0xvY2FsQ29udmVyc2lvblNlcnZpY2UudHMiLCAic3JjL3NlcnZpY2VzL0Jhbm5lclNlcnZpY2UudHMiLCAic3JjL21vZGFscy9GaWxlUGlja2VyTW9kYWwudHMiLCAic3JjL21vZGFscy9SZW1vdGVTZWFyY2hNb2RhbC50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiLyoqXHJcbiAqIENvbmZpcm1hdGlvbiBNb2RhbFxyXG4gKiBTaW1wbGUgbW9kYWwgZm9yIGNvbmZpcm1pbmcgcG90ZW50aWFsbHkgZGVzdHJ1Y3RpdmUgYWN0aW9uc1xyXG4gKi9cclxuXHJcbmltcG9ydCB7IEFwcCwgTW9kYWwgfSBmcm9tICdvYnNpZGlhbic7XHJcblxyXG5leHBvcnQgaW50ZXJmYWNlIENvbmZpcm1SZXN1bHQge1xyXG5cdGNvbmZpcm1lZDogYm9vbGVhbjtcclxufVxyXG5cclxuZXhwb3J0IGNsYXNzIENvbmZpcm1Nb2RhbCBleHRlbmRzIE1vZGFsIHtcclxuXHRwcml2YXRlIHRpdGxlOiBzdHJpbmc7XHJcblx0cHJpdmF0ZSBtZXNzYWdlOiBzdHJpbmc7XHJcblx0cHJpdmF0ZSBjb25maXJtVGV4dDogc3RyaW5nO1xyXG5cdHByaXZhdGUgY2FuY2VsVGV4dDogc3RyaW5nO1xyXG5cdHByaXZhdGUgcmVzb2x2ZTogKHJlc3VsdDogQ29uZmlybVJlc3VsdCkgPT4gdm9pZDtcclxuXHJcblx0Y29uc3RydWN0b3IoXHJcblx0XHRhcHA6IEFwcCxcclxuXHRcdHRpdGxlOiBzdHJpbmcsXHJcblx0XHRtZXNzYWdlOiBzdHJpbmcsXHJcblx0XHRjb25maXJtVGV4dDogc3RyaW5nID0gJ0NvbmZpcm0nLFxyXG5cdFx0Y2FuY2VsVGV4dDogc3RyaW5nID0gJ0NhbmNlbCdcclxuXHQpIHtcclxuXHRcdHN1cGVyKGFwcCk7XHJcblx0XHR0aGlzLnRpdGxlID0gdGl0bGU7XHJcblx0XHR0aGlzLm1lc3NhZ2UgPSBtZXNzYWdlO1xyXG5cdFx0dGhpcy5jb25maXJtVGV4dCA9IGNvbmZpcm1UZXh0O1xyXG5cdFx0dGhpcy5jYW5jZWxUZXh0ID0gY2FuY2VsVGV4dDtcclxuXHR9XHJcblxyXG5cdG9uT3BlbigpOiB2b2lkIHtcclxuXHRcdGNvbnN0IHsgY29udGVudEVsLCB0aXRsZUVsIH0gPSB0aGlzO1xyXG5cdFx0dGl0bGVFbC5zZXRUZXh0KHRoaXMudGl0bGUpO1xyXG5cclxuXHRcdC8vIE1lc3NhZ2VcclxuXHRcdGNvbnN0IG1lc3NhZ2VFbCA9IGNvbnRlbnRFbC5jcmVhdGVEaXYoeyBjbHM6ICdpbWFnZS1tYW5hZ2VyLWNvbmZpcm0tbWVzc2FnZScgfSk7XHJcblx0XHRtZXNzYWdlRWwuY3JlYXRlRWwoJ3AnLCB7IHRleHQ6IHRoaXMubWVzc2FnZSB9KTtcclxuXHJcblx0XHQvLyBCdXR0b25zXHJcblx0XHRjb25zdCBidXR0b25Db250YWluZXIgPSBjb250ZW50RWwuY3JlYXRlRGl2KHsgY2xzOiAnaW1hZ2UtbWFuYWdlci1jb25maXJtLWJ1dHRvbnMnIH0pO1xyXG5cdFx0XHJcblx0XHRidXR0b25Db250YWluZXIuY3JlYXRlRWwoJ2J1dHRvbicsIHtcclxuXHRcdFx0dGV4dDogdGhpcy5jb25maXJtVGV4dCxcclxuXHRcdFx0Y2xzOiAnbW9kLWN0YScsXHJcblx0XHR9KS5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsICgpID0+IHtcclxuXHRcdFx0dGhpcy5yZXNvbHZlKHsgY29uZmlybWVkOiB0cnVlIH0pO1xyXG5cdFx0XHR0aGlzLmNsb3NlKCk7XHJcblx0XHR9KTtcclxuXHJcblx0XHRidXR0b25Db250YWluZXIuY3JlYXRlRWwoJ2J1dHRvbicsIHtcclxuXHRcdFx0dGV4dDogdGhpcy5jYW5jZWxUZXh0LFxyXG5cdFx0fSkuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCAoKSA9PiB7XHJcblx0XHRcdHRoaXMucmVzb2x2ZSh7IGNvbmZpcm1lZDogZmFsc2UgfSk7XHJcblx0XHRcdHRoaXMuY2xvc2UoKTtcclxuXHRcdH0pO1xyXG5cclxuXHRcdC8vIEZvY3VzIHRoZSBjb25maXJtIGJ1dHRvblxyXG5cdFx0c2V0VGltZW91dCgoKSA9PiB7XHJcblx0XHRcdGNvbnN0IGNvbmZpcm1CdXR0b24gPSBidXR0b25Db250YWluZXIucXVlcnlTZWxlY3RvcignLm1vZC1jdGEnKSBhcyBIVE1MQnV0dG9uRWxlbWVudDtcclxuXHRcdFx0Y29uZmlybUJ1dHRvbj8uZm9jdXMoKTtcclxuXHRcdH0sIDUwKTtcclxuXHR9XHJcblxyXG5cdG9uQ2xvc2UoKTogdm9pZCB7XHJcblx0XHRjb25zdCB7IGNvbnRlbnRFbCB9ID0gdGhpcztcclxuXHRcdGNvbnRlbnRFbC5lbXB0eSgpO1xyXG5cdH1cclxuXHJcblx0cHVibGljIG9wZW5BbmRBd2FpdFJlc3VsdCgpOiBQcm9taXNlPENvbmZpcm1SZXN1bHQ+IHtcclxuXHRcdHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4ge1xyXG5cdFx0XHR0aGlzLnJlc29sdmUgPSByZXNvbHZlO1xyXG5cdFx0XHR0aGlzLm9wZW4oKTtcclxuXHRcdH0pO1xyXG5cdH1cclxufVxyXG5cclxuLyoqXHJcbiAqIE9wZW4gYSBjb25maXJtYXRpb24gbW9kYWwgYW5kIHJldHVybiB0aGUgcmVzdWx0XHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gb3BlbkNvbmZpcm1Nb2RhbChcclxuXHRhcHA6IEFwcCxcclxuXHR0aXRsZTogc3RyaW5nLFxyXG5cdG1lc3NhZ2U6IHN0cmluZyxcclxuXHRjb25maXJtVGV4dDogc3RyaW5nID0gJ0NvbmZpcm0nLFxyXG5cdGNhbmNlbFRleHQ6IHN0cmluZyA9ICdDYW5jZWwnXHJcbik6IFByb21pc2U8Q29uZmlybVJlc3VsdD4ge1xyXG5cdGNvbnN0IG1vZGFsID0gbmV3IENvbmZpcm1Nb2RhbChhcHAsIHRpdGxlLCBtZXNzYWdlLCBjb25maXJtVGV4dCwgY2FuY2VsVGV4dCk7XHJcblx0cmV0dXJuIG1vZGFsLm9wZW5BbmRBd2FpdFJlc3VsdCgpO1xyXG59XHJcbiIsICIvKipcbiAqIEltYWdlIE1hbmFnZXIgUGx1Z2luXG4gKiBJbnNlcnQsIHJlbmFtZSwgYW5kIHNvcnQgZXh0ZXJuYWwgaW1hZ2VzIGJ5IHRyYW5zZm9ybWluZyB0aGVtIGludG8gbG9jYWwgZmlsZXNcbiAqL1xuXG5pbXBvcnQgeyBFZGl0b3IsIE1hcmtkb3duVmlldywgTm90aWNlLCBQbHVnaW4sIHJlcXVpcmVBcGlWZXJzaW9uLCBURmlsZSwgV29ya3NwYWNlTGVhZiB9IGZyb20gJ29ic2lkaWFuJztcbmltcG9ydCB7IERFRkFVTFRfU0VUVElOR1MsIEltYWdlTWFuYWdlclNldHRpbmdzLCBJbWFnZU1hbmFnZXJTZXR0aW5nVGFiIH0gZnJvbSAnLi9zZXR0aW5ncyc7XG5pbXBvcnQgeyBTdG9yYWdlTWFuYWdlciB9IGZyb20gJy4vc2VydmljZXMvU3RvcmFnZU1hbmFnZXInO1xuaW1wb3J0IHsgSW1hZ2VQcm9jZXNzb3IgfSBmcm9tICcuL3NlcnZpY2VzL0ltYWdlUHJvY2Vzc29yJztcbmltcG9ydCB7IFByb3BlcnR5SGFuZGxlciB9IGZyb20gJy4vc2VydmljZXMvUHJvcGVydHlIYW5kbGVyJztcbmltcG9ydCB7IFBhc3RlSGFuZGxlciwgRHJvcEhhbmRsZXIgfSBmcm9tICcuL3NlcnZpY2VzL1Bhc3RlSGFuZGxlcic7XG5pbXBvcnQgeyBSZW1vdGVJbWFnZVNlcnZpY2UgfSBmcm9tICcuL3NlcnZpY2VzL1JlbW90ZUltYWdlU2VydmljZSc7XG5pbXBvcnQgeyBMb2NhbENvbnZlcnNpb25TZXJ2aWNlIH0gZnJvbSAnLi9zZXJ2aWNlcy9Mb2NhbENvbnZlcnNpb25TZXJ2aWNlJztcbmltcG9ydCB7IEJhbm5lclNlcnZpY2UgfSBmcm9tICcuL3NlcnZpY2VzL0Jhbm5lclNlcnZpY2UnO1xuaW1wb3J0IHsgb3BlbkZpbGVQaWNrZXIgfSBmcm9tICcuL21vZGFscy9GaWxlUGlja2VyTW9kYWwnO1xuaW1wb3J0IHsgb3BlblJlbW90ZVNlYXJjaCB9IGZyb20gJy4vbW9kYWxzL1JlbW90ZVNlYXJjaE1vZGFsJztcblxuLyoqXG4gKiBTaW1wbGUgb2JzZXJ2ZXIgZm9yIHNldHRpbmdzIGNoYW5nZXNcbiAqIFNlcnZpY2VzIHN1YnNjcmliZSB0byByZWNlaXZlIHNldHRpbmdzIHVwZGF0ZXMgdmlhIGEgc2luZ2xlIG5vdGlmeSgpIGNhbGxcbiAqL1xuY2xhc3MgU2V0dGluZ3NPYnNlcnZhYmxlIHtcblx0cHJpdmF0ZSBvYnNlcnZlcnM6ICgoc2V0dGluZ3M6IEltYWdlTWFuYWdlclNldHRpbmdzKSA9PiB2b2lkKVtdID0gW107XG5cblx0c3Vic2NyaWJlKGZuOiAoc2V0dGluZ3M6IEltYWdlTWFuYWdlclNldHRpbmdzKSA9PiB2b2lkKTogdm9pZCB7XG5cdFx0dGhpcy5vYnNlcnZlcnMucHVzaChmbik7XG5cdH1cblxuXHRub3RpZnkoc2V0dGluZ3M6IEltYWdlTWFuYWdlclNldHRpbmdzKTogdm9pZCB7XG5cdFx0dGhpcy5vYnNlcnZlcnMuZm9yRWFjaChmbiA9PiBmbihzZXR0aW5ncykpO1xuXHR9XG59XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEltYWdlTWFuYWdlclBsdWdpbiBleHRlbmRzIFBsdWdpbiB7XG5cdHNldHRpbmdzOiBJbWFnZU1hbmFnZXJTZXR0aW5ncztcblxuXHQvLyBTZXR0aW5ncyBvYnNlcnZlciBmb3Igbm90aWZ5aW5nIHNlcnZpY2VzIG9mIGNoYW5nZXNcblx0cHJpdmF0ZSBzZXR0aW5nc09ic2VydmFibGUgPSBuZXcgU2V0dGluZ3NPYnNlcnZhYmxlKCk7XG5cblx0Ly8gU2VydmljZXNcblx0cHJpdmF0ZSBzdG9yYWdlTWFuYWdlcjogU3RvcmFnZU1hbmFnZXI7XG5cdHByaXZhdGUgaW1hZ2VQcm9jZXNzb3I6IEltYWdlUHJvY2Vzc29yO1xuXHRwcml2YXRlIHByb3BlcnR5SGFuZGxlcjogUHJvcGVydHlIYW5kbGVyO1xuXHRwcml2YXRlIHBhc3RlSGFuZGxlcjogUGFzdGVIYW5kbGVyO1xuXHRwcml2YXRlIGRyb3BIYW5kbGVyOiBEcm9wSGFuZGxlcjtcblx0cHJpdmF0ZSByZW1vdGVTZXJ2aWNlOiBSZW1vdGVJbWFnZVNlcnZpY2U7XG5cdHByaXZhdGUgY29udmVyc2lvblNlcnZpY2U6IExvY2FsQ29udmVyc2lvblNlcnZpY2U7XG5cdHByaXZhdGUgYmFubmVyU2VydmljZTogQmFubmVyU2VydmljZTtcblxuXHRhc3luYyBvbmxvYWQoKTogUHJvbWlzZTx2b2lkPiB7XG5cdFx0YXdhaXQgdGhpcy5sb2FkU2V0dGluZ3MoKTtcblxuXHRcdC8vIE1pZ3JhdGUgQVBJIGtleXMgdG8gc2VjcmV0cyBpZiBhdmFpbGFibGUgKG9uZS10aW1lIG1pZ3JhdGlvbilcblx0XHRhd2FpdCB0aGlzLm1pZ3JhdGVBcGlLZXlzVG9TZWNyZXRzKCk7XG5cblx0XHQvLyBJbml0aWFsaXplIHNlcnZpY2VzXG5cdFx0dGhpcy5pbml0aWFsaXplU2VydmljZXMoKTtcblxuXHRcdC8vIFJlZ2lzdGVyIGV2ZW50IGhhbmRsZXJzXG5cdFx0dGhpcy5yZWdpc3RlckV2ZW50SGFuZGxlcnMoKTtcblxuXHRcdC8vIFJlZ2lzdGVyIGNvbW1hbmRzXG5cdFx0dGhpcy5yZWdpc3RlckNvbW1hbmRzKCk7XG5cblx0XHQvLyBBZGQgc2V0dGluZ3MgdGFiXG5cdFx0dGhpcy5hZGRTZXR0aW5nVGFiKG5ldyBJbWFnZU1hbmFnZXJTZXR0aW5nVGFiKHRoaXMuYXBwLCB0aGlzKSk7XG5cblx0XHR0aGlzLmxvZygnSW1hZ2UgTWFuYWdlciBwbHVnaW4gbG9hZGVkJyk7XG5cdH1cblxuXHRvbnVubG9hZCgpOiB2b2lkIHtcblx0XHQvLyBDbGVhbiB1cCBiYW5uZXIgc2VydmljZVxuXHRcdHRoaXMuYmFubmVyU2VydmljZT8uZGVzdHJveSgpO1xuXG5cdFx0dGhpcy5sb2coJ0ltYWdlIE1hbmFnZXIgcGx1Z2luIHVubG9hZGVkJyk7XG5cdH1cblxuXHQvKipcblx0ICogTWlncmF0ZSBBUEkga2V5cyBmcm9tIHBsYWludGV4dCB0byBTZWNyZXRTdG9yYWdlIChvbmUtdGltZSBtaWdyYXRpb24gZm9yIDEuMTEuNCspXG5cdCAqIE9ubHkgcnVucyBpZiBTZWNyZXRzIEFQSSBpcyBhdmFpbGFibGUgYW5kIHNlY3JldCBJRHMgYXJlIG5vdCBhbHJlYWR5IHNldFxuXHQgKi9cblx0cHJpdmF0ZSBhc3luYyBtaWdyYXRlQXBpS2V5c1RvU2VjcmV0cygpOiBQcm9taXNlPHZvaWQ+IHtcblx0XHQvLyBPbmx5IG1pZ3JhdGUgaWYgU2VjcmV0cyBBUEkgaXMgYXZhaWxhYmxlXG5cdFx0aWYgKCFyZXF1aXJlQXBpVmVyc2lvbignMS4xMS40JykpIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRsZXQgbWlncmF0ZWQgPSBmYWxzZTtcblx0XHRjb25zdCBmYWlsdXJlczogc3RyaW5nW10gPSBbXTtcblxuXHRcdC8vIEFjY2VzcyBzZWNyZXRTdG9yYWdlIHZpYSB0eXBlIGFzc2VydGlvbiAobWF5IG5vdCBiZSBpbiB0eXBlIGRlZmluaXRpb25zKVxuXHRcdGNvbnN0IHNlY3JldFN0b3JhZ2UgPSAodGhpcy5hcHAgYXMgdW5rbm93biBhcyB7IHNlY3JldFN0b3JhZ2U/OiB7IHNldFNlY3JldChpZDogc3RyaW5nLCBzZWNyZXQ6IHN0cmluZyk6IHZvaWQgfSB9KS5zZWNyZXRTdG9yYWdlO1xuXHRcdGlmICghc2VjcmV0U3RvcmFnZSkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdC8vIE1pZ3JhdGUgUGV4ZWxzIEFQSSBrZXlcblx0XHRpZiAoIXRoaXMuc2V0dGluZ3MucGV4ZWxzQXBpS2V5U2VjcmV0SWQgJiYgdGhpcy5zZXR0aW5ncy5wZXhlbHNBcGlLZXkpIHtcblx0XHRcdGNvbnN0IHNlY3JldElkID0gJ2ltYWdlLW1hbmFnZXItcGV4ZWxzLWFwaS1rZXknO1xuXHRcdFx0dHJ5IHtcblx0XHRcdFx0c2VjcmV0U3RvcmFnZS5zZXRTZWNyZXQoc2VjcmV0SWQsIHRoaXMuc2V0dGluZ3MucGV4ZWxzQXBpS2V5KTtcblx0XHRcdFx0dGhpcy5zZXR0aW5ncy5wZXhlbHNBcGlLZXlTZWNyZXRJZCA9IHNlY3JldElkO1xuXHRcdFx0XHRtaWdyYXRlZCA9IHRydWU7XG5cdFx0XHRcdGNvbnNvbGUuaW5mbygnW0ltYWdlIE1hbmFnZXJdIFN1Y2Nlc3NmdWxseSBtaWdyYXRlZCBQZXhlbHMgQVBJIGtleSB0byBTZWNyZXRTdG9yYWdlJyk7XG5cdFx0XHR9IGNhdGNoIChlcnJvcikge1xuXHRcdFx0XHRjb25zb2xlLmVycm9yKCdbSW1hZ2UgTWFuYWdlcl0gRmFpbGVkIHRvIG1pZ3JhdGUgUGV4ZWxzIEFQSSBrZXkgdG8gU2VjcmV0U3RvcmFnZTonLCBlcnJvcik7XG5cdFx0XHRcdGZhaWx1cmVzLnB1c2goJ1BleGVscycpO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vIE1pZ3JhdGUgUGl4YWJheSBBUEkga2V5XG5cdFx0aWYgKCF0aGlzLnNldHRpbmdzLnBpeGFiYXlBcGlLZXlTZWNyZXRJZCAmJiB0aGlzLnNldHRpbmdzLnBpeGFiYXlBcGlLZXkpIHtcblx0XHRcdGNvbnN0IHNlY3JldElkID0gJ2ltYWdlLW1hbmFnZXItcGl4YWJheS1hcGkta2V5Jztcblx0XHRcdHRyeSB7XG5cdFx0XHRcdHNlY3JldFN0b3JhZ2Uuc2V0U2VjcmV0KHNlY3JldElkLCB0aGlzLnNldHRpbmdzLnBpeGFiYXlBcGlLZXkpO1xuXHRcdFx0XHR0aGlzLnNldHRpbmdzLnBpeGFiYXlBcGlLZXlTZWNyZXRJZCA9IHNlY3JldElkO1xuXHRcdFx0XHRtaWdyYXRlZCA9IHRydWU7XG5cdFx0XHRcdGNvbnNvbGUuaW5mbygnW0ltYWdlIE1hbmFnZXJdIFN1Y2Nlc3NmdWxseSBtaWdyYXRlZCBQaXhhYmF5IEFQSSBrZXkgdG8gU2VjcmV0U3RvcmFnZScpO1xuXHRcdFx0fSBjYXRjaCAoZXJyb3IpIHtcblx0XHRcdFx0Y29uc29sZS5lcnJvcignW0ltYWdlIE1hbmFnZXJdIEZhaWxlZCB0byBtaWdyYXRlIFBpeGFiYXkgQVBJIGtleSB0byBTZWNyZXRTdG9yYWdlOicsIGVycm9yKTtcblx0XHRcdFx0ZmFpbHVyZXMucHVzaCgnUGl4YWJheScpO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vIFNhdmUgc2V0dGluZ3MgaWYgbWlncmF0aW9uIG9jY3VycmVkXG5cdFx0aWYgKG1pZ3JhdGVkKSB7XG5cdFx0XHRhd2FpdCB0aGlzLnNhdmVTZXR0aW5ncygpO1xuXHRcdFx0Y29uc29sZS5pbmZvKCdbSW1hZ2UgTWFuYWdlcl0gQVBJIGtleSBtaWdyYXRpb24gY29tcGxldGVkJyk7XG5cdFx0fVxuXG5cdFx0Ly8gU2hvdyBOb3RpY2UgaWYgYW55IG1pZ3JhdGlvbnMgZmFpbGVkXG5cdFx0aWYgKGZhaWx1cmVzLmxlbmd0aCA+IDApIHtcblx0XHRcdG5ldyBOb3RpY2UoXG5cdFx0XHRcdGBJbWFnZSBNYW5hZ2VyOiBGYWlsZWQgdG8gbWlncmF0ZSAke2ZhaWx1cmVzLmpvaW4oJyBhbmQgJyl9IEFQSSBrZXkocykgdG8gc2VjdXJlIHN0b3JhZ2UuIGAgK1xuXHRcdFx0XHRgUGxlYXNlIHJlLWVudGVyIHlvdXIgQVBJIGtleShzKSBpbiBzZXR0aW5ncy5gLFxuXHRcdFx0XHQxMDAwMFxuXHRcdFx0KTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogSW5pdGlhbGl6ZSBhbGwgc2VydmljZXNcblx0ICovXG5cdHByaXZhdGUgaW5pdGlhbGl6ZVNlcnZpY2VzKCk6IHZvaWQge1xuXHRcdHRoaXMuc3RvcmFnZU1hbmFnZXIgPSBuZXcgU3RvcmFnZU1hbmFnZXIodGhpcy5hcHAsIHRoaXMuc2V0dGluZ3MsIHRoaXMuc2V0dGluZ3NPYnNlcnZhYmxlKTtcblx0XHR0aGlzLnJlbW90ZVNlcnZpY2UgPSBuZXcgUmVtb3RlSW1hZ2VTZXJ2aWNlKHRoaXMuYXBwLCB0aGlzLnNldHRpbmdzLCB0aGlzLnNldHRpbmdzT2JzZXJ2YWJsZSk7XG5cdFx0dGhpcy5pbWFnZVByb2Nlc3NvciA9IG5ldyBJbWFnZVByb2Nlc3Nvcih0aGlzLmFwcCwgdGhpcy5zZXR0aW5ncywgdGhpcy5zdG9yYWdlTWFuYWdlciwgdGhpcy5zZXR0aW5nc09ic2VydmFibGUpO1xuXHRcdHRoaXMucHJvcGVydHlIYW5kbGVyID0gbmV3IFByb3BlcnR5SGFuZGxlcih0aGlzLmFwcCwgdGhpcy5zZXR0aW5ncywgdGhpcy5zdG9yYWdlTWFuYWdlciwgdGhpcy5pbWFnZVByb2Nlc3NvciwgdGhpcy5yZW1vdGVTZXJ2aWNlLCB0aGlzLnNldHRpbmdzT2JzZXJ2YWJsZSk7XG5cdFx0dGhpcy5wYXN0ZUhhbmRsZXIgPSBuZXcgUGFzdGVIYW5kbGVyKFxuXHRcdFx0dGhpcy5hcHAsXG5cdFx0XHR0aGlzLnNldHRpbmdzLFxuXHRcdFx0dGhpcy5pbWFnZVByb2Nlc3Nvcixcblx0XHRcdHRoaXMucHJvcGVydHlIYW5kbGVyLFxuXHRcdFx0dGhpcy5zZXR0aW5nc09ic2VydmFibGVcblx0XHQpO1xuXHRcdHRoaXMuZHJvcEhhbmRsZXIgPSBuZXcgRHJvcEhhbmRsZXIodGhpcy5hcHAsIHRoaXMuc2V0dGluZ3MsIHRoaXMuaW1hZ2VQcm9jZXNzb3IsIHRoaXMuc2V0dGluZ3NPYnNlcnZhYmxlKTtcblx0XHR0aGlzLmNvbnZlcnNpb25TZXJ2aWNlID0gbmV3IExvY2FsQ29udmVyc2lvblNlcnZpY2UodGhpcy5hcHAsIHRoaXMuc2V0dGluZ3MsIHRoaXMuc3RvcmFnZU1hbmFnZXIsIHRoaXMuaW1hZ2VQcm9jZXNzb3IsIHRoaXMuc2V0dGluZ3NPYnNlcnZhYmxlKTtcblx0XHR0aGlzLmJhbm5lclNlcnZpY2UgPSBuZXcgQmFubmVyU2VydmljZSh0aGlzLmFwcCwgdGhpcy5zZXR0aW5ncywgdGhpcy5zZXR0aW5nc09ic2VydmFibGUpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJlZ2lzdGVyIGV2ZW50IGhhbmRsZXJzXG5cdCAqL1xuXHRwcml2YXRlIHJlZ2lzdGVyRXZlbnRIYW5kbGVycygpOiB2b2lkIHtcblx0XHQvLyBFZGl0b3IgcGFzdGUgaGFuZGxlclxuXHRcdHRoaXMucmVnaXN0ZXJFdmVudChcblx0XHRcdHRoaXMuYXBwLndvcmtzcGFjZS5vbignZWRpdG9yLXBhc3RlJywgKGV2dDogQ2xpcGJvYXJkRXZlbnQsIGVkaXRvcjogRWRpdG9yLCB2aWV3OiBNYXJrZG93blZpZXcpID0+IHtcblx0XHRcdFx0dm9pZCB0aGlzLnBhc3RlSGFuZGxlci5oYW5kbGVFZGl0b3JQYXN0ZShldnQsIGVkaXRvciwgdmlldyk7XG5cdFx0XHR9KVxuXHRcdCk7XG5cblx0XHQvLyBFZGl0b3IgZHJvcCBoYW5kbGVyXG5cdFx0dGhpcy5yZWdpc3RlckV2ZW50KFxuXHRcdFx0dGhpcy5hcHAud29ya3NwYWNlLm9uKCdlZGl0b3ItZHJvcCcsIChldnQ6IERyYWdFdmVudCwgZWRpdG9yOiBFZGl0b3IsIHZpZXc6IE1hcmtkb3duVmlldykgPT4ge1xuXHRcdFx0XHR2b2lkIHRoaXMuZHJvcEhhbmRsZXIuaGFuZGxlRWRpdG9yRHJvcChldnQsIGVkaXRvciwgdmlldyk7XG5cdFx0XHR9KVxuXHRcdCk7XG5cblx0XHQvLyBET00gcGFzdGUgaGFuZGxlciBmb3IgZnJvbnRtYXR0ZXIgcHJvcGVydGllc1xuXHRcdC8vIFVzZSBjYXB0dXJlIHBoYXNlIGJ1dCBiZSBkZWZlbnNpdmUgLSBvbmx5IGhhbmRsZSBpZiB3ZSdyZSBkZWZpbml0ZWx5IGluIGEgcHJvcGVydHkgZmllbGRcblx0XHR0aGlzLnJlZ2lzdGVyRG9tRXZlbnQoZG9jdW1lbnQsICdwYXN0ZScsIChldnQ6IENsaXBib2FyZEV2ZW50KSA9PiB7XG5cdFx0XHQvLyBPbmx5IGhhbmRsZSBpZiB3ZSdyZSBpbiB0aGUgT2JzaWRpYW4gd29ya3NwYWNlIChub3Qgc3lzdGVtIFVJIGxpa2UgdGl0bGUgYmFyKVxuXHRcdFx0Y29uc3QgdGFyZ2V0ID0gZXZ0LnRhcmdldCBhcyBIVE1MRWxlbWVudDtcblx0XHRcdGlmICghdGFyZ2V0IHx8ICF0YXJnZXQuY2xvc2VzdCgnLndvcmtzcGFjZScpKSB7XG5cdFx0XHRcdHJldHVybjsgLy8gTm90IGluIHdvcmtzcGFjZSwgZG9uJ3QgaW50ZXJmZXJlXG5cdFx0XHR9XG5cdFx0XHR2b2lkIHRoaXMucGFzdGVIYW5kbGVyLmhhbmRsZVByb3BlcnR5UGFzdGUoZXZ0KTtcblx0XHR9LCB7IGNhcHR1cmU6IHRydWUgfSk7XG5cblx0XHQvLyBGaWxlIG9wZW4gaGFuZGxlciBmb3IgYXV0by1jb252ZXJzaW9uIGFuZCBiYW5uZXJcblx0XHR0aGlzLnJlZ2lzdGVyRXZlbnQoXG5cdFx0XHR0aGlzLmFwcC53b3Jrc3BhY2Uub24oJ2ZpbGUtb3BlbicsIChmaWxlOiBURmlsZSB8IG51bGwpID0+IHtcblx0XHRcdFx0aWYgKCFmaWxlKSB7XG5cdFx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gQXV0by1jb252ZXJzaW9uIChub24tYmxvY2tpbmcpXG5cdFx0XHRcdGlmICh0aGlzLnNldHRpbmdzLmF1dG9Db252ZXJ0UmVtb3RlSW1hZ2VzICYmIHRoaXMuc2V0dGluZ3MuY29udmVydE9uTm90ZU9wZW4pIHtcblx0XHRcdFx0XHRpZiAodGhpcy5zZXR0aW5ncy5zdXBwb3J0ZWRFeHRlbnNpb25zLmluY2x1ZGVzKGZpbGUuZXh0ZW5zaW9uKSkge1xuXHRcdFx0XHRcdFx0Ly8gRmlyZS1hbmQtZm9yZ2V0OiBkb24ndCBibG9jayBmaWxlIG9wZW5cblx0XHRcdFx0XHRcdHZvaWQgKGFzeW5jICgpID0+IHtcblx0XHRcdFx0XHRcdFx0Ly8gU21hbGwgZGVsYXkgdG8gbGV0IGZpbGUgZnVsbHkgbG9hZFxuXHRcdFx0XHRcdFx0XHRhd2FpdCBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHNldFRpbWVvdXQocmVzb2x2ZSwgNTAwKSk7XG5cblx0XHRcdFx0XHRcdFx0Ly8gQ2hlY2sgaWYgdGhpcyBpcyB0aGUgYWN0aXZlIGZpbGVcblx0XHRcdFx0XHRcdFx0Y29uc3QgYWN0aXZlRmlsZSA9IHRoaXMuYXBwLndvcmtzcGFjZS5nZXRBY3RpdmVGaWxlKCk7XG5cdFx0XHRcdFx0XHRcdGNvbnN0IGlzQWN0aXZlRmlsZSA9IGFjdGl2ZUZpbGUgJiYgYWN0aXZlRmlsZS5wYXRoID09PSBmaWxlLnBhdGg7XG5cblx0XHRcdFx0XHRcdFx0Ly8gT25seSBwcm9jZXNzIGlmIGl0J3MgdGhlIGFjdGl2ZSBmaWxlIE9SIGJhY2tncm91bmQgcHJvY2Vzc2luZyBpcyBlbmFibGVkXG5cdFx0XHRcdFx0XHRcdGlmIChpc0FjdGl2ZUZpbGUgfHwgdGhpcy5zZXR0aW5ncy5wcm9jZXNzQmFja2dyb3VuZENoYW5nZXMpIHtcblx0XHRcdFx0XHRcdFx0XHRjb25zdCBjb3VudCA9IGF3YWl0IHRoaXMuY29udmVyc2lvblNlcnZpY2UucHJvY2Vzc0ZpbGUoZmlsZSwgIWlzQWN0aXZlRmlsZSk7XG5cdFx0XHRcdFx0XHRcdFx0aWYgKGNvdW50ID4gMCkge1xuXHRcdFx0XHRcdFx0XHRcdFx0bmV3IE5vdGljZShgQ29udmVydGVkICR7Y291bnR9IHJlbW90ZSBpbWFnZShzKSB0byBsb2NhbGApO1xuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fSkoKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBCYW5uZXIgcmVuZGVyaW5nIC0gb25seSBpZiBlbmFibGVkIGFuZCBmaWxlIGV4dGVuc2lvbiBpcyBzdXBwb3J0ZWRcblx0XHRcdFx0Ly8gQWxzbyBhbGxvdyAnbWQnIGFzIGEgZmFsbGJhY2sgaW4gY2FzZSB1c2VyIGRpZG4ndCBpbmNsdWRlIGl0IGluIHN1cHBvcnRlZEV4dGVuc2lvbnNcblx0XHRcdFx0Y29uc3QgZGV2aWNlU2V0dGluZ3MgPSB0aGlzLmJhbm5lclNlcnZpY2UuZ2V0RGV2aWNlU2V0dGluZ3MoKTtcblx0XHRcdFx0aWYgKGRldmljZVNldHRpbmdzLmVuYWJsZWQgJiYgKHRoaXMuc2V0dGluZ3Muc3VwcG9ydGVkRXh0ZW5zaW9ucy5pbmNsdWRlcyhmaWxlLmV4dGVuc2lvbikgfHwgZmlsZS5leHRlbnNpb24gPT09ICdtZCcpKSB7XG5cdFx0XHRcdFx0Y29uc3QgdmlldyA9IHRoaXMuYXBwLndvcmtzcGFjZS5nZXRBY3RpdmVWaWV3T2ZUeXBlKE1hcmtkb3duVmlldyk7XG5cdFx0XHRcdFx0aWYgKHZpZXcgaW5zdGFuY2VvZiBNYXJrZG93blZpZXcpIHtcblx0XHRcdFx0XHRcdHZvaWQgdGhpcy5iYW5uZXJTZXJ2aWNlLnByb2Nlc3MoZmlsZSwgdmlldyk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9KVxuXHRcdCk7XG5cblx0XHQvLyBMYXlvdXQgY2hhbmdlIGhhbmRsZXIgZm9yIGJhbm5lclxuXHRcdHRoaXMucmVnaXN0ZXJFdmVudChcblx0XHRcdHRoaXMuYXBwLndvcmtzcGFjZS5vbignbGF5b3V0LWNoYW5nZScsICgpID0+IHtcblx0XHRcdFx0Y29uc3QgZGV2aWNlU2V0dGluZ3MgPSB0aGlzLmJhbm5lclNlcnZpY2UuZ2V0RGV2aWNlU2V0dGluZ3MoKTtcblx0XHRcdFx0aWYgKCFkZXZpY2VTZXR0aW5ncy5lbmFibGVkKSB7XG5cdFx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Y29uc3QgdmlldyA9IHRoaXMuYXBwLndvcmtzcGFjZS5nZXRBY3RpdmVWaWV3T2ZUeXBlKE1hcmtkb3duVmlldyk7XG5cdFx0XHRcdC8vIEFsc28gYWxsb3cgJ21kJyBhcyBhIGZhbGxiYWNrIGluIGNhc2UgdXNlciBkaWRuJ3QgaW5jbHVkZSBpdCBpbiBzdXBwb3J0ZWRFeHRlbnNpb25zXG5cdFx0XHRcdGlmICh2aWV3ICYmIHZpZXcuZmlsZSAmJiAodGhpcy5zZXR0aW5ncy5zdXBwb3J0ZWRFeHRlbnNpb25zLmluY2x1ZGVzKHZpZXcuZmlsZS5leHRlbnNpb24pIHx8IHZpZXcuZmlsZS5leHRlbnNpb24gPT09ICdtZCcpKSB7XG5cdFx0XHRcdFx0Ly8gUHJvY2VzcyBpZiB0aGlzIHZpZXcgaGFzbid0IGJlZW4gcHJvY2Vzc2VkIHlldFxuXHRcdFx0XHRcdHZvaWQgdGhpcy5iYW5uZXJTZXJ2aWNlLnByb2Nlc3Modmlldy5maWxlLCB2aWV3KTtcblx0XHRcdFx0fVxuXHRcdFx0fSlcblx0XHQpO1xuXG5cdFx0Ly8gTWV0YWRhdGEgY2hhbmdlIGhhbmRsZXIgZm9yIGJhbm5lciB1cGRhdGVzXG5cdFx0dGhpcy5yZWdpc3RlckV2ZW50KFxuXHRcdFx0dGhpcy5hcHAubWV0YWRhdGFDYWNoZS5vbignY2hhbmdlZCcsIChmaWxlOiBURmlsZSkgPT4ge1xuXHRcdFx0XHQvLyBBdXRvLWNvbnZlcnNpb24gb24gc2F2ZSAobWV0YWRhdGEgY2hhbmdlKVxuXHRcdFx0XHRpZiAodGhpcy5zZXR0aW5ncy5hdXRvQ29udmVydFJlbW90ZUltYWdlcyAmJiB0aGlzLnNldHRpbmdzLmNvbnZlcnRPbk5vdGVTYXZlKSB7XG5cdFx0XHRcdFx0aWYgKHRoaXMuc2V0dGluZ3Muc3VwcG9ydGVkRXh0ZW5zaW9ucy5pbmNsdWRlcyhmaWxlLmV4dGVuc2lvbikpIHtcblx0XHRcdFx0XHRcdHZvaWQgKGFzeW5jICgpID0+IHtcblx0XHRcdFx0XHRcdFx0Ly8gQ2hlY2sgaWYgdGhpcyBpcyB0aGUgYWN0aXZlIGZpbGVcblx0XHRcdFx0XHRcdFx0Y29uc3QgYWN0aXZlRmlsZSA9IHRoaXMuYXBwLndvcmtzcGFjZS5nZXRBY3RpdmVGaWxlKCk7XG5cdFx0XHRcdFx0XHRcdGNvbnN0IGlzQWN0aXZlRmlsZSA9IGFjdGl2ZUZpbGUgJiYgYWN0aXZlRmlsZS5wYXRoID09PSBmaWxlLnBhdGg7XG5cblx0XHRcdFx0XHRcdFx0Ly8gT25seSBwcm9jZXNzIGlmIGl0J3MgdGhlIGFjdGl2ZSBmaWxlIE9SIGJhY2tncm91bmQgcHJvY2Vzc2luZyBpcyBlbmFibGVkXG5cdFx0XHRcdFx0XHRcdGlmIChpc0FjdGl2ZUZpbGUgfHwgdGhpcy5zZXR0aW5ncy5wcm9jZXNzQmFja2dyb3VuZENoYW5nZXMpIHtcblx0XHRcdFx0XHRcdFx0XHRjb25zdCBjb3VudCA9IGF3YWl0IHRoaXMuY29udmVyc2lvblNlcnZpY2UucHJvY2Vzc0ZpbGUoZmlsZSwgIWlzQWN0aXZlRmlsZSk7XG5cdFx0XHRcdFx0XHRcdFx0aWYgKGNvdW50ID4gMCkge1xuXHRcdFx0XHRcdFx0XHRcdFx0bmV3IE5vdGljZShgQ29udmVydGVkICR7Y291bnR9IHJlbW90ZSBpbWFnZShzKSB0byBsb2NhbGApO1xuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fSkoKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRjb25zdCBkZXZpY2VTZXR0aW5ncyA9IHRoaXMuYmFubmVyU2VydmljZS5nZXREZXZpY2VTZXR0aW5ncygpO1xuXHRcdFx0XHQvLyBBbHNvIGFsbG93ICdtZCcgYXMgYSBmYWxsYmFjayBpbiBjYXNlIHVzZXIgZGlkbid0IGluY2x1ZGUgaXQgaW4gc3VwcG9ydGVkRXh0ZW5zaW9uc1xuXHRcdFx0XHRpZiAoIWRldmljZVNldHRpbmdzLmVuYWJsZWQgfHwgKCF0aGlzLnNldHRpbmdzLnN1cHBvcnRlZEV4dGVuc2lvbnMuaW5jbHVkZXMoZmlsZS5leHRlbnNpb24pICYmIGZpbGUuZXh0ZW5zaW9uICE9PSAnbWQnKSkge1xuXHRcdFx0XHRcdHJldHVybjtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIE9ubHkgaXRlcmF0ZSBsZWF2ZXMgdGhhdCBhcmUgbWFya2Rvd24gdmlld3MgZm9yIHRoaXMgZmlsZVxuXHRcdFx0XHR0aGlzLmFwcC53b3Jrc3BhY2UuaXRlcmF0ZVJvb3RMZWF2ZXMoKGxlYWY6IFdvcmtzcGFjZUxlYWYpID0+IHtcblx0XHRcdFx0XHRjb25zdCB2aWV3ID0gbGVhZi52aWV3IGFzIE1hcmtkb3duVmlldztcblx0XHRcdFx0XHRpZiAodmlldyBpbnN0YW5jZW9mIE1hcmtkb3duVmlldyAmJiB2aWV3LmZpbGUgPT09IGZpbGUpIHtcblx0XHRcdFx0XHRcdHZvaWQgdGhpcy5iYW5uZXJTZXJ2aWNlLnByb2Nlc3MoZmlsZSwgdmlldyk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9KTtcblx0XHRcdH0pXG5cdFx0KTtcblxuXHRcdC8vIEFwcGx5IGJhbm5lciBzZXR0aW5ncyB3aGVuIGxheW91dCBpcyByZWFkeVxuXHRcdHRoaXMuYXBwLndvcmtzcGFjZS5vbkxheW91dFJlYWR5KCgpID0+IHtcblx0XHRcdHRoaXMuYmFubmVyU2VydmljZS5hcHBseVNldHRpbmdzKCk7XG5cdFx0fSk7XG5cdH1cblxuXHQvKipcblx0ICogUmVnaXN0ZXIgY29tbWFuZHNcblx0ICovXG5cdHByaXZhdGUgcmVnaXN0ZXJDb21tYW5kcygpOiB2b2lkIHtcblx0XHQvLyBJbnNlcnQgbG9jYWwgaW1hZ2Vcblx0XHR0aGlzLmFkZENvbW1hbmQoe1xuXHRcdFx0aWQ6ICdpbnNlcnQtaW1hZ2UnLFxuXHRcdFx0bmFtZTogJ0luc2VydCBsb2NhbCBpbWFnZScsXG5cdFx0XHRlZGl0b3JDYWxsYmFjazogKGVkaXRvcjogRWRpdG9yLCB2aWV3OiBNYXJrZG93blZpZXcpID0+IHtcblx0XHRcdFx0b3BlbkZpbGVQaWNrZXIodGhpcy5hcHAsIHRoaXMuaW1hZ2VQcm9jZXNzb3IsIHRoaXMucHJvcGVydHlIYW5kbGVyKTtcblx0XHRcdH0sXG5cdFx0fSk7XG5cblx0XHQvLyBJbnNlcnQgcmVtb3RlIGltYWdlXG5cdFx0dGhpcy5hZGRDb21tYW5kKHtcblx0XHRcdGlkOiAnc2VhcmNoLWltYWdlJyxcblx0XHRcdG5hbWU6ICdJbnNlcnQgcmVtb3RlIGltYWdlJyxcblx0XHRcdGVkaXRvckNhbGxiYWNrOiAoZWRpdG9yOiBFZGl0b3IsIHZpZXc6IE1hcmtkb3duVmlldykgPT4ge1xuXHRcdFx0XHRvcGVuUmVtb3RlU2VhcmNoKFxuXHRcdFx0XHRcdHRoaXMuYXBwLFxuXHRcdFx0XHRcdHRoaXMuc2V0dGluZ3MsXG5cdFx0XHRcdFx0dGhpcy5yZW1vdGVTZXJ2aWNlLFxuXHRcdFx0XHRcdHRoaXMuaW1hZ2VQcm9jZXNzb3IsXG5cdFx0XHRcdFx0dGhpcy5wcm9wZXJ0eUhhbmRsZXJcblx0XHRcdFx0KTtcblx0XHRcdH0sXG5cdFx0fSk7XG5cblx0XHQvLyBJbnNlcnQgcmVtb3RlIGltYWdlIHRvIHByb3BlcnR5XG5cdFx0dGhpcy5hZGRDb21tYW5kKHtcblx0XHRcdGlkOiAnaW5zZXJ0LXJlbW90ZS1pbWFnZS10by1wcm9wZXJ0eScsXG5cdFx0XHRuYW1lOiAnSW5zZXJ0IHJlbW90ZSBpbWFnZSB0byBwcm9wZXJ0eScsXG5cdFx0XHRlZGl0b3JDYWxsYmFjazogKGVkaXRvcjogRWRpdG9yLCB2aWV3OiBNYXJrZG93blZpZXcpID0+IHtcblx0XHRcdFx0b3BlblJlbW90ZVNlYXJjaChcblx0XHRcdFx0XHR0aGlzLmFwcCxcblx0XHRcdFx0XHR0aGlzLnNldHRpbmdzLFxuXHRcdFx0XHRcdHRoaXMucmVtb3RlU2VydmljZSxcblx0XHRcdFx0XHR0aGlzLmltYWdlUHJvY2Vzc29yLFxuXHRcdFx0XHRcdHRoaXMucHJvcGVydHlIYW5kbGVyLFxuXHRcdFx0XHRcdHsgaW5zZXJ0VG9Qcm9wZXJ0eTogdHJ1ZSwgcHJvcGVydHlOYW1lOiB0aGlzLnNldHRpbmdzLmRlZmF1bHRQcm9wZXJ0eU5hbWUgfVxuXHRcdFx0XHQpO1xuXHRcdFx0fSxcblx0XHR9KTtcblxuXHRcdC8vIEluc2VydCBsb2NhbCBpbWFnZSB0byBwcm9wZXJ0eVxuXHRcdHRoaXMuYWRkQ29tbWFuZCh7XG5cdFx0XHRpZDogJ2luc2VydC1sb2NhbC1pbWFnZS10by1wcm9wZXJ0eScsXG5cdFx0XHRuYW1lOiAnSW5zZXJ0IGxvY2FsIGltYWdlIHRvIHByb3BlcnR5Jyxcblx0XHRcdGVkaXRvckNhbGxiYWNrOiAoZWRpdG9yOiBFZGl0b3IsIHZpZXc6IE1hcmtkb3duVmlldykgPT4ge1xuXHRcdFx0XHRvcGVuRmlsZVBpY2tlcihcblx0XHRcdFx0XHR0aGlzLmFwcCxcblx0XHRcdFx0XHR0aGlzLmltYWdlUHJvY2Vzc29yLFxuXHRcdFx0XHRcdHRoaXMucHJvcGVydHlIYW5kbGVyLFxuXHRcdFx0XHRcdHRydWUsIC8vIGluc2VydFRvUHJvcGVydHlcblx0XHRcdFx0XHR0aGlzLnNldHRpbmdzLmRlZmF1bHRQcm9wZXJ0eU5hbWVcblx0XHRcdFx0KTtcblx0XHRcdH0sXG5cdFx0fSk7XG5cblx0XHQvLyBJbnNlcnQgcmVtb3RlIGltYWdlIHRvIGljb24gcHJvcGVydHlcblx0XHR0aGlzLmFkZENvbW1hbmQoe1xuXHRcdFx0aWQ6ICdpbnNlcnQtcmVtb3RlLWltYWdlLXRvLWljb24tcHJvcGVydHknLFxuXHRcdFx0bmFtZTogJ0luc2VydCByZW1vdGUgaW1hZ2UgdG8gaWNvbiBwcm9wZXJ0eScsXG5cdFx0XHRlZGl0b3JDYWxsYmFjazogKGVkaXRvcjogRWRpdG9yLCB2aWV3OiBNYXJrZG93blZpZXcpID0+IHtcblx0XHRcdFx0b3BlblJlbW90ZVNlYXJjaChcblx0XHRcdFx0XHR0aGlzLmFwcCxcblx0XHRcdFx0XHR0aGlzLnNldHRpbmdzLFxuXHRcdFx0XHRcdHRoaXMucmVtb3RlU2VydmljZSxcblx0XHRcdFx0XHR0aGlzLmltYWdlUHJvY2Vzc29yLFxuXHRcdFx0XHRcdHRoaXMucHJvcGVydHlIYW5kbGVyLFxuXHRcdFx0XHRcdHsgaW5zZXJ0VG9Qcm9wZXJ0eTogdHJ1ZSwgcHJvcGVydHlOYW1lOiB0aGlzLnNldHRpbmdzLmRlZmF1bHRJY29uUHJvcGVydHlOYW1lIH1cblx0XHRcdFx0KTtcblx0XHRcdH0sXG5cdFx0fSk7XG5cblx0XHQvLyBJbnNlcnQgbG9jYWwgaW1hZ2UgdG8gaWNvbiBwcm9wZXJ0eVxuXHRcdHRoaXMuYWRkQ29tbWFuZCh7XG5cdFx0XHRpZDogJ2luc2VydC1sb2NhbC1pbWFnZS10by1pY29uLXByb3BlcnR5Jyxcblx0XHRcdG5hbWU6ICdJbnNlcnQgbG9jYWwgaW1hZ2UgdG8gaWNvbiBwcm9wZXJ0eScsXG5cdFx0XHRlZGl0b3JDYWxsYmFjazogKGVkaXRvcjogRWRpdG9yLCB2aWV3OiBNYXJrZG93blZpZXcpID0+IHtcblx0XHRcdFx0b3BlbkZpbGVQaWNrZXIoXG5cdFx0XHRcdFx0dGhpcy5hcHAsXG5cdFx0XHRcdFx0dGhpcy5pbWFnZVByb2Nlc3Nvcixcblx0XHRcdFx0XHR0aGlzLnByb3BlcnR5SGFuZGxlcixcblx0XHRcdFx0XHR0cnVlLCAvLyBpbnNlcnRUb1Byb3BlcnR5XG5cdFx0XHRcdFx0dGhpcy5zZXR0aW5ncy5kZWZhdWx0SWNvblByb3BlcnR5TmFtZVxuXHRcdFx0XHQpO1xuXHRcdFx0fSxcblx0XHR9KTtcblxuXHRcdC8vIENvbnZlcnQgcmVtb3RlIGltYWdlcyBpbiBjdXJyZW50IGZpbGVcblx0XHR0aGlzLmFkZENvbW1hbmQoe1xuXHRcdFx0aWQ6ICdjb252ZXJ0LXJlbW90ZS1pbWFnZXMnLFxuXHRcdFx0bmFtZTogJ0NvbnZlcnQgcmVtb3RlIGltYWdlcycsXG5cdFx0XHRlZGl0b3JDYWxsYmFjazogYXN5bmMgKGVkaXRvcjogRWRpdG9yLCB2aWV3OiBNYXJrZG93blZpZXcpID0+IHtcblx0XHRcdFx0Y29uc3QgZmlsZSA9IHZpZXcuZmlsZTtcblx0XHRcdFx0aWYgKCFmaWxlKSB7XG5cdFx0XHRcdFx0bmV3IE5vdGljZSgnTm8gYWN0aXZlIGZpbGUnKTtcblx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRjb25zdCBjb3VudCA9IGF3YWl0IHRoaXMuY29udmVyc2lvblNlcnZpY2UucHJvY2Vzc0ZpbGUoZmlsZSk7XG5cdFx0XHRcdGlmIChjb3VudCA+IDApIHtcblx0XHRcdFx0XHRuZXcgTm90aWNlKGBDb252ZXJ0ZWQgJHtjb3VudH0gcmVtb3RlIGltYWdlKHMpIHRvIGxvY2FsYCk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0bmV3IE5vdGljZSgnTm8gcmVtb3RlIGltYWdlcyBmb3VuZCcpO1xuXHRcdFx0XHR9XG5cdFx0XHR9LFxuXHRcdH0pO1xuXG5cdFx0Ly8gQ29udmVydCByZW1vdGUgaW1hZ2VzIGluIGFsbCBmaWxlc1xuXHRcdHRoaXMuYWRkQ29tbWFuZCh7XG5cdFx0XHRpZDogJ2NvbnZlcnQtYWxsLXJlbW90ZS1pbWFnZXMnLFxuXHRcdFx0bmFtZTogJ0NvbnZlcnQgYWxsIHJlbW90ZSBpbWFnZXMnLFxuXHRcdFx0Y2FsbGJhY2s6IGFzeW5jICgpID0+IHtcblx0XHRcdFx0Y29uc3QgeyBvcGVuQ29uZmlybU1vZGFsIH0gPSBhd2FpdCBpbXBvcnQoJy4vbW9kYWxzL0NvbmZpcm1Nb2RhbCcpO1xuXHRcdFx0XHRjb25zdCByZXN1bHQgPSBhd2FpdCBvcGVuQ29uZmlybU1vZGFsKFxuXHRcdFx0XHRcdHRoaXMuYXBwLFxuXHRcdFx0XHRcdCdDb252ZXJ0IEFsbCBSZW1vdGUgSW1hZ2VzJyxcblx0XHRcdFx0XHQnVGhpcyB3aWxsIHNjYW4gYWxsIGZpbGVzIGluIHlvdXIgdmF1bHQgYW5kIGNvbnZlcnQgZXZlcnkgcmVtb3RlIGltYWdlIFVSTCB0byBhIGxvY2FsIGZpbGUuIFRoaXMgYWN0aW9uIGNhbm5vdCBiZSB1bmRvbmUuXFxuXFxuRWFjaCBpbWFnZSB3aWxsIGJlIGRvd25sb2FkZWQgYW5kIHlvdVxcJ2xsIGJlIHByb21wdGVkIHRvIHJlbmFtZSB0aGVtLiBUaGlzIG1heSB0YWtlIGEgd2hpbGUgaWYgeW91IGhhdmUgbWFueSBpbWFnZXMuXFxuXFxuQXJlIHlvdSBzdXJlIHlvdSB3YW50IHRvIHByb2NlZWQ/Jyxcblx0XHRcdFx0XHQnWWVzLCBjb252ZXJ0IGFsbCBpbWFnZXMnLFxuXHRcdFx0XHRcdCdDYW5jZWwnXG5cdFx0XHRcdCk7XG5cblx0XHRcdFx0aWYgKCFyZXN1bHQuY29uZmlybWVkKSB7XG5cdFx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0bmV3IE5vdGljZSgnUHJvY2Vzc2luZyBhbGwgZmlsZXMuLi4gVGhpcyBtYXkgdGFrZSBhIHdoaWxlLicpO1xuXHRcdFx0XHRjb25zdCBjb3VudCA9IGF3YWl0IHRoaXMuY29udmVyc2lvblNlcnZpY2UucHJvY2Vzc0FsbEZpbGVzKCk7XG5cdFx0XHRcdG5ldyBOb3RpY2UoYENvbnZlcnRlZCAke2NvdW50fSByZW1vdGUgaW1hZ2UocykgdG8gbG9jYWxgKTtcblx0XHRcdH0sXG5cdFx0fSk7XG5cdH1cblxuXHQvKipcblx0ICogTG9hZCBzZXR0aW5ncyBmcm9tIHN0b3JhZ2Vcblx0ICovXG5cdGFzeW5jIGxvYWRTZXR0aW5ncygpOiBQcm9taXNlPHZvaWQ+IHtcblx0XHRjb25zdCBkYXRhID0gYXdhaXQgdGhpcy5sb2FkRGF0YSgpIGFzIFBhcnRpYWw8SW1hZ2VNYW5hZ2VyU2V0dGluZ3M+IHwgbnVsbDtcblx0XHR0aGlzLnNldHRpbmdzID0gT2JqZWN0LmFzc2lnbih7fSwgREVGQVVMVF9TRVRUSU5HUywgZGF0YSA/PyB7fSk7XG5cdH1cblxuXHQvKipcblx0ICogU2F2ZSBzZXR0aW5ncyB0byBzdG9yYWdlXG5cdCAqL1xuXHRhc3luYyBzYXZlU2V0dGluZ3MoKTogUHJvbWlzZTx2b2lkPiB7XG5cdFx0YXdhaXQgdGhpcy5zYXZlRGF0YSh0aGlzLnNldHRpbmdzKTtcblxuXHRcdC8vIE5vdGlmeSBhbGwgc2VydmljZXMgb2YgdGhlIHNldHRpbmdzIGNoYW5nZVxuXHRcdHRoaXMuc2V0dGluZ3NPYnNlcnZhYmxlLm5vdGlmeSh0aGlzLnNldHRpbmdzKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBEZWJ1ZyBsb2dnaW5nXG5cdCAqL1xuXHRwcml2YXRlIGxvZyguLi5hcmdzOiB1bmtub3duW10pOiB2b2lkIHtcblx0XHRpZiAodGhpcy5zZXR0aW5ncz8uZGVidWdNb2RlKSB7XG5cdFx0XHRjb25zb2xlLmRlYnVnKCdbSW1hZ2UgTWFuYWdlcl0nLCAuLi5hcmdzKTtcblx0XHR9XG5cdH1cbn1cbiIsICIvKipcclxuICogSW1hZ2UgTWFuYWdlciBQbHVnaW4gU2V0dGluZ3NcclxuICogU2V0dGluZ3MgdGFiIHdpdGggU2V0dGluZ0dyb3VwIGNvbXBhdGliaWxpdHkgZm9yIE9ic2lkaWFuIDEuMTEuMCtcclxuICovXHJcblxyXG5pbXBvcnQgeyBBcHAsIEJhc2VDb21wb25lbnQsIFBsYXRmb3JtLCBQbHVnaW5TZXR0aW5nVGFiLCByZXF1aXJlQXBpVmVyc2lvbiAsIFNldHRpbmdHcm91cH0gZnJvbSAnb2JzaWRpYW4nO1xyXG5cclxuaW1wb3J0IHtcclxuXHRJbWFnZU1hbmFnZXJTZXR0aW5ncyxcclxuXHRERUZBVUxUX1NFVFRJTkdTLFxyXG5cdEltYWdlUHJvdmlkZXIsXHJcblx0SW1hZ2VPcmllbnRhdGlvbixcclxuXHRJbWFnZVNpemUsXHJcblx0UHJvcGVydHlMaW5rRm9ybWF0LFxyXG5cdEF0dGFjaG1lbnRMb2NhdGlvbixcclxuXHREZXZpY2VUeXBlLFxyXG5cdERFRkFVTFRfQkFOTkVSX0RFVklDRV9TRVRUSU5HUyxcclxufSBmcm9tICcuL3R5cGVzJztcclxuaW1wb3J0IHR5cGUgSW1hZ2VNYW5hZ2VyUGx1Z2luIGZyb20gJy4vbWFpbic7XHJcblxyXG4vKipcclxuICogSW50ZXJmYWNlIGZvciBTZWNyZXRDb21wb25lbnQgYWNjZXNzZWQgdmlhIGR5bmFtaWMgcmVxdWlyZVxyXG4gKiBTZWNyZXRDb21wb25lbnQgaXMgbm90IGF2YWlsYWJsZSBpbiB0eXBlIGRlZmluaXRpb25zIGZvciBhbGwgT2JzaWRpYW4gdmVyc2lvbnNcclxuICovXHJcbmludGVyZmFjZSBTZWNyZXRDb21wb25lbnRUeXBlIHtcclxuXHRuZXcoYXBwOiBBcHAsIGVsOiBIVE1MRWxlbWVudCk6IEJhc2VDb21wb25lbnQgJiB7XHJcblx0XHRzZXRWYWx1ZSh2YWx1ZTogc3RyaW5nKTogdm9pZDtcclxuXHRcdG9uQ2hhbmdlKGNhbGxiYWNrOiAodmFsdWU6IHN0cmluZykgPT4gdm9pZCk6IHZvaWQ7XHJcblx0fTtcclxufVxyXG5cclxuZXhwb3J0IHsgREVGQVVMVF9TRVRUSU5HUyB9O1xyXG5leHBvcnQgdHlwZSB7IEltYWdlTWFuYWdlclNldHRpbmdzIH07XHJcblxyXG5leHBvcnQgY2xhc3MgSW1hZ2VNYW5hZ2VyU2V0dGluZ1RhYiBleHRlbmRzIFBsdWdpblNldHRpbmdUYWIge1xyXG5cdHBsdWdpbjogSW1hZ2VNYW5hZ2VyUGx1Z2luO1xyXG5cdHB1YmxpYyBpY29uID0gJ2x1Y2lkZS1pbWFnZS1kb3duJztcclxuXHJcblx0Y29uc3RydWN0b3IoYXBwOiBBcHAsIHBsdWdpbjogSW1hZ2VNYW5hZ2VyUGx1Z2luKSB7XHJcblx0XHRzdXBlcihhcHAsIHBsdWdpbik7XHJcblx0XHR0aGlzLnBsdWdpbiA9IHBsdWdpbjtcclxuXHR9XHJcblxyXG5cdGRpc3BsYXkoKTogdm9pZCB7XHJcblx0XHRjb25zdCB7IGNvbnRhaW5lckVsIH0gPSB0aGlzO1xyXG5cdFx0Y29udGFpbmVyRWwuZW1wdHkoKTtcclxuXHJcblx0XHQvLyBHZW5lcmFsIFNldHRpbmdzXHJcblx0XHR0aGlzLnJlbmRlckdlbmVyYWxTZXR0aW5ncyhjb250YWluZXJFbCk7XHJcblxyXG5cdFx0Ly8gSW1hZ2UgU2VydmljZXNcclxuXHRcdHRoaXMucmVuZGVySW1hZ2VTZXJ2aWNlc1NldHRpbmdzKGNvbnRhaW5lckVsKTtcclxuXHJcblx0XHQvLyBQcm9wZXJ0eSBJbnNlcnRpb25cclxuXHRcdHRoaXMucmVuZGVyUHJvcGVydHlTZXR0aW5ncyhjb250YWluZXJFbCk7XHJcblxyXG5cdFx0Ly8gQ29udmVyc2lvblxyXG5cdFx0dGhpcy5yZW5kZXJDb252ZXJzaW9uU2V0dGluZ3MoY29udGFpbmVyRWwpO1xyXG5cclxuXHRcdC8vIFJlbmFtZSBPcHRpb25zXHJcblx0XHR0aGlzLnJlbmRlclJlbmFtZVNldHRpbmdzKGNvbnRhaW5lckVsKTtcclxuXHJcblx0XHQvLyBCYW5uZXIgSW1hZ2VzXHJcblx0XHR0aGlzLnJlbmRlckJhbm5lclNldHRpbmdzKGNvbnRhaW5lckVsKTtcclxuXHJcblx0XHQvLyBBZHZhbmNlZFxyXG5cdFx0dGhpcy5yZW5kZXJBZHZhbmNlZFNldHRpbmdzKGNvbnRhaW5lckVsKTtcclxuXHR9XHJcblxyXG5cdHByaXZhdGUgcmVuZGVyR2VuZXJhbFNldHRpbmdzKGNvbnRhaW5lckVsOiBIVE1MRWxlbWVudCk6IHZvaWQge1xyXG5cdFx0Ly8gR2VuZXJhbCBzZXR0aW5ncyB3aXRob3V0IGhlYWRpbmcgKGZpcnN0IHNlY3Rpb24gZG9lc24ndCBuZWVkIGEgaGVhZGluZylcclxuXHRcdGNvbnN0IGdyb3VwID0gbmV3IFNldHRpbmdHcm91cChjb250YWluZXJFbCk7XHJcblxyXG5cdFx0Z3JvdXAuYWRkU2V0dGluZyhzZXR0aW5nID0+IHtcclxuXHRcdFx0c2V0dGluZ1xyXG5cdFx0XHRcdC5zZXROYW1lKCdJbWFnZSBuYW1lIHRlbXBsYXRlJylcclxuXHRcdFx0XHQuc2V0RGVzYygnVGVtcGxhdGUgZm9yIGdlbmVyYXRlZCBpbWFnZSBuYW1lcy4gVmFyaWFibGVzOiB7e2ZpbGVOYW1lfX0sIHt7ZGlyTmFtZX19LCB7e0RBVEU6WVlZWS1NTS1ERH19LCB7e1RJTUU6SEgtbW0tc3N9fScpXHJcblx0XHRcdFx0LmFkZFRleHQodGV4dCA9PiB7XHJcblx0XHRcdFx0XHR0ZXh0XHJcblx0XHRcdFx0XHRcdC5zZXRQbGFjZWhvbGRlcigne3tmaWxlTmFtZX19JylcclxuXHRcdFx0XHRcdFx0LnNldFZhbHVlKHRoaXMucGx1Z2luLnNldHRpbmdzLmltYWdlTmFtZVRlbXBsYXRlKVxyXG5cdFx0XHRcdFx0XHQub25DaGFuZ2UoYXN5bmMgdmFsdWUgPT4ge1xyXG5cdFx0XHRcdFx0XHRcdHRoaXMucGx1Z2luLnNldHRpbmdzLmltYWdlTmFtZVRlbXBsYXRlID0gdmFsdWU7XHJcblx0XHRcdFx0XHRcdFx0YXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XHJcblx0XHRcdFx0XHRcdH0pO1xyXG5cdFx0XHRcdH0pO1xyXG5cdFx0fSk7XHJcblxyXG5cdFx0Z3JvdXAuYWRkU2V0dGluZyhzZXR0aW5nID0+IHtcclxuXHRcdFx0c2V0dGluZ1xyXG5cdFx0XHRcdC5zZXROYW1lKCdBdHRhY2htZW50IGxvY2F0aW9uJylcclxuXHRcdFx0XHQuc2V0RGVzYygnV2hlcmUgdG8gc2F2ZSBpbnNlcnRlZCBpbWFnZXMnKVxyXG5cdFx0XHRcdC5hZGREcm9wZG93bihkcm9wZG93biA9PiB7XHJcblx0XHRcdFx0XHRkcm9wZG93blxyXG5cdFx0XHRcdFx0XHQuYWRkT3B0aW9uKEF0dGFjaG1lbnRMb2NhdGlvbi5PYnNpZGlhbkRlZmF1bHQsIFwiVXNlIE9ic2lkaWFuJ3Mgc2V0dGluZ3NcIilcclxuXHRcdFx0XHRcdFx0LmFkZE9wdGlvbihBdHRhY2htZW50TG9jYXRpb24uU2FtZUZvbGRlciwgJ1NhbWUgZm9sZGVyIGFzIG5vdGUnKVxyXG5cdFx0XHRcdFx0XHQuYWRkT3B0aW9uKEF0dGFjaG1lbnRMb2NhdGlvbi5TdWJmb2xkZXIsICdTdWJmb2xkZXIgKGNvbmZpZ3VyZSBiZWxvdyknKVxyXG5cdFx0XHRcdFx0XHQuYWRkT3B0aW9uKEF0dGFjaG1lbnRMb2NhdGlvbi5WYXVsdEZvbGRlciwgJ1ZhdWx0IGZvbGRlciAoY29uZmlndXJlIGJlbG93KScpXHJcblx0XHRcdFx0XHRcdC5zZXRWYWx1ZSh0aGlzLnBsdWdpbi5zZXR0aW5ncy5hdHRhY2htZW50TG9jYXRpb24pXHJcblx0XHRcdFx0XHRcdC5vbkNoYW5nZShhc3luYyB2YWx1ZSA9PiB7XHJcblx0XHRcdFx0XHRcdFx0dGhpcy5wbHVnaW4uc2V0dGluZ3MuYXR0YWNobWVudExvY2F0aW9uID0gdmFsdWUgYXMgQXR0YWNobWVudExvY2F0aW9uO1xyXG5cdFx0XHRcdFx0XHRcdGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xyXG5cclxuXHRcdFx0XHRcdFx0XHQvLyBQcmVzZXJ2ZSBzY3JvbGwgcG9zaXRpb24gd2hlbiByZS1yZW5kZXJpbmdcclxuXHRcdFx0XHRcdFx0XHRjb25zdCBzY3JvbGxDb250YWluZXIgPSBjb250YWluZXJFbC5jbG9zZXN0KCcudmVydGljYWwtdGFiLWNvbnRlbnQnKSB8fFxyXG5cdFx0XHRcdFx0XHRcdFx0Y29udGFpbmVyRWwuY2xvc2VzdCgnLnNldHRpbmdzLWNvbnRlbnQnKSB8fFxyXG5cdFx0XHRcdFx0XHRcdFx0Y29udGFpbmVyRWwucGFyZW50RWxlbWVudDtcclxuXHRcdFx0XHRcdFx0XHRjb25zdCBzY3JvbGxUb3AgPSBzY3JvbGxDb250YWluZXI/LnNjcm9sbFRvcCB8fCAwO1xyXG5cclxuXHRcdFx0XHRcdFx0XHR0aGlzLmRpc3BsYXkoKTsgLy8gUmVmcmVzaCB0byBzaG93L2hpZGUgcGF0aCBpbnB1dFxyXG5cclxuXHRcdFx0XHRcdFx0XHQvLyBSZXN0b3JlIHNjcm9sbCBwb3NpdGlvbiBhZnRlciByZW5kZXJpbmdcclxuXHRcdFx0XHRcdFx0XHRyZXF1ZXN0QW5pbWF0aW9uRnJhbWUoKCkgPT4ge1xyXG5cdFx0XHRcdFx0XHRcdFx0aWYgKHNjcm9sbENvbnRhaW5lcikge1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRzY3JvbGxDb250YWluZXIuc2Nyb2xsVG9wID0gc2Nyb2xsVG9wO1xyXG5cdFx0XHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHRcdH0pO1xyXG5cdFx0XHRcdFx0XHR9KTtcclxuXHRcdFx0XHR9KTtcclxuXHRcdH0pO1xyXG5cclxuXHRcdC8vIFNob3cgY3VzdG9tIHBhdGggaW5wdXQgaWYgbm90IHVzaW5nIE9ic2lkaWFuIGRlZmF1bHRcclxuXHRcdGlmICh0aGlzLnBsdWdpbi5zZXR0aW5ncy5hdHRhY2htZW50TG9jYXRpb24gIT09IEF0dGFjaG1lbnRMb2NhdGlvbi5PYnNpZGlhbkRlZmF1bHQgJiZcclxuXHRcdFx0dGhpcy5wbHVnaW4uc2V0dGluZ3MuYXR0YWNobWVudExvY2F0aW9uICE9PSBBdHRhY2htZW50TG9jYXRpb24uU2FtZUZvbGRlcikge1xyXG5cdFx0XHRncm91cC5hZGRTZXR0aW5nKHNldHRpbmcgPT4ge1xyXG5cdFx0XHRcdHNldHRpbmdcclxuXHRcdFx0XHRcdC5zZXROYW1lKCdDdXN0b20gYXR0YWNobWVudCBwYXRoJylcclxuXHRcdFx0XHRcdC5zZXREZXNjKCdQYXRoIGZvciBhdHRhY2htZW50cy4gVXNlIFwiLi9cIiBmb3IgcmVsYXRpdmUgdG8gbm90ZSwgb3IgXCIvXCIgZm9yIHZhdWx0IHJvb3QuJylcclxuXHRcdFx0XHRcdC5hZGRUZXh0KHRleHQgPT4ge1xyXG5cdFx0XHRcdFx0XHR0ZXh0XHJcblx0XHRcdFx0XHRcdFx0LnNldFBsYWNlaG9sZGVyKCcuL2Fzc2V0cycpXHJcblx0XHRcdFx0XHRcdFx0LnNldFZhbHVlKHRoaXMucGx1Z2luLnNldHRpbmdzLmN1c3RvbUF0dGFjaG1lbnRQYXRoKVxyXG5cdFx0XHRcdFx0XHRcdC5vbkNoYW5nZShhc3luYyB2YWx1ZSA9PiB7XHJcblx0XHRcdFx0XHRcdFx0XHR0aGlzLnBsdWdpbi5zZXR0aW5ncy5jdXN0b21BdHRhY2htZW50UGF0aCA9IHZhbHVlO1xyXG5cdFx0XHRcdFx0XHRcdFx0YXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XHJcblx0XHRcdFx0XHRcdFx0fSk7XHJcblx0XHRcdFx0XHR9KTtcclxuXHRcdFx0fSk7XHJcblx0XHR9XHJcblx0fVxyXG5cclxuXHRwcml2YXRlIHJlbmRlckltYWdlU2VydmljZXNTZXR0aW5ncyhjb250YWluZXJFbDogSFRNTEVsZW1lbnQpOiB2b2lkIHtcclxuXHRcdGNvbnN0IGdyb3VwID0gbmV3IFNldHRpbmdHcm91cChjb250YWluZXJFbCkuc2V0SGVhZGluZygnSW1hZ2Ugc2VydmljZXMnKTtcclxuXHJcblx0XHRncm91cC5hZGRTZXR0aW5nKHNldHRpbmcgPT4ge1xyXG5cdFx0XHRzZXR0aW5nXHJcblx0XHRcdFx0LnNldE5hbWUoJ0RlZmF1bHQgcHJvdmlkZXInKVxyXG5cdFx0XHRcdC5zZXREZXNjKCdEZWZhdWx0IGltYWdlIHByb3ZpZGVyIGZvciBzZWFyY2gnKVxyXG5cdFx0XHRcdC5hZGREcm9wZG93bihkcm9wZG93biA9PiB7XHJcblx0XHRcdFx0XHRkcm9wZG93blxyXG5cdFx0XHRcdFx0XHQuYWRkT3B0aW9uKEltYWdlUHJvdmlkZXIuVW5zcGxhc2gsICdVbnNwbGFzaCcpXHJcblx0XHRcdFx0XHRcdC5hZGRPcHRpb24oSW1hZ2VQcm92aWRlci5QZXhlbHMsICdQZXhlbHMnKVxyXG5cdFx0XHRcdFx0XHQuYWRkT3B0aW9uKEltYWdlUHJvdmlkZXIuUGl4YWJheSwgJ1BpeGFiYXknKVxyXG5cdFx0XHRcdFx0XHQuYWRkT3B0aW9uKEltYWdlUHJvdmlkZXIuTG9jYWwsICdMb2NhbCBmaWxlcycpXHJcblx0XHRcdFx0XHRcdC5zZXRWYWx1ZSh0aGlzLnBsdWdpbi5zZXR0aW5ncy5kZWZhdWx0UHJvdmlkZXIpXHJcblx0XHRcdFx0XHRcdC5vbkNoYW5nZShhc3luYyB2YWx1ZSA9PiB7XHJcblx0XHRcdFx0XHRcdFx0dGhpcy5wbHVnaW4uc2V0dGluZ3MuZGVmYXVsdFByb3ZpZGVyID0gdmFsdWUgYXMgSW1hZ2VQcm92aWRlcjtcclxuXHRcdFx0XHRcdFx0XHRhd2FpdCB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKTtcclxuXHRcdFx0XHRcdFx0fSk7XHJcblx0XHRcdFx0fSk7XHJcblx0XHR9KTtcclxuXHJcblx0XHRncm91cC5hZGRTZXR0aW5nKHNldHRpbmcgPT4ge1xyXG5cdFx0XHRzZXR0aW5nXHJcblx0XHRcdFx0LnNldE5hbWUoJ0RlZmF1bHQgb3JpZW50YXRpb24nKVxyXG5cdFx0XHRcdC5zZXREZXNjKCdGaWx0ZXIgaW1hZ2VzIGJ5IG9yaWVudGF0aW9uJylcclxuXHRcdFx0XHQuYWRkRHJvcGRvd24oZHJvcGRvd24gPT4ge1xyXG5cdFx0XHRcdFx0ZHJvcGRvd25cclxuXHRcdFx0XHRcdFx0LmFkZE9wdGlvbihJbWFnZU9yaWVudGF0aW9uLkFueSwgJ0FueScpXHJcblx0XHRcdFx0XHRcdC5hZGRPcHRpb24oSW1hZ2VPcmllbnRhdGlvbi5MYW5kc2NhcGUsICdMYW5kc2NhcGUnKVxyXG5cdFx0XHRcdFx0XHQuYWRkT3B0aW9uKEltYWdlT3JpZW50YXRpb24uUG9ydHJhaXQsICdQb3J0cmFpdCcpXHJcblx0XHRcdFx0XHRcdC5hZGRPcHRpb24oSW1hZ2VPcmllbnRhdGlvbi5TcXVhcmUsICdTcXVhcmUnKVxyXG5cdFx0XHRcdFx0XHQuc2V0VmFsdWUodGhpcy5wbHVnaW4uc2V0dGluZ3MuZGVmYXVsdE9yaWVudGF0aW9uKVxyXG5cdFx0XHRcdFx0XHQub25DaGFuZ2UoYXN5bmMgdmFsdWUgPT4ge1xyXG5cdFx0XHRcdFx0XHRcdHRoaXMucGx1Z2luLnNldHRpbmdzLmRlZmF1bHRPcmllbnRhdGlvbiA9IHZhbHVlIGFzIEltYWdlT3JpZW50YXRpb247XHJcblx0XHRcdFx0XHRcdFx0YXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XHJcblx0XHRcdFx0XHRcdH0pO1xyXG5cdFx0XHRcdH0pO1xyXG5cdFx0fSk7XHJcblxyXG5cdFx0Z3JvdXAuYWRkU2V0dGluZyhzZXR0aW5nID0+IHtcclxuXHRcdFx0c2V0dGluZ1xyXG5cdFx0XHRcdC5zZXROYW1lKCdEZWZhdWx0IGltYWdlIHNpemUnKVxyXG5cdFx0XHRcdC5zZXREZXNjKCdQcmVmZXJyZWQgc2l6ZSB3aGVuIGRvd25sb2FkaW5nIGltYWdlcycpXHJcblx0XHRcdFx0LmFkZERyb3Bkb3duKGRyb3Bkb3duID0+IHtcclxuXHRcdFx0XHRcdGRyb3Bkb3duXHJcblx0XHRcdFx0XHRcdC5hZGRPcHRpb24oSW1hZ2VTaXplLk9yaWdpbmFsLCAnT3JpZ2luYWwnKVxyXG5cdFx0XHRcdFx0XHQuYWRkT3B0aW9uKEltYWdlU2l6ZS5MYXJnZSwgJ0xhcmdlJylcclxuXHRcdFx0XHRcdFx0LmFkZE9wdGlvbihJbWFnZVNpemUuTWVkaXVtLCAnTWVkaXVtJylcclxuXHRcdFx0XHRcdFx0LmFkZE9wdGlvbihJbWFnZVNpemUuU21hbGwsICdTbWFsbCcpXHJcblx0XHRcdFx0XHRcdC5zZXRWYWx1ZSh0aGlzLnBsdWdpbi5zZXR0aW5ncy5kZWZhdWx0SW1hZ2VTaXplKVxyXG5cdFx0XHRcdFx0XHQub25DaGFuZ2UoYXN5bmMgdmFsdWUgPT4ge1xyXG5cdFx0XHRcdFx0XHRcdHRoaXMucGx1Z2luLnNldHRpbmdzLmRlZmF1bHRJbWFnZVNpemUgPSB2YWx1ZSBhcyBJbWFnZVNpemU7XHJcblx0XHRcdFx0XHRcdFx0YXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XHJcblx0XHRcdFx0XHRcdH0pO1xyXG5cdFx0XHRcdH0pO1xyXG5cdFx0fSk7XHJcblxyXG5cdFx0Z3JvdXAuYWRkU2V0dGluZyhzZXR0aW5nID0+IHtcclxuXHRcdFx0c2V0dGluZ1xyXG5cdFx0XHRcdC5zZXROYW1lKCdVbnNwbGFzaCBwcm94eSBzZXJ2ZXInKVxyXG5cdFx0XHRcdC5zZXREZXNjKCdPcHRpb25hbCBwcm94eSBzZXJ2ZXIgKGxlYXZlIGVtcHR5IHRvIHVzZSBidWlsdC1pbiknKVxyXG5cdFx0XHRcdC5hZGRUZXh0KHRleHQgPT4ge1xyXG5cdFx0XHRcdFx0dGV4dFxyXG5cdFx0XHRcdFx0XHQuc2V0UGxhY2Vob2xkZXIoJ2h0dHBzOi8veW91ci1wcm94eS5jb20vJylcclxuXHRcdFx0XHRcdFx0LnNldFZhbHVlKHRoaXMucGx1Z2luLnNldHRpbmdzLnVuc3BsYXNoUHJveHlTZXJ2ZXIpXHJcblx0XHRcdFx0XHRcdC5vbkNoYW5nZShhc3luYyB2YWx1ZSA9PiB7XHJcblx0XHRcdFx0XHRcdFx0dGhpcy5wbHVnaW4uc2V0dGluZ3MudW5zcGxhc2hQcm94eVNlcnZlciA9IHZhbHVlO1xyXG5cdFx0XHRcdFx0XHRcdGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xyXG5cdFx0XHRcdFx0XHR9KTtcclxuXHRcdFx0XHR9KTtcclxuXHRcdH0pO1xyXG5cclxuXHRcdGdyb3VwLmFkZFNldHRpbmcoc2V0dGluZyA9PiB7XHJcblx0XHRcdHNldHRpbmcuc2V0TmFtZSgnUGV4ZWxzIEFQSSBrZXknKTtcclxuXHJcblx0XHRcdGlmIChyZXF1aXJlQXBpVmVyc2lvbignMS4xMS40JykpIHtcclxuXHRcdFx0XHQvLyBVc2UgU2VjcmV0Q29tcG9uZW50IGZvciBuZXdlciB2ZXJzaW9uc1xyXG5cdFx0XHRcdHNldHRpbmdcclxuXHRcdFx0XHRcdC5zZXREZXNjKCdDaG9vc2UgYSBzZWNyZXQgdGhhdCBjb250YWlucyB5b3VyIFBleGVscyBBUEkga2V5LicpXHJcblx0XHRcdFx0XHQuYWRkQ29tcG9uZW50KChlbCkgPT4ge1xyXG5cdFx0XHRcdFx0XHQvLyBVc2UgZHluYW1pYyByZXF1aXJlIHRvIGFjY2VzcyBTZWNyZXRDb21wb25lbnQgKG1heSBub3QgYmUgaW4gdHlwZSBkZWZpbml0aW9ucylcclxuXHRcdFx0XHRcdFx0Ly8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1yZXF1aXJlLWltcG9ydHMgLS0gU2VjcmV0Q29tcG9uZW50IG5vdCBpbiB0eXBlIGRlZmluaXRpb25zIGZvciBhbGwgT2JzaWRpYW4gdmVyc2lvbnNcclxuXHRcdFx0XHRcdFx0Y29uc3Qgb2JzaWRpYW4gPSByZXF1aXJlKCdvYnNpZGlhbicpIGFzIHsgU2VjcmV0Q29tcG9uZW50PzogU2VjcmV0Q29tcG9uZW50VHlwZSB9O1xyXG5cdFx0XHRcdFx0XHRjb25zdCBTZWNyZXRDb21wb25lbnQgPSBvYnNpZGlhbi5TZWNyZXRDb21wb25lbnQgYXMgU2VjcmV0Q29tcG9uZW50VHlwZTtcclxuXHRcdFx0XHRcdFx0Y29uc3QgY29tcG9uZW50ID0gbmV3IFNlY3JldENvbXBvbmVudCh0aGlzLmFwcCwgZWwpO1xyXG5cdFx0XHRcdFx0XHRjb21wb25lbnQuc2V0VmFsdWUodGhpcy5wbHVnaW4uc2V0dGluZ3MucGV4ZWxzQXBpS2V5U2VjcmV0SWQpO1xyXG5cdFx0XHRcdFx0XHRjb21wb25lbnQub25DaGFuZ2UoKHZhbHVlOiBzdHJpbmcpID0+IHtcclxuXHRcdFx0XHRcdFx0XHR2b2lkIChhc3luYyAoKSA9PiB7XHJcblx0XHRcdFx0XHRcdFx0XHR0aGlzLnBsdWdpbi5zZXR0aW5ncy5wZXhlbHNBcGlLZXlTZWNyZXRJZCA9IHZhbHVlO1xyXG5cdFx0XHRcdFx0XHRcdFx0YXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XHJcblx0XHRcdFx0XHRcdFx0fSkoKTtcclxuXHRcdFx0XHRcdFx0fSk7XHJcblx0XHRcdFx0XHRcdHJldHVybiBjb21wb25lbnQ7XHJcblx0XHRcdFx0XHR9KTtcclxuXHRcdFx0fSBlbHNlIHtcclxuXHRcdFx0XHQvLyBGYWxsIGJhY2sgdG8gcGxhaW50ZXh0IGZvciBvbGRlciB2ZXJzaW9uc1xyXG5cdFx0XHRcdHNldHRpbmdcclxuXHRcdFx0XHRcdC5zZXREZXNjKCdHZXQgeW91ciBBUEkga2V5IGZyb20gaHR0cHM6Ly93d3cucGV4ZWxzLmNvbS9hcGkvbmV3LycpXHJcblx0XHRcdFx0XHQuYWRkVGV4dCh0ZXh0ID0+IHtcclxuXHRcdFx0XHRcdFx0dGV4dFxyXG5cdFx0XHRcdFx0XHRcdC5zZXRQbGFjZWhvbGRlcignUGV4ZWxzIEFQSSBrZXknKVxyXG5cdFx0XHRcdFx0XHRcdC5zZXRWYWx1ZSh0aGlzLnBsdWdpbi5zZXR0aW5ncy5wZXhlbHNBcGlLZXkpXHJcblx0XHRcdFx0XHRcdFx0Lm9uQ2hhbmdlKGFzeW5jIHZhbHVlID0+IHtcclxuXHRcdFx0XHRcdFx0XHRcdHRoaXMucGx1Z2luLnNldHRpbmdzLnBleGVsc0FwaUtleSA9IHZhbHVlO1xyXG5cdFx0XHRcdFx0XHRcdFx0YXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XHJcblx0XHRcdFx0XHRcdFx0fSk7XHJcblx0XHRcdFx0XHR9KTtcclxuXHRcdFx0fVxyXG5cdFx0fSk7XHJcblxyXG5cdFx0Z3JvdXAuYWRkU2V0dGluZyhzZXR0aW5nID0+IHtcclxuXHRcdFx0c2V0dGluZy5zZXROYW1lKCdQaXhhYmF5IEFQSSBrZXknKTtcclxuXHJcblx0XHRcdGlmIChyZXF1aXJlQXBpVmVyc2lvbignMS4xMS40JykpIHtcclxuXHRcdFx0XHQvLyBVc2UgU2VjcmV0Q29tcG9uZW50IGZvciBuZXdlciB2ZXJzaW9uc1xyXG5cdFx0XHRcdHNldHRpbmdcclxuXHRcdFx0XHRcdC5zZXREZXNjKCdDaG9vc2UgYSBzZWNyZXQgdGhhdCBjb250YWlucyB5b3VyIFBpeGFiYXkgQVBJIGtleS4nKVxyXG5cdFx0XHRcdFx0LmFkZENvbXBvbmVudCgoZWwpID0+IHtcclxuXHRcdFx0XHRcdFx0Ly8gVXNlIGR5bmFtaWMgcmVxdWlyZSB0byBhY2Nlc3MgU2VjcmV0Q29tcG9uZW50IChtYXkgbm90IGJlIGluIHR5cGUgZGVmaW5pdGlvbnMpXHJcblx0XHRcdFx0XHRcdC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tcmVxdWlyZS1pbXBvcnRzIC0tIFNlY3JldENvbXBvbmVudCBub3QgaW4gdHlwZSBkZWZpbml0aW9ucyBmb3IgYWxsIE9ic2lkaWFuIHZlcnNpb25zXHJcblx0XHRcdFx0XHRcdGNvbnN0IG9ic2lkaWFuID0gcmVxdWlyZSgnb2JzaWRpYW4nKSBhcyB7IFNlY3JldENvbXBvbmVudD86IFNlY3JldENvbXBvbmVudFR5cGUgfTtcclxuXHRcdFx0XHRcdFx0Y29uc3QgU2VjcmV0Q29tcG9uZW50ID0gb2JzaWRpYW4uU2VjcmV0Q29tcG9uZW50IGFzIFNlY3JldENvbXBvbmVudFR5cGU7XHJcblx0XHRcdFx0XHRcdGNvbnN0IGNvbXBvbmVudCA9IG5ldyBTZWNyZXRDb21wb25lbnQodGhpcy5hcHAsIGVsKTtcclxuXHRcdFx0XHRcdFx0Y29tcG9uZW50LnNldFZhbHVlKHRoaXMucGx1Z2luLnNldHRpbmdzLnBpeGFiYXlBcGlLZXlTZWNyZXRJZCk7XHJcblx0XHRcdFx0XHRcdGNvbXBvbmVudC5vbkNoYW5nZSgodmFsdWU6IHN0cmluZykgPT4ge1xyXG5cdFx0XHRcdFx0XHRcdHZvaWQgKGFzeW5jICgpID0+IHtcclxuXHRcdFx0XHRcdFx0XHRcdHRoaXMucGx1Z2luLnNldHRpbmdzLnBpeGFiYXlBcGlLZXlTZWNyZXRJZCA9IHZhbHVlO1xyXG5cdFx0XHRcdFx0XHRcdFx0YXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XHJcblx0XHRcdFx0XHRcdFx0fSkoKTtcclxuXHRcdFx0XHRcdFx0fSk7XHJcblx0XHRcdFx0XHRcdHJldHVybiBjb21wb25lbnQ7XHJcblx0XHRcdFx0XHR9KTtcclxuXHRcdFx0fSBlbHNlIHtcclxuXHRcdFx0XHQvLyBGYWxsIGJhY2sgdG8gcGxhaW50ZXh0IGZvciBvbGRlciB2ZXJzaW9uc1xyXG5cdFx0XHRcdHNldHRpbmdcclxuXHRcdFx0XHRcdC5zZXREZXNjKCdHZXQgeW91ciBBUEkga2V5IGZyb20gaHR0cHM6Ly9waXhhYmF5LmNvbS9hcGkvZG9jcy8nKVxyXG5cdFx0XHRcdFx0LmFkZFRleHQodGV4dCA9PiB7XHJcblx0XHRcdFx0XHRcdHRleHRcclxuXHRcdFx0XHRcdFx0XHQuc2V0UGxhY2Vob2xkZXIoJ1BpeGFiYXkgQVBJIGtleScpXHJcblx0XHRcdFx0XHRcdFx0LnNldFZhbHVlKHRoaXMucGx1Z2luLnNldHRpbmdzLnBpeGFiYXlBcGlLZXkpXHJcblx0XHRcdFx0XHRcdFx0Lm9uQ2hhbmdlKGFzeW5jIHZhbHVlID0+IHtcclxuXHRcdFx0XHRcdFx0XHRcdHRoaXMucGx1Z2luLnNldHRpbmdzLnBpeGFiYXlBcGlLZXkgPSB2YWx1ZTtcclxuXHRcdFx0XHRcdFx0XHRcdGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xyXG5cdFx0XHRcdFx0XHRcdH0pO1xyXG5cdFx0XHRcdFx0fSk7XHJcblx0XHRcdH1cclxuXHRcdH0pO1xyXG5cclxuXHRcdGdyb3VwLmFkZFNldHRpbmcoc2V0dGluZyA9PiB7XHJcblx0XHRcdHNldHRpbmdcclxuXHRcdFx0XHQuc2V0TmFtZSgnSW5zZXJ0IHNpemUnKVxyXG5cdFx0XHRcdC5zZXREZXNjKCdTZXQgdGhlIHNpemUgb2YgdGhlIGltYWdlIHdoZW4gaW5zZXJ0aW5nLiBGb3JtYXQgY291bGQgYmUgb25seSB0aGUgd2lkdGggXCIyMDBcIiBvciB0aGUgd2lkdGggYW5kIGhlaWdodCBcIjIwMHgxMDBcIi4gTGVhdmUgZW1wdHkgZm9yIG5vIHNpemUuJylcclxuXHRcdFx0XHQuYWRkVGV4dCh0ZXh0ID0+IHtcclxuXHRcdFx0XHRcdHRleHRcclxuXHRcdFx0XHRcdFx0LnNldFBsYWNlaG9sZGVyKCcyMDAgb3IgMjAweDEwMCcpXHJcblx0XHRcdFx0XHRcdC5zZXRWYWx1ZSh0aGlzLnBsdWdpbi5zZXR0aW5ncy5pbnNlcnRTaXplKVxyXG5cdFx0XHRcdFx0XHQub25DaGFuZ2UoYXN5bmMgdmFsdWUgPT4ge1xyXG5cdFx0XHRcdFx0XHRcdHRoaXMucGx1Z2luLnNldHRpbmdzLmluc2VydFNpemUgPSB2YWx1ZTtcclxuXHRcdFx0XHRcdFx0XHRhd2FpdCB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKTtcclxuXHRcdFx0XHRcdFx0fSk7XHJcblx0XHRcdFx0fSk7XHJcblx0XHR9KTtcclxuXHJcblx0XHRncm91cC5hZGRTZXR0aW5nKHNldHRpbmcgPT4ge1xyXG5cdFx0XHRzZXR0aW5nXHJcblx0XHRcdFx0LnNldE5hbWUoJ0luc2VydCByZWZlcnJhbCcpXHJcblx0XHRcdFx0LnNldERlc2MoJ0luc2VydCB0aGUgcmVmZXJlbmNlIHRleHQnKVxyXG5cdFx0XHRcdC5hZGRUb2dnbGUodG9nZ2xlID0+IHtcclxuXHRcdFx0XHRcdHRvZ2dsZVxyXG5cdFx0XHRcdFx0XHQuc2V0VmFsdWUodGhpcy5wbHVnaW4uc2V0dGluZ3MuaW5zZXJ0UmVmZXJyYWwpXHJcblx0XHRcdFx0XHRcdC5vbkNoYW5nZShhc3luYyB2YWx1ZSA9PiB7XHJcblx0XHRcdFx0XHRcdFx0dGhpcy5wbHVnaW4uc2V0dGluZ3MuaW5zZXJ0UmVmZXJyYWwgPSB2YWx1ZTtcclxuXHRcdFx0XHRcdFx0XHRhd2FpdCB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKTtcclxuXHRcdFx0XHRcdFx0fSk7XHJcblx0XHRcdFx0fSk7XHJcblx0XHR9KTtcclxuXHJcblx0XHRncm91cC5hZGRTZXR0aW5nKHNldHRpbmcgPT4ge1xyXG5cdFx0XHRzZXR0aW5nXHJcblx0XHRcdFx0LnNldE5hbWUoJ0luc2VydCBiYWNrbGluaycpXHJcblx0XHRcdFx0LnNldERlc2MoJ0luc2VydCBhIGJhY2tsaW5rIGluIGZyb250IG9mIHRoZSByZWZlcmVuY2UgdGV4dCcpXHJcblx0XHRcdFx0LmFkZFRvZ2dsZSh0b2dnbGUgPT4ge1xyXG5cdFx0XHRcdFx0dG9nZ2xlXHJcblx0XHRcdFx0XHRcdC5zZXRWYWx1ZSh0aGlzLnBsdWdpbi5zZXR0aW5ncy5pbnNlcnRCYWNrTGluaylcclxuXHRcdFx0XHRcdFx0Lm9uQ2hhbmdlKGFzeW5jIHZhbHVlID0+IHtcclxuXHRcdFx0XHRcdFx0XHR0aGlzLnBsdWdpbi5zZXR0aW5ncy5pbnNlcnRCYWNrTGluayA9IHZhbHVlO1xyXG5cdFx0XHRcdFx0XHRcdGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xyXG5cdFx0XHRcdFx0XHR9KTtcclxuXHRcdFx0XHR9KTtcclxuXHRcdH0pO1xyXG5cdH1cclxuXHJcblx0cHJpdmF0ZSByZW5kZXJQcm9wZXJ0eVNldHRpbmdzKGNvbnRhaW5lckVsOiBIVE1MRWxlbWVudCk6IHZvaWQge1xyXG5cdFx0Y29uc3QgZ3JvdXAgPSBuZXcgU2V0dGluZ0dyb3VwKGNvbnRhaW5lckVsKS5zZXRIZWFkaW5nKCdQcm9wZXJ0eSBpbnNlcnRpb24nKTtcclxuXHJcblx0XHRncm91cC5hZGRTZXR0aW5nKHNldHRpbmcgPT4ge1xyXG5cdFx0XHRzZXR0aW5nXHJcblx0XHRcdFx0LnNldE5hbWUoJ0VuYWJsZSBwYXN0ZSBpbnRvIHByb3BlcnRpZXMnKVxyXG5cdFx0XHRcdC5zZXREZXNjKCdBbGxvdyBwYXN0aW5nIGltYWdlcyBkaXJlY3RseSBpbnRvIHByb3BlcnRpZXMnKVxyXG5cdFx0XHRcdC5hZGRUb2dnbGUodG9nZ2xlID0+IHtcclxuXHRcdFx0XHRcdHRvZ2dsZVxyXG5cdFx0XHRcdFx0XHQuc2V0VmFsdWUodGhpcy5wbHVnaW4uc2V0dGluZ3MuZW5hYmxlUHJvcGVydHlQYXN0ZSlcclxuXHRcdFx0XHRcdFx0Lm9uQ2hhbmdlKGFzeW5jIHZhbHVlID0+IHtcclxuXHRcdFx0XHRcdFx0XHR0aGlzLnBsdWdpbi5zZXR0aW5ncy5lbmFibGVQcm9wZXJ0eVBhc3RlID0gdmFsdWU7XHJcblx0XHRcdFx0XHRcdFx0YXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XHJcblx0XHRcdFx0XHRcdH0pO1xyXG5cdFx0XHRcdH0pO1xyXG5cdFx0fSk7XHJcblxyXG5cdFx0Z3JvdXAuYWRkU2V0dGluZyhzZXR0aW5nID0+IHtcclxuXHRcdFx0c2V0dGluZ1xyXG5cdFx0XHRcdC5zZXROYW1lKCdQcm9wZXJ0eSBsaW5rIGZvcm1hdCcpXHJcblx0XHRcdFx0LnNldERlc2MoJ0hvdyB0byBmb3JtYXQgdGhlIGltYWdlIGxpbmsgaW4gcHJvcGVydGllcycpXHJcblx0XHRcdFx0LmFkZERyb3Bkb3duKGRyb3Bkb3duID0+IHtcclxuXHRcdFx0XHRcdGRyb3Bkb3duXHJcblx0XHRcdFx0XHRcdC5hZGRPcHRpb24oUHJvcGVydHlMaW5rRm9ybWF0Lk9ic2lkaWFuRGVmYXVsdCwgXCJVc2UgT2JzaWRpYW4ncyBzZXR0aW5nc1wiKVxyXG5cdFx0XHRcdFx0XHQuYWRkT3B0aW9uKFByb3BlcnR5TGlua0Zvcm1hdC5QYXRoLCAnUGxhaW4gcGF0aCAocGF0aC90by9pbWFnZS5qcGcpJylcclxuXHRcdFx0XHRcdFx0LmFkZE9wdGlvbihQcm9wZXJ0eUxpbmtGb3JtYXQuUmVsYXRpdmVQYXRoLCAnUmVsYXRpdmUgcGF0aCAoLi9pbWFnZS5qcGcpJylcclxuXHRcdFx0XHRcdFx0LmFkZE9wdGlvbihQcm9wZXJ0eUxpbmtGb3JtYXQuV2lraWxpbmssICdXaWtpbGluayAoW1twYXRoL3RvL2ltYWdlLmpwZ11dKScpXHJcblx0XHRcdFx0XHRcdC5hZGRPcHRpb24oUHJvcGVydHlMaW5rRm9ybWF0Lk1hcmtkb3duLCAnTWFya2Rvd24gKCFbXShwYXRoL3RvL2ltYWdlLmpwZykpJylcclxuXHRcdFx0XHRcdFx0LmFkZE9wdGlvbihQcm9wZXJ0eUxpbmtGb3JtYXQuQ3VzdG9tLCAnQ3VzdG9tIGZvcm1hdCcpXHJcblx0XHRcdFx0XHRcdC5zZXRWYWx1ZSh0aGlzLnBsdWdpbi5zZXR0aW5ncy5wcm9wZXJ0eUxpbmtGb3JtYXQpXHJcblx0XHRcdFx0XHRcdC5vbkNoYW5nZShhc3luYyB2YWx1ZSA9PiB7XHJcblx0XHRcdFx0XHRcdFx0dGhpcy5wbHVnaW4uc2V0dGluZ3MucHJvcGVydHlMaW5rRm9ybWF0ID0gdmFsdWUgYXMgUHJvcGVydHlMaW5rRm9ybWF0O1xyXG5cdFx0XHRcdFx0XHRcdGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xyXG5cclxuXHRcdFx0XHRcdFx0XHQvLyBQcmVzZXJ2ZSBzY3JvbGwgcG9zaXRpb24gd2hlbiByZS1yZW5kZXJpbmdcclxuXHRcdFx0XHRcdFx0XHRjb25zdCBzY3JvbGxDb250YWluZXIgPSBjb250YWluZXJFbC5jbG9zZXN0KCcudmVydGljYWwtdGFiLWNvbnRlbnQnKSB8fFxyXG5cdFx0XHRcdFx0XHRcdFx0Y29udGFpbmVyRWwuY2xvc2VzdCgnLnNldHRpbmdzLWNvbnRlbnQnKSB8fFxyXG5cdFx0XHRcdFx0XHRcdFx0Y29udGFpbmVyRWwucGFyZW50RWxlbWVudDtcclxuXHRcdFx0XHRcdFx0XHRjb25zdCBzY3JvbGxUb3AgPSBzY3JvbGxDb250YWluZXI/LnNjcm9sbFRvcCB8fCAwO1xyXG5cclxuXHRcdFx0XHRcdFx0XHR0aGlzLmRpc3BsYXkoKTsgLy8gUmVmcmVzaCB0byBzaG93L2hpZGUgY3VzdG9tIGZvcm1hdCBpbnB1dFxyXG5cclxuXHRcdFx0XHRcdFx0XHQvLyBSZXN0b3JlIHNjcm9sbCBwb3NpdGlvbiBhZnRlciByZW5kZXJpbmdcclxuXHRcdFx0XHRcdFx0XHRyZXF1ZXN0QW5pbWF0aW9uRnJhbWUoKCkgPT4ge1xyXG5cdFx0XHRcdFx0XHRcdFx0aWYgKHNjcm9sbENvbnRhaW5lcikge1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRzY3JvbGxDb250YWluZXIuc2Nyb2xsVG9wID0gc2Nyb2xsVG9wO1xyXG5cdFx0XHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHRcdH0pO1xyXG5cdFx0XHRcdFx0XHR9KTtcclxuXHRcdFx0XHR9KTtcclxuXHRcdH0pO1xyXG5cclxuXHRcdC8vIFNob3cgY3VzdG9tIGZvcm1hdCBpbnB1dCB3aGVuIFwiQ3VzdG9tXCIgaXMgc2VsZWN0ZWRcclxuXHRcdGlmICh0aGlzLnBsdWdpbi5zZXR0aW5ncy5wcm9wZXJ0eUxpbmtGb3JtYXQgPT09IFByb3BlcnR5TGlua0Zvcm1hdC5DdXN0b20pIHtcclxuXHRcdFx0Z3JvdXAuYWRkU2V0dGluZyhzZXR0aW5nID0+IHtcclxuXHRcdFx0XHRzZXR0aW5nXHJcblx0XHRcdFx0XHQuc2V0TmFtZSgnQ3VzdG9tIGZvcm1hdCB0ZW1wbGF0ZScpXHJcblx0XHRcdFx0XHQuc2V0RGVzYygnVXNlIHtpbWFnZS11cmx9IGFzIHBsYWNlaG9sZGVyIGZvciB0aGUgaW1hZ2UgcGF0aCcpXHJcblx0XHRcdFx0XHQuYWRkVGV4dCh0ZXh0ID0+IHtcclxuXHRcdFx0XHRcdFx0dGV4dFxyXG5cdFx0XHRcdFx0XHRcdC5zZXRQbGFjZWhvbGRlcigne2ltYWdlLXVybH0nKVxyXG5cdFx0XHRcdFx0XHRcdC5zZXRWYWx1ZSh0aGlzLnBsdWdpbi5zZXR0aW5ncy5jdXN0b21Qcm9wZXJ0eUxpbmtGb3JtYXQpXHJcblx0XHRcdFx0XHRcdFx0Lm9uQ2hhbmdlKGFzeW5jIHZhbHVlID0+IHtcclxuXHRcdFx0XHRcdFx0XHRcdHRoaXMucGx1Z2luLnNldHRpbmdzLmN1c3RvbVByb3BlcnR5TGlua0Zvcm1hdCA9IHZhbHVlO1xyXG5cdFx0XHRcdFx0XHRcdFx0YXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XHJcblx0XHRcdFx0XHRcdFx0fSk7XHJcblx0XHRcdFx0XHR9KTtcclxuXHRcdFx0fSk7XHJcblx0XHR9XHJcblxyXG5cdFx0Z3JvdXAuYWRkU2V0dGluZyhzZXR0aW5nID0+IHtcclxuXHRcdFx0c2V0dGluZ1xyXG5cdFx0XHRcdC5zZXROYW1lKCdEZWZhdWx0IHByb3BlcnR5IG5hbWUnKVxyXG5cdFx0XHRcdC5zZXREZXNjKCdEZWZhdWx0IHByb3BlcnR5IG5hbWUgd2hlbiBpbnNlcnRpbmcgdG8gcHJvcGVydGllcyB2aWEgY29tbWFuZCcpXHJcblx0XHRcdFx0LmFkZFRleHQodGV4dCA9PiB7XHJcblx0XHRcdFx0XHR0ZXh0XHJcblx0XHRcdFx0XHRcdC5zZXRQbGFjZWhvbGRlcignQmFubmVyJylcclxuXHRcdFx0XHRcdFx0LnNldFZhbHVlKHRoaXMucGx1Z2luLnNldHRpbmdzLmRlZmF1bHRQcm9wZXJ0eU5hbWUpXHJcblx0XHRcdFx0XHRcdC5vbkNoYW5nZShhc3luYyB2YWx1ZSA9PiB7XHJcblx0XHRcdFx0XHRcdFx0dGhpcy5wbHVnaW4uc2V0dGluZ3MuZGVmYXVsdFByb3BlcnR5TmFtZSA9IHZhbHVlO1xyXG5cdFx0XHRcdFx0XHRcdGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xyXG5cdFx0XHRcdFx0XHR9KTtcclxuXHRcdFx0XHR9KTtcclxuXHRcdH0pO1xyXG5cclxuXHRcdGdyb3VwLmFkZFNldHRpbmcoc2V0dGluZyA9PiB7XHJcblx0XHRcdHNldHRpbmdcclxuXHRcdFx0XHQuc2V0TmFtZSgnRGVmYXVsdCBpY29uIHByb3BlcnR5IG5hbWUnKVxyXG5cdFx0XHRcdC5zZXREZXNjKCdEZWZhdWx0IHByb3BlcnR5IG5hbWUgd2hlbiBpbnNlcnRpbmcgdG8gaWNvbiBwcm9wZXJ0eSB2aWEgY29tbWFuZCcpXHJcblx0XHRcdFx0LmFkZFRleHQodGV4dCA9PiB7XHJcblx0XHRcdFx0XHR0ZXh0XHJcblx0XHRcdFx0XHRcdC5zZXRQbGFjZWhvbGRlcignSWNvbicpXHJcblx0XHRcdFx0XHRcdC5zZXRWYWx1ZSh0aGlzLnBsdWdpbi5zZXR0aW5ncy5kZWZhdWx0SWNvblByb3BlcnR5TmFtZSlcclxuXHRcdFx0XHRcdFx0Lm9uQ2hhbmdlKGFzeW5jIHZhbHVlID0+IHtcclxuXHRcdFx0XHRcdFx0XHR0aGlzLnBsdWdpbi5zZXR0aW5ncy5kZWZhdWx0SWNvblByb3BlcnR5TmFtZSA9IHZhbHVlO1xyXG5cdFx0XHRcdFx0XHRcdGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xyXG5cdFx0XHRcdFx0XHR9KTtcclxuXHRcdFx0XHR9KTtcclxuXHRcdH0pO1xyXG5cclxuXHRcdGdyb3VwLmFkZFNldHRpbmcoc2V0dGluZyA9PiB7XHJcblx0XHRcdHNldHRpbmdcclxuXHRcdFx0XHQuc2V0TmFtZSgnQWx0IHRleHQgcHJvcGVydHkgbmFtZScpXHJcblx0XHRcdFx0LnNldERlc2MoJ1Byb3BlcnR5IG5hbWUgdG8gdXNlIGZvciBpbWFnZSBhbHQgdGV4dCAoZGVzY3JpcHRpb24pIHdoZW4gaW5zZXJ0aW5nIHRvIHByb3BlcnRpZXMuIElmIFwiRGVzY3JpcHRpdmUgaW1hZ2VzXCIgaXMgZW5hYmxlZCwgdGhpcyB3aWxsIGJlIGZpbGxlZCB3aXRoIHRoZSBkZXNjcmlwdGlvbiB5b3UgcHJvdmlkZS4gSWYgZGlzYWJsZWQsIGl0IHdpbGwgYmUgZmlsbGVkIHdpdGggdGhlIHNlYXJjaCB0ZXJtIGZvciBleHRlcm5hbCBpbWFnZXMuJylcclxuXHRcdFx0XHQuYWRkVGV4dCh0ZXh0ID0+IHtcclxuXHRcdFx0XHRcdHRleHRcclxuXHRcdFx0XHRcdFx0LnNldFBsYWNlaG9sZGVyKCdhbHQnKVxyXG5cdFx0XHRcdFx0XHQuc2V0VmFsdWUodGhpcy5wbHVnaW4uc2V0dGluZ3MuYWx0VGV4dFByb3BlcnR5KVxyXG5cdFx0XHRcdFx0XHQub25DaGFuZ2UoYXN5bmMgdmFsdWUgPT4ge1xyXG5cdFx0XHRcdFx0XHRcdHRoaXMucGx1Z2luLnNldHRpbmdzLmFsdFRleHRQcm9wZXJ0eSA9IHZhbHVlO1xyXG5cdFx0XHRcdFx0XHRcdGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xyXG5cdFx0XHRcdFx0XHR9KTtcclxuXHRcdFx0XHR9KTtcclxuXHRcdH0pO1xyXG5cdH1cclxuXHJcblx0cHJpdmF0ZSByZW5kZXJDb252ZXJzaW9uU2V0dGluZ3MoY29udGFpbmVyRWw6IEhUTUxFbGVtZW50KTogdm9pZCB7XHJcblx0XHRjb25zdCBncm91cCA9IG5ldyBTZXR0aW5nR3JvdXAoY29udGFpbmVyRWwpLnNldEhlYWRpbmcoJ1JlbW90ZSBpbWFnZSBjb252ZXJzaW9uJyk7XHJcblxyXG5cdFx0Z3JvdXAuYWRkU2V0dGluZyhzZXR0aW5nID0+IHtcclxuXHRcdFx0c2V0dGluZ1xyXG5cdFx0XHRcdC5zZXROYW1lKCdBdXRvLWNvbnZlcnQgcmVtb3RlIGltYWdlcycpXHJcblx0XHRcdFx0LnNldERlc2MoJ0F1dG9tYXRpY2FsbHkgZG93bmxvYWQgYW5kIHJlcGxhY2UgcmVtb3RlIGltYWdlIHVybHMgd2l0aCBsb2NhbCBmaWxlcycpXHJcblx0XHRcdFx0LmFkZFRvZ2dsZSh0b2dnbGUgPT4ge1xyXG5cdFx0XHRcdFx0dG9nZ2xlXHJcblx0XHRcdFx0XHRcdC5zZXRWYWx1ZSh0aGlzLnBsdWdpbi5zZXR0aW5ncy5hdXRvQ29udmVydFJlbW90ZUltYWdlcylcclxuXHRcdFx0XHRcdFx0Lm9uQ2hhbmdlKGFzeW5jIHZhbHVlID0+IHtcclxuXHRcdFx0XHRcdFx0XHR0aGlzLnBsdWdpbi5zZXR0aW5ncy5hdXRvQ29udmVydFJlbW90ZUltYWdlcyA9IHZhbHVlO1xyXG5cdFx0XHRcdFx0XHRcdGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xyXG5cclxuXHRcdFx0XHRcdFx0XHQvLyBQcmVzZXJ2ZSBzY3JvbGwgcG9zaXRpb24gd2hlbiByZS1yZW5kZXJpbmdcclxuXHRcdFx0XHRcdFx0XHRjb25zdCBzY3JvbGxDb250YWluZXIgPSBjb250YWluZXJFbC5jbG9zZXN0KCcudmVydGljYWwtdGFiLWNvbnRlbnQnKSB8fFxyXG5cdFx0XHRcdFx0XHRcdFx0Y29udGFpbmVyRWwuY2xvc2VzdCgnLnNldHRpbmdzLWNvbnRlbnQnKSB8fFxyXG5cdFx0XHRcdFx0XHRcdFx0Y29udGFpbmVyRWwucGFyZW50RWxlbWVudDtcclxuXHRcdFx0XHRcdFx0XHRjb25zdCBzY3JvbGxUb3AgPSBzY3JvbGxDb250YWluZXI/LnNjcm9sbFRvcCB8fCAwO1xyXG5cclxuXHRcdFx0XHRcdFx0XHR0aGlzLmRpc3BsYXkoKTsgLy8gUmVmcmVzaCB0byBzaG93L2hpZGUgc3ViLW9wdGlvbnNcclxuXHJcblx0XHRcdFx0XHRcdFx0Ly8gUmVzdG9yZSBzY3JvbGwgcG9zaXRpb24gYWZ0ZXIgcmVuZGVyaW5nXHJcblx0XHRcdFx0XHRcdFx0cmVxdWVzdEFuaW1hdGlvbkZyYW1lKCgpID0+IHtcclxuXHRcdFx0XHRcdFx0XHRcdGlmIChzY3JvbGxDb250YWluZXIpIHtcclxuXHRcdFx0XHRcdFx0XHRcdFx0c2Nyb2xsQ29udGFpbmVyLnNjcm9sbFRvcCA9IHNjcm9sbFRvcDtcclxuXHRcdFx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0XHR9KTtcclxuXHRcdFx0XHRcdFx0fSk7XHJcblx0XHRcdFx0fSk7XHJcblx0XHR9KTtcclxuXHJcblx0XHRpZiAodGhpcy5wbHVnaW4uc2V0dGluZ3MuYXV0b0NvbnZlcnRSZW1vdGVJbWFnZXMpIHtcclxuXHRcdFx0Z3JvdXAuYWRkU2V0dGluZyhzZXR0aW5nID0+IHtcclxuXHRcdFx0XHRzZXR0aW5nXHJcblx0XHRcdFx0XHQuc2V0TmFtZSgnQ29udmVydCBvbiBub3RlIG9wZW4nKVxyXG5cdFx0XHRcdFx0LnNldERlc2MoJ1Byb2Nlc3MgcmVtb3RlIGltYWdlcyB3aGVuIG9wZW5pbmcgYSBub3RlJylcclxuXHRcdFx0XHRcdC5hZGRUb2dnbGUodG9nZ2xlID0+IHtcclxuXHRcdFx0XHRcdFx0dG9nZ2xlXHJcblx0XHRcdFx0XHRcdFx0LnNldFZhbHVlKHRoaXMucGx1Z2luLnNldHRpbmdzLmNvbnZlcnRPbk5vdGVPcGVuKVxyXG5cdFx0XHRcdFx0XHRcdC5vbkNoYW5nZShhc3luYyB2YWx1ZSA9PiB7XHJcblx0XHRcdFx0XHRcdFx0XHR0aGlzLnBsdWdpbi5zZXR0aW5ncy5jb252ZXJ0T25Ob3RlT3BlbiA9IHZhbHVlO1xyXG5cdFx0XHRcdFx0XHRcdFx0YXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XHJcblx0XHRcdFx0XHRcdFx0fSk7XHJcblx0XHRcdFx0XHR9KTtcclxuXHRcdFx0fSk7XHJcblxyXG5cdFx0XHRncm91cC5hZGRTZXR0aW5nKHNldHRpbmcgPT4ge1xyXG5cdFx0XHRcdHNldHRpbmdcclxuXHRcdFx0XHRcdC5zZXROYW1lKCdDb252ZXJ0IG9uIG5vdGUgc2F2ZScpXHJcblx0XHRcdFx0XHQuc2V0RGVzYygnUHJvY2VzcyByZW1vdGUgaW1hZ2VzIHdoZW4gc2F2aW5nIGEgbm90ZScpXHJcblx0XHRcdFx0XHQuYWRkVG9nZ2xlKHRvZ2dsZSA9PiB7XHJcblx0XHRcdFx0XHRcdHRvZ2dsZVxyXG5cdFx0XHRcdFx0XHRcdC5zZXRWYWx1ZSh0aGlzLnBsdWdpbi5zZXR0aW5ncy5jb252ZXJ0T25Ob3RlU2F2ZSlcclxuXHRcdFx0XHRcdFx0XHQub25DaGFuZ2UoYXN5bmMgdmFsdWUgPT4ge1xyXG5cdFx0XHRcdFx0XHRcdFx0dGhpcy5wbHVnaW4uc2V0dGluZ3MuY29udmVydE9uTm90ZVNhdmUgPSB2YWx1ZTtcclxuXHRcdFx0XHRcdFx0XHRcdGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xyXG5cdFx0XHRcdFx0XHRcdH0pO1xyXG5cdFx0XHRcdFx0fSk7XHJcblx0XHRcdH0pO1xyXG5cdFx0fVxyXG5cdH1cclxuXHJcblx0cHJpdmF0ZSByZW5kZXJSZW5hbWVTZXR0aW5ncyhjb250YWluZXJFbDogSFRNTEVsZW1lbnQpOiB2b2lkIHtcclxuXHRcdGNvbnN0IGdyb3VwID0gbmV3IFNldHRpbmdHcm91cChjb250YWluZXJFbCkuc2V0SGVhZGluZygnUmVuYW1lIG9wdGlvbnMnKTtcclxuXHJcblx0XHRncm91cC5hZGRTZXR0aW5nKHNldHRpbmcgPT4ge1xyXG5cdFx0XHRzZXR0aW5nXHJcblx0XHRcdFx0LnNldE5hbWUoJ1Nob3cgaW1hZ2UgcmVuYW1lIGRpYWxvZyBhdXRvbWF0aWNhbGx5JylcclxuXHRcdFx0XHQuc2V0RGVzYygnSGFuZGxlIGFuZCByZW5hbWUgaW1hZ2VzIHdoZW4gdGhleSBhcmUgYWRkZWQgdG8gdGhlIHZhdWx0IHZpYSBwYXN0ZSBvciBkcmFnIGFuZCBkcm9wJylcclxuXHRcdFx0XHQuYWRkVG9nZ2xlKHRvZ2dsZSA9PiB7XHJcblx0XHRcdFx0XHR0b2dnbGVcclxuXHRcdFx0XHRcdFx0LnNldFZhbHVlKHRoaXMucGx1Z2luLnNldHRpbmdzLnNob3dSZW5hbWVEaWFsb2cpXHJcblx0XHRcdFx0XHRcdC5vbkNoYW5nZShhc3luYyB2YWx1ZSA9PiB7XHJcblx0XHRcdFx0XHRcdFx0dGhpcy5wbHVnaW4uc2V0dGluZ3Muc2hvd1JlbmFtZURpYWxvZyA9IHZhbHVlO1xyXG5cdFx0XHRcdFx0XHRcdGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xyXG5cdFx0XHRcdFx0XHRcdHRoaXMucmVmcmVzaFdpdGhTY3JvbGxQcmVzZXJ2ZShjb250YWluZXJFbCk7XHJcblx0XHRcdFx0XHRcdH0pO1xyXG5cdFx0XHRcdH0pO1xyXG5cdFx0fSk7XHJcblxyXG5cdFx0aWYgKHRoaXMucGx1Z2luLnNldHRpbmdzLnNob3dSZW5hbWVEaWFsb2cpIHtcclxuXHRcdFx0Z3JvdXAuYWRkU2V0dGluZyhzZXR0aW5nID0+IHtcclxuXHRcdFx0XHRzZXR0aW5nXHJcblx0XHRcdFx0XHQuc2V0TmFtZSgnUmVuYW1lIG9uIHBhc3RlJylcclxuXHRcdFx0XHRcdC5zZXREZXNjKCdIYW5kbGUgYW5kIHJlbmFtZSBpbWFnZXMgd2hlbiBwYXN0aW5nIGludG8gdGhlIGVkaXRvcicpXHJcblx0XHRcdFx0XHQuYWRkVG9nZ2xlKHRvZ2dsZSA9PiB7XHJcblx0XHRcdFx0XHRcdHRvZ2dsZVxyXG5cdFx0XHRcdFx0XHRcdC5zZXRWYWx1ZSh0aGlzLnBsdWdpbi5zZXR0aW5ncy5lbmFibGVSZW5hbWVPblBhc3RlKVxyXG5cdFx0XHRcdFx0XHRcdC5vbkNoYW5nZShhc3luYyB2YWx1ZSA9PiB7XHJcblx0XHRcdFx0XHRcdFx0XHR0aGlzLnBsdWdpbi5zZXR0aW5ncy5lbmFibGVSZW5hbWVPblBhc3RlID0gdmFsdWU7XHJcblx0XHRcdFx0XHRcdFx0XHRhd2FpdCB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKTtcclxuXHRcdFx0XHRcdFx0XHR9KTtcclxuXHRcdFx0XHRcdH0pO1xyXG5cdFx0XHR9KTtcclxuXHJcblx0XHRcdGdyb3VwLmFkZFNldHRpbmcoc2V0dGluZyA9PiB7XHJcblx0XHRcdFx0c2V0dGluZ1xyXG5cdFx0XHRcdFx0LnNldE5hbWUoJ1JlbmFtZSBvbiBkcmFnIGFuZCBkcm9wJylcclxuXHRcdFx0XHRcdC5zZXREZXNjKCdIYW5kbGUgYW5kIHJlbmFtZSBpbWFnZXMgd2hlbiBkcm9wcGluZyBpbnRvIHRoZSBlZGl0b3InKVxyXG5cdFx0XHRcdFx0LmFkZFRvZ2dsZSh0b2dnbGUgPT4ge1xyXG5cdFx0XHRcdFx0XHR0b2dnbGVcclxuXHRcdFx0XHRcdFx0XHQuc2V0VmFsdWUodGhpcy5wbHVnaW4uc2V0dGluZ3MuZW5hYmxlUmVuYW1lT25Ecm9wKVxyXG5cdFx0XHRcdFx0XHRcdC5vbkNoYW5nZShhc3luYyB2YWx1ZSA9PiB7XHJcblx0XHRcdFx0XHRcdFx0XHR0aGlzLnBsdWdpbi5zZXR0aW5ncy5lbmFibGVSZW5hbWVPbkRyb3AgPSB2YWx1ZTtcclxuXHRcdFx0XHRcdFx0XHRcdGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xyXG5cdFx0XHRcdFx0XHRcdH0pO1xyXG5cdFx0XHRcdFx0fSk7XHJcblx0XHRcdH0pO1xyXG5cdFx0fVxyXG5cclxuXHRcdGdyb3VwLmFkZFNldHRpbmcoc2V0dGluZyA9PiB7XHJcblx0XHRcdHNldHRpbmdcclxuXHRcdFx0XHQuc2V0TmFtZSgnUHJvY2VzcyBiYWNrZ3JvdW5kIGZpbGUgY2hhbmdlcycpXHJcblx0XHRcdFx0LnNldERlc2MoJ0F1dG9tYXRpY2FsbHkgY29udmVydCBhbmQgcmVuYW1lIHJlbW90ZSBpbWFnZXMgd2hlbiBmaWxlcyBhcmUgY2hhbmdlZCBpbiB0aGUgYmFja2dyb3VuZCAoYnkgR2l0IG9yIG90aGVyIHBsdWdpbnMpLiBXYXJuaW5nOiBUdXJuaW5nIHRoaXMgb24gbWF5IGNhdXNlIHRoZSByZW5hbWUgbW9kYWwgdG8gYXBwZWFyIGZvciBpbWFnZXMgeW91XFwndmUgYWxyZWFkeSBwcm9jZXNzZWQgb24gb3RoZXIgZGV2aWNlcyBkdXJpbmcgYSBzeW5jLicpXHJcblx0XHRcdFx0LmFkZFRvZ2dsZSh0b2dnbGUgPT4ge1xyXG5cdFx0XHRcdFx0dG9nZ2xlXHJcblx0XHRcdFx0XHRcdC5zZXRWYWx1ZSh0aGlzLnBsdWdpbi5zZXR0aW5ncy5wcm9jZXNzQmFja2dyb3VuZENoYW5nZXMpXHJcblx0XHRcdFx0XHRcdC5vbkNoYW5nZShhc3luYyB2YWx1ZSA9PiB7XHJcblx0XHRcdFx0XHRcdFx0dGhpcy5wbHVnaW4uc2V0dGluZ3MucHJvY2Vzc0JhY2tncm91bmRDaGFuZ2VzID0gdmFsdWU7XHJcblx0XHRcdFx0XHRcdFx0YXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XHJcblx0XHRcdFx0XHRcdH0pO1xyXG5cdFx0XHRcdH0pO1xyXG5cdFx0fSk7XHJcblxyXG5cdFx0Z3JvdXAuYWRkU2V0dGluZyhzZXR0aW5nID0+IHtcclxuXHRcdFx0c2V0dGluZ1xyXG5cdFx0XHRcdC5zZXROYW1lKCdEZXNjcmlwdGl2ZSBpbWFnZXMnKVxyXG5cdFx0XHRcdC5zZXREZXNjKCdBc2sgZm9yIGltYWdlIGRlc2NyaXB0aW9uLCB1c2UgYXMgZGlzcGxheSB0ZXh0IGFuZCBrZWJhYi1jYXNlIGZvciBmaWxlIG5hbWUgKGFwcGxpZXMgdG8gbm90ZSBib2R5IGluc2VydGlvbnMgb25seSwgbm90IHByb3BlcnRpZXMpJylcclxuXHRcdFx0XHQuYWRkVG9nZ2xlKHRvZ2dsZSA9PiB7XHJcblx0XHRcdFx0XHR0b2dnbGVcclxuXHRcdFx0XHRcdFx0LnNldFZhbHVlKHRoaXMucGx1Z2luLnNldHRpbmdzLmVuYWJsZURlc2NyaXB0aXZlSW1hZ2VzKVxyXG5cdFx0XHRcdFx0XHQub25DaGFuZ2UoYXN5bmMgdmFsdWUgPT4ge1xyXG5cdFx0XHRcdFx0XHRcdHRoaXMucGx1Z2luLnNldHRpbmdzLmVuYWJsZURlc2NyaXB0aXZlSW1hZ2VzID0gdmFsdWU7XHJcblx0XHRcdFx0XHRcdFx0YXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XHJcblx0XHRcdFx0XHRcdH0pO1xyXG5cdFx0XHRcdH0pO1xyXG5cdFx0fSk7XHJcblxyXG5cdFx0Z3JvdXAuYWRkU2V0dGluZyhzZXR0aW5nID0+IHtcclxuXHRcdFx0c2V0dGluZ1xyXG5cdFx0XHRcdC5zZXROYW1lKCdBdXRvIHJlbmFtZScpXHJcblx0XHRcdFx0LnNldERlc2MoJ0F1dG9tYXRpY2FsbHkgcmVuYW1lIHdpdGhvdXQgc2hvd2luZyBkaWFsb2cgKHVzZXMgdGVtcGxhdGUpJylcclxuXHRcdFx0XHQuYWRkVG9nZ2xlKHRvZ2dsZSA9PiB7XHJcblx0XHRcdFx0XHR0b2dnbGVcclxuXHRcdFx0XHRcdFx0LnNldFZhbHVlKHRoaXMucGx1Z2luLnNldHRpbmdzLmF1dG9SZW5hbWUpXHJcblx0XHRcdFx0XHRcdC5vbkNoYW5nZShhc3luYyB2YWx1ZSA9PiB7XHJcblx0XHRcdFx0XHRcdFx0dGhpcy5wbHVnaW4uc2V0dGluZ3MuYXV0b1JlbmFtZSA9IHZhbHVlO1xyXG5cdFx0XHRcdFx0XHRcdGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xyXG5cdFx0XHRcdFx0XHR9KTtcclxuXHRcdFx0XHR9KTtcclxuXHRcdH0pO1xyXG5cclxuXHRcdGdyb3VwLmFkZFNldHRpbmcoc2V0dGluZyA9PiB7XHJcblx0XHRcdHNldHRpbmdcclxuXHRcdFx0XHQuc2V0TmFtZSgnRHVwbGljYXRlIG51bWJlciBkZWxpbWl0ZXInKVxyXG5cdFx0XHRcdC5zZXREZXNjKCdDaGFyYWN0ZXIocykgYmV0d2VlbiBuYW1lIGFuZCBudW1iZXIgZm9yIGR1cGxpY2F0ZXMgKGUuZy4sIFwiLVwiIGdpdmVzIFwiaW1hZ2UtMVwiKScpXHJcblx0XHRcdFx0LmFkZFRleHQodGV4dCA9PiB7XHJcblx0XHRcdFx0XHR0ZXh0XHJcblx0XHRcdFx0XHRcdC5zZXRQbGFjZWhvbGRlcignLScpXHJcblx0XHRcdFx0XHRcdC5zZXRWYWx1ZSh0aGlzLnBsdWdpbi5zZXR0aW5ncy5kdXBOdW1iZXJEZWxpbWl0ZXIpXHJcblx0XHRcdFx0XHRcdC5vbkNoYW5nZShhc3luYyB2YWx1ZSA9PiB7XHJcblx0XHRcdFx0XHRcdFx0dGhpcy5wbHVnaW4uc2V0dGluZ3MuZHVwTnVtYmVyRGVsaW1pdGVyID0gdmFsdWU7XHJcblx0XHRcdFx0XHRcdFx0YXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XHJcblx0XHRcdFx0XHRcdH0pO1xyXG5cdFx0XHRcdH0pO1xyXG5cdFx0fSk7XHJcblxyXG5cdFx0Z3JvdXAuYWRkU2V0dGluZyhzZXR0aW5nID0+IHtcclxuXHRcdFx0c2V0dGluZ1xyXG5cdFx0XHRcdC5zZXROYW1lKCdEdXBsaWNhdGUgbnVtYmVyIGF0IHN0YXJ0JylcclxuXHRcdFx0XHQuc2V0RGVzYygnUHV0IHRoZSBkdXBsaWNhdGUgbnVtYmVyIGF0IHRoZSBzdGFydCAoXCIxLWltYWdlXCIgaW5zdGVhZCBvZiBcImltYWdlLTFcIiknKVxyXG5cdFx0XHRcdC5hZGRUb2dnbGUodG9nZ2xlID0+IHtcclxuXHRcdFx0XHRcdHRvZ2dsZVxyXG5cdFx0XHRcdFx0XHQuc2V0VmFsdWUodGhpcy5wbHVnaW4uc2V0dGluZ3MuZHVwTnVtYmVyQXRTdGFydClcclxuXHRcdFx0XHRcdFx0Lm9uQ2hhbmdlKGFzeW5jIHZhbHVlID0+IHtcclxuXHRcdFx0XHRcdFx0XHR0aGlzLnBsdWdpbi5zZXR0aW5ncy5kdXBOdW1iZXJBdFN0YXJ0ID0gdmFsdWU7XHJcblx0XHRcdFx0XHRcdFx0YXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XHJcblx0XHRcdFx0XHRcdH0pO1xyXG5cdFx0XHRcdH0pO1xyXG5cdFx0fSk7XHJcblxyXG5cdFx0Z3JvdXAuYWRkU2V0dGluZyhzZXR0aW5nID0+IHtcclxuXHRcdFx0c2V0dGluZ1xyXG5cdFx0XHRcdC5zZXROYW1lKCdEaXNhYmxlIHJlbmFtZSBub3RpY2UnKVxyXG5cdFx0XHRcdC5zZXREZXNjKCdEbyBub3Qgc2hvdyBhIG5vdGljZSBhZnRlciByZW5hbWluZyBhbiBpbWFnZScpXHJcblx0XHRcdFx0LmFkZFRvZ2dsZSh0b2dnbGUgPT4ge1xyXG5cdFx0XHRcdFx0dG9nZ2xlXHJcblx0XHRcdFx0XHRcdC5zZXRWYWx1ZSh0aGlzLnBsdWdpbi5zZXR0aW5ncy5kaXNhYmxlUmVuYW1lTm90aWNlKVxyXG5cdFx0XHRcdFx0XHQub25DaGFuZ2UoYXN5bmMgdmFsdWUgPT4ge1xyXG5cdFx0XHRcdFx0XHRcdHRoaXMucGx1Z2luLnNldHRpbmdzLmRpc2FibGVSZW5hbWVOb3RpY2UgPSB2YWx1ZTtcclxuXHRcdFx0XHRcdFx0XHRhd2FpdCB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKTtcclxuXHRcdFx0XHRcdFx0fSk7XHJcblx0XHRcdFx0fSk7XHJcblx0XHR9KTtcclxuXHR9XHJcblxyXG5cdC8qKlxyXG5cdCAqIEdldCB0aGUgY3VycmVudCBkZXZpY2UgdHlwZVxyXG5cdCAqL1xyXG5cdHByaXZhdGUgZ2V0Q3VycmVudERldmljZSgpOiBEZXZpY2VUeXBlIHtcclxuXHRcdGlmIChQbGF0Zm9ybS5pc1Bob25lKSB7XHJcblx0XHRcdHJldHVybiBEZXZpY2VUeXBlLlBob25lO1xyXG5cdFx0fVxyXG5cdFx0aWYgKFBsYXRmb3JtLmlzVGFibGV0KSB7XHJcblx0XHRcdHJldHVybiBEZXZpY2VUeXBlLlRhYmxldDtcclxuXHRcdH1cclxuXHRcdHJldHVybiBEZXZpY2VUeXBlLkRlc2t0b3A7XHJcblx0fVxyXG5cclxuXHQvKipcclxuXHQgKiBIZWxwZXIgdG8gcHJlc2VydmUgc2Nyb2xsIHBvc2l0aW9uIHdoZW4gcmUtcmVuZGVyaW5nIHNldHRpbmdzXHJcblx0ICovXHJcblx0cHJpdmF0ZSByZWZyZXNoV2l0aFNjcm9sbFByZXNlcnZlKGNvbnRhaW5lckVsOiBIVE1MRWxlbWVudCk6IHZvaWQge1xyXG5cdFx0Y29uc3Qgc2Nyb2xsQ29udGFpbmVyID0gY29udGFpbmVyRWwuY2xvc2VzdCgnLnZlcnRpY2FsLXRhYi1jb250ZW50JykgfHxcclxuXHRcdFx0Y29udGFpbmVyRWwuY2xvc2VzdCgnLnNldHRpbmdzLWNvbnRlbnQnKSB8fFxyXG5cdFx0XHRjb250YWluZXJFbC5wYXJlbnRFbGVtZW50O1xyXG5cdFx0Y29uc3Qgc2Nyb2xsVG9wID0gc2Nyb2xsQ29udGFpbmVyPy5zY3JvbGxUb3AgfHwgMDtcclxuXHJcblx0XHR0aGlzLmRpc3BsYXkoKTtcclxuXHJcblx0XHRyZXF1ZXN0QW5pbWF0aW9uRnJhbWUoKCkgPT4ge1xyXG5cdFx0XHRpZiAoc2Nyb2xsQ29udGFpbmVyKSB7XHJcblx0XHRcdFx0c2Nyb2xsQ29udGFpbmVyLnNjcm9sbFRvcCA9IHNjcm9sbFRvcDtcclxuXHRcdFx0fVxyXG5cdFx0fSk7XHJcblx0fVxyXG5cclxuXHRwcml2YXRlIHJlbmRlckJhbm5lclNldHRpbmdzKGNvbnRhaW5lckVsOiBIVE1MRWxlbWVudCk6IHZvaWQge1xyXG5cdFx0Y29uc3QgZ3JvdXAgPSBuZXcgU2V0dGluZ0dyb3VwKGNvbnRhaW5lckVsKS5zZXRIZWFkaW5nKCdCYW5uZXIgaW1hZ2VzJyk7XHJcblx0XHRjb25zdCBjdXJyZW50RGV2aWNlID0gdGhpcy5nZXRDdXJyZW50RGV2aWNlKCk7XHJcblx0XHRjb25zdCBkZXZpY2VTZXR0aW5ncyA9IHRoaXMucGx1Z2luLnNldHRpbmdzLmJhbm5lcltjdXJyZW50RGV2aWNlXTtcclxuXHRcdGNvbnN0IGRlZmF1bHREZXZpY2VTZXR0aW5ncyA9IERFRkFVTFRfQkFOTkVSX0RFVklDRV9TRVRUSU5HU1tjdXJyZW50RGV2aWNlXTtcclxuXHRcdGNvbnN0IHByb3BlcnR5U2V0dGluZ3MgPSB0aGlzLnBsdWdpbi5zZXR0aW5ncy5iYW5uZXIucHJvcGVydGllcztcclxuXHJcblx0XHQvLyBEZXZpY2Utc3BlY2lmaWMgZW5hYmxlIHRvZ2dsZVxyXG5cdFx0Z3JvdXAuYWRkU2V0dGluZyhzZXR0aW5nID0+IHtcclxuXHRcdFx0c2V0dGluZ1xyXG5cdFx0XHRcdC5zZXROYW1lKCdTaG93IGJhbm5lcicpXHJcblx0XHRcdFx0LnNldERlc2MoYEVuYWJsZSBvciBkaXNhYmxlIGJhbm5lcnMgb24geW91ciAke2N1cnJlbnREZXZpY2V9IGRldmljZWApXHJcblx0XHRcdFx0LmFkZFRvZ2dsZSh0b2dnbGUgPT4ge1xyXG5cdFx0XHRcdFx0dG9nZ2xlXHJcblx0XHRcdFx0XHRcdC5zZXRWYWx1ZShkZXZpY2VTZXR0aW5ncy5lbmFibGVkKVxyXG5cdFx0XHRcdFx0XHQub25DaGFuZ2UoYXN5bmMgdmFsdWUgPT4ge1xyXG5cdFx0XHRcdFx0XHRcdHRoaXMucGx1Z2luLnNldHRpbmdzLmJhbm5lcltjdXJyZW50RGV2aWNlXS5lbmFibGVkID0gdmFsdWU7XHJcblx0XHRcdFx0XHRcdFx0YXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XHJcblx0XHRcdFx0XHRcdFx0dGhpcy5yZWZyZXNoV2l0aFNjcm9sbFByZXNlcnZlKGNvbnRhaW5lckVsKTtcclxuXHRcdFx0XHRcdFx0fSk7XHJcblx0XHRcdFx0fSk7XHJcblx0XHR9KTtcclxuXHJcblx0XHQvLyBPbmx5IHNob3cgb3RoZXIgc2V0dGluZ3MgaWYgZW5hYmxlZFxyXG5cdFx0aWYgKCFkZXZpY2VTZXR0aW5ncy5lbmFibGVkKSB7XHJcblx0XHRcdHJldHVybjtcclxuXHRcdH1cclxuXHJcblx0XHQvLyBCYW5uZXIgaGVpZ2h0XHJcblx0XHRncm91cC5hZGRTZXR0aW5nKHNldHRpbmcgPT4ge1xyXG5cdFx0XHRzZXR0aW5nXHJcblx0XHRcdFx0LnNldE5hbWUoJ0hlaWdodCcpXHJcblx0XHRcdFx0LnNldERlc2MoYEhlaWdodCBvZiB0aGUgYmFubmVyIG9uIHlvdXIgJHtjdXJyZW50RGV2aWNlfSBkZXZpY2UgKGluIHBpeGVscylgKVxyXG5cdFx0XHRcdC5hZGRUZXh0KHRleHQgPT4ge1xyXG5cdFx0XHRcdFx0dGV4dFxyXG5cdFx0XHRcdFx0XHQuc2V0UGxhY2Vob2xkZXIoU3RyaW5nKGRlZmF1bHREZXZpY2VTZXR0aW5ncy5oZWlnaHQpKVxyXG5cdFx0XHRcdFx0XHQuc2V0VmFsdWUoU3RyaW5nKGRldmljZVNldHRpbmdzLmhlaWdodCkpXHJcblx0XHRcdFx0XHRcdC5vbkNoYW5nZShhc3luYyB2YWx1ZSA9PiB7XHJcblx0XHRcdFx0XHRcdFx0Y29uc3QgbnVtID0gcGFyc2VJbnQodmFsdWUsIDEwKTtcclxuXHRcdFx0XHRcdFx0XHRpZiAoIWlzTmFOKG51bSkgJiYgbnVtID4gMCkge1xyXG5cdFx0XHRcdFx0XHRcdFx0dGhpcy5wbHVnaW4uc2V0dGluZ3MuYmFubmVyW2N1cnJlbnREZXZpY2VdLmhlaWdodCA9IG51bTtcclxuXHRcdFx0XHRcdFx0XHRcdGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xyXG5cdFx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0fSk7XHJcblx0XHRcdFx0fSk7XHJcblx0XHR9KTtcclxuXHJcblx0XHQvLyBCYW5uZXIgcGFkZGluZ1xyXG5cdFx0Z3JvdXAuYWRkU2V0dGluZyhzZXR0aW5nID0+IHtcclxuXHRcdFx0c2V0dGluZ1xyXG5cdFx0XHRcdC5zZXROYW1lKCdQYWRkaW5nJylcclxuXHRcdFx0XHQuc2V0RGVzYygnUGFkZGluZyBvZiB0aGUgYmFubmVyIGZyb20gdGhlIGVkZ2VzIG9mIHRoZSBub3RlIChpbiBwaXhlbHMpJylcclxuXHRcdFx0XHQuYWRkVGV4dCh0ZXh0ID0+IHtcclxuXHRcdFx0XHRcdHRleHRcclxuXHRcdFx0XHRcdFx0LnNldFBsYWNlaG9sZGVyKFN0cmluZyhkZWZhdWx0RGV2aWNlU2V0dGluZ3MucGFkZGluZykpXHJcblx0XHRcdFx0XHRcdC5zZXRWYWx1ZShTdHJpbmcoZGV2aWNlU2V0dGluZ3MucGFkZGluZykpXHJcblx0XHRcdFx0XHRcdC5vbkNoYW5nZShhc3luYyB2YWx1ZSA9PiB7XHJcblx0XHRcdFx0XHRcdFx0Y29uc3QgbnVtID0gcGFyc2VJbnQodmFsdWUsIDEwKTtcclxuXHRcdFx0XHRcdFx0XHRpZiAoIWlzTmFOKG51bSkgJiYgbnVtID49IDApIHtcclxuXHRcdFx0XHRcdFx0XHRcdHRoaXMucGx1Z2luLnNldHRpbmdzLmJhbm5lcltjdXJyZW50RGV2aWNlXS5wYWRkaW5nID0gbnVtO1xyXG5cdFx0XHRcdFx0XHRcdFx0YXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XHJcblx0XHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHR9KTtcclxuXHRcdFx0XHR9KTtcclxuXHRcdH0pO1xyXG5cclxuXHRcdC8vIE5vdGUgb2Zmc2V0XHJcblx0XHRncm91cC5hZGRTZXR0aW5nKHNldHRpbmcgPT4ge1xyXG5cdFx0XHRzZXR0aW5nXHJcblx0XHRcdFx0LnNldE5hbWUoJ05vdGUgb2Zmc2V0JylcclxuXHRcdFx0XHQuc2V0RGVzYygnTW92ZSB0aGUgcG9zaXRpb24gb2YgdGhlIG5vdGUgY29udGVudCAoaW4gcGl4ZWxzKScpXHJcblx0XHRcdFx0LmFkZFRleHQodGV4dCA9PiB7XHJcblx0XHRcdFx0XHR0ZXh0XHJcblx0XHRcdFx0XHRcdC5zZXRQbGFjZWhvbGRlcihTdHJpbmcoZGVmYXVsdERldmljZVNldHRpbmdzLm5vdGVPZmZzZXQpKVxyXG5cdFx0XHRcdFx0XHQuc2V0VmFsdWUoU3RyaW5nKGRldmljZVNldHRpbmdzLm5vdGVPZmZzZXQpKVxyXG5cdFx0XHRcdFx0XHQub25DaGFuZ2UoYXN5bmMgdmFsdWUgPT4ge1xyXG5cdFx0XHRcdFx0XHRcdGNvbnN0IG51bSA9IHBhcnNlSW50KHZhbHVlLCAxMCk7XHJcblx0XHRcdFx0XHRcdFx0aWYgKCFpc05hTihudW0pKSB7XHJcblx0XHRcdFx0XHRcdFx0XHR0aGlzLnBsdWdpbi5zZXR0aW5ncy5iYW5uZXJbY3VycmVudERldmljZV0ubm90ZU9mZnNldCA9IG51bTtcclxuXHRcdFx0XHRcdFx0XHRcdGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xyXG5cdFx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0fSk7XHJcblx0XHRcdFx0fSk7XHJcblx0XHR9KTtcclxuXHJcblx0XHQvLyBWaWV3IG9mZnNldFxyXG5cdFx0Z3JvdXAuYWRkU2V0dGluZyhzZXR0aW5nID0+IHtcclxuXHRcdFx0c2V0dGluZ1xyXG5cdFx0XHRcdC5zZXROYW1lKCdWaWV3IG9mZnNldCcpXHJcblx0XHRcdFx0LnNldERlc2MoJ01vdmUgdGhlIHBvc2l0aW9uIG9mIHRoZSB2aWV3IGNvbnRlbnQgKGluIHBpeGVscyknKVxyXG5cdFx0XHRcdC5hZGRUZXh0KHRleHQgPT4ge1xyXG5cdFx0XHRcdFx0dGV4dFxyXG5cdFx0XHRcdFx0XHQuc2V0UGxhY2Vob2xkZXIoU3RyaW5nKGRlZmF1bHREZXZpY2VTZXR0aW5ncy52aWV3T2Zmc2V0KSlcclxuXHRcdFx0XHRcdFx0LnNldFZhbHVlKFN0cmluZyhkZXZpY2VTZXR0aW5ncy52aWV3T2Zmc2V0KSlcclxuXHRcdFx0XHRcdFx0Lm9uQ2hhbmdlKGFzeW5jIHZhbHVlID0+IHtcclxuXHRcdFx0XHRcdFx0XHRjb25zdCBudW0gPSBwYXJzZUludCh2YWx1ZSwgMTApO1xyXG5cdFx0XHRcdFx0XHRcdGlmICghaXNOYU4obnVtKSkge1xyXG5cdFx0XHRcdFx0XHRcdFx0dGhpcy5wbHVnaW4uc2V0dGluZ3MuYmFubmVyW2N1cnJlbnREZXZpY2VdLnZpZXdPZmZzZXQgPSBudW07XHJcblx0XHRcdFx0XHRcdFx0XHRhd2FpdCB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKTtcclxuXHRcdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdH0pO1xyXG5cdFx0XHRcdH0pO1xyXG5cdFx0fSk7XHJcblxyXG5cdFx0Ly8gRmFkZVxyXG5cdFx0Z3JvdXAuYWRkU2V0dGluZyhzZXR0aW5nID0+IHtcclxuXHRcdFx0c2V0dGluZ1xyXG5cdFx0XHRcdC5zZXROYW1lKCdGYWRlJylcclxuXHRcdFx0XHQuc2V0RGVzYygnRmFkZSB0aGUgaW1hZ2Ugb3V0IHRvd2FyZHMgdGhlIGNvbnRlbnQnKVxyXG5cdFx0XHRcdC5hZGRUb2dnbGUodG9nZ2xlID0+IHtcclxuXHRcdFx0XHRcdHRvZ2dsZVxyXG5cdFx0XHRcdFx0XHQuc2V0VmFsdWUoZGV2aWNlU2V0dGluZ3MuZmFkZSlcclxuXHRcdFx0XHRcdFx0Lm9uQ2hhbmdlKGFzeW5jIHZhbHVlID0+IHtcclxuXHRcdFx0XHRcdFx0XHR0aGlzLnBsdWdpbi5zZXR0aW5ncy5iYW5uZXJbY3VycmVudERldmljZV0uZmFkZSA9IHZhbHVlO1xyXG5cdFx0XHRcdFx0XHRcdGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xyXG5cdFx0XHRcdFx0XHR9KTtcclxuXHRcdFx0XHR9KTtcclxuXHRcdH0pO1xyXG5cclxuXHRcdC8vIFJvdW5kZWQgY29ybmVyc1xyXG5cdFx0Z3JvdXAuYWRkU2V0dGluZyhzZXR0aW5nID0+IHtcclxuXHRcdFx0c2V0dGluZ1xyXG5cdFx0XHRcdC5zZXROYW1lKCdSb3VuZGVkIGNvcm5lcnMnKVxyXG5cdFx0XHRcdC5zZXREZXNjKCdFbmFibGUgcm91bmRlZCBjb3JuZXJzIGZvciB0aGUgYmFubmVyJylcclxuXHRcdFx0XHQuYWRkVG9nZ2xlKHRvZ2dsZSA9PiB7XHJcblx0XHRcdFx0XHR0b2dnbGVcclxuXHRcdFx0XHRcdFx0LnNldFZhbHVlKGRldmljZVNldHRpbmdzLmJhbm5lclJhZGl1c0VuYWJsZWQpXHJcblx0XHRcdFx0XHRcdC5vbkNoYW5nZShhc3luYyB2YWx1ZSA9PiB7XHJcblx0XHRcdFx0XHRcdFx0dGhpcy5wbHVnaW4uc2V0dGluZ3MuYmFubmVyW2N1cnJlbnREZXZpY2VdLmJhbm5lclJhZGl1c0VuYWJsZWQgPSB2YWx1ZTtcclxuXHRcdFx0XHRcdFx0XHRhd2FpdCB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKTtcclxuXHRcdFx0XHRcdFx0fSk7XHJcblx0XHRcdFx0fSk7XHJcblx0XHR9KTtcclxuXHJcblx0XHQvLyBBbmltYXRpb25cclxuXHRcdGdyb3VwLmFkZFNldHRpbmcoc2V0dGluZyA9PiB7XHJcblx0XHRcdHNldHRpbmdcclxuXHRcdFx0XHQuc2V0TmFtZSgnQW5pbWF0aW9uJylcclxuXHRcdFx0XHQuc2V0RGVzYygnRW5hYmxlIGJhbm5lciBhbmltYXRpb24gd2hlbiBvcGVuaW5nIGZpbGVzJylcclxuXHRcdFx0XHQuYWRkVG9nZ2xlKHRvZ2dsZSA9PiB7XHJcblx0XHRcdFx0XHR0b2dnbGVcclxuXHRcdFx0XHRcdFx0LnNldFZhbHVlKGRldmljZVNldHRpbmdzLmFuaW1hdGlvbilcclxuXHRcdFx0XHRcdFx0Lm9uQ2hhbmdlKGFzeW5jIHZhbHVlID0+IHtcclxuXHRcdFx0XHRcdFx0XHR0aGlzLnBsdWdpbi5zZXR0aW5ncy5iYW5uZXJbY3VycmVudERldmljZV0uYW5pbWF0aW9uID0gdmFsdWU7XHJcblx0XHRcdFx0XHRcdFx0YXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XHJcblx0XHRcdFx0XHRcdH0pO1xyXG5cdFx0XHRcdH0pO1xyXG5cdFx0fSk7XHJcblxyXG5cdFx0Ly8gRnJvbnRtYXR0ZXIgcHJvcGVydHkgc2V0dGluZ3MgKGdsb2JhbCwgbm90IGRldmljZS1zcGVjaWZpYylcclxuXHRcdGdyb3VwLmFkZFNldHRpbmcoc2V0dGluZyA9PiB7XHJcblx0XHRcdHNldHRpbmdcclxuXHRcdFx0XHQuc2V0TmFtZSgnQmFubmVyIHByb3BlcnR5JylcclxuXHRcdFx0XHQuc2V0RGVzYygnTmFtZSBvZiB0aGUgYmFubmVyIHByb3BlcnR5IHRoaXMgcGx1Z2luIHdpbGwgbG9vayBmb3IgaW4gdGhlIHByb3BlcnRpZXMnKVxyXG5cdFx0XHRcdC5hZGRUZXh0KHRleHQgPT4ge1xyXG5cdFx0XHRcdFx0dGV4dFxyXG5cdFx0XHRcdFx0XHQuc2V0UGxhY2Vob2xkZXIoJ0Jhbm5lcicpXHJcblx0XHRcdFx0XHRcdC5zZXRWYWx1ZShwcm9wZXJ0eVNldHRpbmdzLmltYWdlUHJvcGVydHkpXHJcblx0XHRcdFx0XHRcdC5vbkNoYW5nZShhc3luYyB2YWx1ZSA9PiB7XHJcblx0XHRcdFx0XHRcdFx0dGhpcy5wbHVnaW4uc2V0dGluZ3MuYmFubmVyLnByb3BlcnRpZXMuaW1hZ2VQcm9wZXJ0eSA9IHZhbHVlIHx8ICdiYW5uZXInO1xyXG5cdFx0XHRcdFx0XHRcdGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xyXG5cdFx0XHRcdFx0XHR9KTtcclxuXHRcdFx0XHR9KTtcclxuXHRcdH0pO1xyXG5cclxuXHRcdGdyb3VwLmFkZFNldHRpbmcoc2V0dGluZyA9PiB7XHJcblx0XHRcdHNldHRpbmdcclxuXHRcdFx0XHQuc2V0TmFtZSgnSWNvbiBwcm9wZXJ0eScpXHJcblx0XHRcdFx0LnNldERlc2MoJ05hbWUgb2YgdGhlIGljb24gcHJvcGVydHkgdGhpcyBwbHVnaW4gd2lsbCBsb29rIGZvciBpbiB0aGUgcHJvcGVydGllcycpXHJcblx0XHRcdFx0LmFkZFRleHQodGV4dCA9PiB7XHJcblx0XHRcdFx0XHR0ZXh0XHJcblx0XHRcdFx0XHRcdC5zZXRQbGFjZWhvbGRlcignSWNvbicpXHJcblx0XHRcdFx0XHRcdC5zZXRWYWx1ZShwcm9wZXJ0eVNldHRpbmdzLmljb25Qcm9wZXJ0eSlcclxuXHRcdFx0XHRcdFx0Lm9uQ2hhbmdlKGFzeW5jIHZhbHVlID0+IHtcclxuXHRcdFx0XHRcdFx0XHR0aGlzLnBsdWdpbi5zZXR0aW5ncy5iYW5uZXIucHJvcGVydGllcy5pY29uUHJvcGVydHkgPSB2YWx1ZSB8fCAnaWNvbic7XHJcblx0XHRcdFx0XHRcdFx0YXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XHJcblx0XHRcdFx0XHRcdH0pO1xyXG5cdFx0XHRcdH0pO1xyXG5cdFx0fSk7XHJcblxyXG5cdFx0Z3JvdXAuYWRkU2V0dGluZyhzZXR0aW5nID0+IHtcclxuXHRcdFx0c2V0dGluZ1xyXG5cdFx0XHRcdC5zZXROYW1lKCdFbmFibGUgcGVyLW5vdGUgYmFubmVyIGhpZGluZycpXHJcblx0XHRcdFx0LnNldERlc2MoJ0FsbG93IGRpc2FibGluZyBiYW5uZXJzIG9uIGEgcGVyLW5vdGUgYmFzaXMgdXNpbmcgYSBwcm9wZXJ0aWVzIGZpZWxkJylcclxuXHRcdFx0XHQuYWRkVG9nZ2xlKHRvZ2dsZSA9PiB7XHJcblx0XHRcdFx0XHR0b2dnbGVcclxuXHRcdFx0XHRcdFx0LnNldFZhbHVlKHByb3BlcnR5U2V0dGluZ3MuaGlkZVByb3BlcnR5RW5hYmxlZClcclxuXHRcdFx0XHRcdFx0Lm9uQ2hhbmdlKGFzeW5jIHZhbHVlID0+IHtcclxuXHRcdFx0XHRcdFx0XHR0aGlzLnBsdWdpbi5zZXR0aW5ncy5iYW5uZXIucHJvcGVydGllcy5oaWRlUHJvcGVydHlFbmFibGVkID0gdmFsdWU7XHJcblx0XHRcdFx0XHRcdFx0YXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XHJcblx0XHRcdFx0XHRcdFx0dGhpcy5yZWZyZXNoV2l0aFNjcm9sbFByZXNlcnZlKGNvbnRhaW5lckVsKTtcclxuXHRcdFx0XHRcdFx0fSk7XHJcblx0XHRcdFx0fSk7XHJcblx0XHR9KTtcclxuXHJcblx0XHQvLyBTaG93IGhpZGUgcHJvcGVydHkgaW5wdXQgd2hlbiBlbmFibGVkXHJcblx0XHRpZiAocHJvcGVydHlTZXR0aW5ncy5oaWRlUHJvcGVydHlFbmFibGVkKSB7XHJcblx0XHRcdGdyb3VwLmFkZFNldHRpbmcoc2V0dGluZyA9PiB7XHJcblx0XHRcdFx0c2V0dGluZ1xyXG5cdFx0XHRcdFx0LnNldE5hbWUoJ0hpZGUgYmFubmVyIHByb3BlcnR5JylcclxuXHRcdFx0XHRcdC5zZXREZXNjKCdOYW1lIG9mIHRoZSBwcm9wZXJ0eSB0aGF0LCB3aGVuIHNldCB0byB0cnVlLCB3aWxsIGhpZGUgdGhlIGJhbm5lciBmb3IgdGhhdCBub3RlJylcclxuXHRcdFx0XHRcdC5hZGRUZXh0KHRleHQgPT4ge1xyXG5cdFx0XHRcdFx0XHR0ZXh0XHJcblx0XHRcdFx0XHRcdFx0LnNldFBsYWNlaG9sZGVyKCdoaWRlQmFubmVyJylcclxuXHRcdFx0XHRcdFx0XHQuc2V0VmFsdWUocHJvcGVydHlTZXR0aW5ncy5oaWRlUHJvcGVydHkpXHJcblx0XHRcdFx0XHRcdFx0Lm9uQ2hhbmdlKGFzeW5jIHZhbHVlID0+IHtcclxuXHRcdFx0XHRcdFx0XHRcdHRoaXMucGx1Z2luLnNldHRpbmdzLmJhbm5lci5wcm9wZXJ0aWVzLmhpZGVQcm9wZXJ0eSA9IHZhbHVlIHx8ICcnO1xyXG5cdFx0XHRcdFx0XHRcdFx0YXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XHJcblx0XHRcdFx0XHRcdFx0fSk7XHJcblx0XHRcdFx0XHR9KTtcclxuXHRcdFx0fSk7XHJcblx0XHR9XHJcblxyXG5cdFx0Ly8gSWNvbiBzZXR0aW5nc1xyXG5cdFx0Z3JvdXAuYWRkU2V0dGluZyhzZXR0aW5nID0+IHtcclxuXHRcdFx0c2V0dGluZ1xyXG5cdFx0XHRcdC5zZXROYW1lKCdTaG93IGljb24nKVxyXG5cdFx0XHRcdC5zZXREZXNjKCdFbmFibGUgb3IgZGlzYWJsZSB0aGUgaWNvbicpXHJcblx0XHRcdFx0LmFkZFRvZ2dsZSh0b2dnbGUgPT4ge1xyXG5cdFx0XHRcdFx0dG9nZ2xlXHJcblx0XHRcdFx0XHRcdC5zZXRWYWx1ZShkZXZpY2VTZXR0aW5ncy5pY29uRW5hYmxlZClcclxuXHRcdFx0XHRcdFx0Lm9uQ2hhbmdlKGFzeW5jIHZhbHVlID0+IHtcclxuXHRcdFx0XHRcdFx0XHR0aGlzLnBsdWdpbi5zZXR0aW5ncy5iYW5uZXJbY3VycmVudERldmljZV0uaWNvbkVuYWJsZWQgPSB2YWx1ZTtcclxuXHRcdFx0XHRcdFx0XHRhd2FpdCB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKTtcclxuXHRcdFx0XHRcdFx0XHR0aGlzLnJlZnJlc2hXaXRoU2Nyb2xsUHJlc2VydmUoY29udGFpbmVyRWwpO1xyXG5cdFx0XHRcdFx0XHR9KTtcclxuXHRcdFx0XHR9KTtcclxuXHRcdH0pO1xyXG5cclxuXHRcdC8vIE9ubHkgc2hvdyBpY29uIHNldHRpbmdzIGlmIGVuYWJsZWRcclxuXHRcdGlmIChkZXZpY2VTZXR0aW5ncy5pY29uRW5hYmxlZCkge1xyXG5cdFx0XHRncm91cC5hZGRTZXR0aW5nKHNldHRpbmcgPT4ge1xyXG5cdFx0XHRcdHNldHRpbmdcclxuXHRcdFx0XHRcdC5zZXROYW1lKCdJY29uIHNpemUnKVxyXG5cdFx0XHRcdFx0LnNldERlc2MoJ1NpemUgb2YgdGhlIGljb24gKGluIHBpeGVscyknKVxyXG5cdFx0XHRcdFx0LmFkZFRleHQodGV4dCA9PiB7XHJcblx0XHRcdFx0XHRcdHRleHRcclxuXHRcdFx0XHRcdFx0XHQuc2V0UGxhY2Vob2xkZXIoU3RyaW5nKGRlZmF1bHREZXZpY2VTZXR0aW5ncy5pY29uU2l6ZSkpXHJcblx0XHRcdFx0XHRcdFx0LnNldFZhbHVlKFN0cmluZyhkZXZpY2VTZXR0aW5ncy5pY29uU2l6ZSkpXHJcblx0XHRcdFx0XHRcdFx0Lm9uQ2hhbmdlKGFzeW5jIHZhbHVlID0+IHtcclxuXHRcdFx0XHRcdFx0XHRcdGNvbnN0IG51bSA9IHBhcnNlSW50KHZhbHVlLCAxMCk7XHJcblx0XHRcdFx0XHRcdFx0XHRpZiAoIWlzTmFOKG51bSkgJiYgbnVtID4gMCkge1xyXG5cdFx0XHRcdFx0XHRcdFx0XHR0aGlzLnBsdWdpbi5zZXR0aW5ncy5iYW5uZXJbY3VycmVudERldmljZV0uaWNvblNpemUgPSBudW07XHJcblx0XHRcdFx0XHRcdFx0XHRcdGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xyXG5cdFx0XHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHRcdH0pO1xyXG5cdFx0XHRcdFx0fSk7XHJcblx0XHRcdH0pO1xyXG5cclxuXHRcdFx0Z3JvdXAuYWRkU2V0dGluZyhzZXR0aW5nID0+IHtcclxuXHRcdFx0XHRzZXR0aW5nXHJcblx0XHRcdFx0XHQuc2V0TmFtZSgnSWNvbiBiYWNrZ3JvdW5kJylcclxuXHRcdFx0XHRcdC5zZXREZXNjKCdFbmFibGUgb3IgZGlzYWJsZSB0aGUgaWNvbiBiYWNrZ3JvdW5kJylcclxuXHRcdFx0XHRcdC5hZGRUb2dnbGUodG9nZ2xlID0+IHtcclxuXHRcdFx0XHRcdFx0dG9nZ2xlXHJcblx0XHRcdFx0XHRcdFx0LnNldFZhbHVlKGRldmljZVNldHRpbmdzLmljb25CYWNrZ3JvdW5kKVxyXG5cdFx0XHRcdFx0XHRcdC5vbkNoYW5nZShhc3luYyB2YWx1ZSA9PiB7XHJcblx0XHRcdFx0XHRcdFx0XHR0aGlzLnBsdWdpbi5zZXR0aW5ncy5iYW5uZXJbY3VycmVudERldmljZV0uaWNvbkJhY2tncm91bmQgPSB2YWx1ZTtcclxuXHRcdFx0XHRcdFx0XHRcdGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xyXG5cdFx0XHRcdFx0XHRcdH0pO1xyXG5cdFx0XHRcdFx0fSk7XHJcblx0XHRcdH0pO1xyXG5cclxuXHRcdFx0Z3JvdXAuYWRkU2V0dGluZyhzZXR0aW5nID0+IHtcclxuXHRcdFx0XHRzZXR0aW5nXHJcblx0XHRcdFx0XHQuc2V0TmFtZSgnSWNvbiBmcmFtZScpXHJcblx0XHRcdFx0XHQuc2V0RGVzYygnU2hvdyB0aGUgYm9yZGVyL2JhY2tncm91bmQgZnJhbWUgYXJvdW5kIHRoZSBpY29uIChkaXNhYmxlIHRvIGRpc3BsYXkganVzdCB0aGUgaWNvbiBncmFwaGljKScpXHJcblx0XHRcdFx0XHQuYWRkVG9nZ2xlKHRvZ2dsZSA9PiB7XHJcblx0XHRcdFx0XHRcdHRvZ2dsZVxyXG5cdFx0XHRcdFx0XHRcdC5zZXRWYWx1ZShkZXZpY2VTZXR0aW5ncy5pY29uRnJhbWUpXHJcblx0XHRcdFx0XHRcdFx0Lm9uQ2hhbmdlKGFzeW5jIHZhbHVlID0+IHtcclxuXHRcdFx0XHRcdFx0XHRcdHRoaXMucGx1Z2luLnNldHRpbmdzLmJhbm5lcltjdXJyZW50RGV2aWNlXS5pY29uRnJhbWUgPSB2YWx1ZTtcclxuXHRcdFx0XHRcdFx0XHRcdGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xyXG5cdFx0XHRcdFx0XHRcdH0pO1xyXG5cdFx0XHRcdFx0fSk7XHJcblx0XHRcdH0pO1xyXG5cclxuXHRcdFx0Z3JvdXAuYWRkU2V0dGluZyhzZXR0aW5nID0+IHtcclxuXHRcdFx0XHRzZXR0aW5nXHJcblx0XHRcdFx0XHQuc2V0TmFtZSgnSWNvbiBib3JkZXIgc2l6ZScpXHJcblx0XHRcdFx0XHQuc2V0RGVzYygnU2l6ZSBvZiB0aGUgaWNvbiBib3JkZXIgKGluIHBpeGVscyknKVxyXG5cdFx0XHRcdFx0LmFkZFRleHQodGV4dCA9PiB7XHJcblx0XHRcdFx0XHRcdHRleHRcclxuXHRcdFx0XHRcdFx0XHQuc2V0UGxhY2Vob2xkZXIoU3RyaW5nKGRlZmF1bHREZXZpY2VTZXR0aW5ncy5pY29uQm9yZGVyKSlcclxuXHRcdFx0XHRcdFx0XHQuc2V0VmFsdWUoU3RyaW5nKGRldmljZVNldHRpbmdzLmljb25Cb3JkZXIpKVxyXG5cdFx0XHRcdFx0XHRcdC5vbkNoYW5nZShhc3luYyB2YWx1ZSA9PiB7XHJcblx0XHRcdFx0XHRcdFx0XHRjb25zdCBudW0gPSBwYXJzZUludCh2YWx1ZSwgMTApO1xyXG5cdFx0XHRcdFx0XHRcdFx0aWYgKCFpc05hTihudW0pICYmIG51bSA+PSAwKSB7XHJcblx0XHRcdFx0XHRcdFx0XHRcdHRoaXMucGx1Z2luLnNldHRpbmdzLmJhbm5lcltjdXJyZW50RGV2aWNlXS5pY29uQm9yZGVyID0gbnVtO1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRhd2FpdCB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKTtcclxuXHRcdFx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0XHR9KTtcclxuXHRcdFx0XHRcdH0pO1xyXG5cdFx0XHR9KTtcclxuXHJcblx0XHRcdGdyb3VwLmFkZFNldHRpbmcoc2V0dGluZyA9PiB7XHJcblx0XHRcdFx0c2V0dGluZ1xyXG5cdFx0XHRcdFx0LnNldE5hbWUoJ0ljb24gYm9yZGVyIHJhZGl1cycpXHJcblx0XHRcdFx0XHQuc2V0RGVzYygnU2l6ZSBvZiB0aGUgaWNvbiBib3JkZXIgcmFkaXVzIChpbiBwaXhlbHMpJylcclxuXHRcdFx0XHRcdC5hZGRUZXh0KHRleHQgPT4ge1xyXG5cdFx0XHRcdFx0XHR0ZXh0XHJcblx0XHRcdFx0XHRcdFx0LnNldFBsYWNlaG9sZGVyKFN0cmluZyhkZWZhdWx0RGV2aWNlU2V0dGluZ3MuaWNvblJhZGl1cykpXHJcblx0XHRcdFx0XHRcdFx0LnNldFZhbHVlKFN0cmluZyhkZXZpY2VTZXR0aW5ncy5pY29uUmFkaXVzKSlcclxuXHRcdFx0XHRcdFx0XHQub25DaGFuZ2UoYXN5bmMgdmFsdWUgPT4ge1xyXG5cdFx0XHRcdFx0XHRcdFx0Y29uc3QgbnVtID0gcGFyc2VJbnQodmFsdWUsIDEwKTtcclxuXHRcdFx0XHRcdFx0XHRcdGlmICghaXNOYU4obnVtKSAmJiBudW0gPj0gMCkge1xyXG5cdFx0XHRcdFx0XHRcdFx0XHR0aGlzLnBsdWdpbi5zZXR0aW5ncy5iYW5uZXJbY3VycmVudERldmljZV0uaWNvblJhZGl1cyA9IG51bTtcclxuXHRcdFx0XHRcdFx0XHRcdFx0YXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XHJcblx0XHRcdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdFx0fSk7XHJcblx0XHRcdFx0XHR9KTtcclxuXHRcdFx0fSk7XHJcblxyXG5cdFx0XHRncm91cC5hZGRTZXR0aW5nKHNldHRpbmcgPT4ge1xyXG5cdFx0XHRcdHNldHRpbmdcclxuXHRcdFx0XHRcdC5zZXROYW1lKCdJY29uIGFsaWdubWVudCAtIGhvcml6b250YWwnKVxyXG5cdFx0XHRcdFx0LnNldERlc2MoJ0hvcml6b250YWwgYWxpZ25tZW50IG9mIHRoZSBpY29uJylcclxuXHRcdFx0XHRcdC5hZGREcm9wZG93bihkcm9wZG93biA9PiB7XHJcblx0XHRcdFx0XHRcdGRyb3Bkb3duXHJcblx0XHRcdFx0XHRcdFx0LmFkZE9wdGlvbignZmxleC1zdGFydCcsICdMZWZ0JylcclxuXHRcdFx0XHRcdFx0XHQuYWRkT3B0aW9uKCdjZW50ZXInLCAnQ2VudGVyJylcclxuXHRcdFx0XHRcdFx0XHQuYWRkT3B0aW9uKCdmbGV4LWVuZCcsICdSaWdodCcpXHJcblx0XHRcdFx0XHRcdFx0LnNldFZhbHVlKGRldmljZVNldHRpbmdzLmljb25BbGlnbm1lbnRIKVxyXG5cdFx0XHRcdFx0XHRcdC5vbkNoYW5nZShhc3luYyB2YWx1ZSA9PiB7XHJcblx0XHRcdFx0XHRcdFx0XHR0aGlzLnBsdWdpbi5zZXR0aW5ncy5iYW5uZXJbY3VycmVudERldmljZV0uaWNvbkFsaWdubWVudEggPSB2YWx1ZSBhcyAnZmxleC1zdGFydCcgfCAnY2VudGVyJyB8ICdmbGV4LWVuZCc7XHJcblx0XHRcdFx0XHRcdFx0XHRhd2FpdCB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKTtcclxuXHRcdFx0XHRcdFx0XHR9KTtcclxuXHRcdFx0XHRcdH0pO1xyXG5cdFx0XHR9KTtcclxuXHJcblx0XHRcdGdyb3VwLmFkZFNldHRpbmcoc2V0dGluZyA9PiB7XHJcblx0XHRcdFx0c2V0dGluZ1xyXG5cdFx0XHRcdFx0LnNldE5hbWUoJ0ljb24gYWxpZ25tZW50IC0gdmVydGljYWwnKVxyXG5cdFx0XHRcdFx0LnNldERlc2MoJ1ZlcnRpY2FsIGFsaWdubWVudCBvZiB0aGUgaWNvbicpXHJcblx0XHRcdFx0XHQuYWRkRHJvcGRvd24oZHJvcGRvd24gPT4ge1xyXG5cdFx0XHRcdFx0XHRkcm9wZG93blxyXG5cdFx0XHRcdFx0XHRcdC5hZGRPcHRpb24oJ2ZsZXgtc3RhcnQnLCAnVG9wJylcclxuXHRcdFx0XHRcdFx0XHQuYWRkT3B0aW9uKCdjZW50ZXInLCAnQ2VudGVyJylcclxuXHRcdFx0XHRcdFx0XHQuYWRkT3B0aW9uKCdmbGV4LWVuZCcsICdCb3R0b20nKVxyXG5cdFx0XHRcdFx0XHRcdC5zZXRWYWx1ZShkZXZpY2VTZXR0aW5ncy5pY29uQWxpZ25tZW50VilcclxuXHRcdFx0XHRcdFx0XHQub25DaGFuZ2UoYXN5bmMgdmFsdWUgPT4ge1xyXG5cdFx0XHRcdFx0XHRcdFx0dGhpcy5wbHVnaW4uc2V0dGluZ3MuYmFubmVyW2N1cnJlbnREZXZpY2VdLmljb25BbGlnbm1lbnRWID0gdmFsdWUgYXMgJ2ZsZXgtc3RhcnQnIHwgJ2NlbnRlcicgfCAnZmxleC1lbmQnO1xyXG5cdFx0XHRcdFx0XHRcdFx0YXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XHJcblx0XHRcdFx0XHRcdFx0fSk7XHJcblx0XHRcdFx0XHR9KTtcclxuXHRcdFx0fSk7XHJcblx0XHR9XHJcblx0fVxyXG5cclxuXHRwcml2YXRlIHJlbmRlckFkdmFuY2VkU2V0dGluZ3MoY29udGFpbmVyRWw6IEhUTUxFbGVtZW50KTogdm9pZCB7XHJcblx0XHRjb25zdCBncm91cCA9IG5ldyBTZXR0aW5nR3JvdXAoY29udGFpbmVyRWwpLnNldEhlYWRpbmcoJ0FkdmFuY2VkJyk7XHJcblxyXG5cdFx0Z3JvdXAuYWRkU2V0dGluZyhzZXR0aW5nID0+IHtcclxuXHRcdFx0c2V0dGluZ1xyXG5cdFx0XHRcdC5zZXROYW1lKCdTdXBwb3J0ZWQgZmlsZSBleHRlbnNpb25zJylcclxuXHRcdFx0XHQuc2V0RGVzYygnRmlsZSBleHRlbnNpb25zIHRvIHByb2Nlc3MgKGNvbW1hLXNlcGFyYXRlZCknKVxyXG5cdFx0XHRcdC5hZGRUZXh0KHRleHQgPT4ge1xyXG5cdFx0XHRcdFx0Y29uc3QgY3VycmVudFZhbHVlID0gdGhpcy5wbHVnaW4uc2V0dGluZ3Muc3VwcG9ydGVkRXh0ZW5zaW9ucy5sZW5ndGggPiAwXHJcblx0XHRcdFx0XHRcdD8gdGhpcy5wbHVnaW4uc2V0dGluZ3Muc3VwcG9ydGVkRXh0ZW5zaW9ucy5qb2luKCcsICcpXHJcblx0XHRcdFx0XHRcdDogJyc7XHJcblx0XHRcdFx0XHR0ZXh0XHJcblx0XHRcdFx0XHRcdC5zZXRQbGFjZWhvbGRlcignRmlsZSBleHRlbnNpb25zJylcclxuXHRcdFx0XHRcdFx0LnNldFZhbHVlKGN1cnJlbnRWYWx1ZSlcclxuXHRcdFx0XHRcdFx0Lm9uQ2hhbmdlKGFzeW5jIHZhbHVlID0+IHtcclxuXHRcdFx0XHRcdFx0XHRjb25zdCBleHRlbnNpb25zID0gdmFsdWVcclxuXHRcdFx0XHRcdFx0XHRcdC5zcGxpdCgnLCcpXHJcblx0XHRcdFx0XHRcdFx0XHQubWFwKChleHQpID0+IGV4dC50cmltKCkudG9Mb3dlckNhc2UoKSlcclxuXHRcdFx0XHRcdFx0XHRcdC5maWx0ZXIoKGV4dCkgPT4gZXh0Lmxlbmd0aCA+IDApO1xyXG5cdFx0XHRcdFx0XHRcdC8vIERlZmF1bHQgdG8gJ21kJyBpZiBlbXB0eVxyXG5cdFx0XHRcdFx0XHRcdHRoaXMucGx1Z2luLnNldHRpbmdzLnN1cHBvcnRlZEV4dGVuc2lvbnMgPSBleHRlbnNpb25zLmxlbmd0aCA+IDAgPyBleHRlbnNpb25zIDogWydtZCddO1xyXG5cdFx0XHRcdFx0XHRcdGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xyXG5cdFx0XHRcdFx0XHR9KTtcclxuXHRcdFx0XHR9KTtcclxuXHRcdH0pO1xyXG5cclxuXHRcdGdyb3VwLmFkZFNldHRpbmcoc2V0dGluZyA9PiB7XHJcblx0XHRcdHNldHRpbmdcclxuXHRcdFx0XHQuc2V0TmFtZSgnRGVidWcgbW9kZScpXHJcblx0XHRcdFx0LnNldERlc2MoJ0VuYWJsZSBkZWJ1ZyBsb2dnaW5nIHRvIGNvbnNvbGUnKVxyXG5cdFx0XHRcdC5hZGRUb2dnbGUodG9nZ2xlID0+IHtcclxuXHRcdFx0XHRcdHRvZ2dsZVxyXG5cdFx0XHRcdFx0XHQuc2V0VmFsdWUodGhpcy5wbHVnaW4uc2V0dGluZ3MuZGVidWdNb2RlKVxyXG5cdFx0XHRcdFx0XHQub25DaGFuZ2UoYXN5bmMgdmFsdWUgPT4ge1xyXG5cdFx0XHRcdFx0XHRcdHRoaXMucGx1Z2luLnNldHRpbmdzLmRlYnVnTW9kZSA9IHZhbHVlO1xyXG5cdFx0XHRcdFx0XHRcdGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xyXG5cdFx0XHRcdFx0XHR9KTtcclxuXHRcdFx0XHR9KTtcclxuXHRcdH0pO1xyXG5cdH1cclxufVxyXG4iLCAiLyoqXHJcbiAqIEltYWdlIE1hbmFnZXIgUGx1Z2luIFR5cGVzXHJcbiAqIFNoYXJlZCBUeXBlU2NyaXB0IGludGVyZmFjZXMgYW5kIHR5cGUgZGVmaW5pdGlvbnNcclxuICovXHJcblxyXG4vKipcclxuICogU3VwcG9ydGVkIGltYWdlIHByb3ZpZGVycyBmb3IgcmVtb3RlIHNlYXJjaFxyXG4gKi9cclxuZXhwb3J0IGVudW0gSW1hZ2VQcm92aWRlciB7XHJcblx0VW5zcGxhc2ggPSAndW5zcGxhc2gnLFxyXG5cdFBleGVscyA9ICdwZXhlbHMnLFxyXG5cdFBpeGFiYXkgPSAncGl4YWJheScsXHJcblx0TG9jYWwgPSAnbG9jYWwnLFxyXG59XHJcblxyXG4vKipcclxuICogSW1hZ2Ugb3JpZW50YXRpb24gZmlsdGVyXHJcbiAqL1xyXG5leHBvcnQgZW51bSBJbWFnZU9yaWVudGF0aW9uIHtcclxuXHRBbnkgPSAnYW55JyxcclxuXHRMYW5kc2NhcGUgPSAnbGFuZHNjYXBlJyxcclxuXHRQb3J0cmFpdCA9ICdwb3J0cmFpdCcsXHJcblx0U3F1YXJlID0gJ3NxdWFyZScsXHJcbn1cclxuXHJcbi8qKlxyXG4gKiBJbWFnZSBzaXplIHByZWZlcmVuY2VcclxuICovXHJcbmV4cG9ydCBlbnVtIEltYWdlU2l6ZSB7XHJcblx0T3JpZ2luYWwgPSAnb3JpZ2luYWwnLFxyXG5cdExhcmdlID0gJ2xhcmdlJyxcclxuXHRNZWRpdW0gPSAnbWVkaXVtJyxcclxuXHRTbWFsbCA9ICdzbWFsbCcsXHJcbn1cclxuXHJcbi8qKlxyXG4gKiBMaW5rIGZvcm1hdCBmb3IgaW5zZXJ0aW5nIGltYWdlcyBpbnRvIHByb3BlcnRpZXNcclxuICovXHJcbmV4cG9ydCBlbnVtIFByb3BlcnR5TGlua0Zvcm1hdCB7XHJcblx0T2JzaWRpYW5EZWZhdWx0ID0gJ29ic2lkaWFuJywgLy8gVXNlIE9ic2lkaWFuJ3MgZGVmYXVsdCBsaW5rIGZvcm1hdCAocmVzcGVjdHMgdXNlTWFya2Rvd25MaW5rcywgbmV3TGlua0Zvcm1hdClcclxuXHRQYXRoID0gJ3BhdGgnLCAgICAgICAgICAgLy8gY292ZXI6IHBhdGgvdG8vaW1hZ2UuanBnXHJcblx0UmVsYXRpdmVQYXRoID0gJ3JlbGF0aXZlJywgLy8gY292ZXI6IC4vaW1hZ2UuanBnIG9yIGltYWdlLmpwZyAoc2FtZSBmb2xkZXIpXHJcblx0V2lraWxpbmsgPSAnd2lraWxpbmsnLCAgIC8vIGNvdmVyOiBcIltbcGF0aC90by9pbWFnZS5qcGddXVwiXHJcblx0TWFya2Rvd24gPSAnbWFya2Rvd24nLCAgIC8vIGNvdmVyOiBcIiFbXShwYXRoL3RvL2ltYWdlLmpwZylcIlxyXG5cdEN1c3RvbSA9ICdjdXN0b20nLCAgICAgICAvLyBjb3ZlcjogXCJ7aW1hZ2UtdXJsfVwiIHdpdGggY3VzdG9tIGZvcm1hdFxyXG59XHJcblxyXG4vKipcclxuICogQXR0YWNobWVudCBsb2NhdGlvbiBvdmVycmlkZSBvcHRpb25zXHJcbiAqL1xyXG5leHBvcnQgZW51bSBBdHRhY2htZW50TG9jYXRpb24ge1xyXG5cdE9ic2lkaWFuRGVmYXVsdCA9ICdvYnNpZGlhbicsICAvLyBGb2xsb3cgT2JzaWRpYW4ncyBzZXR0aW5nXHJcblx0U2FtZUZvbGRlciA9ICdzYW1lJywgICAgICAgICAgIC8vIFNhbWUgZm9sZGVyIGFzIG5vdGVcclxuXHRTdWJmb2xkZXIgPSAnc3ViZm9sZGVyJywgICAgICAgLy8gQ29uZmlndXJhYmxlIHN1YmZvbGRlclxyXG5cdFZhdWx0Rm9sZGVyID0gJ3ZhdWx0JywgICAgICAgICAvLyBDZW50cmFsaXplZCB2YXVsdCBmb2xkZXJcclxufVxyXG5cclxuLyoqXHJcbiAqIERldmljZSB0eXBlcyBmb3IgYmFubmVyIHNldHRpbmdzXHJcbiAqL1xyXG5leHBvcnQgZW51bSBEZXZpY2VUeXBlIHtcclxuXHREZXNrdG9wID0gJ2Rlc2t0b3AnLFxyXG5cdFRhYmxldCA9ICd0YWJsZXQnLFxyXG5cdFBob25lID0gJ3Bob25lJyxcclxufVxyXG5cclxuLyoqXHJcbiAqIEljb24gdHlwZSBmb3IgYmFubmVyIGljb25zXHJcbiAqL1xyXG5leHBvcnQgZW51bSBCYW5uZXJJY29uVHlwZSB7XHJcblx0TGluayA9ICdsaW5rJyxcclxuXHRUZXh0ID0gJ3RleHQnLFxyXG59XHJcblxyXG4vKipcclxuICogQ29udGVudCB0eXBlIGZvciBiYW5uZXIgKGltYWdlIG9yIHZpZGVvKVxyXG4gKi9cclxuZXhwb3J0IGVudW0gQmFubmVyQ29udGVudFR5cGUge1xyXG5cdEltYWdlID0gJ2ltYWdlJyxcclxuXHRWaWRlbyA9ICd2aWRlbycsXHJcbn1cclxuXHJcbi8qKlxyXG4gKiBEZXZpY2Utc3BlY2lmaWMgYmFubmVyIHNldHRpbmdzXHJcbiAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIEJhbm5lckRldmljZVNldHRpbmdzIHtcclxuXHQvLyBDb3JlIGJhbm5lciBzZXR0aW5nc1xyXG5cdGVuYWJsZWQ6IGJvb2xlYW47XHJcblx0aGVpZ2h0OiBudW1iZXI7XHJcblx0dmlld09mZnNldDogbnVtYmVyO1xyXG5cdG5vdGVPZmZzZXQ6IG51bWJlcjtcclxuXHRiYW5uZXJSYWRpdXNFbmFibGVkOiBib29sZWFuO1xyXG5cdGJvcmRlclJhZGl1czogW251bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlcl07XHJcblx0cGFkZGluZzogbnVtYmVyO1xyXG5cdGZhZGU6IGJvb2xlYW47XHJcblx0YW5pbWF0aW9uOiBib29sZWFuO1xyXG5cclxuXHQvLyBJY29uIHNldHRpbmdzXHJcblx0aWNvbkVuYWJsZWQ6IGJvb2xlYW47XHJcblx0aWNvblNpemU6IG51bWJlcjtcclxuXHRpY29uUmFkaXVzOiBudW1iZXI7XHJcblx0aWNvbkJhY2tncm91bmQ6IGJvb2xlYW47XHJcblx0aWNvbkJvcmRlcjogbnVtYmVyO1xyXG5cdGljb25GcmFtZTogYm9vbGVhbjtcclxuXHRpY29uQWxpZ25tZW50SDogJ2ZsZXgtc3RhcnQnIHwgJ2NlbnRlcicgfCAnZmxleC1lbmQnO1xyXG5cdGljb25BbGlnbm1lbnRWOiAnZmxleC1zdGFydCcgfCAnY2VudGVyJyB8ICdmbGV4LWVuZCc7XHJcblx0aWNvbk9mZnNldFg6IG51bWJlcjtcclxuXHRpY29uT2Zmc2V0WTogbnVtYmVyO1xyXG59XHJcblxyXG4vKipcclxuICogQmFubmVyIHByb3BlcnR5IHNldHRpbmdzIChnbG9iYWwsIG5vdCBkZXZpY2Utc3BlY2lmaWMpXHJcbiAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIEJhbm5lclByb3BlcnR5U2V0dGluZ3Mge1xyXG5cdGltYWdlUHJvcGVydHk6IHN0cmluZztcclxuXHRpY29uUHJvcGVydHk6IHN0cmluZztcclxuXHRoaWRlUHJvcGVydHlFbmFibGVkOiBib29sZWFuO1xyXG5cdGhpZGVQcm9wZXJ0eTogc3RyaW5nO1xyXG59XHJcblxyXG4vKipcclxuICogQ29tcGxldGUgYmFubmVyIHNldHRpbmdzXHJcbiAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIEJhbm5lclNldHRpbmdzIHtcclxuXHRwcm9wZXJ0aWVzOiBCYW5uZXJQcm9wZXJ0eVNldHRpbmdzO1xyXG5cdGRlc2t0b3A6IEJhbm5lckRldmljZVNldHRpbmdzO1xyXG5cdHRhYmxldDogQmFubmVyRGV2aWNlU2V0dGluZ3M7XHJcblx0cGhvbmU6IEJhbm5lckRldmljZVNldHRpbmdzO1xyXG59XHJcblxyXG4vKipcclxuICogUGFyc2VkIGJhbm5lciBpbWFnZSBvcHRpb25zXHJcbiAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIEJhbm5lckltYWdlT3B0aW9ucyB7XHJcblx0dXJsOiBzdHJpbmc7XHJcblx0ZXh0ZXJuYWw6IGJvb2xlYW47XHJcblx0eDogbnVtYmVyO1xyXG5cdHk6IG51bWJlcjtcclxuXHR0eXBlOiBCYW5uZXJDb250ZW50VHlwZSB8IG51bGw7XHJcblx0cmVwZWF0YWJsZTogYm9vbGVhbjtcclxufVxyXG5cclxuLyoqXHJcbiAqIEJhbm5lciBkYXRhIGZvciBhIHNwZWNpZmljIHZpZXdcclxuICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgQmFubmVyRGF0YSB7XHJcblx0ZmlsZXBhdGg6IHN0cmluZyB8IG51bGw7XHJcblx0aW1hZ2U6IHN0cmluZyB8IG51bGw7XHJcblx0aWNvbjogc3RyaW5nIHwgbnVsbDtcclxuXHR2aWV3TW9kZTogJ3NvdXJjZScgfCAncHJldmlldycgfCBudWxsO1xyXG5cdGxhc3RWaWV3TW9kZTogJ3NvdXJjZScgfCAncHJldmlldycgfCBudWxsO1xyXG5cdGlzSW1hZ2VDaGFuZ2U6IGJvb2xlYW47XHJcblx0aXNJbWFnZVByb3BzVXBkYXRlOiBib29sZWFuO1xyXG5cdG5lZWRzVXBkYXRlOiBib29sZWFuO1xyXG59XHJcblxyXG4vKipcclxuICogRGVmYXVsdCBkZXZpY2Utc3BlY2lmaWMgYmFubmVyIHNldHRpbmdzXHJcbiAqL1xyXG5leHBvcnQgY29uc3QgREVGQVVMVF9CQU5ORVJfREVWSUNFX1NFVFRJTkdTOiBSZWNvcmQ8RGV2aWNlVHlwZSwgQmFubmVyRGV2aWNlU2V0dGluZ3M+ID0ge1xyXG5cdFtEZXZpY2VUeXBlLkRlc2t0b3BdOiB7XHJcblx0XHRlbmFibGVkOiB0cnVlLFxyXG5cdFx0aGVpZ2h0OiAyNDAsXHJcblx0XHR2aWV3T2Zmc2V0OiAwLFxyXG5cdFx0bm90ZU9mZnNldDogLTMyLFxyXG5cdFx0YmFubmVyUmFkaXVzRW5hYmxlZDogZmFsc2UsXHJcblx0XHRib3JkZXJSYWRpdXM6IFs4LCA4LCA4LCA4XSxcclxuXHRcdHBhZGRpbmc6IDgsXHJcblx0XHRmYWRlOiB0cnVlLFxyXG5cdFx0YW5pbWF0aW9uOiBmYWxzZSxcclxuXHRcdGljb25FbmFibGVkOiBmYWxzZSxcclxuXHRcdGljb25TaXplOiA5NixcclxuXHRcdGljb25SYWRpdXM6IDgsXHJcblx0XHRpY29uQmFja2dyb3VuZDogdHJ1ZSxcclxuXHRcdGljb25Cb3JkZXI6IDIsXHJcblx0XHRpY29uRnJhbWU6IHRydWUsXHJcblx0XHRpY29uQWxpZ25tZW50SDogJ2ZsZXgtc3RhcnQnLFxyXG5cdFx0aWNvbkFsaWdubWVudFY6ICdmbGV4LWVuZCcsXHJcblx0XHRpY29uT2Zmc2V0WDogMCxcclxuXHRcdGljb25PZmZzZXRZOiAtMjQsXHJcblx0fSxcclxuXHRbRGV2aWNlVHlwZS5UYWJsZXRdOiB7XHJcblx0XHRlbmFibGVkOiB0cnVlLFxyXG5cdFx0aGVpZ2h0OiAxOTAsXHJcblx0XHR2aWV3T2Zmc2V0OiAwLFxyXG5cdFx0bm90ZU9mZnNldDogLTMyLFxyXG5cdFx0YmFubmVyUmFkaXVzRW5hYmxlZDogZmFsc2UsXHJcblx0XHRib3JkZXJSYWRpdXM6IFs4LCA4LCA4LCA4XSxcclxuXHRcdHBhZGRpbmc6IDgsXHJcblx0XHRmYWRlOiB0cnVlLFxyXG5cdFx0YW5pbWF0aW9uOiBmYWxzZSxcclxuXHRcdGljb25FbmFibGVkOiBmYWxzZSxcclxuXHRcdGljb25TaXplOiA5NixcclxuXHRcdGljb25SYWRpdXM6IDgsXHJcblx0XHRpY29uQmFja2dyb3VuZDogdHJ1ZSxcclxuXHRcdGljb25Cb3JkZXI6IDIsXHJcblx0XHRpY29uRnJhbWU6IHRydWUsXHJcblx0XHRpY29uQWxpZ25tZW50SDogJ2ZsZXgtc3RhcnQnLFxyXG5cdFx0aWNvbkFsaWdubWVudFY6ICdmbGV4LWVuZCcsXHJcblx0XHRpY29uT2Zmc2V0WDogMCxcclxuXHRcdGljb25PZmZzZXRZOiAtMjQsXHJcblx0fSxcclxuXHRbRGV2aWNlVHlwZS5QaG9uZV06IHtcclxuXHRcdGVuYWJsZWQ6IHRydWUsXHJcblx0XHRoZWlnaHQ6IDE2MCxcclxuXHRcdHZpZXdPZmZzZXQ6IDAsXHJcblx0XHRub3RlT2Zmc2V0OiAtMzIsXHJcblx0XHRiYW5uZXJSYWRpdXNFbmFibGVkOiBmYWxzZSxcclxuXHRcdGJvcmRlclJhZGl1czogWzgsIDgsIDgsIDhdLFxyXG5cdFx0cGFkZGluZzogOCxcclxuXHRcdGZhZGU6IHRydWUsXHJcblx0XHRhbmltYXRpb246IGZhbHNlLFxyXG5cdFx0aWNvbkVuYWJsZWQ6IGZhbHNlLFxyXG5cdFx0aWNvblNpemU6IDU2LFxyXG5cdFx0aWNvblJhZGl1czogOCxcclxuXHRcdGljb25CYWNrZ3JvdW5kOiB0cnVlLFxyXG5cdFx0aWNvbkJvcmRlcjogMixcclxuXHRcdGljb25GcmFtZTogdHJ1ZSxcclxuXHRcdGljb25BbGlnbm1lbnRIOiAnZmxleC1zdGFydCcsXHJcblx0XHRpY29uQWxpZ25tZW50VjogJ2ZsZXgtZW5kJyxcclxuXHRcdGljb25PZmZzZXRYOiAwLFxyXG5cdFx0aWNvbk9mZnNldFk6IC0yNCxcclxuXHR9LFxyXG59O1xyXG5cclxuLyoqXHJcbiAqIERlZmF1bHQgYmFubmVyIHNldHRpbmdzXHJcbiAqL1xyXG5leHBvcnQgY29uc3QgREVGQVVMVF9CQU5ORVJfU0VUVElOR1M6IEJhbm5lclNldHRpbmdzID0ge1xyXG5cdHByb3BlcnRpZXM6IHtcclxuXHRcdGltYWdlUHJvcGVydHk6ICdiYW5uZXInLFxyXG5cdFx0aWNvblByb3BlcnR5OiAnaWNvbicsXHJcblx0XHRoaWRlUHJvcGVydHlFbmFibGVkOiBmYWxzZSxcclxuXHRcdGhpZGVQcm9wZXJ0eTogJycsXHJcblx0fSxcclxuXHRkZXNrdG9wOiB7IC4uLkRFRkFVTFRfQkFOTkVSX0RFVklDRV9TRVRUSU5HU1tEZXZpY2VUeXBlLkRlc2t0b3BdIH0sXHJcblx0dGFibGV0OiB7IC4uLkRFRkFVTFRfQkFOTkVSX0RFVklDRV9TRVRUSU5HU1tEZXZpY2VUeXBlLlRhYmxldF0gfSxcclxuXHRwaG9uZTogeyAuLi5ERUZBVUxUX0JBTk5FUl9ERVZJQ0VfU0VUVElOR1NbRGV2aWNlVHlwZS5QaG9uZV0gfSxcclxufTtcclxuXHJcbi8qKlxyXG4gKiBQbHVnaW4gc2V0dGluZ3MgaW50ZXJmYWNlXHJcbiAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIEltYWdlTWFuYWdlclNldHRpbmdzIHtcclxuXHQvLyBHZW5lcmFsIFNldHRpbmdzXHJcblx0ZW5hYmxlUmVuYW1lT25QYXN0ZTogYm9vbGVhbjtcclxuXHRlbmFibGVSZW5hbWVPbkRyb3A6IGJvb2xlYW47XHJcblx0aW1hZ2VOYW1lVGVtcGxhdGU6IHN0cmluZztcclxuXHRhdHRhY2htZW50TG9jYXRpb246IEF0dGFjaG1lbnRMb2NhdGlvbjtcclxuXHRjdXN0b21BdHRhY2htZW50UGF0aDogc3RyaW5nO1xyXG5cclxuXHQvLyBJbWFnZSBTZXJ2aWNlc1xyXG5cdGRlZmF1bHRQcm92aWRlcjogSW1hZ2VQcm92aWRlcjtcclxuXHR1bnNwbGFzaFByb3h5U2VydmVyOiBzdHJpbmc7XHJcblx0cGV4ZWxzQXBpS2V5OiBzdHJpbmc7IC8vIFBsYWludGV4dCBBUEkga2V5IChiYWNrd2FyZCBjb21wYXRpYmlsaXR5LCBmYWxsYmFjaylcclxuXHRwZXhlbHNBcGlLZXlTZWNyZXRJZDogc3RyaW5nOyAvLyBTZWNyZXQgSUQgZm9yIFNlY3JldFN0b3JhZ2UgKDEuMTEuNCspXHJcblx0cGl4YWJheUFwaUtleTogc3RyaW5nOyAvLyBQbGFpbnRleHQgQVBJIGtleSAoYmFja3dhcmQgY29tcGF0aWJpbGl0eSwgZmFsbGJhY2spXHJcblx0cGl4YWJheUFwaUtleVNlY3JldElkOiBzdHJpbmc7IC8vIFNlY3JldCBJRCBmb3IgU2VjcmV0U3RvcmFnZSAoMS4xMS40KylcclxuXHRkZWZhdWx0T3JpZW50YXRpb246IEltYWdlT3JpZW50YXRpb247XHJcblx0ZGVmYXVsdEltYWdlU2l6ZTogSW1hZ2VTaXplO1xyXG5cclxuXHQvLyBQcm9wZXJ0eSBJbnNlcnRpb25cclxuXHRlbmFibGVQcm9wZXJ0eVBhc3RlOiBib29sZWFuO1xyXG5cdHByb3BlcnR5TGlua0Zvcm1hdDogUHJvcGVydHlMaW5rRm9ybWF0O1xyXG5cdGN1c3RvbVByb3BlcnR5TGlua0Zvcm1hdDogc3RyaW5nO1xyXG5cdGRlZmF1bHRQcm9wZXJ0eU5hbWU6IHN0cmluZztcclxuXHRkZWZhdWx0SWNvblByb3BlcnR5TmFtZTogc3RyaW5nO1xyXG5cclxuXHQvLyBBbHQgdGV4dCBwcm9wZXJ0eVxyXG5cdGFsdFRleHRQcm9wZXJ0eTogc3RyaW5nO1xyXG5cclxuXHQvLyBDb252ZXJzaW9uXHJcblx0YXV0b0NvbnZlcnRSZW1vdGVJbWFnZXM6IGJvb2xlYW47XHJcblx0Y29udmVydE9uTm90ZU9wZW46IGJvb2xlYW47XHJcblx0Y29udmVydE9uTm90ZVNhdmU6IGJvb2xlYW47XHJcblx0cHJvY2Vzc0JhY2tncm91bmRDaGFuZ2VzOiBib29sZWFuO1xyXG5cclxuXHQvLyBSZW5hbWUgT3B0aW9uc1xyXG5cdHNob3dSZW5hbWVEaWFsb2c6IGJvb2xlYW47XHJcblx0YXV0b1JlbmFtZTogYm9vbGVhbjtcclxuXHRkdXBOdW1iZXJEZWxpbWl0ZXI6IHN0cmluZztcclxuXHRkdXBOdW1iZXJBdFN0YXJ0OiBib29sZWFuO1xyXG5cdGRpc2FibGVSZW5hbWVOb3RpY2U6IGJvb2xlYW47XHJcblx0ZW5hYmxlRGVzY3JpcHRpdmVJbWFnZXM6IGJvb2xlYW47IC8vIEFzayBmb3IgZGVzY3JpcHRpb24sIHVzZSBhcyBkaXNwbGF5IHRleHQgKG5vdGUgYm9keSBvbmx5KVxyXG5cclxuXHQvLyBJbWFnZSBJbnNlcnRpb24gT3B0aW9ucyAocmVtb3RlIGltYWdlIGF0dHJpYnV0aW9uIG9wdGlvbnMpXHJcblx0aW5zZXJ0U2l6ZTogc3RyaW5nOyAvLyBJbWFnZSBzaXplIGluIG1hcmtkb3duIChlLmcuLCBcIjIwMFwiIG9yIFwiMjAweDEwMFwiKVxyXG5cdGluc2VydFJlZmVycmFsOiBib29sZWFuOyAvLyBJbnNlcnQgYXR0cmlidXRpb24gdGV4dCAoZS5nLiwgXCJQaG90byBieSBbYXV0aG9yXSBvbiBbcHJvdmlkZXJdXCIpXHJcblx0aW5zZXJ0QmFja0xpbms6IGJvb2xlYW47IC8vIEluc2VydCBiYWNrbGluayBiZWZvcmUgYXR0cmlidXRpb24gKGUuZy4sIFwiW0JhY2tsaW5rXSh1cmwpIHwgUGhvdG8gYnkuLi5cIilcclxuXHRhcHBlbmRSZWZlcnJhbDogYm9vbGVhbjsgLy8gQXBwZW5kIHJlZmVycmFsIGF0IGVuZCBvZiBmaWxlIHdoZW4gaW5zZXJ0aW5nIHRvIGZyb250bWF0dGVyXHJcblxyXG5cdC8vIEJhbm5lciBTZXR0aW5nc1xyXG5cdGJhbm5lcjogQmFubmVyU2V0dGluZ3M7XHJcblxyXG5cdC8vIEFkdmFuY2VkXHJcblx0c3VwcG9ydGVkRXh0ZW5zaW9uczogc3RyaW5nW107XHJcblx0ZGVidWdNb2RlOiBib29sZWFuO1xyXG59XHJcblxyXG4vKipcclxuICogRGVmYXVsdCBzZXR0aW5nc1xyXG4gKi9cclxuZXhwb3J0IGNvbnN0IERFRkFVTFRfU0VUVElOR1M6IEltYWdlTWFuYWdlclNldHRpbmdzID0ge1xyXG5cdC8vIEdlbmVyYWwgU2V0dGluZ3NcclxuXHRlbmFibGVSZW5hbWVPblBhc3RlOiB0cnVlLFxyXG5cdGVuYWJsZVJlbmFtZU9uRHJvcDogdHJ1ZSxcclxuXHRpbWFnZU5hbWVUZW1wbGF0ZTogJycsXHJcblx0YXR0YWNobWVudExvY2F0aW9uOiBBdHRhY2htZW50TG9jYXRpb24uT2JzaWRpYW5EZWZhdWx0LFxyXG5cdGN1c3RvbUF0dGFjaG1lbnRQYXRoOiAnLi9hc3NldHMnLFxyXG5cclxuXHQvLyBJbWFnZSBTZXJ2aWNlc1xyXG5cdGRlZmF1bHRQcm92aWRlcjogSW1hZ2VQcm92aWRlci5VbnNwbGFzaCxcclxuXHR1bnNwbGFzaFByb3h5U2VydmVyOiAnJyxcclxuXHRwZXhlbHNBcGlLZXk6ICcnLFxyXG5cdHBleGVsc0FwaUtleVNlY3JldElkOiAnJyxcclxuXHRwaXhhYmF5QXBpS2V5OiAnJyxcclxuXHRwaXhhYmF5QXBpS2V5U2VjcmV0SWQ6ICcnLFxyXG5cdGRlZmF1bHRPcmllbnRhdGlvbjogSW1hZ2VPcmllbnRhdGlvbi5BbnksXHJcblx0ZGVmYXVsdEltYWdlU2l6ZTogSW1hZ2VTaXplLkxhcmdlLFxyXG5cclxuXHQvLyBQcm9wZXJ0eSBJbnNlcnRpb25cclxuXHRlbmFibGVQcm9wZXJ0eVBhc3RlOiB0cnVlLFxyXG5cdHByb3BlcnR5TGlua0Zvcm1hdDogUHJvcGVydHlMaW5rRm9ybWF0Lk9ic2lkaWFuRGVmYXVsdCxcclxuXHRjdXN0b21Qcm9wZXJ0eUxpbmtGb3JtYXQ6ICd7aW1hZ2UtdXJsfScsXHJcblx0ZGVmYXVsdFByb3BlcnR5TmFtZTogJ2Jhbm5lcicsXHJcblx0ZGVmYXVsdEljb25Qcm9wZXJ0eU5hbWU6ICdpY29uJyxcclxuXHRhbHRUZXh0UHJvcGVydHk6ICcnLFxyXG5cclxuXHQvLyBDb252ZXJzaW9uXHJcblx0YXV0b0NvbnZlcnRSZW1vdGVJbWFnZXM6IGZhbHNlLFxyXG5cdGNvbnZlcnRPbk5vdGVPcGVuOiBmYWxzZSxcclxuXHRjb252ZXJ0T25Ob3RlU2F2ZTogZmFsc2UsXHJcblx0cHJvY2Vzc0JhY2tncm91bmRDaGFuZ2VzOiB0cnVlLFxyXG5cclxuXHQvLyBSZW5hbWUgT3B0aW9uc1xyXG5cdHNob3dSZW5hbWVEaWFsb2c6IHRydWUsXHJcblx0YXV0b1JlbmFtZTogZmFsc2UsXHJcblx0ZHVwTnVtYmVyRGVsaW1pdGVyOiAnLScsXHJcblx0ZHVwTnVtYmVyQXRTdGFydDogZmFsc2UsXHJcblx0ZGlzYWJsZVJlbmFtZU5vdGljZTogZmFsc2UsXHJcblx0ZW5hYmxlRGVzY3JpcHRpdmVJbWFnZXM6IGZhbHNlLFxyXG5cclxuXHQvLyBJbWFnZSBJbnNlcnRpb24gT3B0aW9ucyAocmVtb3RlIGltYWdlIGF0dHJpYnV0aW9uIG9wdGlvbnMpXHJcblx0aW5zZXJ0U2l6ZTogJycsIC8vIEVtcHR5ID0gbm8gc2l6ZSBzcGVjaWZpZWRcclxuXHRpbnNlcnRSZWZlcnJhbDogdHJ1ZSwgLy8gRGVmYXVsdCB0byB0cnVlIChhdHRyaWJ1dGlvbilcclxuXHRpbnNlcnRCYWNrTGluazogZmFsc2UsIC8vIERlZmF1bHQgdG8gZmFsc2VcclxuXHRhcHBlbmRSZWZlcnJhbDogZmFsc2UsIC8vIERlZmF1bHQgdG8gZmFsc2VcclxuXHJcblx0Ly8gQmFubmVyIFNldHRpbmdzXHJcblx0YmFubmVyOiB7IC4uLkRFRkFVTFRfQkFOTkVSX1NFVFRJTkdTIH0sXHJcblxyXG5cdC8vIEFkdmFuY2VkXHJcblx0c3VwcG9ydGVkRXh0ZW5zaW9uczogWydtZCcsICdtZHgnXSxcclxuXHRkZWJ1Z01vZGU6IGZhbHNlLFxyXG59O1xyXG5cclxuLyoqXHJcbiAqIFJlcHJlc2VudHMgYW4gaW1hZ2UgZnJvbSBhIHJlbW90ZSBwcm92aWRlclxyXG4gKi9cclxuZXhwb3J0IGludGVyZmFjZSBSZW1vdGVJbWFnZSB7XHJcblx0aWQ6IHN0cmluZztcclxuXHRwcm92aWRlcjogSW1hZ2VQcm92aWRlcjtcclxuXHR0aHVtYm5haWxVcmw6IHN0cmluZztcclxuXHRyZWd1bGFyVXJsOiBzdHJpbmc7XHJcblx0ZnVsbFVybDogc3RyaW5nO1xyXG5cdGRvd25sb2FkVXJsOiBzdHJpbmc7XHJcblx0d2lkdGg6IG51bWJlcjtcclxuXHRoZWlnaHQ6IG51bWJlcjtcclxuXHRkZXNjcmlwdGlvbj86IHN0cmluZztcclxuXHRhdXRob3I/OiBzdHJpbmc7XHJcblx0YXV0aG9yVXJsPzogc3RyaW5nO1xyXG5cdHBhZ2VVcmw/OiBzdHJpbmc7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBSZXN1bHQgb2YgcHJvY2Vzc2luZyBhbiBpbWFnZVxyXG4gKi9cclxuZXhwb3J0IGludGVyZmFjZSBQcm9jZXNzZWRJbWFnZSB7XHJcblx0ZmlsZTogVEZpbGUgfCBudWxsO1xyXG5cdHBhdGg6IHN0cmluZztcclxuXHRsaW5rVGV4dDogc3RyaW5nO1xyXG5cdGRlc2NyaXB0aW9uPzogc3RyaW5nO1xyXG5cdHN1Y2Nlc3M6IGJvb2xlYW47XHJcblx0ZXJyb3I/OiBzdHJpbmc7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBJbWFnZSBpbnNlcnRpb24gY29udGV4dFxyXG4gKi9cclxuZXhwb3J0IGludGVyZmFjZSBJbnNlcnRpb25Db250ZXh0IHtcclxuXHRpc1Byb3BlcnR5OiBib29sZWFuO1xyXG5cdHByb3BlcnR5TmFtZT86IHN0cmluZztcclxuXHRjdXJzb3JQb3NpdGlvbj86IEVkaXRvclBvc2l0aW9uO1xyXG5cdGFjdGl2ZUZpbGU6IFRGaWxlO1xyXG59XHJcblxyXG4vKipcclxuICogTmFtZSB0ZW1wbGF0ZSB2YXJpYWJsZXNcclxuICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgTmFtZVRlbXBsYXRlVmFyaWFibGVzIHtcclxuXHRmaWxlTmFtZTogc3RyaW5nO1xyXG5cdGRpck5hbWU6IHN0cmluZztcclxuXHRpbWFnZU5hbWVLZXk/OiBzdHJpbmc7XHJcblx0Zmlyc3RIZWFkaW5nPzogc3RyaW5nO1xyXG5cdGRhdGU6IHN0cmluZztcclxuXHR0aW1lOiBzdHJpbmc7XHJcblx0aW5kZXg/OiBudW1iZXI7XHJcbn1cclxuXHJcbi8vIEltcG9ydCB0eXBlcyBmcm9tIE9ic2lkaWFuIGZvciB1c2UgaW4gaW50ZXJmYWNlc1xyXG5pbXBvcnQgdHlwZSB7IFRGaWxlLCBFZGl0b3JQb3NpdGlvbiB9IGZyb20gJ29ic2lkaWFuJztcclxuIiwgIi8qKlxyXG4gKiBTdG9yYWdlIE1hbmFnZXIgU2VydmljZVxyXG4gKiBIYW5kbGVzIGZpbGUgc3RvcmFnZSwgcGF0aCByZXNvbHV0aW9uLCBhbmQgT2JzaWRpYW4gYXR0YWNobWVudCBsb2NhdGlvbiBpbnRlZ3JhdGlvblxyXG4gKi9cclxuXHJcbmltcG9ydCB7IEFwcCwgVEZpbGUsIFRGb2xkZXIsIG5vcm1hbGl6ZVBhdGggfSBmcm9tICdvYnNpZGlhbic7XHJcbmltcG9ydCB7IEltYWdlTWFuYWdlclNldHRpbmdzLCBBdHRhY2htZW50TG9jYXRpb24gfSBmcm9tICcuLi90eXBlcyc7XHJcblxyXG5leHBvcnQgY2xhc3MgU3RvcmFnZU1hbmFnZXIge1xyXG5cdHByaXZhdGUgYXBwOiBBcHA7XHJcblx0cHJpdmF0ZSBzZXR0aW5nczogSW1hZ2VNYW5hZ2VyU2V0dGluZ3M7XHJcblxyXG5cdGNvbnN0cnVjdG9yKGFwcDogQXBwLCBzZXR0aW5nczogSW1hZ2VNYW5hZ2VyU2V0dGluZ3MsIG9ic2VydmFibGU/OiB7IHN1YnNjcmliZShmbjogKHNldHRpbmdzOiBJbWFnZU1hbmFnZXJTZXR0aW5ncykgPT4gdm9pZCk6IHZvaWQgfSkge1xyXG5cdFx0dGhpcy5hcHAgPSBhcHA7XHJcblx0XHR0aGlzLnNldHRpbmdzID0gc2V0dGluZ3M7XHJcblxyXG5cdFx0Ly8gU3Vic2NyaWJlIHRvIHNldHRpbmdzIHVwZGF0ZXMgaWYgb2JzZXJ2YWJsZSBpcyBwcm92aWRlZFxyXG5cdFx0b2JzZXJ2YWJsZT8uc3Vic2NyaWJlKChuZXdTZXR0aW5ncykgPT4ge1xyXG5cdFx0XHR0aGlzLnVwZGF0ZVNldHRpbmdzKG5ld1NldHRpbmdzKTtcclxuXHRcdH0pO1xyXG5cdH1cclxuXHJcblx0LyoqXHJcblx0ICogVXBkYXRlIHNldHRpbmdzIHJlZmVyZW5jZVxyXG5cdCAqL1xyXG5cdHVwZGF0ZVNldHRpbmdzKHNldHRpbmdzOiBJbWFnZU1hbmFnZXJTZXR0aW5ncyk6IHZvaWQge1xyXG5cdFx0dGhpcy5zZXR0aW5ncyA9IHNldHRpbmdzO1xyXG5cdH1cclxuXHJcblx0LyoqXHJcblx0ICogR2V0IHRoZSBhdHRhY2htZW50IGZvbGRlciBwYXRoIGZvciBhIGdpdmVuIG5vdGVcclxuXHQgKi9cclxuXHRnZXRBdHRhY2htZW50Rm9sZGVyKG5vdGVGaWxlOiBURmlsZSk6IHN0cmluZyB7XHJcblx0XHRjb25zdCBub3RlUGF0aCA9IG5vdGVGaWxlLnBhcmVudD8ucGF0aCA/PyAnJztcclxuXHJcblx0XHRzd2l0Y2ggKHRoaXMuc2V0dGluZ3MuYXR0YWNobWVudExvY2F0aW9uKSB7XHJcblx0XHRcdGNhc2UgQXR0YWNobWVudExvY2F0aW9uLlNhbWVGb2xkZXI6XHJcblx0XHRcdFx0cmV0dXJuIG5vdGVQYXRoO1xyXG5cclxuXHRcdFx0Y2FzZSBBdHRhY2htZW50TG9jYXRpb24uU3ViZm9sZGVyOlxyXG5cdFx0XHRcdHJldHVybiBub3JtYWxpemVQYXRoKHRoaXMuam9pblBhdGhzKG5vdGVQYXRoLCB0aGlzLnNldHRpbmdzLmN1c3RvbUF0dGFjaG1lbnRQYXRoKSk7XHJcblxyXG5cdFx0XHRjYXNlIEF0dGFjaG1lbnRMb2NhdGlvbi5WYXVsdEZvbGRlcjpcclxuXHRcdFx0XHRyZXR1cm4gbm9ybWFsaXplUGF0aCh0aGlzLnNldHRpbmdzLmN1c3RvbUF0dGFjaG1lbnRQYXRoKTtcclxuXHJcblx0XHRcdGNhc2UgQXR0YWNobWVudExvY2F0aW9uLk9ic2lkaWFuRGVmYXVsdDpcclxuXHRcdFx0ZGVmYXVsdDpcclxuXHRcdFx0XHRyZXR1cm4gdGhpcy5nZXRPYnNpZGlhbkF0dGFjaG1lbnRGb2xkZXIobm90ZUZpbGUpO1xyXG5cdFx0fVxyXG5cdH1cclxuXHJcblx0LyoqXHJcblx0ICogR2V0IE9ic2lkaWFuJ3MgY29uZmlndXJlZCBhdHRhY2htZW50IGZvbGRlclxyXG5cdCAqL1xyXG5cdHByaXZhdGUgZ2V0T2JzaWRpYW5BdHRhY2htZW50Rm9sZGVyKG5vdGVGaWxlOiBURmlsZSk6IHN0cmluZyB7XHJcblx0XHQvLyBBY2Nlc3MgT2JzaWRpYW4ncyBpbnRlcm5hbCBjb25maWcgZm9yIGF0dGFjaG1lbnQgZm9sZGVyIChub3QgaW4gcHVibGljIEFQSSB0eXBlcyBidXQgYWNjZXNzaWJsZSBhdCBydW50aW1lKVxyXG5cdFx0Y29uc3QgdmF1bHRDb25maWcgPSAodGhpcy5hcHAudmF1bHQgYXMgdW5rbm93biBhcyB7IGNvbmZpZz86IHsgYXR0YWNobWVudEZvbGRlclBhdGg/OiBzdHJpbmcgfSB9KS5jb25maWc7XHJcblx0XHRjb25zdCBhdHRhY2htZW50Rm9sZGVyUGF0aDogc3RyaW5nID0gdmF1bHRDb25maWc/LmF0dGFjaG1lbnRGb2xkZXJQYXRoID8/ICcvJztcclxuXHRcdGNvbnN0IG5vdGVQYXRoID0gbm90ZUZpbGUucGFyZW50Py5wYXRoID8/ICcnO1xyXG5cclxuXHRcdGlmIChhdHRhY2htZW50Rm9sZGVyUGF0aCA9PT0gJy8nKSB7XHJcblx0XHRcdC8vIFZhdWx0IHJvb3RcclxuXHRcdFx0cmV0dXJuICcnO1xyXG5cdFx0fSBlbHNlIGlmIChhdHRhY2htZW50Rm9sZGVyUGF0aCA9PT0gJy4vJykge1xyXG5cdFx0XHQvLyBTYW1lIGZvbGRlciBhcyBub3RlXHJcblx0XHRcdHJldHVybiBub3RlUGF0aDtcclxuXHRcdH0gZWxzZSBpZiAoYXR0YWNobWVudEZvbGRlclBhdGguc3RhcnRzV2l0aCgnLi8nKSkge1xyXG5cdFx0XHQvLyBSZWxhdGl2ZSB0byBub3RlXHJcblx0XHRcdGNvbnN0IHJlbGF0aXZlUGF0aCA9IGF0dGFjaG1lbnRGb2xkZXJQYXRoLnNsaWNlKDIpO1xyXG5cdFx0XHRyZXR1cm4gbm9ybWFsaXplUGF0aCh0aGlzLmpvaW5QYXRocyhub3RlUGF0aCwgcmVsYXRpdmVQYXRoKSk7XHJcblx0XHR9IGVsc2Uge1xyXG5cdFx0XHQvLyBBYnNvbHV0ZSBwYXRoIGluIHZhdWx0XHJcblx0XHRcdHJldHVybiBub3JtYWxpemVQYXRoKGF0dGFjaG1lbnRGb2xkZXJQYXRoKTtcclxuXHRcdH1cclxuXHR9XHJcblxyXG5cdC8qKlxyXG5cdCAqIEpvaW4gcGF0aCBzZWdtZW50c1xyXG5cdCAqL1xyXG5cdHByaXZhdGUgam9pblBhdGhzKC4uLnBhcnRzOiBzdHJpbmdbXSk6IHN0cmluZyB7XHJcblx0XHRyZXR1cm4gcGFydHMuZmlsdGVyKHAgPT4gcCkuam9pbignLycpO1xyXG5cdH1cclxuXHJcblx0LyoqXHJcblx0ICogRW5zdXJlIGEgZm9sZGVyIGV4aXN0cywgY3JlYXRpbmcgaXQgaWYgbmVjZXNzYXJ5XHJcblx0ICovXHJcblx0YXN5bmMgZW5zdXJlRm9sZGVyRXhpc3RzKGZvbGRlclBhdGg6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xyXG5cdFx0aWYgKCFmb2xkZXJQYXRoKSByZXR1cm47XHJcblxyXG5cdFx0Y29uc3Qgbm9ybWFsaXplZFBhdGggPSBub3JtYWxpemVQYXRoKGZvbGRlclBhdGgpO1xyXG5cdFx0Y29uc3QgZm9sZGVyID0gdGhpcy5hcHAudmF1bHQuZ2V0QWJzdHJhY3RGaWxlQnlQYXRoKG5vcm1hbGl6ZWRQYXRoKTtcclxuXHJcblx0XHRpZiAoIWZvbGRlcikge1xyXG5cdFx0XHRhd2FpdCB0aGlzLmFwcC52YXVsdC5jcmVhdGVGb2xkZXIobm9ybWFsaXplZFBhdGgpO1xyXG5cdFx0fSBlbHNlIGlmICghKGZvbGRlciBpbnN0YW5jZW9mIFRGb2xkZXIpKSB7XHJcblx0XHRcdHRocm93IG5ldyBFcnJvcihgUGF0aCBleGlzdHMgYnV0IGlzIG5vdCBhIGZvbGRlcjogJHtub3JtYWxpemVkUGF0aH1gKTtcclxuXHRcdH1cclxuXHR9XHJcblxyXG5cdC8qKlxyXG5cdCAqIEdlbmVyYXRlIGEgdW5pcXVlIGZpbGUgcGF0aCBmb3IgYW4gaW1hZ2VcclxuXHQgKi9cclxuXHRhc3luYyBnZXRBdmFpbGFibGVQYXRoKGJhc2VOYW1lOiBzdHJpbmcsIGV4dGVuc2lvbjogc3RyaW5nLCBub3RlRmlsZTogVEZpbGUpOiBQcm9taXNlPHN0cmluZz4ge1xyXG5cdFx0Y29uc3QgZm9sZGVyID0gdGhpcy5nZXRBdHRhY2htZW50Rm9sZGVyKG5vdGVGaWxlKTtcclxuXHRcdGF3YWl0IHRoaXMuZW5zdXJlRm9sZGVyRXhpc3RzKGZvbGRlcik7XHJcblxyXG5cdFx0Y29uc3Qgc2FuaXRpemVkTmFtZSA9IHRoaXMuc2FuaXRpemVGaWxlTmFtZShiYXNlTmFtZSk7XHJcblx0XHRsZXQgZmlsZU5hbWUgPSBgJHtzYW5pdGl6ZWROYW1lfS4ke2V4dGVuc2lvbn1gO1xyXG5cdFx0bGV0IGZpbGVQYXRoID0gZm9sZGVyID8gbm9ybWFsaXplUGF0aCh0aGlzLmpvaW5QYXRocyhmb2xkZXIsIGZpbGVOYW1lKSkgOiBub3JtYWxpemVQYXRoKGZpbGVOYW1lKTtcclxuXHJcblx0XHQvLyBDaGVjayBmb3IgZHVwbGljYXRlc1xyXG5cdFx0bGV0IGNvdW50ZXIgPSAxO1xyXG5cdFx0d2hpbGUgKHRoaXMuYXBwLnZhdWx0LmdldEFic3RyYWN0RmlsZUJ5UGF0aChmaWxlUGF0aCkpIHtcclxuXHRcdFx0aWYgKHRoaXMuc2V0dGluZ3MuZHVwTnVtYmVyQXRTdGFydCkge1xyXG5cdFx0XHRcdGZpbGVOYW1lID0gYCR7Y291bnRlcn0ke3RoaXMuc2V0dGluZ3MuZHVwTnVtYmVyRGVsaW1pdGVyfSR7c2FuaXRpemVkTmFtZX0uJHtleHRlbnNpb259YDtcclxuXHRcdFx0fSBlbHNlIHtcclxuXHRcdFx0XHRmaWxlTmFtZSA9IGAke3Nhbml0aXplZE5hbWV9JHt0aGlzLnNldHRpbmdzLmR1cE51bWJlckRlbGltaXRlcn0ke2NvdW50ZXJ9LiR7ZXh0ZW5zaW9ufWA7XHJcblx0XHRcdH1cclxuXHRcdFx0ZmlsZVBhdGggPSBmb2xkZXIgPyBub3JtYWxpemVQYXRoKHRoaXMuam9pblBhdGhzKGZvbGRlciwgZmlsZU5hbWUpKSA6IG5vcm1hbGl6ZVBhdGgoZmlsZU5hbWUpO1xyXG5cdFx0XHRjb3VudGVyKys7XHJcblx0XHR9XHJcblxyXG5cdFx0cmV0dXJuIGZpbGVQYXRoO1xyXG5cdH1cclxuXHJcblx0LyoqXHJcblx0ICogU2F2ZSBiaW5hcnkgZGF0YSBhcyBhIGZpbGVcclxuXHQgKi9cclxuXHRhc3luYyBzYXZlRmlsZShkYXRhOiBBcnJheUJ1ZmZlciwgZmlsZVBhdGg6IHN0cmluZyk6IFByb21pc2U8VEZpbGU+IHtcclxuXHRcdGNvbnN0IG5vcm1hbGl6ZWRQYXRoID0gbm9ybWFsaXplUGF0aChmaWxlUGF0aCk7XHJcblxyXG5cdFx0Ly8gRW5zdXJlIHBhcmVudCBmb2xkZXIgZXhpc3RzXHJcblx0XHRjb25zdCBsYXN0U2xhc2ggPSBub3JtYWxpemVkUGF0aC5sYXN0SW5kZXhPZignLycpO1xyXG5cdFx0Y29uc3QgcGFyZW50UGF0aCA9IGxhc3RTbGFzaCA+IDAgPyBub3JtYWxpemVkUGF0aC5zbGljZSgwLCBsYXN0U2xhc2gpIDogJyc7XHJcblx0XHRpZiAocGFyZW50UGF0aCkge1xyXG5cdFx0XHRhd2FpdCB0aGlzLmVuc3VyZUZvbGRlckV4aXN0cyhwYXJlbnRQYXRoKTtcclxuXHRcdH1cclxuXHJcblx0XHRyZXR1cm4gYXdhaXQgdGhpcy5hcHAudmF1bHQuY3JlYXRlQmluYXJ5KG5vcm1hbGl6ZWRQYXRoLCBkYXRhKTtcclxuXHR9XHJcblxyXG5cdC8qKlxyXG5cdCAqIEdlbmVyYXRlIG1hcmtkb3duIGltYWdlIGxpbmsgZm9yIGEgZmlsZVxyXG5cdCAqIEVuc3VyZXMgdGhlIGxpbmsgaW5jbHVkZXMgJyEnIGZvciBpbWFnZXNcclxuXHQgKiBAcGFyYW0gZGlzcGxheVRleHQgT3B0aW9uYWwgZGlzcGxheSB0ZXh0IHRvIGFkZCBhZnRlciB0aGUgbGluayAoZS5nLiwgIVtbaW1hZ2UuanBnfGRpc3BsYXkgdGV4dF1dKVxyXG5cdCAqIEBwYXJhbSBpbnNlcnRTaXplIE9wdGlvbmFsIHNpemUgdG8gYWRkIChlLmcuLCBcIjIwMFwiIG9yIFwiMjAweDEwMFwiKVxyXG5cdCAqL1xyXG5cdGdlbmVyYXRlTWFya2Rvd25MaW5rKGZpbGU6IFRGaWxlLCBzb3VyY2VQYXRoOiBzdHJpbmcsIGRpc3BsYXlUZXh0Pzogc3RyaW5nLCBpbnNlcnRTaXplPzogc3RyaW5nKTogc3RyaW5nIHtcclxuXHRcdGNvbnN0IGxpbmsgPSB0aGlzLmFwcC5maWxlTWFuYWdlci5nZW5lcmF0ZU1hcmtkb3duTGluayhmaWxlLCBzb3VyY2VQYXRoKTtcclxuXHRcdC8vIE9ic2lkaWFuJ3MgZ2VuZXJhdGVNYXJrZG93bkxpbmsgc2hvdWxkIGluY2x1ZGUgJyEnIGZvciBpbWFnZXMsIGJ1dCBlbnN1cmUgaXQgZG9lc1xyXG5cdFx0bGV0IGltYWdlTGluayA9IGxpbms7XHJcblx0XHRpZiAodGhpcy5pc0ltYWdlRmlsZShmaWxlKSAmJiAhbGluay5zdGFydHNXaXRoKCchJykpIHtcclxuXHRcdFx0Ly8gSWYgaXQncyBhbiBpbWFnZSBidXQgZG9lc24ndCBzdGFydCB3aXRoICchJywgYWRkIGl0XHJcblx0XHRcdGltYWdlTGluayA9IGAhJHtsaW5rfWA7XHJcblx0XHR9XHJcblxyXG5cdFx0Ly8gRGVidWcgbG9nZ2luZ1xyXG5cdFx0aWYgKHRoaXMuc2V0dGluZ3MuZGVidWdNb2RlKSB7XHJcblx0XHRcdGNvbnNvbGUuZGVidWcoJ1tJbWFnZSBNYW5hZ2VyXSBnZW5lcmF0ZU1hcmtkb3duTGluaycsIHtcclxuXHRcdFx0XHRvcmlnaW5hbExpbms6IGxpbmssXHJcblx0XHRcdFx0aW1hZ2VMaW5rLFxyXG5cdFx0XHRcdGluc2VydFNpemUsXHJcblx0XHRcdFx0ZGlzcGxheVRleHQsXHJcblx0XHRcdFx0aGFzU2l6ZTogISEoaW5zZXJ0U2l6ZSAmJiBpbnNlcnRTaXplLnRyaW0oKSlcclxuXHRcdFx0fSk7XHJcblx0XHR9XHJcblxyXG5cdFx0Ly8gSGFuZGxlIHNpemUgYW5kIGRpc3BsYXkgdGV4dFxyXG5cdFx0Ly8gRm9yIHdpa2lsaW5rczogIVtbcGF0aF1dIC0+ICFbW3BhdGh8c2l6ZV1dIG9yICFbW3BhdGh8c2l6ZXxkaXNwbGF5VGV4dF1dXHJcblx0XHQvLyBGb3IgbWFya2Rvd246ICFbYWx0XShwYXRoKSAtPiAhW2FsdHxzaXplXShwYXRoKSBvciAhW2Rpc3BsYXlUZXh0fHNpemVdKHBhdGgpXHJcblx0XHRpZiAoaW1hZ2VMaW5rLnN0YXJ0c1dpdGgoJyFbJykgJiYgaW1hZ2VMaW5rLmluY2x1ZGVzKCddKCcpKSB7XHJcblx0XHRcdC8vIE1hcmtkb3duIGxpbms6ICFbYWx0XShwYXRoKVxyXG5cdFx0XHRpZiAoaW5zZXJ0U2l6ZSAmJiBpbnNlcnRTaXplLnRyaW0oKSkge1xyXG5cdFx0XHRcdC8vIEFkZCBzaXplOiAhW2FsdHxzaXplXShwYXRoKVxyXG5cdFx0XHRcdGNvbnN0IHNpemVQYXJ0ID0gYHwke2luc2VydFNpemV9YDtcclxuXHRcdFx0XHRpZiAoZGlzcGxheVRleHQgJiYgZGlzcGxheVRleHQudHJpbSgpKSB7XHJcblx0XHRcdFx0XHQvLyBCb3RoIHNpemUgYW5kIGRpc3BsYXkgdGV4dDogIVtkaXNwbGF5VGV4dHxzaXplXShwYXRoKVxyXG5cdFx0XHRcdFx0aW1hZ2VMaW5rID0gaW1hZ2VMaW5rLnJlcGxhY2UoL14hXFxbKFteXFxdXSopXFxdLywgYCFbJHtkaXNwbGF5VGV4dH0ke3NpemVQYXJ0fV1gKTtcclxuXHRcdFx0XHR9IGVsc2Uge1xyXG5cdFx0XHRcdFx0Ly8gSnVzdCBzaXplOiAhW2FsdHxzaXplXShwYXRoKVxyXG5cdFx0XHRcdFx0Ly8gSGFuZGxlIGVtcHR5IGFsdCB0ZXh0IGNhc2U6ICFbXSAtPiAhW3xzaXplXVxyXG5cdFx0XHRcdFx0Y29uc3QgYWx0TWF0Y2ggPSBpbWFnZUxpbmsubWF0Y2goL14hXFxbKFteXFxdXSopXFxdLyk7XHJcblx0XHRcdFx0XHRpZiAoYWx0TWF0Y2gpIHtcclxuXHRcdFx0XHRcdFx0Y29uc3QgYWx0ID0gYWx0TWF0Y2hbMV0gfHwgJyc7XHJcblx0XHRcdFx0XHRcdGltYWdlTGluayA9IGltYWdlTGluay5yZXBsYWNlKC9eIVxcWyhbXlxcXV0qKVxcXS8sIGAhWyR7YWx0fSR7c2l6ZVBhcnR9XWApO1xyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdH1cclxuXHRcdFx0fSBlbHNlIGlmIChkaXNwbGF5VGV4dCAmJiBkaXNwbGF5VGV4dC50cmltKCkpIHtcclxuXHRcdFx0XHQvLyBKdXN0IGRpc3BsYXkgdGV4dDogIVtkaXNwbGF5VGV4dF0ocGF0aClcclxuXHRcdFx0XHRpbWFnZUxpbmsgPSBpbWFnZUxpbmsucmVwbGFjZSgvXiFcXFsoW15cXF1dKilcXF0vLCBgIVske2Rpc3BsYXlUZXh0fV1gKTtcclxuXHRcdFx0fVxyXG5cdFx0fSBlbHNlIGlmIChpbWFnZUxpbmsuc3RhcnRzV2l0aCgnIVsnKSAmJiBpbWFnZUxpbmsuaW5jbHVkZXMoJ11dJykpIHtcclxuXHRcdFx0Ly8gV2lraWxpbms6ICFbW3BhdGhdXVxyXG5cdFx0XHRjb25zdCBwYXJ0czogc3RyaW5nW10gPSBbXTtcclxuXHRcdFx0aWYgKGluc2VydFNpemUgJiYgaW5zZXJ0U2l6ZS50cmltKCkpIHtcclxuXHRcdFx0XHRwYXJ0cy5wdXNoKGluc2VydFNpemUpO1xyXG5cdFx0XHR9XHJcblx0XHRcdGlmIChkaXNwbGF5VGV4dCAmJiBkaXNwbGF5VGV4dC50cmltKCkpIHtcclxuXHRcdFx0XHRwYXJ0cy5wdXNoKGRpc3BsYXlUZXh0KTtcclxuXHRcdFx0fVxyXG5cdFx0XHRpZiAocGFydHMubGVuZ3RoID4gMCkge1xyXG5cdFx0XHRcdC8vIEFkZCBzaXplIGFuZC9vciBkaXNwbGF5IHRleHQ6ICFbW3BhdGh8c2l6ZV1dIG9yICFbW3BhdGh8c2l6ZXxkaXNwbGF5VGV4dF1dXHJcblx0XHRcdFx0aW1hZ2VMaW5rID0gaW1hZ2VMaW5rLnJlcGxhY2UoL1xcXVxcXSQvLCBgfCR7cGFydHMuam9pbignfCcpfV1dYCk7XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHJcblx0XHQvLyBEZWJ1ZyBsb2dnaW5nXHJcblx0XHRpZiAodGhpcy5zZXR0aW5ncy5kZWJ1Z01vZGUpIHtcclxuXHRcdFx0Y29uc29sZS5kZWJ1ZygnW0ltYWdlIE1hbmFnZXJdIGdlbmVyYXRlTWFya2Rvd25MaW5rIHJlc3VsdCcsIHtcclxuXHRcdFx0XHRmaW5hbExpbms6IGltYWdlTGlua1xyXG5cdFx0XHR9KTtcclxuXHRcdH1cclxuXHJcblx0XHRyZXR1cm4gaW1hZ2VMaW5rO1xyXG5cdH1cclxuXHJcblx0LyoqXHJcblx0ICogR2V0IHJlbGF0aXZlIHBhdGggZnJvbSBzb3VyY2UgZmlsZSB0byB0YXJnZXQgZmlsZVxyXG5cdCAqL1xyXG5cdGdldFJlbGF0aXZlUGF0aChmcm9tOiBURmlsZSwgdG86IFRGaWxlKTogc3RyaW5nIHtcclxuXHRcdGNvbnN0IGZyb21EaXIgPSBmcm9tLnBhcmVudD8ucGF0aCA/PyAnJztcclxuXHRcdGNvbnN0IHRvUGF0aCA9IHRvLnBhdGg7XHJcblxyXG5cdFx0aWYgKCFmcm9tRGlyKSB7XHJcblx0XHRcdHJldHVybiB0b1BhdGg7XHJcblx0XHR9XHJcblxyXG5cdFx0Ly8gU2ltcGxlIHJlbGF0aXZlIHBhdGggY2FsY3VsYXRpb25cclxuXHRcdC8vIEZvciBzYW1lIGRpcmVjdG9yeSwganVzdCByZXR1cm4gZmlsZSBuYW1lXHJcblx0XHRjb25zdCB0b0RpciA9IHRvLnBhcmVudD8ucGF0aCA/PyAnJztcclxuXHRcdGlmIChmcm9tRGlyID09PSB0b0Rpcikge1xyXG5cdFx0XHRyZXR1cm4gdG8ubmFtZTtcclxuXHRcdH1cclxuXHJcblx0XHQvLyBPdGhlcndpc2UgcmV0dXJuIHRoZSBmdWxsIHBhdGhcclxuXHRcdHJldHVybiB0b1BhdGg7XHJcblx0fVxyXG5cclxuXHQvKipcclxuXHQgKiBTYW5pdGl6ZSBhIGZpbGUgbmFtZVxyXG5cdCAqL1xyXG5cdHNhbml0aXplRmlsZU5hbWUobmFtZTogc3RyaW5nKTogc3RyaW5nIHtcclxuXHRcdC8vIFJlbW92ZSBvciByZXBsYWNlIGludmFsaWQgY2hhcmFjdGVyc1xyXG5cdFx0cmV0dXJuIG5hbWVcclxuXHRcdFx0LnJlcGxhY2UoL1tcXFxcLzoqP1wiPD58XS9nLCAnLScpICAvLyBSZXBsYWNlIFdpbmRvd3MgaW52YWxpZCBjaGFyc1xyXG5cdFx0XHQucmVwbGFjZSgvXFxzKy9nLCAnLScpICAgICAgICAgICAgLy8gUmVwbGFjZSB3aGl0ZXNwYWNlIHdpdGggaHlwaGVuc1xyXG5cdFx0XHQucmVwbGFjZSgvXlxcLisvLCAnJykgICAgICAgICAgICAgLy8gUmVtb3ZlIGxlYWRpbmcgZG90c1xyXG5cdFx0XHQucmVwbGFjZSgvXFwuKyQvLCAnJykgICAgICAgICAgICAgLy8gUmVtb3ZlIHRyYWlsaW5nIGRvdHNcclxuXHRcdFx0LnRyaW0oKTtcclxuXHR9XHJcblxyXG5cdC8qKlxyXG5cdCAqIEdldCBmaWxlIGV4dGVuc2lvbiBmcm9tIE1JTUUgdHlwZVxyXG5cdCAqL1xyXG5cdGdldEV4dGVuc2lvbkZyb21NaW1lVHlwZShtaW1lVHlwZTogc3RyaW5nKTogc3RyaW5nIHtcclxuXHRcdGNvbnN0IG1pbWVUb0V4dDogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHtcclxuXHRcdFx0J2ltYWdlL2pwZWcnOiAnanBnJyxcclxuXHRcdFx0J2ltYWdlL2pwZyc6ICdqcGcnLFxyXG5cdFx0XHQnaW1hZ2UvcG5nJzogJ3BuZycsXHJcblx0XHRcdCdpbWFnZS9naWYnOiAnZ2lmJyxcclxuXHRcdFx0J2ltYWdlL3dlYnAnOiAnd2VicCcsXHJcblx0XHRcdCdpbWFnZS9zdmcreG1sJzogJ3N2ZycsXHJcblx0XHRcdCdpbWFnZS9ibXAnOiAnYm1wJyxcclxuXHRcdFx0J2ltYWdlL3RpZmYnOiAndGlmZicsXHJcblx0XHRcdCdpbWFnZS9hdmlmJzogJ2F2aWYnLFxyXG5cdFx0fTtcclxuXHJcblx0XHRyZXR1cm4gbWltZVRvRXh0W21pbWVUeXBlXSA/PyAncG5nJztcclxuXHR9XHJcblxyXG5cdC8qKlxyXG5cdCAqIENoZWNrIGlmIGEgZmlsZSBpcyBhbiBpbWFnZSBiYXNlZCBvbiBleHRlbnNpb25cclxuXHQgKi9cclxuXHRpc0ltYWdlRmlsZShmaWxlOiBURmlsZSk6IGJvb2xlYW4ge1xyXG5cdFx0Y29uc3QgaW1hZ2VFeHRlbnNpb25zID0gWydqcGcnLCAnanBlZycsICdwbmcnLCAnZ2lmJywgJ3dlYnAnLCAnc3ZnJywgJ2JtcCcsICd0aWZmJywgJ2F2aWYnXTtcclxuXHRcdHJldHVybiBpbWFnZUV4dGVuc2lvbnMuaW5jbHVkZXMoZmlsZS5leHRlbnNpb24udG9Mb3dlckNhc2UoKSk7XHJcblx0fVxyXG5cclxuXHQvKipcclxuXHQgKiBDaGVjayBpZiBhIFVSTCBwb2ludHMgdG8gYW4gZXh0ZXJuYWwgaW1hZ2VcclxuXHQgKi9cclxuXHRpc0V4dGVybmFsSW1hZ2VVcmwodXJsOiBzdHJpbmcpOiBib29sZWFuIHtcclxuXHRcdHRyeSB7XHJcblx0XHRcdGNvbnN0IHBhcnNlZCA9IG5ldyBVUkwodXJsKTtcclxuXHRcdFx0aWYgKCFbJ2h0dHA6JywgJ2h0dHBzOiddLmluY2x1ZGVzKHBhcnNlZC5wcm90b2NvbCkpIHtcclxuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XHJcblx0XHRcdH1cclxuXHJcblx0XHRcdC8vIENoZWNrIGlmIFVSTCBlbmRzIHdpdGggY29tbW9uIGltYWdlIGV4dGVuc2lvbnNcclxuXHRcdFx0Y29uc3QgcGF0aG5hbWUgPSBwYXJzZWQucGF0aG5hbWUudG9Mb3dlckNhc2UoKTtcclxuXHRcdFx0Y29uc3QgaW1hZ2VFeHRlbnNpb25zID0gWycuanBnJywgJy5qcGVnJywgJy5wbmcnLCAnLmdpZicsICcud2VicCcsICcuc3ZnJywgJy5ibXAnLCAnLnRpZmYnLCAnLmF2aWYnXTtcclxuXHJcblx0XHRcdC8vIEFsc28gY2hlY2sgZm9yIGltYWdlLXJlbGF0ZWQgcXVlcnkgcGFyYW1zIG9yIHBhdGhzXHJcblx0XHRcdGlmIChpbWFnZUV4dGVuc2lvbnMuc29tZShleHQgPT4gcGF0aG5hbWUuZW5kc1dpdGgoZXh0KSkpIHtcclxuXHRcdFx0XHRyZXR1cm4gdHJ1ZTtcclxuXHRcdFx0fVxyXG5cclxuXHRcdFx0Ly8gQ29tbW9uIGltYWdlIGhvc3RpbmcgcGF0dGVybnNcclxuXHRcdFx0Y29uc3QgaW1hZ2VIb3N0cyA9IFtcclxuXHRcdFx0XHQnaW1hZ2VzLnVuc3BsYXNoLmNvbScsXHJcblx0XHRcdFx0J2ltYWdlcy5wZXhlbHMuY29tJyxcclxuXHRcdFx0XHQncGl4YWJheS5jb20nLFxyXG5cdFx0XHRcdCdpLmltZ3VyLmNvbScsXHJcblx0XHRcdFx0J2Nkbi5kaXNjb3JkYXBwLmNvbScsXHJcblx0XHRcdF07XHJcblxyXG5cdFx0XHRyZXR1cm4gaW1hZ2VIb3N0cy5zb21lKGhvc3QgPT4gcGFyc2VkLmhvc3RuYW1lLmluY2x1ZGVzKGhvc3QpKTtcclxuXHRcdH0gY2F0Y2gge1xyXG5cdFx0XHRyZXR1cm4gZmFsc2U7XHJcblx0XHR9XHJcblx0fVxyXG59XHJcbiIsICIvKipcclxuICogSW1hZ2UgUHJvY2Vzc29yIFNlcnZpY2VcclxuICogQ29yZSBpbWFnZSBoYW5kbGluZywgZG93bmxvYWRpbmcsIGFuZCBwcm9jZXNzaW5nXHJcbiAqL1xyXG5cclxuaW1wb3J0IHsgQXBwLCBURmlsZSwgTm90aWNlLCBNYXJrZG93blZpZXcsIHJlcXVlc3RVcmwgfSBmcm9tICdvYnNpZGlhbic7XHJcbmltcG9ydCB7IEltYWdlTWFuYWdlclNldHRpbmdzLCBQcm9jZXNzZWRJbWFnZSB9IGZyb20gJy4uL3R5cGVzJztcclxuaW1wb3J0IHsgU3RvcmFnZU1hbmFnZXIgfSBmcm9tICcuL1N0b3JhZ2VNYW5hZ2VyJztcclxuaW1wb3J0IHsgcmVuZGVyVGVtcGxhdGUsIGJ1aWxkVGVtcGxhdGVWYXJpYWJsZXMsIGlzVGVtcGxhdGVNZWFuaW5nZnVsIH0gZnJvbSAnLi4vdXRpbHMvdGVtcGxhdGUnO1xyXG5pbXBvcnQgeyBvcGVuUmVuYW1lTW9kYWwgfSBmcm9tICcuLi9tb2RhbHMvUmVuYW1lTW9kYWwnO1xyXG5pbXBvcnQgeyBvcGVuRGVzY3JpcHRpdmVJbWFnZU1vZGFsIH0gZnJvbSAnLi4vbW9kYWxzL0Rlc2NyaXB0aXZlSW1hZ2VNb2RhbCc7XHJcblxyXG5leHBvcnQgY2xhc3MgSW1hZ2VQcm9jZXNzb3Ige1xyXG5cdHByaXZhdGUgYXBwOiBBcHA7XHJcblx0cHJpdmF0ZSBzZXR0aW5nczogSW1hZ2VNYW5hZ2VyU2V0dGluZ3M7XHJcblx0cHJpdmF0ZSBzdG9yYWdlTWFuYWdlcjogU3RvcmFnZU1hbmFnZXI7XHJcblxyXG5cdGNvbnN0cnVjdG9yKGFwcDogQXBwLCBzZXR0aW5nczogSW1hZ2VNYW5hZ2VyU2V0dGluZ3MsIHN0b3JhZ2VNYW5hZ2VyOiBTdG9yYWdlTWFuYWdlciwgb2JzZXJ2YWJsZT86IHsgc3Vic2NyaWJlKGZuOiAoc2V0dGluZ3M6IEltYWdlTWFuYWdlclNldHRpbmdzKSA9PiB2b2lkKTogdm9pZCB9KSB7XHJcblx0XHR0aGlzLmFwcCA9IGFwcDtcclxuXHRcdHRoaXMuc2V0dGluZ3MgPSBzZXR0aW5ncztcclxuXHRcdHRoaXMuc3RvcmFnZU1hbmFnZXIgPSBzdG9yYWdlTWFuYWdlcjtcclxuXHJcblx0XHQvLyBTdWJzY3JpYmUgdG8gc2V0dGluZ3MgdXBkYXRlcyBpZiBvYnNlcnZhYmxlIGlzIHByb3ZpZGVkXHJcblx0XHRvYnNlcnZhYmxlPy5zdWJzY3JpYmUoKG5ld1NldHRpbmdzKSA9PiB7XHJcblx0XHRcdHRoaXMudXBkYXRlU2V0dGluZ3MobmV3U2V0dGluZ3MpO1xyXG5cdFx0fSk7XHJcblx0fVxyXG5cclxuXHQvKipcclxuXHQgKiBVcGRhdGUgc2V0dGluZ3MgcmVmZXJlbmNlXHJcblx0ICovXHJcblx0dXBkYXRlU2V0dGluZ3Moc2V0dGluZ3M6IEltYWdlTWFuYWdlclNldHRpbmdzKTogdm9pZCB7XHJcblx0XHR0aGlzLnNldHRpbmdzID0gc2V0dGluZ3M7XHJcblx0XHR0aGlzLnN0b3JhZ2VNYW5hZ2VyLnVwZGF0ZVNldHRpbmdzKHNldHRpbmdzKTtcclxuXHR9XHJcblxyXG5cdC8qKlxyXG5cdCAqIFByb2Nlc3MgYSBwYXN0ZWQvZHJvcHBlZCBpbWFnZSBmaWxlXHJcblx0ICogVGhpcyBpcyBjYWxsZWQgZnJvbSBvdXIgZXZlbnQgaGFuZGxlcnMgKHVzZXItaW5pdGlhdGVkIGFjdGlvbilcclxuXHQgKiBAcGFyYW0gaXNQcm9wZXJ0eUluc2VydGlvbiAtIElmIHRydWUsIHNraXAgZGVzY3JpcHRpdmUgaW1hZ2VzIChvbmx5IGFwcGxpZXMgdG8gbm90ZSBib2R5KVxyXG5cdCAqL1xyXG5cdGFzeW5jIHByb2Nlc3NJbWFnZUZpbGUoXHJcblx0XHRmaWxlOiBGaWxlLFxyXG5cdFx0YWN0aXZlRmlsZTogVEZpbGUsXHJcblx0XHRzaG93UmVuYW1lTW9kYWw6IGJvb2xlYW4gPSB0cnVlLFxyXG5cdFx0aXNQcm9wZXJ0eUluc2VydGlvbjogYm9vbGVhbiA9IGZhbHNlXHJcblx0KTogUHJvbWlzZTxQcm9jZXNzZWRJbWFnZT4ge1xyXG5cdFx0dHJ5IHtcclxuXHRcdFx0Ly8gUmVhZCBmaWxlIGRhdGFcclxuXHRcdFx0Y29uc3QgYXJyYXlCdWZmZXIgPSBhd2FpdCBmaWxlLmFycmF5QnVmZmVyKCk7XHJcblx0XHRcdGNvbnN0IGV4dGVuc2lvbiA9IHRoaXMuZ2V0RXh0ZW5zaW9uKGZpbGUpO1xyXG5cclxuXHRcdFx0Ly8gR2VuZXJhdGUgc3VnZ2VzdGVkIG5hbWUgZnJvbSB0ZW1wbGF0ZSAobm8gc3VmZml4IGZvciBsb2NhbCBmaWxlcylcclxuXHRcdFx0Y29uc3Qgc3VnZ2VzdGVkTmFtZSA9IHRoaXMuZ2VuZXJhdGVOYW1lV2l0aFN1ZmZpeChhY3RpdmVGaWxlKTtcclxuXHJcblx0XHRcdC8vIEdldCB0aGUgbmFtZSB0byB1c2VcclxuXHRcdFx0bGV0IGZpbmFsTmFtZSA9IHN1Z2dlc3RlZE5hbWU7XHJcblxyXG5cdFx0XHRpZiAoc2hvd1JlbmFtZU1vZGFsICYmICF0aGlzLnNldHRpbmdzLmF1dG9SZW5hbWUpIHtcclxuXHRcdFx0XHQvLyBDcmVhdGUgYSB0ZW1wb3JhcnkgZmlsZSB0byBzaG93IGluIG1vZGFsXHJcblx0XHRcdFx0Y29uc3QgdGVtcFBhdGggPSBhd2FpdCB0aGlzLnN0b3JhZ2VNYW5hZ2VyLmdldEF2YWlsYWJsZVBhdGgoXHJcblx0XHRcdFx0XHRgdGVtcC0ke0RhdGUubm93KCl9YCxcclxuXHRcdFx0XHRcdGV4dGVuc2lvbixcclxuXHRcdFx0XHRcdGFjdGl2ZUZpbGVcclxuXHRcdFx0XHQpO1xyXG5cdFx0XHRcdGNvbnN0IHRlbXBGaWxlID0gYXdhaXQgdGhpcy5zdG9yYWdlTWFuYWdlci5zYXZlRmlsZShhcnJheUJ1ZmZlciwgdGVtcFBhdGgpO1xyXG5cclxuXHRcdFx0XHRsZXQgZmluYWxOYW1lOiBzdHJpbmc7XHJcblx0XHRcdFx0bGV0IGRpc3BsYXlUZXh0OiBzdHJpbmcgfCB1bmRlZmluZWQ7XHJcblxyXG5cdFx0XHRcdC8vIFNob3cgZGVzY3JpcHRpdmUgaW1hZ2UgbW9kYWwgaWYgZW5hYmxlZCwgb3RoZXJ3aXNlIHNob3cgcmVuYW1lIG1vZGFsXHJcblx0XHRcdFx0aWYgKHRoaXMuc2V0dGluZ3MuZW5hYmxlRGVzY3JpcHRpdmVJbWFnZXMpIHtcclxuXHRcdFx0XHRcdGNvbnN0IGRlc2NSZXN1bHQgPSBhd2FpdCBvcGVuRGVzY3JpcHRpdmVJbWFnZU1vZGFsKHRoaXMuYXBwLCB0ZW1wRmlsZSwgc3VnZ2VzdGVkTmFtZSk7XHJcblxyXG5cdFx0XHRcdFx0aWYgKGRlc2NSZXN1bHQuY2FuY2VsbGVkKSB7XHJcblx0XHRcdFx0XHRcdC8vIFVzZXIgY2FuY2VsbGVkIC0gZGVsZXRlIHRlbXAgZmlsZSBhbmQgcmV0dXJuXHJcblx0XHRcdFx0XHRcdGF3YWl0IHRoaXMuYXBwLmZpbGVNYW5hZ2VyLnRyYXNoRmlsZSh0ZW1wRmlsZSk7XHJcblx0XHRcdFx0XHRcdHJldHVybiB7XHJcblx0XHRcdFx0XHRcdFx0ZmlsZTogbnVsbCxcclxuXHRcdFx0XHRcdFx0XHRwYXRoOiAnJyxcclxuXHRcdFx0XHRcdFx0XHRsaW5rVGV4dDogJycsXHJcblx0XHRcdFx0XHRcdFx0c3VjY2VzczogZmFsc2UsXHJcblx0XHRcdFx0XHRcdFx0ZXJyb3I6ICdDYW5jZWxsZWQgYnkgdXNlcicsXHJcblx0XHRcdFx0XHRcdH07XHJcblx0XHRcdFx0XHR9XHJcblxyXG5cdFx0XHRcdFx0ZmluYWxOYW1lID0gZGVzY1Jlc3VsdC5maWxlTmFtZTtcclxuXHRcdFx0XHRcdGRpc3BsYXlUZXh0ID0gZGVzY1Jlc3VsdC5kZXNjcmlwdGlvbjtcclxuXHRcdFx0XHR9IGVsc2Uge1xyXG5cdFx0XHRcdFx0Ly8gU2hvdyByZW5hbWUgbW9kYWxcclxuXHRcdFx0XHRcdGNvbnN0IHJlc3VsdCA9IGF3YWl0IG9wZW5SZW5hbWVNb2RhbCh0aGlzLmFwcCwgdGVtcEZpbGUsIHN1Z2dlc3RlZE5hbWUpO1xyXG5cclxuXHRcdFx0XHRcdGlmIChyZXN1bHQuY2FuY2VsbGVkKSB7XHJcblx0XHRcdFx0XHRcdC8vIFVzZXIgY2FuY2VsbGVkIC0gZGVsZXRlIHRlbXAgZmlsZSBhbmQgcmV0dXJuXHJcblx0XHRcdFx0XHRcdGF3YWl0IHRoaXMuYXBwLmZpbGVNYW5hZ2VyLnRyYXNoRmlsZSh0ZW1wRmlsZSk7XHJcblx0XHRcdFx0XHRcdHJldHVybiB7XHJcblx0XHRcdFx0XHRcdFx0ZmlsZTogbnVsbCxcclxuXHRcdFx0XHRcdFx0XHRwYXRoOiAnJyxcclxuXHRcdFx0XHRcdFx0XHRsaW5rVGV4dDogJycsXHJcblx0XHRcdFx0XHRcdFx0c3VjY2VzczogZmFsc2UsXHJcblx0XHRcdFx0XHRcdFx0ZXJyb3I6ICdDYW5jZWxsZWQgYnkgdXNlcicsXHJcblx0XHRcdFx0XHRcdH07XHJcblx0XHRcdFx0XHR9XHJcblxyXG5cdFx0XHRcdFx0ZmluYWxOYW1lID0gcmVzdWx0Lm5ld05hbWU7XHJcblx0XHRcdFx0fVxyXG5cclxuXHRcdFx0XHQvLyBSZW5hbWUgdGhlIHRlbXAgZmlsZSB0byB0aGUgZmluYWwgbmFtZVxyXG5cdFx0XHRcdGNvbnN0IGZpbmFsUGF0aCA9IGF3YWl0IHRoaXMuZ2V0RGVkdXBsaWNhdGVkUGF0aChmaW5hbE5hbWUsIGV4dGVuc2lvbiwgYWN0aXZlRmlsZSk7XHJcblx0XHRcdFx0YXdhaXQgdGhpcy5hcHAuZmlsZU1hbmFnZXIucmVuYW1lRmlsZSh0ZW1wRmlsZSwgZmluYWxQYXRoKTtcclxuXHJcblx0XHRcdFx0Y29uc3QgYWJzdHJhY3RGaWxlID0gdGhpcy5hcHAudmF1bHQuZ2V0QWJzdHJhY3RGaWxlQnlQYXRoKGZpbmFsUGF0aCk7XHJcblx0XHRcdFx0aWYgKCEoYWJzdHJhY3RGaWxlIGluc3RhbmNlb2YgVEZpbGUpKSB7XHJcblx0XHRcdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ1JlbmFtZWQgZmlsZSBub3QgZm91bmQnKTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdFx0Y29uc3QgcmVuYW1lZEZpbGUgPSBhYnN0cmFjdEZpbGU7XHJcblx0XHRcdFx0Y29uc3QgbGlua1RleHQgPSB0aGlzLnN0b3JhZ2VNYW5hZ2VyLmdlbmVyYXRlTWFya2Rvd25MaW5rKFxyXG5cdFx0XHRcdFx0cmVuYW1lZEZpbGUsXHJcblx0XHRcdFx0XHRhY3RpdmVGaWxlLnBhdGgsXHJcblx0XHRcdFx0XHRkaXNwbGF5VGV4dCxcclxuXHRcdFx0XHRcdHRoaXMuc2V0dGluZ3MuaW5zZXJ0U2l6ZVxyXG5cdFx0XHRcdCk7XHJcblxyXG5cdFx0XHRcdGlmICghdGhpcy5zZXR0aW5ncy5kaXNhYmxlUmVuYW1lTm90aWNlKSB7XHJcblx0XHRcdFx0XHRuZXcgTm90aWNlKGBJbWFnZSBzYXZlZCBhczogJHtyZW5hbWVkRmlsZS5uYW1lfWApO1xyXG5cdFx0XHRcdH1cclxuXHJcblx0XHRcdFx0cmV0dXJuIHtcclxuXHRcdFx0XHRcdGZpbGU6IHJlbmFtZWRGaWxlLFxyXG5cdFx0XHRcdFx0cGF0aDogZmluYWxQYXRoLFxyXG5cdFx0XHRcdFx0bGlua1RleHQsXHJcblx0XHRcdFx0XHRkZXNjcmlwdGlvbjogZGlzcGxheVRleHQsXHJcblx0XHRcdFx0XHRzdWNjZXNzOiB0cnVlLFxyXG5cdFx0XHRcdH07XHJcblx0XHRcdH0gZWxzZSB7XHJcblx0XHRcdFx0Ly8gQXV0by1yZW5hbWUgd2l0aG91dCBtb2RhbFxyXG5cdFx0XHRcdGNvbnN0IGZpbmFsUGF0aCA9IGF3YWl0IHRoaXMuZ2V0RGVkdXBsaWNhdGVkUGF0aChmaW5hbE5hbWUsIGV4dGVuc2lvbiwgYWN0aXZlRmlsZSk7XHJcblx0XHRcdFx0Y29uc3Qgc2F2ZWRGaWxlID0gYXdhaXQgdGhpcy5zdG9yYWdlTWFuYWdlci5zYXZlRmlsZShhcnJheUJ1ZmZlciwgZmluYWxQYXRoKTtcclxuXHRcdFx0XHRjb25zdCBsaW5rVGV4dCA9IHRoaXMuc3RvcmFnZU1hbmFnZXIuZ2VuZXJhdGVNYXJrZG93bkxpbmsoXHJcblx0XHRcdFx0XHRzYXZlZEZpbGUsXHJcblx0XHRcdFx0XHRhY3RpdmVGaWxlLnBhdGgsXHJcblx0XHRcdFx0XHR1bmRlZmluZWQsXHJcblx0XHRcdFx0XHR0aGlzLnNldHRpbmdzLmluc2VydFNpemVcclxuXHRcdFx0XHQpO1xyXG5cclxuXHRcdFx0XHRpZiAoIXRoaXMuc2V0dGluZ3MuZGlzYWJsZVJlbmFtZU5vdGljZSkge1xyXG5cdFx0XHRcdFx0bmV3IE5vdGljZShgSW1hZ2Ugc2F2ZWQgYXM6ICR7c2F2ZWRGaWxlLm5hbWV9YCk7XHJcblx0XHRcdFx0fVxyXG5cclxuXHRcdFx0XHRyZXR1cm4ge1xyXG5cdFx0XHRcdFx0ZmlsZTogc2F2ZWRGaWxlLFxyXG5cdFx0XHRcdFx0cGF0aDogZmluYWxQYXRoLFxyXG5cdFx0XHRcdFx0bGlua1RleHQsXHJcblx0XHRcdFx0XHRkZXNjcmlwdGlvbjogdW5kZWZpbmVkLFxyXG5cdFx0XHRcdFx0c3VjY2VzczogdHJ1ZSxcclxuXHRcdFx0XHR9O1xyXG5cdFx0XHR9XHJcblx0XHR9IGNhdGNoIChlcnJvcikge1xyXG5cdFx0XHRjb25zb2xlLmVycm9yKCdFcnJvciBwcm9jZXNzaW5nIGltYWdlOicsIGVycm9yKTtcclxuXHRcdFx0cmV0dXJuIHtcclxuXHRcdFx0XHRmaWxlOiBudWxsLFxyXG5cdFx0XHRcdHBhdGg6ICcnLFxyXG5cdFx0XHRcdGxpbmtUZXh0OiAnJyxcclxuXHRcdFx0XHRzdWNjZXNzOiBmYWxzZSxcclxuXHRcdFx0XHRlcnJvcjogZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yLm1lc3NhZ2UgOiBTdHJpbmcoZXJyb3IpLFxyXG5cdFx0XHR9O1xyXG5cdFx0fVxyXG5cdH1cclxuXHJcblx0LyoqXHJcblx0ICogUHJvY2VzcyBhbiBpbWFnZSBmcm9tIGEgVVJMIChkb3dubG9hZCBhbmQgc2F2ZSBsb2NhbGx5KVxyXG5cdCAqIEBwYXJhbSBpc1Byb3BlcnR5SW5zZXJ0aW9uIC0gSWYgdHJ1ZSwgc2tpcCBkZXNjcmlwdGl2ZSBpbWFnZXMgKG9ubHkgYXBwbGllcyB0byBub3RlIGJvZHkpXHJcblx0ICogQHBhcmFtIHN1Z2dlc3RlZE5hbWVPdmVycmlkZSAtIE9wdGlvbmFsIG92ZXJyaWRlIGZvciBzdWdnZXN0ZWQgbmFtZSAoZS5nLiwgZnJvbSBzZWFyY2ggdGVybSlcclxuXHQgKi9cclxuXHRhc3luYyBwcm9jZXNzSW1hZ2VVcmwoXHJcblx0XHR1cmw6IHN0cmluZyxcclxuXHRcdGFjdGl2ZUZpbGU6IFRGaWxlLFxyXG5cdFx0c2hvd1JlbmFtZU1vZGFsOiBib29sZWFuID0gdHJ1ZSxcclxuXHRcdGlzUHJvcGVydHlJbnNlcnRpb246IGJvb2xlYW4gPSBmYWxzZSxcclxuXHRcdHN1Z2dlc3RlZE5hbWVPdmVycmlkZT86IHN0cmluZ1xyXG5cdCk6IFByb21pc2U8UHJvY2Vzc2VkSW1hZ2U+IHtcclxuXHRcdHRyeSB7XHJcblx0XHRcdC8vIERvd25sb2FkIHRoZSBpbWFnZVxyXG5cdFx0XHRjb25zdCByZXNwb25zZSA9IGF3YWl0IHJlcXVlc3RVcmwoeyB1cmwgfSk7XHJcblx0XHRcdGlmIChyZXNwb25zZS5zdGF0dXMgPj0gNDAwKSB7XHJcblx0XHRcdFx0dGhyb3cgbmV3IEVycm9yKGBGYWlsZWQgdG8gZG93bmxvYWQgaW1hZ2U6ICR7cmVzcG9uc2Uuc3RhdHVzfWApO1xyXG5cdFx0XHR9XHJcblxyXG5cdFx0XHRjb25zdCBhcnJheUJ1ZmZlciA9IHJlc3BvbnNlLmFycmF5QnVmZmVyO1xyXG5cdFx0XHRjb25zdCBjb250ZW50VHlwZSA9IHJlc3BvbnNlLmhlYWRlcnNbJ2NvbnRlbnQtdHlwZSddID8/ICdpbWFnZS9wbmcnO1xyXG5cdFx0XHRjb25zdCBleHRlbnNpb24gPSB0aGlzLnN0b3JhZ2VNYW5hZ2VyLmdldEV4dGVuc2lvbkZyb21NaW1lVHlwZShjb250ZW50VHlwZSk7XHJcblxyXG5cdFx0XHQvLyBHZW5lcmF0ZSBzdWdnZXN0ZWQgbmFtZSAodXNlIG92ZXJyaWRlIGlmIHByb3ZpZGVkIGFzIHN1ZmZpeCwgb3RoZXJ3aXNlIGdlbmVyYXRlIGZyb20gdGVtcGxhdGUpXHJcblx0XHRcdGNvbnN0IHN1Z2dlc3RlZE5hbWUgPSB0aGlzLmdlbmVyYXRlTmFtZVdpdGhTdWZmaXgoYWN0aXZlRmlsZSwgc3VnZ2VzdGVkTmFtZU92ZXJyaWRlKTtcclxuXHJcblx0XHRcdC8vIEdldCBmaW5hbCBuYW1lXHJcblx0XHRcdGxldCBmaW5hbE5hbWUgPSBzdWdnZXN0ZWROYW1lO1xyXG5cclxuXHRcdFx0aWYgKHNob3dSZW5hbWVNb2RhbCAmJiAhdGhpcy5zZXR0aW5ncy5hdXRvUmVuYW1lKSB7XHJcblx0XHRcdFx0Ly8gU2F2ZSB0ZW1wIGZpbGUgZmlyc3RcclxuXHRcdFx0XHRjb25zdCB0ZW1wUGF0aCA9IGF3YWl0IHRoaXMuc3RvcmFnZU1hbmFnZXIuZ2V0QXZhaWxhYmxlUGF0aChcclxuXHRcdFx0XHRcdGB0ZW1wLSR7RGF0ZS5ub3coKX1gLFxyXG5cdFx0XHRcdFx0ZXh0ZW5zaW9uLFxyXG5cdFx0XHRcdFx0YWN0aXZlRmlsZVxyXG5cdFx0XHRcdCk7XHJcblx0XHRcdFx0Y29uc3QgdGVtcEZpbGUgPSBhd2FpdCB0aGlzLnN0b3JhZ2VNYW5hZ2VyLnNhdmVGaWxlKGFycmF5QnVmZmVyLCB0ZW1wUGF0aCk7XHJcblxyXG5cdFx0XHRcdGxldCBmaW5hbE5hbWU6IHN0cmluZztcclxuXHRcdFx0XHRsZXQgZGlzcGxheVRleHQ6IHN0cmluZyB8IHVuZGVmaW5lZDtcclxuXHJcblx0XHRcdFx0Ly8gU2hvdyBkZXNjcmlwdGl2ZSBpbWFnZSBtb2RhbCBpZiBlbmFibGVkXHJcblx0XHRcdFx0Ly8gRm9yIHByb3BlcnR5IGluc2VydGlvbnMsIHdlIG9ubHkgc2hvdyBpdCBpZiBhbiBhbHQgdGV4dCBwcm9wZXJ0eSBpcyBjb25maWd1cmVkXHJcblx0XHRcdFx0Y29uc3Qgc2hvdWxkU2hvd0Rlc2NyaXB0aXZlID0gdGhpcy5zZXR0aW5ncy5lbmFibGVEZXNjcmlwdGl2ZUltYWdlcyAmJiAoIWlzUHJvcGVydHlJbnNlcnRpb24gfHwgdGhpcy5zZXR0aW5ncy5hbHRUZXh0UHJvcGVydHkgIT09ICcnKTtcclxuXHJcblx0XHRcdFx0aWYgKHNob3VsZFNob3dEZXNjcmlwdGl2ZSkge1xyXG5cdFx0XHRcdFx0Y29uc3QgZGVzY1Jlc3VsdCA9IGF3YWl0IG9wZW5EZXNjcmlwdGl2ZUltYWdlTW9kYWwodGhpcy5hcHAsIHRlbXBGaWxlLCBzdWdnZXN0ZWROYW1lKTtcclxuXHJcblx0XHRcdFx0XHRpZiAoZGVzY1Jlc3VsdC5jYW5jZWxsZWQpIHtcclxuXHRcdFx0XHRcdFx0YXdhaXQgdGhpcy5hcHAuZmlsZU1hbmFnZXIudHJhc2hGaWxlKHRlbXBGaWxlKTtcclxuXHRcdFx0XHRcdFx0cmV0dXJuIHtcclxuXHRcdFx0XHRcdFx0XHRmaWxlOiBudWxsLFxyXG5cdFx0XHRcdFx0XHRcdHBhdGg6ICcnLFxyXG5cdFx0XHRcdFx0XHRcdGxpbmtUZXh0OiAnJyxcclxuXHRcdFx0XHRcdFx0XHRzdWNjZXNzOiBmYWxzZSxcclxuXHRcdFx0XHRcdFx0XHRlcnJvcjogJ0NhbmNlbGxlZCBieSB1c2VyJyxcclxuXHRcdFx0XHRcdFx0fTtcclxuXHRcdFx0XHRcdH1cclxuXHJcblx0XHRcdFx0XHRmaW5hbE5hbWUgPSBkZXNjUmVzdWx0LmZpbGVOYW1lO1xyXG5cdFx0XHRcdFx0ZGlzcGxheVRleHQgPSBkZXNjUmVzdWx0LmRlc2NyaXB0aW9uO1xyXG5cdFx0XHRcdH0gZWxzZSB7XHJcblx0XHRcdFx0XHQvLyBTaG93IHJlbmFtZSBtb2RhbFxyXG5cdFx0XHRcdFx0Y29uc3QgcmVzdWx0ID0gYXdhaXQgb3BlblJlbmFtZU1vZGFsKHRoaXMuYXBwLCB0ZW1wRmlsZSwgc3VnZ2VzdGVkTmFtZSk7XHJcblxyXG5cdFx0XHRcdFx0aWYgKHJlc3VsdC5jYW5jZWxsZWQpIHtcclxuXHRcdFx0XHRcdFx0YXdhaXQgdGhpcy5hcHAuZmlsZU1hbmFnZXIudHJhc2hGaWxlKHRlbXBGaWxlKTtcclxuXHRcdFx0XHRcdFx0cmV0dXJuIHtcclxuXHRcdFx0XHRcdFx0XHRmaWxlOiBudWxsLFxyXG5cdFx0XHRcdFx0XHRcdHBhdGg6ICcnLFxyXG5cdFx0XHRcdFx0XHRcdGxpbmtUZXh0OiAnJyxcclxuXHRcdFx0XHRcdFx0XHRzdWNjZXNzOiBmYWxzZSxcclxuXHRcdFx0XHRcdFx0XHRlcnJvcjogJ0NhbmNlbGxlZCBieSB1c2VyJyxcclxuXHRcdFx0XHRcdFx0fTtcclxuXHRcdFx0XHRcdH1cclxuXHJcblx0XHRcdFx0XHRmaW5hbE5hbWUgPSByZXN1bHQubmV3TmFtZTtcclxuXHRcdFx0XHR9XHJcblxyXG5cdFx0XHRcdGNvbnN0IGZpbmFsUGF0aCA9IGF3YWl0IHRoaXMuZ2V0RGVkdXBsaWNhdGVkUGF0aChmaW5hbE5hbWUsIGV4dGVuc2lvbiwgYWN0aXZlRmlsZSk7XHJcblx0XHRcdFx0YXdhaXQgdGhpcy5hcHAuZmlsZU1hbmFnZXIucmVuYW1lRmlsZSh0ZW1wRmlsZSwgZmluYWxQYXRoKTtcclxuXHJcblx0XHRcdFx0Y29uc3QgYWJzdHJhY3RGaWxlID0gdGhpcy5hcHAudmF1bHQuZ2V0QWJzdHJhY3RGaWxlQnlQYXRoKGZpbmFsUGF0aCk7XHJcblx0XHRcdFx0aWYgKCEoYWJzdHJhY3RGaWxlIGluc3RhbmNlb2YgVEZpbGUpKSB7XHJcblx0XHRcdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ1JlbmFtZWQgZmlsZSBub3QgZm91bmQnKTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdFx0Y29uc3QgcmVuYW1lZEZpbGUgPSBhYnN0cmFjdEZpbGU7XHJcblx0XHRcdFx0Y29uc3QgbGlua1RleHQgPSB0aGlzLnN0b3JhZ2VNYW5hZ2VyLmdlbmVyYXRlTWFya2Rvd25MaW5rKFxyXG5cdFx0XHRcdFx0cmVuYW1lZEZpbGUsXHJcblx0XHRcdFx0XHRhY3RpdmVGaWxlLnBhdGgsXHJcblx0XHRcdFx0XHRkaXNwbGF5VGV4dCxcclxuXHRcdFx0XHRcdHRoaXMuc2V0dGluZ3MuaW5zZXJ0U2l6ZVxyXG5cdFx0XHRcdCk7XHJcblxyXG5cdFx0XHRcdGlmICghdGhpcy5zZXR0aW5ncy5kaXNhYmxlUmVuYW1lTm90aWNlKSB7XHJcblx0XHRcdFx0XHRuZXcgTm90aWNlKGBJbWFnZSBkb3dubG9hZGVkIGFuZCBzYXZlZCBhczogJHtyZW5hbWVkRmlsZS5uYW1lfWApO1xyXG5cdFx0XHRcdH1cclxuXHJcblx0XHRcdFx0cmV0dXJuIHtcclxuXHRcdFx0XHRcdGZpbGU6IHJlbmFtZWRGaWxlLFxyXG5cdFx0XHRcdFx0cGF0aDogZmluYWxQYXRoLFxyXG5cdFx0XHRcdFx0bGlua1RleHQsXHJcblx0XHRcdFx0XHRkZXNjcmlwdGlvbjogZGlzcGxheVRleHQsXHJcblx0XHRcdFx0XHRzdWNjZXNzOiB0cnVlLFxyXG5cdFx0XHRcdH07XHJcblx0XHRcdH0gZWxzZSB7XHJcblx0XHRcdFx0Y29uc3QgZmluYWxQYXRoID0gYXdhaXQgdGhpcy5nZXREZWR1cGxpY2F0ZWRQYXRoKGZpbmFsTmFtZSwgZXh0ZW5zaW9uLCBhY3RpdmVGaWxlKTtcclxuXHRcdFx0XHRjb25zdCBzYXZlZEZpbGUgPSBhd2FpdCB0aGlzLnN0b3JhZ2VNYW5hZ2VyLnNhdmVGaWxlKGFycmF5QnVmZmVyLCBmaW5hbFBhdGgpO1xyXG5cdFx0XHRcdGNvbnN0IGxpbmtUZXh0ID0gdGhpcy5zdG9yYWdlTWFuYWdlci5nZW5lcmF0ZU1hcmtkb3duTGluayhcclxuXHRcdFx0XHRcdHNhdmVkRmlsZSxcclxuXHRcdFx0XHRcdGFjdGl2ZUZpbGUucGF0aCxcclxuXHRcdFx0XHRcdHVuZGVmaW5lZCxcclxuXHRcdFx0XHRcdHRoaXMuc2V0dGluZ3MuaW5zZXJ0U2l6ZVxyXG5cdFx0XHRcdCk7XHJcblxyXG5cdFx0XHRcdGlmICghdGhpcy5zZXR0aW5ncy5kaXNhYmxlUmVuYW1lTm90aWNlKSB7XHJcblx0XHRcdFx0XHRuZXcgTm90aWNlKGBJbWFnZSBkb3dubG9hZGVkIGFuZCBzYXZlZCBhczogJHtzYXZlZEZpbGUubmFtZX1gKTtcclxuXHRcdFx0XHR9XHJcblxyXG5cdFx0XHRcdHJldHVybiB7XHJcblx0XHRcdFx0XHRmaWxlOiBzYXZlZEZpbGUsXHJcblx0XHRcdFx0XHRwYXRoOiBmaW5hbFBhdGgsXHJcblx0XHRcdFx0XHRsaW5rVGV4dCxcclxuXHRcdFx0XHRcdGRlc2NyaXB0aW9uOiBpc1Byb3BlcnR5SW5zZXJ0aW9uID8gc3VnZ2VzdGVkTmFtZU92ZXJyaWRlIDogdW5kZWZpbmVkLFxyXG5cdFx0XHRcdFx0c3VjY2VzczogdHJ1ZSxcclxuXHRcdFx0XHR9O1xyXG5cdFx0XHR9XHJcblx0XHR9IGNhdGNoIChlcnJvcikge1xyXG5cdFx0XHRjb25zb2xlLmVycm9yKCdFcnJvciBwcm9jZXNzaW5nIGltYWdlIFVSTDonLCBlcnJvcik7XHJcblx0XHRcdHJldHVybiB7XHJcblx0XHRcdFx0ZmlsZTogbnVsbCxcclxuXHRcdFx0XHRwYXRoOiAnJyxcclxuXHRcdFx0XHRsaW5rVGV4dDogJycsXHJcblx0XHRcdFx0c3VjY2VzczogZmFsc2UsXHJcblx0XHRcdFx0ZXJyb3I6IGVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvci5tZXNzYWdlIDogU3RyaW5nKGVycm9yKSxcclxuXHRcdFx0fTtcclxuXHRcdH1cclxuXHR9XHJcblxyXG5cdC8qKlxyXG5cdCAqIEdlbmVyYXRlIGEgc3VnZ2VzdGVkIG5hbWUgYmFzZWQgb24gdGhlIHRlbXBsYXRlIGFuZCBvcHRpb25hbCBzdWZmaXhcclxuXHQgKi9cclxuXHRnZW5lcmF0ZU5hbWVXaXRoU3VmZml4KGFjdGl2ZUZpbGU6IFRGaWxlLCBzdWZmaXg/OiBzdHJpbmcpOiBzdHJpbmcge1xyXG5cdFx0Y29uc3QgdmFyaWFibGVzID0gYnVpbGRUZW1wbGF0ZVZhcmlhYmxlcyh0aGlzLmFwcCwgYWN0aXZlRmlsZSk7XHJcblx0XHRjb25zdCByZW5kZXJlZCA9IHJlbmRlclRlbXBsYXRlKHRoaXMuc2V0dGluZ3MuaW1hZ2VOYW1lVGVtcGxhdGUsIHZhcmlhYmxlcyk7XHJcblxyXG5cdFx0Y29uc3QgaXNNZWFuaW5nZnVsID0gaXNUZW1wbGF0ZU1lYW5pbmdmdWwocmVuZGVyZWQsIHRoaXMuc2V0dGluZ3MuZHVwTnVtYmVyRGVsaW1pdGVyKTtcclxuXHRcdGNvbnN0IGJhc2UgPSBpc01lYW5pbmdmdWwgPyByZW5kZXJlZCA6ICcnO1xyXG5cclxuXHRcdGlmIChiYXNlICYmIHN1ZmZpeCkge1xyXG5cdFx0XHRyZXR1cm4gYCR7YmFzZX0gLSAke3N1ZmZpeH1gO1xyXG5cdFx0fSBlbHNlIGlmIChiYXNlKSB7XHJcblx0XHRcdHJldHVybiBgJHtiYXNlfSAtIGA7XHJcblx0XHR9IGVsc2UgaWYgKHN1ZmZpeCkge1xyXG5cdFx0XHRyZXR1cm4gc3VmZml4O1xyXG5cdFx0fVxyXG5cclxuXHRcdHJldHVybiAnJztcclxuXHR9XHJcblxyXG5cdC8qKlxyXG5cdCAqIEdlbmVyYXRlIGEgc3VnZ2VzdGVkIG5hbWUgYmFzZWQgb24gdGhlIHRlbXBsYXRlXHJcblx0ICovXHJcblx0Z2VuZXJhdGVTdWdnZXN0ZWROYW1lKGFjdGl2ZUZpbGU6IFRGaWxlKTogc3RyaW5nIHtcclxuXHRcdHJldHVybiB0aGlzLmdlbmVyYXRlTmFtZVdpdGhTdWZmaXgoYWN0aXZlRmlsZSk7XHJcblx0fVxyXG5cclxuXHQvKipcclxuXHQgKiBHZXQgYSBkZWR1cGxpY2F0ZWQgZmlsZSBwYXRoXHJcblx0ICovXHJcblx0cHJpdmF0ZSBhc3luYyBnZXREZWR1cGxpY2F0ZWRQYXRoKFxyXG5cdFx0YmFzZU5hbWU6IHN0cmluZyxcclxuXHRcdGV4dGVuc2lvbjogc3RyaW5nLFxyXG5cdFx0YWN0aXZlRmlsZTogVEZpbGVcclxuXHQpOiBQcm9taXNlPHN0cmluZz4ge1xyXG5cdFx0cmV0dXJuIGF3YWl0IHRoaXMuc3RvcmFnZU1hbmFnZXIuZ2V0QXZhaWxhYmxlUGF0aChiYXNlTmFtZSwgZXh0ZW5zaW9uLCBhY3RpdmVGaWxlKTtcclxuXHR9XHJcblxyXG5cdC8qKlxyXG5cdCAqIEdldCBmaWxlIGV4dGVuc2lvbiBmcm9tIEZpbGUgb2JqZWN0XHJcblx0ICovXHJcblx0cHJpdmF0ZSBnZXRFeHRlbnNpb24oZmlsZTogRmlsZSk6IHN0cmluZyB7XHJcblx0XHQvLyBUcnkgdG8gZ2V0IGZyb20gZmlsZSBuYW1lIGZpcnN0XHJcblx0XHRjb25zdCBuYW1lUGFydHMgPSBmaWxlLm5hbWUuc3BsaXQoJy4nKTtcclxuXHRcdGlmIChuYW1lUGFydHMubGVuZ3RoID4gMSkge1xyXG5cdFx0XHRjb25zdCBuYW1lRXh0ID0gbmFtZVBhcnRzW25hbWVQYXJ0cy5sZW5ndGggLSAxXT8udG9Mb3dlckNhc2UoKTtcclxuXHRcdFx0aWYgKG5hbWVFeHQpIHtcclxuXHRcdFx0XHRyZXR1cm4gbmFtZUV4dDtcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cclxuXHRcdC8vIEZhbGwgYmFjayB0byBNSU1FIHR5cGVcclxuXHRcdHJldHVybiB0aGlzLnN0b3JhZ2VNYW5hZ2VyLmdldEV4dGVuc2lvbkZyb21NaW1lVHlwZShmaWxlLnR5cGUpO1xyXG5cdH1cclxuXHJcblx0LyoqXHJcblx0ICogSW5zZXJ0IGxpbmsgdGV4dCBhdCBjdXJzb3IgcG9zaXRpb25cclxuXHQgKi9cclxuXHRpbnNlcnRMaW5rQXRDdXJzb3IobGlua1RleHQ6IHN0cmluZyk6IHZvaWQge1xyXG5cdFx0Y29uc3QgdmlldyA9IHRoaXMuYXBwLndvcmtzcGFjZS5nZXRBY3RpdmVWaWV3T2ZUeXBlKE1hcmtkb3duVmlldyk7XHJcblx0XHRpZiAodmlldz8uZWRpdG9yKSB7XHJcblx0XHRcdHZpZXcuZWRpdG9yLnJlcGxhY2VTZWxlY3Rpb24obGlua1RleHQpO1xyXG5cdFx0fVxyXG5cdH1cclxuXHJcblx0LyoqXHJcblx0ICogR2V0IHRoZSBhY3RpdmUgbWFya2Rvd24gZmlsZVxyXG5cdCAqL1xyXG5cdGdldEFjdGl2ZUZpbGUoKTogVEZpbGUgfCBudWxsIHtcclxuXHRcdGNvbnN0IHZpZXcgPSB0aGlzLmFwcC53b3Jrc3BhY2UuZ2V0QWN0aXZlVmlld09mVHlwZShNYXJrZG93blZpZXcpO1xyXG5cdFx0cmV0dXJuIHZpZXc/LmZpbGUgPz8gbnVsbDtcclxuXHR9XHJcblxyXG5cdC8qKlxyXG5cdCAqIFJlbmFtZSBhbiBleGlzdGluZyBpbWFnZSBmaWxlIHdpdGggb3B0aW9uYWwgcmVuYW1lIG1vZGFsXHJcblx0ICogVXNlZCBieSBMb2NhbENvbnZlcnNpb25TZXJ2aWNlIHRvIHJlbmFtZSBjb252ZXJ0ZWQgaW1hZ2VzXHJcblx0ICovXHJcblx0YXN5bmMgcmVuYW1lSW1hZ2VGaWxlKFxyXG5cdFx0aW1hZ2VGaWxlOiBURmlsZSxcclxuXHRcdHN1Z2dlc3RlZE5hbWU6IHN0cmluZyxcclxuXHRcdGFjdGl2ZUZpbGU6IFRGaWxlXHJcblx0KTogUHJvbWlzZTxQcm9jZXNzZWRJbWFnZSB8IG51bGw+IHtcclxuXHRcdHRyeSB7XHJcblx0XHRcdGNvbnN0IGV4dGVuc2lvbiA9IGltYWdlRmlsZS5leHRlbnNpb247XHJcblx0XHRcdGxldCBmaW5hbE5hbWUgPSBzdWdnZXN0ZWROYW1lO1xyXG5cdFx0XHRsZXQgZGlzcGxheVRleHQgPSAnJztcclxuXHJcblx0XHRcdC8vIEhhbmRsZSBkZXNjcmlwdGl2ZSBpbWFnZXMgaWYgZW5hYmxlZCAobm90ZTogdGhpcyBpcyBmb3IgcmVuYW1pbmcgZXhpc3RpbmcgZmlsZXMsIG5vdCBwcm9wZXJ0eSBpbnNlcnRpb24pXHJcblx0XHRcdC8vIElmIGRlc2NyaXB0aXZlIGltYWdlcyBpcyBlbmFibGVkLCBpdCBoYW5kbGVzIHRoZSBuYW1pbmcgYW5kIHdlIHNraXAgdGhlIHJlbmFtZSBtb2RhbFxyXG5cdFx0XHRpZiAodGhpcy5zZXR0aW5ncy5lbmFibGVEZXNjcmlwdGl2ZUltYWdlcykge1xyXG5cdFx0XHRcdGNvbnN0IGRlc2NSZXN1bHQgPSBhd2FpdCBvcGVuRGVzY3JpcHRpdmVJbWFnZU1vZGFsKHRoaXMuYXBwLCBpbWFnZUZpbGUsIHN1Z2dlc3RlZE5hbWUpO1xyXG5cdFx0XHRcdGlmIChkZXNjUmVzdWx0LmNhbmNlbGxlZCkge1xyXG5cdFx0XHRcdFx0cmV0dXJuIG51bGw7IC8vIFVzZXIgY2FuY2VsbGVkXHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdGRpc3BsYXlUZXh0ID0gZGVzY1Jlc3VsdC5kZXNjcmlwdGlvbjtcclxuXHRcdFx0XHRmaW5hbE5hbWUgPSBkZXNjUmVzdWx0LmZpbGVOYW1lOyAvLyBBbHJlYWR5IGtlYmFiLWNhc2VkXHJcblx0XHRcdH0gZWxzZSBpZiAoIXRoaXMuc2V0dGluZ3MuYXV0b1JlbmFtZSkge1xyXG5cdFx0XHRcdC8vIE9ubHkgc2hvdyByZW5hbWUgbW9kYWwgaWYgZGVzY3JpcHRpdmUgaW1hZ2VzIGlzIGRpc2FibGVkIEFORCBhdXRvLXJlbmFtZSBpcyBvZmZcclxuXHRcdFx0XHRjb25zdCByZXN1bHQgPSBhd2FpdCBvcGVuUmVuYW1lTW9kYWwoXHJcblx0XHRcdFx0XHR0aGlzLmFwcCxcclxuXHRcdFx0XHRcdGltYWdlRmlsZSxcclxuXHRcdFx0XHRcdGZpbmFsTmFtZVxyXG5cdFx0XHRcdCk7XHJcblx0XHRcdFx0aWYgKHJlc3VsdC5jYW5jZWxsZWQpIHtcclxuXHRcdFx0XHRcdHJldHVybiBudWxsOyAvLyBVc2VyIGNhbmNlbGxlZFxyXG5cdFx0XHRcdH1cclxuXHRcdFx0XHRmaW5hbE5hbWUgPSByZXN1bHQubmV3TmFtZTtcclxuXHRcdFx0fVxyXG5cclxuXHRcdFx0Ly8gUmVuYW1lIHRoZSBmaWxlXHJcblx0XHRcdGNvbnN0IGZpbmFsUGF0aCA9IGF3YWl0IHRoaXMuZ2V0RGVkdXBsaWNhdGVkUGF0aChmaW5hbE5hbWUsIGV4dGVuc2lvbiwgYWN0aXZlRmlsZSk7XHJcblx0XHRcdGF3YWl0IHRoaXMuYXBwLmZpbGVNYW5hZ2VyLnJlbmFtZUZpbGUoaW1hZ2VGaWxlLCBmaW5hbFBhdGgpO1xyXG5cclxuXHRcdFx0Y29uc3QgYWJzdHJhY3RGaWxlID0gdGhpcy5hcHAudmF1bHQuZ2V0QWJzdHJhY3RGaWxlQnlQYXRoKGZpbmFsUGF0aCk7XHJcblx0XHRcdGlmICghKGFic3RyYWN0RmlsZSBpbnN0YW5jZW9mIFRGaWxlKSkge1xyXG5cdFx0XHRcdHRocm93IG5ldyBFcnJvcignUmVuYW1lZCBmaWxlIG5vdCBmb3VuZCcpO1xyXG5cdFx0XHR9XHJcblx0XHRcdGNvbnN0IHJlbmFtZWRGaWxlID0gYWJzdHJhY3RGaWxlO1xyXG5cdFx0XHRjb25zdCBsaW5rVGV4dCA9IHRoaXMuc3RvcmFnZU1hbmFnZXIuZ2VuZXJhdGVNYXJrZG93bkxpbmsoXHJcblx0XHRcdFx0cmVuYW1lZEZpbGUsXHJcblx0XHRcdFx0YWN0aXZlRmlsZS5wYXRoLFxyXG5cdFx0XHRcdGRpc3BsYXlUZXh0LFxyXG5cdFx0XHRcdHRoaXMuc2V0dGluZ3MuaW5zZXJ0U2l6ZVxyXG5cdFx0XHQpO1xyXG5cclxuXHRcdFx0cmV0dXJuIHtcclxuXHRcdFx0XHRmaWxlOiByZW5hbWVkRmlsZSxcclxuXHRcdFx0XHRwYXRoOiBmaW5hbFBhdGgsXHJcblx0XHRcdFx0bGlua1RleHQsXHJcblx0XHRcdFx0c3VjY2VzczogdHJ1ZSxcclxuXHRcdFx0fTtcclxuXHRcdH0gY2F0Y2ggKGVycm9yKSB7XHJcblx0XHRcdGNvbnNvbGUuZXJyb3IoJ0Vycm9yIHJlbmFtaW5nIGltYWdlIGZpbGU6JywgZXJyb3IpO1xyXG5cdFx0XHRyZXR1cm4ge1xyXG5cdFx0XHRcdGZpbGU6IG51bGwsXHJcblx0XHRcdFx0cGF0aDogJycsXHJcblx0XHRcdFx0bGlua1RleHQ6ICcnLFxyXG5cdFx0XHRcdHN1Y2Nlc3M6IGZhbHNlLFxyXG5cdFx0XHRcdGVycm9yOiBlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IubWVzc2FnZSA6IFN0cmluZyhlcnJvciksXHJcblx0XHRcdH07XHJcblx0XHR9XHJcblx0fVxyXG5cclxuXHQvKipcclxuXHQgKiBEZWJ1ZyBsb2dnaW5nXHJcblx0ICovXHJcblx0cHJpdmF0ZSBsb2coLi4uYXJnczogdW5rbm93bltdKTogdm9pZCB7XHJcblx0XHRpZiAodGhpcy5zZXR0aW5ncy5kZWJ1Z01vZGUpIHtcclxuXHRcdFx0Y29uc29sZS5kZWJ1ZygnW0ltYWdlIE1hbmFnZXJdJywgLi4uYXJncyk7XHJcblx0XHR9XHJcblx0fVxyXG59XHJcbiIsICIvKipcclxuICogVGVtcGxhdGUgRW5naW5lIGZvciBJbWFnZSBOYW1pbmdcclxuICogUmVuZGVycyBuYW1lIHRlbXBsYXRlcyB3aXRoIHZhcmlhYmxlIHN1YnN0aXR1dGlvblxyXG4gKi9cclxuXHJcbmltcG9ydCB7IFRGaWxlLCBBcHAgfSBmcm9tICdvYnNpZGlhbic7XHJcbmltcG9ydCB7IE5hbWVUZW1wbGF0ZVZhcmlhYmxlcyB9IGZyb20gJy4uL3R5cGVzJztcclxuXHJcbi8qKlxyXG4gKiBBdmFpbGFibGUgdGVtcGxhdGUgdmFyaWFibGVzIGFuZCB0aGVpciBkZXNjcmlwdGlvbnNcclxuICovXHJcbmV4cG9ydCBjb25zdCBURU1QTEFURV9WQVJJQUJMRVMgPSB7XHJcblx0J3t7ZmlsZU5hbWV9fSc6ICdOYW1lIG9mIHRoZSBjdXJyZW50IG5vdGUgKHdpdGhvdXQgZXh0ZW5zaW9uKScsXHJcblx0J3t7ZGlyTmFtZX19JzogJ05hbWUgb2YgdGhlIGNvbnRhaW5pbmcgZm9sZGVyJyxcclxuXHQne3tpbWFnZU5hbWVLZXl9fSc6ICdWYWx1ZSBmcm9tIGltYWdlTmFtZUtleSBwcm9wZXJ0eScsXHJcblx0J3t7Zmlyc3RIZWFkaW5nfX0nOiAnRmlyc3QgSDEgaGVhZGluZyBpbiB0aGUgbm90ZScsXHJcblx0J3t7REFURTpmb3JtYXR9fSc6ICdDdXJyZW50IGRhdGUgKGUuZy4sIHt7REFURTpZWVlZLU1NLUREfX0pJyxcclxuXHQne3tUSU1FOmZvcm1hdH19JzogJ0N1cnJlbnQgdGltZSAoZS5nLiwge3tUSU1FOkhILW1tLXNzfX0pJyxcclxufTtcclxuXHJcbi8qKlxyXG4gKiBSZW5kZXIgYSB0ZW1wbGF0ZSBzdHJpbmcgd2l0aCB2YXJpYWJsZSBzdWJzdGl0dXRpb25cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiByZW5kZXJUZW1wbGF0ZShcclxuXHR0ZW1wbGF0ZTogc3RyaW5nLFxyXG5cdHZhcmlhYmxlczogTmFtZVRlbXBsYXRlVmFyaWFibGVzLFxyXG5cdGZyb250bWF0dGVyPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj5cclxuKTogc3RyaW5nIHtcclxuXHRsZXQgcmVzdWx0ID0gdGVtcGxhdGU7XHJcblxyXG5cdC8vIEJhc2ljIHZhcmlhYmxlc1xyXG5cdHJlc3VsdCA9IHJlc3VsdC5yZXBsYWNlKC9cXHtcXHtmaWxlTmFtZVxcfVxcfS9nLCB2YXJpYWJsZXMuZmlsZU5hbWUpO1xyXG5cdHJlc3VsdCA9IHJlc3VsdC5yZXBsYWNlKC9cXHtcXHtkaXJOYW1lXFx9XFx9L2csIHZhcmlhYmxlcy5kaXJOYW1lKTtcclxuXHRyZXN1bHQgPSByZXN1bHQucmVwbGFjZSgvXFx7XFx7aW1hZ2VOYW1lS2V5XFx9XFx9L2csIHZhcmlhYmxlcy5pbWFnZU5hbWVLZXkgPz8gJycpO1xyXG5cdHJlc3VsdCA9IHJlc3VsdC5yZXBsYWNlKC9cXHtcXHtmaXJzdEhlYWRpbmdcXH1cXH0vZywgdmFyaWFibGVzLmZpcnN0SGVhZGluZyA/PyAnJyk7XHJcblxyXG5cdC8vIERhdGUgZm9ybWF0dGluZ1xyXG5cdHJlc3VsdCA9IHJlc3VsdC5yZXBsYWNlKC9cXHtcXHtEQVRFOihbXn1dKylcXH1cXH0vZywgKF8sIGZvcm1hdDogc3RyaW5nKSA9PiB7XHJcblx0XHRyZXR1cm4gZm9ybWF0RGF0ZShuZXcgRGF0ZSgpLCBmb3JtYXQpO1xyXG5cdH0pO1xyXG5cclxuXHQvLyBUaW1lIGZvcm1hdHRpbmdcclxuXHRyZXN1bHQgPSByZXN1bHQucmVwbGFjZSgvXFx7XFx7VElNRTooW159XSspXFx9XFx9L2csIChfLCBmb3JtYXQ6IHN0cmluZykgPT4ge1xyXG5cdFx0cmV0dXJuIGZvcm1hdFRpbWUobmV3IERhdGUoKSwgZm9ybWF0KTtcclxuXHR9KTtcclxuXHJcblx0Ly8gRnJvbnRtYXR0ZXIgdmFyaWFibGVzIChpZiBwcm92aWRlZClcclxuXHRpZiAoZnJvbnRtYXR0ZXIpIHtcclxuXHRcdHJlc3VsdCA9IHJlc3VsdC5yZXBsYWNlKC9cXHtcXHtmbTooW159XSspXFx9XFx9L2csIChfLCBrZXk6IHN0cmluZykgPT4ge1xyXG5cdFx0XHRjb25zdCB2YWx1ZSA9IGZyb250bWF0dGVyW2tleS50cmltKCldO1xyXG5cdFx0XHRpZiAodmFsdWUgPT0gbnVsbCkgcmV0dXJuICcnO1xyXG5cdFx0XHRpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJykgcmV0dXJuIHZhbHVlO1xyXG5cdFx0XHRpZiAodHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJyB8fCB0eXBlb2YgdmFsdWUgPT09ICdib29sZWFuJykgcmV0dXJuIFN0cmluZyh2YWx1ZSk7XHJcblx0XHRcdHJldHVybiAnJztcclxuXHRcdH0pO1xyXG5cdH1cclxuXHJcblx0cmV0dXJuIHJlc3VsdDtcclxufVxyXG5cclxuLyoqXHJcbiAqIEZvcm1hdCBhIGRhdGUgdXNpbmcgYSBzaW1wbGUgZm9ybWF0IHN0cmluZ1xyXG4gKiBTdXBwb3J0czogWVlZWSwgWVksIE1NLCBERCwgTSwgRFxyXG4gKi9cclxuZnVuY3Rpb24gZm9ybWF0RGF0ZShkYXRlOiBEYXRlLCBmb3JtYXQ6IHN0cmluZyk6IHN0cmluZyB7XHJcblx0Y29uc3QgeWVhciA9IGRhdGUuZ2V0RnVsbFllYXIoKTtcclxuXHRjb25zdCBtb250aCA9IGRhdGUuZ2V0TW9udGgoKSArIDE7XHJcblx0Y29uc3QgZGF5ID0gZGF0ZS5nZXREYXRlKCk7XHJcblxyXG5cdHJldHVybiBmb3JtYXRcclxuXHRcdC5yZXBsYWNlKCdZWVlZJywgU3RyaW5nKHllYXIpKVxyXG5cdFx0LnJlcGxhY2UoJ1lZJywgU3RyaW5nKHllYXIpLnNsaWNlKC0yKSlcclxuXHRcdC5yZXBsYWNlKCdNTScsIFN0cmluZyhtb250aCkucGFkU3RhcnQoMiwgJzAnKSlcclxuXHRcdC5yZXBsYWNlKCdERCcsIFN0cmluZyhkYXkpLnBhZFN0YXJ0KDIsICcwJykpXHJcblx0XHQucmVwbGFjZSgnTScsIFN0cmluZyhtb250aCkpXHJcblx0XHQucmVwbGFjZSgnRCcsIFN0cmluZyhkYXkpKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIEZvcm1hdCB0aW1lIHVzaW5nIGEgc2ltcGxlIGZvcm1hdCBzdHJpbmdcclxuICogU3VwcG9ydHM6IEhILCBtbSwgc3MsIEgsIG0sIHNcclxuICovXHJcbmZ1bmN0aW9uIGZvcm1hdFRpbWUoZGF0ZTogRGF0ZSwgZm9ybWF0OiBzdHJpbmcpOiBzdHJpbmcge1xyXG5cdGNvbnN0IGhvdXJzID0gZGF0ZS5nZXRIb3VycygpO1xyXG5cdGNvbnN0IG1pbnV0ZXMgPSBkYXRlLmdldE1pbnV0ZXMoKTtcclxuXHRjb25zdCBzZWNvbmRzID0gZGF0ZS5nZXRTZWNvbmRzKCk7XHJcblxyXG5cdHJldHVybiBmb3JtYXRcclxuXHRcdC5yZXBsYWNlKCdISCcsIFN0cmluZyhob3VycykucGFkU3RhcnQoMiwgJzAnKSlcclxuXHRcdC5yZXBsYWNlKCdtbScsIFN0cmluZyhtaW51dGVzKS5wYWRTdGFydCgyLCAnMCcpKVxyXG5cdFx0LnJlcGxhY2UoJ3NzJywgU3RyaW5nKHNlY29uZHMpLnBhZFN0YXJ0KDIsICcwJykpXHJcblx0XHQucmVwbGFjZSgnSCcsIFN0cmluZyhob3VycykpXHJcblx0XHQucmVwbGFjZSgnbScsIFN0cmluZyhtaW51dGVzKSlcclxuXHRcdC5yZXBsYWNlKCdzJywgU3RyaW5nKHNlY29uZHMpKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIEJ1aWxkIHRlbXBsYXRlIHZhcmlhYmxlcyBmcm9tIGEgZmlsZSBhbmQgYXBwIGNvbnRleHRcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBidWlsZFRlbXBsYXRlVmFyaWFibGVzKFxyXG5cdGFwcDogQXBwLFxyXG5cdGFjdGl2ZUZpbGU6IFRGaWxlXHJcbik6IE5hbWVUZW1wbGF0ZVZhcmlhYmxlcyB7XHJcblx0Y29uc3QgY2FjaGUgPSBhcHAubWV0YWRhdGFDYWNoZS5nZXRGaWxlQ2FjaGUoYWN0aXZlRmlsZSk7XHJcblx0Y29uc3QgZnJvbnRtYXR0ZXIgPSBjYWNoZT8uZnJvbnRtYXR0ZXI7XHJcblx0XHJcblx0Ly8gR2V0IGZpcnN0IEgxIGhlYWRpbmdcclxuXHRsZXQgZmlyc3RIZWFkaW5nID0gJyc7XHJcblx0aWYgKGNhY2hlPy5oZWFkaW5ncykge1xyXG5cdFx0Zm9yIChjb25zdCBoZWFkaW5nIG9mIGNhY2hlLmhlYWRpbmdzKSB7XHJcblx0XHRcdGlmIChoZWFkaW5nLmxldmVsID09PSAxKSB7XHJcblx0XHRcdFx0Zmlyc3RIZWFkaW5nID0gaGVhZGluZy5oZWFkaW5nO1xyXG5cdFx0XHRcdGJyZWFrO1xyXG5cdFx0XHR9XHJcblx0XHR9XHJcblx0fVxyXG5cclxuXHRyZXR1cm4ge1xyXG5cdFx0ZmlsZU5hbWU6IGFjdGl2ZUZpbGUuYmFzZW5hbWUsXHJcblx0XHRkaXJOYW1lOiBhY3RpdmVGaWxlLnBhcmVudD8ubmFtZSA/PyAnJyxcclxuXHRcdGltYWdlTmFtZUtleTogZnJvbnRtYXR0ZXI/LmltYWdlTmFtZUtleSBhcyBzdHJpbmcgfCB1bmRlZmluZWQsXHJcblx0XHRmaXJzdEhlYWRpbmcsXHJcblx0XHRkYXRlOiBmb3JtYXREYXRlKG5ldyBEYXRlKCksICdZWVlZLU1NLUREJyksXHJcblx0XHR0aW1lOiBmb3JtYXRUaW1lKG5ldyBEYXRlKCksICdISC1tbS1zcycpLFxyXG5cdH07XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBDaGVjayBpZiBhIHJlbmRlcmVkIHRlbXBsYXRlIHJlc3VsdCBpcyBtZWFuaW5nZnVsIChub3QgZW1wdHkvd2hpdGVzcGFjZSlcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBpc1RlbXBsYXRlTWVhbmluZ2Z1bChyZXN1bHQ6IHN0cmluZywgZGVsaW1pdGVyOiBzdHJpbmcpOiBib29sZWFuIHtcclxuXHQvLyBSZW1vdmUgZGVsaW1pdGVycyBhbmQgd2hpdGVzcGFjZSB0byBjaGVjayBpZiB0aGVyZSdzIGFjdHVhbCBjb250ZW50XHJcblx0Y29uc3QgbWVhbmluZ2xlc3NSZWdleCA9IG5ldyBSZWdFeHAoYFske2VzY2FwZVJlZ0V4cChkZWxpbWl0ZXIpfVxcXFxzXWAsICdnbScpO1xyXG5cdHJldHVybiByZXN1bHQucmVwbGFjZShtZWFuaW5nbGVzc1JlZ2V4LCAnJykgIT09ICcnO1xyXG59XHJcblxyXG4vKipcclxuICogRXNjYXBlIHNwZWNpYWwgcmVnZXggY2hhcmFjdGVyc1xyXG4gKi9cclxuZnVuY3Rpb24gZXNjYXBlUmVnRXhwKHN0cmluZzogc3RyaW5nKTogc3RyaW5nIHtcclxuXHRyZXR1cm4gc3RyaW5nLnJlcGxhY2UoL1suKis/XiR7fSgpfFtcXF1cXFxcXS9nLCAnXFxcXCQmJyk7XHJcbn1cclxuIiwgIi8qKlxyXG4gKiBSZW5hbWUgTW9kYWxcclxuICogRGlhbG9nIGZvciByZW5hbWluZyBpbWFnZXMgd2l0aCBwcmV2aWV3IGFuZCB0ZW1wbGF0ZSBzdWdnZXN0aW9uc1xyXG4gKi9cclxuXHJcbmltcG9ydCB7IEFwcCwgTW9kYWwsIFNldHRpbmcsIFRGaWxlIH0gZnJvbSAnb2JzaWRpYW4nO1xyXG5cclxuZXhwb3J0IGludGVyZmFjZSBSZW5hbWVSZXN1bHQge1xyXG5cdG5ld05hbWU6IHN0cmluZztcclxuXHRjYW5jZWxsZWQ6IGJvb2xlYW47XHJcbn1cclxuXHJcbmV4cG9ydCBjbGFzcyBSZW5hbWVNb2RhbCBleHRlbmRzIE1vZGFsIHtcclxuXHRwcml2YXRlIGltYWdlRmlsZTogVEZpbGU7XHJcblx0cHJpdmF0ZSBzdWdnZXN0ZWROYW1lOiBzdHJpbmc7XHJcblx0cHJpdmF0ZSBjdXJyZW50TmFtZTogc3RyaW5nO1xyXG5cdHByaXZhdGUgb25TdWJtaXQ6IChyZXN1bHQ6IFJlbmFtZVJlc3VsdCkgPT4gdm9pZDtcclxuXHJcblx0cHJpdmF0ZSBuYW1lSW5wdXQ6IEhUTUxJbnB1dEVsZW1lbnQgfCBudWxsID0gbnVsbDtcclxuXHRwcml2YXRlIHByZXZpZXdFbDogSFRNTEVsZW1lbnQgfCBudWxsID0gbnVsbDtcclxuXHRwcml2YXRlIGVycm9yRWw6IEhUTUxFbGVtZW50IHwgbnVsbCA9IG51bGw7XHJcblxyXG5cdGNvbnN0cnVjdG9yKFxyXG5cdFx0YXBwOiBBcHAsXHJcblx0XHRpbWFnZUZpbGU6IFRGaWxlLFxyXG5cdFx0c3VnZ2VzdGVkTmFtZTogc3RyaW5nLFxyXG5cdFx0b25TdWJtaXQ6IChyZXN1bHQ6IFJlbmFtZVJlc3VsdCkgPT4gdm9pZFxyXG5cdCkge1xyXG5cdFx0c3VwZXIoYXBwKTtcclxuXHRcdHRoaXMuaW1hZ2VGaWxlID0gaW1hZ2VGaWxlO1xyXG5cdFx0dGhpcy5zdWdnZXN0ZWROYW1lID0gc3VnZ2VzdGVkTmFtZTtcclxuXHRcdHRoaXMuY3VycmVudE5hbWUgPSBzdWdnZXN0ZWROYW1lO1xyXG5cdFx0dGhpcy5vblN1Ym1pdCA9IG9uU3VibWl0O1xyXG5cdH1cclxuXHJcblx0b25PcGVuKCk6IHZvaWQge1xyXG5cdFx0Y29uc3QgeyBjb250ZW50RWwsIHRpdGxlRWwgfSA9IHRoaXM7XHJcblx0XHRcclxuXHRcdHRoaXMuY29udGFpbmVyRWwuYWRkQ2xhc3MoJ2ltYWdlLW1hbmFnZXItcmVuYW1lLW1vZGFsJyk7XHJcblx0XHR0aXRsZUVsLnNldFRleHQoJ1JlbmFtZSBpbWFnZScpO1xyXG5cclxuXHRcdC8vIEltYWdlIHByZXZpZXdcclxuXHRcdHRoaXMucmVuZGVySW1hZ2VQcmV2aWV3KGNvbnRlbnRFbCk7XHJcblxyXG5cdFx0Ly8gRmlsZSBpbmZvXHJcblx0XHR0aGlzLnJlbmRlckZpbGVJbmZvKGNvbnRlbnRFbCk7XHJcblxyXG5cdFx0Ly8gTmFtZSBpbnB1dFxyXG5cdFx0dGhpcy5yZW5kZXJOYW1lSW5wdXQoY29udGVudEVsKTtcclxuXHJcblx0XHQvLyBFcnJvciBkaXNwbGF5XHJcblx0XHR0aGlzLmVycm9yRWwgPSBjb250ZW50RWwuY3JlYXRlRGl2KHsgY2xzOiAnaW1hZ2UtbWFuYWdlci1lcnJvciBpbWFnZS1tYW5hZ2VyLWVycm9yLWhpZGRlbicgfSk7XHJcblxyXG5cdFx0Ly8gQnV0dG9uc1xyXG5cdFx0dGhpcy5yZW5kZXJCdXR0b25zKGNvbnRlbnRFbCk7XHJcblxyXG5cdFx0Ly8gRm9jdXMgYW5kIHNlbGVjdCBpbnB1dFxyXG5cdFx0c2V0VGltZW91dCgoKSA9PiB7XHJcblx0XHRcdGlmICh0aGlzLm5hbWVJbnB1dCkge1xyXG5cdFx0XHRcdHRoaXMubmFtZUlucHV0LmZvY3VzKCk7XHJcblx0XHRcdFx0dGhpcy5uYW1lSW5wdXQuc2VsZWN0KCk7XHJcblx0XHRcdH1cclxuXHRcdH0sIDUwKTtcclxuXHR9XHJcblxyXG5cdHByaXZhdGUgcmVuZGVySW1hZ2VQcmV2aWV3KGNvbnRhaW5lckVsOiBIVE1MRWxlbWVudCk6IHZvaWQge1xyXG5cdFx0Y29uc3QgcHJldmlld0NvbnRhaW5lciA9IGNvbnRhaW5lckVsLmNyZWF0ZURpdih7IGNsczogJ2ltYWdlLW1hbmFnZXItcHJldmlldycgfSk7XHJcblx0XHRcclxuXHRcdGNvbnN0IGltZyA9IHByZXZpZXdDb250YWluZXIuY3JlYXRlRWwoJ2ltZycsIHtcclxuXHRcdFx0YXR0cjoge1xyXG5cdFx0XHRcdHNyYzogdGhpcy5hcHAudmF1bHQuZ2V0UmVzb3VyY2VQYXRoKHRoaXMuaW1hZ2VGaWxlKSxcclxuXHRcdFx0XHRhbHQ6IHRoaXMuaW1hZ2VGaWxlLm5hbWUsXHJcblx0XHRcdH0sXHJcblx0XHR9KTtcclxuXHJcblx0XHQvLyBBZGQgY2xhc3MgZm9yIHByZXZpZXcgc3R5bGluZyAoc3R5bGVzIGluIHN0eWxlcy5jc3MpXHJcblx0XHRpbWcuYWRkQ2xhc3MoJ2ltYWdlLW1hbmFnZXItcHJldmlldy1pbWcnKTtcclxuXHR9XHJcblxyXG5cdHByaXZhdGUgcmVuZGVyRmlsZUluZm8oY29udGFpbmVyRWw6IEhUTUxFbGVtZW50KTogdm9pZCB7XHJcblx0XHRjb25zdCBpbmZvQ29udGFpbmVyID0gY29udGFpbmVyRWwuY3JlYXRlRGl2KHsgY2xzOiAnaW1hZ2UtbWFuYWdlci1pbmZvJyB9KTtcclxuXHRcdFxyXG5cdFx0Y29uc3QgaW5mb0xpc3QgPSBpbmZvQ29udGFpbmVyLmNyZWF0ZUVsKCd1bCcpO1xyXG5cdFx0XHJcblx0XHQvLyBPcmlnaW5hbCBwYXRoXHJcblx0XHRjb25zdCBvcmlnaW5hbEl0ZW0gPSBpbmZvTGlzdC5jcmVhdGVFbCgnbGknKTtcclxuXHRcdG9yaWdpbmFsSXRlbS5jcmVhdGVFbCgnc3Ryb25nJywgeyB0ZXh0OiAnT3JpZ2luYWw6ICcgfSk7XHJcblx0XHRvcmlnaW5hbEl0ZW0uY3JlYXRlRWwoJ3NwYW4nLCB7IHRleHQ6IHRoaXMuaW1hZ2VGaWxlLnBhdGggfSk7XHJcblxyXG5cdFx0Ly8gTmV3IHBhdGggcHJldmlld1xyXG5cdFx0Y29uc3QgbmV3SXRlbSA9IGluZm9MaXN0LmNyZWF0ZUVsKCdsaScpO1xyXG5cdFx0bmV3SXRlbS5jcmVhdGVFbCgnc3Ryb25nJywgeyB0ZXh0OiAnTmV3IHBhdGg6ICcgfSk7XHJcblx0XHR0aGlzLnByZXZpZXdFbCA9IG5ld0l0ZW0uY3JlYXRlRWwoJ3NwYW4nLCB7IHRleHQ6IHRoaXMuZ2V0TmV3UGF0aCh0aGlzLmN1cnJlbnROYW1lKSB9KTtcclxuXHR9XHJcblxyXG5cdHByaXZhdGUgcmVuZGVyTmFtZUlucHV0KGNvbnRhaW5lckVsOiBIVE1MRWxlbWVudCk6IHZvaWQge1xyXG5cdFx0bmV3IFNldHRpbmcoY29udGFpbmVyRWwpXHJcblx0XHRcdC5zZXROYW1lKCdOZXcgbmFtZScpXHJcblx0XHRcdC5zZXREZXNjKCdFbnRlciBhIG5ldyBuYW1lIGZvciB0aGUgaW1hZ2UgKHdpdGhvdXQgZXh0ZW5zaW9uKScpXHJcblx0XHRcdC5hZGRUZXh0KHRleHQgPT4ge1xyXG5cdFx0XHRcdHRoaXMubmFtZUlucHV0ID0gdGV4dC5pbnB1dEVsO1xyXG5cdFx0XHRcdHRleHRcclxuXHRcdFx0XHRcdC5zZXRQbGFjZWhvbGRlcignRW50ZXIgbmFtZScpXHJcblx0XHRcdFx0XHQuc2V0VmFsdWUodGhpcy5jdXJyZW50TmFtZSlcclxuXHRcdFx0XHRcdC5vbkNoYW5nZSh2YWx1ZSA9PiB7XHJcblx0XHRcdFx0XHRcdHRoaXMuY3VycmVudE5hbWUgPSB0aGlzLnNhbml0aXplTmFtZSh2YWx1ZSk7XHJcblx0XHRcdFx0XHRcdHRoaXMudXBkYXRlUHJldmlldygpO1xyXG5cdFx0XHRcdFx0fSk7XHJcblxyXG5cdFx0XHRcdC8vIEhhbmRsZSBlbnRlciBrZXlcclxuXHRcdFx0XHR0ZXh0LmlucHV0RWwuYWRkRXZlbnRMaXN0ZW5lcigna2V5ZG93bicsIChlOiBLZXlib2FyZEV2ZW50KSA9PiB7XHJcblx0XHRcdFx0XHRpZiAoZS5rZXkgPT09ICdFbnRlcicgJiYgIWUuaXNDb21wb3NpbmcpIHtcclxuXHRcdFx0XHRcdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xyXG5cdFx0XHRcdFx0XHR0aGlzLnN1Ym1pdCgpO1xyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdH0pO1xyXG5cdFx0XHR9KTtcclxuXHR9XHJcblxyXG5cdHByaXZhdGUgcmVuZGVyQnV0dG9ucyhjb250YWluZXJFbDogSFRNTEVsZW1lbnQpOiB2b2lkIHtcclxuXHRcdG5ldyBTZXR0aW5nKGNvbnRhaW5lckVsKVxyXG5cdFx0XHQuYWRkQnV0dG9uKChidG4pID0+IHtcclxuXHRcdFx0XHRidG5cclxuXHRcdFx0XHRcdC5zZXRCdXR0b25UZXh0KCdSZW5hbWUnKVxyXG5cdFx0XHRcdFx0LnNldEN0YSgpXHJcblx0XHRcdFx0XHQub25DbGljaygoKSA9PiB0aGlzLnN1Ym1pdCgpKTtcclxuXHRcdFx0fSlcclxuXHRcdFx0LmFkZEJ1dHRvbigoYnRuKSA9PiB7XHJcblx0XHRcdFx0YnRuXHJcblx0XHRcdFx0XHQuc2V0QnV0dG9uVGV4dCgnU2tpcCcpXHJcblx0XHRcdFx0XHQub25DbGljaygoKSA9PiB0aGlzLmNhbmNlbCgpKTtcclxuXHRcdFx0fSk7XHJcblx0fVxyXG5cclxuXHRwcml2YXRlIGdldE5ld1BhdGgobmFtZTogc3RyaW5nKTogc3RyaW5nIHtcclxuXHRcdGNvbnN0IGZvbGRlciA9IHRoaXMuaW1hZ2VGaWxlLnBhcmVudD8ucGF0aCA/PyAnJztcclxuXHRcdGNvbnN0IGV4dGVuc2lvbiA9IHRoaXMuaW1hZ2VGaWxlLmV4dGVuc2lvbjtcclxuXHRcdGNvbnN0IGZpbGVOYW1lID0gYCR7bmFtZX0uJHtleHRlbnNpb259YDtcclxuXHRcdHJldHVybiBmb2xkZXIgPyBgJHtmb2xkZXJ9LyR7ZmlsZU5hbWV9YCA6IGZpbGVOYW1lO1xyXG5cdH1cclxuXHJcblx0cHJpdmF0ZSB1cGRhdGVQcmV2aWV3KCk6IHZvaWQge1xyXG5cdFx0aWYgKHRoaXMucHJldmlld0VsKSB7XHJcblx0XHRcdHRoaXMucHJldmlld0VsLnNldFRleHQodGhpcy5nZXROZXdQYXRoKHRoaXMuY3VycmVudE5hbWUpKTtcclxuXHRcdH1cclxuXHR9XHJcblxyXG5cdHByaXZhdGUgc2FuaXRpemVOYW1lKG5hbWU6IHN0cmluZyk6IHN0cmluZyB7XHJcblx0XHRyZXR1cm4gbmFtZVxyXG5cdFx0XHQucmVwbGFjZSgvW1xcXFwvOio/XCI8PnxdL2csICctJylcclxuXHRcdFx0LnJlcGxhY2UoL1xccysvZywgJy0nKVxyXG5cdFx0XHQudHJpbSgpO1xyXG5cdH1cclxuXHJcblx0cHJpdmF0ZSBzaG93RXJyb3IobWVzc2FnZTogc3RyaW5nKTogdm9pZCB7XHJcblx0XHRpZiAodGhpcy5lcnJvckVsKSB7XHJcblx0XHRcdHRoaXMuZXJyb3JFbC5zZXRUZXh0KG1lc3NhZ2UpO1xyXG5cdFx0XHR0aGlzLmVycm9yRWwuYWRkQ2xhc3MoJ2ltYWdlLW1hbmFnZXItZXJyb3ItdmlzaWJsZScpO1xyXG5cdFx0XHR0aGlzLmVycm9yRWwucmVtb3ZlQ2xhc3MoJ2ltYWdlLW1hbmFnZXItZXJyb3ItaGlkZGVuJyk7XHJcblx0XHR9XHJcblx0fVxyXG5cclxuXHRwcml2YXRlIGhpZGVFcnJvcigpOiB2b2lkIHtcclxuXHRcdGlmICh0aGlzLmVycm9yRWwpIHtcclxuXHRcdFx0dGhpcy5lcnJvckVsLmFkZENsYXNzKCdpbWFnZS1tYW5hZ2VyLWVycm9yLWhpZGRlbicpO1xyXG5cdFx0XHR0aGlzLmVycm9yRWwucmVtb3ZlQ2xhc3MoJ2ltYWdlLW1hbmFnZXItZXJyb3ItdmlzaWJsZScpO1xyXG5cdFx0fVxyXG5cdH1cclxuXHJcblx0cHJpdmF0ZSBzdWJtaXQoKTogdm9pZCB7XHJcblx0XHR0aGlzLmhpZGVFcnJvcigpO1xyXG5cclxuXHRcdGlmICghdGhpcy5jdXJyZW50TmFtZSB8fCB0aGlzLmN1cnJlbnROYW1lLnRyaW0oKSA9PT0gJycpIHtcclxuXHRcdFx0dGhpcy5zaG93RXJyb3IoJ05hbWUgY2Fubm90IGJlIGVtcHR5Jyk7XHJcblx0XHRcdHJldHVybjtcclxuXHRcdH1cclxuXHJcblx0XHR0aGlzLm9uU3VibWl0KHtcclxuXHRcdFx0bmV3TmFtZTogdGhpcy5jdXJyZW50TmFtZSxcclxuXHRcdFx0Y2FuY2VsbGVkOiBmYWxzZSxcclxuXHRcdH0pO1xyXG5cdFx0dGhpcy5jbG9zZSgpO1xyXG5cdH1cclxuXHJcblx0cHJpdmF0ZSBjYW5jZWwoKTogdm9pZCB7XHJcblx0XHR0aGlzLm9uU3VibWl0KHtcclxuXHRcdFx0bmV3TmFtZTogJycsXHJcblx0XHRcdGNhbmNlbGxlZDogdHJ1ZSxcclxuXHRcdH0pO1xyXG5cdFx0dGhpcy5jbG9zZSgpO1xyXG5cdH1cclxuXHJcblx0b25DbG9zZSgpOiB2b2lkIHtcclxuXHRcdGNvbnN0IHsgY29udGVudEVsIH0gPSB0aGlzO1xyXG5cdFx0Y29udGVudEVsLmVtcHR5KCk7XHJcblx0fVxyXG59XHJcblxyXG4vKipcclxuICogT3BlbiB0aGUgcmVuYW1lIG1vZGFsIGFuZCByZXR1cm4gdGhlIHJlc3VsdFxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIG9wZW5SZW5hbWVNb2RhbChcclxuXHRhcHA6IEFwcCxcclxuXHRpbWFnZUZpbGU6IFRGaWxlLFxyXG5cdHN1Z2dlc3RlZE5hbWU6IHN0cmluZ1xyXG4pOiBQcm9taXNlPFJlbmFtZVJlc3VsdD4ge1xyXG5cdHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4ge1xyXG5cdFx0Y29uc3QgbW9kYWwgPSBuZXcgUmVuYW1lTW9kYWwoYXBwLCBpbWFnZUZpbGUsIHN1Z2dlc3RlZE5hbWUsIHJlc29sdmUpO1xyXG5cdFx0bW9kYWwub3BlbigpO1xyXG5cdH0pO1xyXG59XHJcbiIsICIvKipcclxuICogRGVzY3JpcHRpdmUgSW1hZ2UgTW9kYWxcclxuICogQXNrcyB1c2VyIHRvIGRlc2NyaWJlIHRoZSBpbWFnZSwgdXNlcyBkZXNjcmlwdGlvbiBhcyBkaXNwbGF5IHRleHQgYW5kIGtlYmFiLWNhc2UgZm9yIGZpbGVuYW1lXHJcbiAqL1xyXG5cclxuaW1wb3J0IHsgQXBwLCBNb2RhbCwgU2V0dGluZywgVEZpbGUgfSBmcm9tICdvYnNpZGlhbic7XHJcbmltcG9ydCB7IHRvS2ViYWJDYXNlIH0gZnJvbSAnLi4vdXRpbHMva2ViYWItY2FzZSc7XHJcblxyXG5leHBvcnQgaW50ZXJmYWNlIERlc2NyaXB0aXZlSW1hZ2VSZXN1bHQge1xyXG5cdGRlc2NyaXB0aW9uOiBzdHJpbmc7XHJcblx0ZmlsZU5hbWU6IHN0cmluZzsgLy8ga2ViYWItY2FzZSB2ZXJzaW9uXHJcblx0Y2FuY2VsbGVkOiBib29sZWFuO1xyXG59XHJcblxyXG5leHBvcnQgY2xhc3MgRGVzY3JpcHRpdmVJbWFnZU1vZGFsIGV4dGVuZHMgTW9kYWwge1xyXG5cdHByaXZhdGUgaW1hZ2VGaWxlOiBURmlsZTtcclxuXHRwcml2YXRlIGRlc2NyaXB0aW9uOiBzdHJpbmcgPSAnJztcclxuXHRwcml2YXRlIG9uU3VibWl0OiAocmVzdWx0OiBEZXNjcmlwdGl2ZUltYWdlUmVzdWx0KSA9PiB2b2lkO1xyXG5cclxuXHRwcml2YXRlIGRlc2NyaXB0aW9uSW5wdXQ6IEhUTUxJbnB1dEVsZW1lbnQgfCBudWxsID0gbnVsbDtcclxuXHRwcml2YXRlIHByZXZpZXdFbDogSFRNTEVsZW1lbnQgfCBudWxsID0gbnVsbDtcclxuXHRwcml2YXRlIGZpbGVOYW1lUHJldmlld0VsOiBIVE1MRWxlbWVudCB8IG51bGwgPSBudWxsO1xyXG5cdHByaXZhdGUgZXJyb3JFbDogSFRNTEVsZW1lbnQgfCBudWxsID0gbnVsbDtcclxuXHJcblx0Y29uc3RydWN0b3IoXHJcblx0XHRhcHA6IEFwcCxcclxuXHRcdGltYWdlRmlsZTogVEZpbGUsXHJcblx0XHRvblN1Ym1pdDogKHJlc3VsdDogRGVzY3JpcHRpdmVJbWFnZVJlc3VsdCkgPT4gdm9pZCxcclxuXHRcdHN1Z2dlc3RlZERlc2NyaXB0aW9uPzogc3RyaW5nXHJcblx0KSB7XHJcblx0XHRzdXBlcihhcHApO1xyXG5cdFx0dGhpcy5pbWFnZUZpbGUgPSBpbWFnZUZpbGU7XHJcblx0XHR0aGlzLm9uU3VibWl0ID0gb25TdWJtaXQ7XHJcblx0XHR0aGlzLmRlc2NyaXB0aW9uID0gc3VnZ2VzdGVkRGVzY3JpcHRpb24gPz8gJyc7XHJcblx0fVxyXG5cclxuXHRvbk9wZW4oKTogdm9pZCB7XHJcblx0XHRjb25zdCB7IGNvbnRlbnRFbCwgdGl0bGVFbCB9ID0gdGhpcztcclxuXHRcdFxyXG5cdFx0dGhpcy5jb250YWluZXJFbC5hZGRDbGFzcygnaW1hZ2UtbWFuYWdlci1yZW5hbWUtbW9kYWwnKTtcclxuXHRcdHRpdGxlRWwuc2V0VGV4dCgnRGVzY3JpYmUgaW1hZ2UnKTtcclxuXHJcblx0XHQvLyBJbWFnZSBwcmV2aWV3XHJcblx0XHR0aGlzLnJlbmRlckltYWdlUHJldmlldyhjb250ZW50RWwpO1xyXG5cclxuXHRcdC8vIERlc2NyaXB0aW9uIGlucHV0XHJcblx0XHRuZXcgU2V0dGluZyhjb250ZW50RWwpXHJcblx0XHRcdC5zZXROYW1lKCdJbWFnZSBkZXNjcmlwdGlvbicpXHJcblx0XHRcdC5zZXREZXNjKCdEZXNjcmliZSB0aGlzIGltYWdlLiBUaGlzIHdpbGwgYmUgdXNlZCBhcyBkaXNwbGF5IHRleHQgYW5kIGZvciB0aGUgZmlsZSBuYW1lLicpXHJcblx0XHRcdC5hZGRUZXh0KHRleHQgPT4ge1xyXG5cdFx0XHRcdHRoaXMuZGVzY3JpcHRpb25JbnB1dCA9IHRleHQuaW5wdXRFbDtcclxuXHRcdFx0XHR0ZXh0XHJcblx0XHRcdFx0XHQuc2V0UGxhY2Vob2xkZXIoJ0EgYmVhdXRpZnVsIHN1bnNldCBvdmVyIG1vdW50YWlucycpXHJcblx0XHRcdFx0XHQuc2V0VmFsdWUodGhpcy5kZXNjcmlwdGlvbilcclxuXHRcdFx0XHRcdC5vbkNoYW5nZSh2YWx1ZSA9PiB7XHJcblx0XHRcdFx0XHRcdHRoaXMuZGVzY3JpcHRpb24gPSB2YWx1ZTtcclxuXHRcdFx0XHRcdFx0dGhpcy51cGRhdGVQcmV2aWV3KCk7XHJcblx0XHRcdFx0XHR9KTtcclxuXHJcblx0XHRcdFx0Ly8gSGFuZGxlIGVudGVyIGtleSAoc3VibWl0KVxyXG5cdFx0XHRcdHRleHQuaW5wdXRFbC5hZGRFdmVudExpc3RlbmVyKCdrZXlkb3duJywgKGU6IEtleWJvYXJkRXZlbnQpID0+IHtcclxuXHRcdFx0XHRcdGlmIChlLmtleSA9PT0gJ0VudGVyJyAmJiAhZS5pc0NvbXBvc2luZykge1xyXG5cdFx0XHRcdFx0XHRlLnByZXZlbnREZWZhdWx0KCk7XHJcblx0XHRcdFx0XHRcdHRoaXMuc3VibWl0KCk7XHJcblx0XHRcdFx0XHR9XHJcblx0XHRcdFx0fSk7XHJcblx0XHRcdH0pO1xyXG5cclxuXHRcdC8vIFByZXZpZXcgc2VjdGlvblxyXG5cdFx0Y29uc3QgcHJldmlld0NvbnRhaW5lciA9IGNvbnRlbnRFbC5jcmVhdGVEaXYoeyBjbHM6ICdpbWFnZS1tYW5hZ2VyLWluZm8nIH0pO1xyXG5cdFx0cHJldmlld0NvbnRhaW5lci5jcmVhdGVFbCgncCcsIHsgdGV4dDogJ1ByZXZpZXc6JyB9KTtcclxuXHRcdFxyXG5cdFx0Y29uc3QgZmlsZU5hbWVQcmV2aWV3ID0gcHJldmlld0NvbnRhaW5lci5jcmVhdGVFbCgncCcpO1xyXG5cdFx0ZmlsZU5hbWVQcmV2aWV3LmNyZWF0ZUVsKCdzdHJvbmcnLCB7IHRleHQ6ICdGaWxlbmFtZTogJyB9KTtcclxuXHRcdHRoaXMuZmlsZU5hbWVQcmV2aWV3RWwgPSBmaWxlTmFtZVByZXZpZXcuY3JlYXRlRWwoJ3NwYW4nKTtcclxuXHRcdFxyXG5cdFx0Y29uc3QgbGlua1ByZXZpZXcgPSBwcmV2aWV3Q29udGFpbmVyLmNyZWF0ZUVsKCdwJyk7XHJcblx0XHRsaW5rUHJldmlldy5jcmVhdGVFbCgnc3Ryb25nJywgeyB0ZXh0OiAnTGluazogJyB9KTtcclxuXHRcdHRoaXMucHJldmlld0VsID0gbGlua1ByZXZpZXcuY3JlYXRlRWwoJ3NwYW4nLCB7IGNsczogJ2NvZGUnIH0pO1xyXG5cclxuXHRcdC8vIEVycm9yIGRpc3BsYXlcclxuXHRcdHRoaXMuZXJyb3JFbCA9IGNvbnRlbnRFbC5jcmVhdGVEaXYoeyBjbHM6ICdpbWFnZS1tYW5hZ2VyLWVycm9yIGltYWdlLW1hbmFnZXItZXJyb3ItaGlkZGVuJyB9KTtcclxuXHJcblx0XHQvLyBCdXR0b25zXHJcblx0XHRuZXcgU2V0dGluZyhjb250ZW50RWwpXHJcblx0XHRcdC5hZGRCdXR0b24oKGJ0bikgPT4ge1xyXG5cdFx0XHRcdGJ0blxyXG5cdFx0XHRcdFx0LnNldEJ1dHRvblRleHQoJ0luc2VydCcpXHJcblx0XHRcdFx0XHQuc2V0Q3RhKClcclxuXHRcdFx0XHRcdC5vbkNsaWNrKCgpID0+IHRoaXMuc3VibWl0KCkpO1xyXG5cdFx0XHR9KVxyXG5cdFx0XHQuYWRkQnV0dG9uKChidG4pID0+IHtcclxuXHRcdFx0XHRidG5cclxuXHRcdFx0XHRcdC5zZXRCdXR0b25UZXh0KCdDYW5jZWwnKVxyXG5cdFx0XHRcdFx0Lm9uQ2xpY2soKCkgPT4gdGhpcy5jYW5jZWwoKSk7XHJcblx0XHRcdH0pO1xyXG5cclxuXHRcdC8vIFVwZGF0ZSBwcmV2aWV3IGlmIHdlIGhhdmUgYSBzdWdnZXN0ZWQgZGVzY3JpcHRpb25cclxuXHRcdGlmICh0aGlzLmRlc2NyaXB0aW9uKSB7XHJcblx0XHRcdHRoaXMudXBkYXRlUHJldmlldygpO1xyXG5cdFx0fVxyXG5cclxuXHRcdC8vIEZvY3VzIGlucHV0XHJcblx0XHRzZXRUaW1lb3V0KCgpID0+IHtcclxuXHRcdFx0aWYgKHRoaXMuZGVzY3JpcHRpb25JbnB1dCkge1xyXG5cdFx0XHRcdHRoaXMuZGVzY3JpcHRpb25JbnB1dC5mb2N1cygpO1xyXG5cdFx0XHR9XHJcblx0XHR9LCA1MCk7XHJcblx0fVxyXG5cclxuXHRwcml2YXRlIHJlbmRlckltYWdlUHJldmlldyhjb250YWluZXJFbDogSFRNTEVsZW1lbnQpOiB2b2lkIHtcclxuXHRcdGNvbnN0IHByZXZpZXdDb250YWluZXIgPSBjb250YWluZXJFbC5jcmVhdGVEaXYoeyBjbHM6ICdpbWFnZS1tYW5hZ2VyLXByZXZpZXcnIH0pO1xyXG5cdFx0XHJcblx0XHRjb25zdCBpbWcgPSBwcmV2aWV3Q29udGFpbmVyLmNyZWF0ZUVsKCdpbWcnLCB7XHJcblx0XHRcdGF0dHI6IHtcclxuXHRcdFx0XHRzcmM6IHRoaXMuYXBwLnZhdWx0LmdldFJlc291cmNlUGF0aCh0aGlzLmltYWdlRmlsZSksXHJcblx0XHRcdFx0YWx0OiB0aGlzLmltYWdlRmlsZS5uYW1lLFxyXG5cdFx0XHR9LFxyXG5cdFx0fSk7XHJcblxyXG5cdFx0aW1nLmFkZENsYXNzKCdpbWFnZS1tYW5hZ2VyLXByZXZpZXctaW1nJyk7XHJcblx0fVxyXG5cclxuXHRwcml2YXRlIHVwZGF0ZVByZXZpZXcoKTogdm9pZCB7XHJcblx0XHRpZiAoIXRoaXMuZGVzY3JpcHRpb24gfHwgdGhpcy5kZXNjcmlwdGlvbi50cmltKCkgPT09ICcnKSB7XHJcblx0XHRcdGlmICh0aGlzLmZpbGVOYW1lUHJldmlld0VsKSB7XHJcblx0XHRcdFx0dGhpcy5maWxlTmFtZVByZXZpZXdFbC5zZXRUZXh0KCcoZW50ZXIgZGVzY3JpcHRpb24pJyk7XHJcblx0XHRcdH1cclxuXHRcdFx0aWYgKHRoaXMucHJldmlld0VsKSB7XHJcblx0XHRcdFx0dGhpcy5wcmV2aWV3RWwuc2V0VGV4dCgnKGVudGVyIGRlc2NyaXB0aW9uKScpO1xyXG5cdFx0XHR9XHJcblx0XHRcdHJldHVybjtcclxuXHRcdH1cclxuXHJcblx0XHRjb25zdCBrZWJhYk5hbWUgPSB0b0tlYmFiQ2FzZSh0aGlzLmRlc2NyaXB0aW9uKTtcclxuXHRcdGNvbnN0IGV4dGVuc2lvbiA9IHRoaXMuaW1hZ2VGaWxlLmV4dGVuc2lvbjtcclxuXHRcdGNvbnN0IGZpbGVOYW1lID0gYCR7a2ViYWJOYW1lfS4ke2V4dGVuc2lvbn1gO1xyXG5cdFx0Y29uc3QgZGlzcGxheVRleHQgPSB0aGlzLmRlc2NyaXB0aW9uLnRyaW0oKTtcclxuXHJcblx0XHRpZiAodGhpcy5maWxlTmFtZVByZXZpZXdFbCkge1xyXG5cdFx0XHR0aGlzLmZpbGVOYW1lUHJldmlld0VsLnNldFRleHQoZmlsZU5hbWUpO1xyXG5cdFx0fVxyXG5cclxuXHRcdGlmICh0aGlzLnByZXZpZXdFbCkge1xyXG5cdFx0XHQvLyBTaG93IHByZXZpZXcgYXM6ICFbW2ZpbGVuYW1lLmpwZ3xkaXNwbGF5IHRleHRdXVxyXG5cdFx0XHR0aGlzLnByZXZpZXdFbC5zZXRUZXh0KGAhW1ske2ZpbGVOYW1lfXwke2Rpc3BsYXlUZXh0fV1dYCk7XHJcblx0XHR9XHJcblx0fVxyXG5cclxuXHRwcml2YXRlIHNob3dFcnJvcihtZXNzYWdlOiBzdHJpbmcpOiB2b2lkIHtcclxuXHRcdGlmICh0aGlzLmVycm9yRWwpIHtcclxuXHRcdFx0dGhpcy5lcnJvckVsLnNldFRleHQobWVzc2FnZSk7XHJcblx0XHRcdHRoaXMuZXJyb3JFbC5hZGRDbGFzcygnaW1hZ2UtbWFuYWdlci1lcnJvci12aXNpYmxlJyk7XHJcblx0XHRcdHRoaXMuZXJyb3JFbC5yZW1vdmVDbGFzcygnaW1hZ2UtbWFuYWdlci1lcnJvci1oaWRkZW4nKTtcclxuXHRcdH1cclxuXHR9XHJcblxyXG5cdHByaXZhdGUgaGlkZUVycm9yKCk6IHZvaWQge1xyXG5cdFx0aWYgKHRoaXMuZXJyb3JFbCkge1xyXG5cdFx0XHR0aGlzLmVycm9yRWwuYWRkQ2xhc3MoJ2ltYWdlLW1hbmFnZXItZXJyb3ItaGlkZGVuJyk7XHJcblx0XHRcdHRoaXMuZXJyb3JFbC5yZW1vdmVDbGFzcygnaW1hZ2UtbWFuYWdlci1lcnJvci12aXNpYmxlJyk7XHJcblx0XHR9XHJcblx0fVxyXG5cclxuXHRwcml2YXRlIHN1Ym1pdCgpOiB2b2lkIHtcclxuXHRcdHRoaXMuaGlkZUVycm9yKCk7XHJcblxyXG5cdFx0aWYgKCF0aGlzLmRlc2NyaXB0aW9uIHx8IHRoaXMuZGVzY3JpcHRpb24udHJpbSgpID09PSAnJykge1xyXG5cdFx0XHR0aGlzLnNob3dFcnJvcignRGVzY3JpcHRpb24gY2Fubm90IGJlIGVtcHR5Jyk7XHJcblx0XHRcdHJldHVybjtcclxuXHRcdH1cclxuXHJcblx0XHRjb25zdCBrZWJhYk5hbWUgPSB0b0tlYmFiQ2FzZSh0aGlzLmRlc2NyaXB0aW9uKTtcclxuXHRcdGlmICgha2ViYWJOYW1lIHx8IGtlYmFiTmFtZSA9PT0gJycpIHtcclxuXHRcdFx0dGhpcy5zaG93RXJyb3IoJ0Rlc2NyaXB0aW9uIG11c3QgY29udGFpbiB2YWxpZCBjaGFyYWN0ZXJzJyk7XHJcblx0XHRcdHJldHVybjtcclxuXHRcdH1cclxuXHJcblx0XHR0aGlzLm9uU3VibWl0KHtcclxuXHRcdFx0ZGVzY3JpcHRpb246IHRoaXMuZGVzY3JpcHRpb24udHJpbSgpLFxyXG5cdFx0XHRmaWxlTmFtZToga2ViYWJOYW1lLFxyXG5cdFx0XHRjYW5jZWxsZWQ6IGZhbHNlLFxyXG5cdFx0fSk7XHJcblx0XHR0aGlzLmNsb3NlKCk7XHJcblx0fVxyXG5cclxuXHRwcml2YXRlIGNhbmNlbCgpOiB2b2lkIHtcclxuXHRcdHRoaXMub25TdWJtaXQoe1xyXG5cdFx0XHRkZXNjcmlwdGlvbjogJycsXHJcblx0XHRcdGZpbGVOYW1lOiAnJyxcclxuXHRcdFx0Y2FuY2VsbGVkOiB0cnVlLFxyXG5cdFx0fSk7XHJcblx0XHR0aGlzLmNsb3NlKCk7XHJcblx0fVxyXG5cclxuXHRvbkNsb3NlKCk6IHZvaWQge1xyXG5cdFx0Y29uc3QgeyBjb250ZW50RWwgfSA9IHRoaXM7XHJcblx0XHRjb250ZW50RWwuZW1wdHkoKTtcclxuXHR9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBPcGVuIHRoZSBkZXNjcmlwdGl2ZSBpbWFnZSBtb2RhbCBhbmQgcmV0dXJuIHRoZSByZXN1bHRcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBvcGVuRGVzY3JpcHRpdmVJbWFnZU1vZGFsKFxyXG5cdGFwcDogQXBwLFxyXG5cdGltYWdlRmlsZTogVEZpbGUsXHJcblx0c3VnZ2VzdGVkRGVzY3JpcHRpb24/OiBzdHJpbmdcclxuKTogUHJvbWlzZTxEZXNjcmlwdGl2ZUltYWdlUmVzdWx0PiB7XHJcblx0cmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB7XHJcblx0XHRjb25zdCBtb2RhbCA9IG5ldyBEZXNjcmlwdGl2ZUltYWdlTW9kYWwoYXBwLCBpbWFnZUZpbGUsIHJlc29sdmUsIHN1Z2dlc3RlZERlc2NyaXB0aW9uKTtcclxuXHRcdG1vZGFsLm9wZW4oKTtcclxuXHR9KTtcclxufVxyXG4iLCAiLyoqXHJcbiAqIEtlYmFiLWNhc2UgdXRpbGl0eVxyXG4gKiBDb252ZXJ0cyBzdHJpbmdzIHRvIGtlYmFiLWNhc2UgZm9yIHNhZmUgZmlsZW5hbWVzXHJcbiAqIEJhc2VkIG9uIEFzdHJvIENvbXBvc2VyJ3MgaW1wbGVtZW50YXRpb25cclxuICovXHJcblxyXG4vKipcclxuICogQ29udmVydCBhIHN0cmluZyB0byBrZWJhYi1jYXNlXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gdG9LZWJhYkNhc2Uoc3RyOiBzdHJpbmcpOiBzdHJpbmcge1xyXG5cdHJldHVybiBzdHJcclxuXHRcdC50b0xvd2VyQ2FzZSgpXHJcblx0XHQvLyBSZW1vdmUgb3IgcmVwbGFjZSBwcm9ibGVtYXRpYyBjaGFyYWN0ZXJzIGZvciBmaWxlbmFtZXNcclxuXHRcdC5yZXBsYWNlKC9bPD46XCIvXFxcXHw/Kl0vZywgJycpIC8vIFJlbW92ZSBXaW5kb3dzL1VuaXggaW52YWxpZCBmaWxlbmFtZSBjaGFyYWN0ZXJzXHJcblx0XHQucmVwbGFjZSgvWydcIl0vZywgJycpIC8vIFJlbW92ZSBxdW90ZXNcclxuXHRcdC5yZXBsYWNlKC9bXlxcd1xccy1dL2csICcnKSAvLyBSZW1vdmUgb3RoZXIgc3BlY2lhbCBjaGFyYWN0ZXJzIGJ1dCBrZWVwIGxldHRlcnMsIG51bWJlcnMsIHNwYWNlcywgaHlwaGVuc1xyXG5cdFx0LnRyaW0oKVxyXG5cdFx0LnJlcGxhY2UoL1xccysvZywgJy0nKVxyXG5cdFx0LnJlcGxhY2UoLy0rL2csICctJylcclxuXHRcdC5yZXBsYWNlKC9eLXwtJC9nLCAnJyk7XHJcbn1cclxuIiwgIi8qKlxyXG4gKiBQcm9wZXJ0eSBIYW5kbGVyIFNlcnZpY2VcclxuICogSGFuZGxlcyBpbnNlcnRpbmcgaW1hZ2VzIGludG8gZnJvbnRtYXR0ZXIgcHJvcGVydGllcyAoTUQgYW5kIE1EWClcclxuICovXHJcblxyXG5pbXBvcnQgeyBBcHAsIFRGaWxlLCBOb3RpY2UgfSBmcm9tICdvYnNpZGlhbic7XHJcbmltcG9ydCB7IEltYWdlTWFuYWdlclNldHRpbmdzLCBQcm9wZXJ0eUxpbmtGb3JtYXQsIFJlbW90ZUltYWdlIH0gZnJvbSAnLi4vdHlwZXMnO1xyXG5pbXBvcnQgeyBpc01keEZpbGUsIHByb2Nlc3NNZHhGcm9udE1hdHRlciB9IGZyb20gJy4uL3V0aWxzL21keC1mcm9udG1hdHRlcic7XHJcbmltcG9ydCB7IFN0b3JhZ2VNYW5hZ2VyIH0gZnJvbSAnLi9TdG9yYWdlTWFuYWdlcic7XHJcbmltcG9ydCB7IEltYWdlUHJvY2Vzc29yIH0gZnJvbSAnLi9JbWFnZVByb2Nlc3Nvcic7XHJcbmltcG9ydCB0eXBlIHsgUmVtb3RlSW1hZ2VTZXJ2aWNlIH0gZnJvbSAnLi9SZW1vdGVJbWFnZVNlcnZpY2UnO1xyXG5cclxuZXhwb3J0IGNsYXNzIFByb3BlcnR5SGFuZGxlciB7XHJcblx0cHJpdmF0ZSBhcHA6IEFwcDtcclxuXHRwcml2YXRlIHNldHRpbmdzOiBJbWFnZU1hbmFnZXJTZXR0aW5ncztcclxuXHRwcml2YXRlIHN0b3JhZ2VNYW5hZ2VyOiBTdG9yYWdlTWFuYWdlcjtcclxuXHRwcml2YXRlIGltYWdlUHJvY2Vzc29yOiBJbWFnZVByb2Nlc3NvcjtcclxuXHRwcml2YXRlIHJlbW90ZVNlcnZpY2U/OiBSZW1vdGVJbWFnZVNlcnZpY2U7XHJcblxyXG5cdGNvbnN0cnVjdG9yKGFwcDogQXBwLCBzZXR0aW5nczogSW1hZ2VNYW5hZ2VyU2V0dGluZ3MsIHN0b3JhZ2VNYW5hZ2VyOiBTdG9yYWdlTWFuYWdlciwgaW1hZ2VQcm9jZXNzb3I6IEltYWdlUHJvY2Vzc29yLCByZW1vdGVTZXJ2aWNlPzogUmVtb3RlSW1hZ2VTZXJ2aWNlLCBvYnNlcnZhYmxlPzogeyBzdWJzY3JpYmUoZm46IChzZXR0aW5nczogSW1hZ2VNYW5hZ2VyU2V0dGluZ3MpID0+IHZvaWQpOiB2b2lkIH0pIHtcclxuXHRcdHRoaXMuYXBwID0gYXBwO1xyXG5cdFx0dGhpcy5zZXR0aW5ncyA9IHNldHRpbmdzO1xyXG5cdFx0dGhpcy5zdG9yYWdlTWFuYWdlciA9IHN0b3JhZ2VNYW5hZ2VyO1xyXG5cdFx0dGhpcy5pbWFnZVByb2Nlc3NvciA9IGltYWdlUHJvY2Vzc29yO1xyXG5cdFx0dGhpcy5yZW1vdGVTZXJ2aWNlID0gcmVtb3RlU2VydmljZTtcclxuXHJcblx0XHQvLyBTdWJzY3JpYmUgdG8gc2V0dGluZ3MgdXBkYXRlcyBpZiBvYnNlcnZhYmxlIGlzIHByb3ZpZGVkXHJcblx0XHRvYnNlcnZhYmxlPy5zdWJzY3JpYmUoKG5ld1NldHRpbmdzKSA9PiB7XHJcblx0XHRcdHRoaXMudXBkYXRlU2V0dGluZ3MobmV3U2V0dGluZ3MpO1xyXG5cdFx0fSk7XHJcblx0fVxyXG5cclxuXHQvKipcclxuXHQgKiBVcGRhdGUgc2V0dGluZ3MgcmVmZXJlbmNlXHJcblx0ICovXHJcblx0dXBkYXRlU2V0dGluZ3Moc2V0dGluZ3M6IEltYWdlTWFuYWdlclNldHRpbmdzKTogdm9pZCB7XHJcblx0XHR0aGlzLnNldHRpbmdzID0gc2V0dGluZ3M7XHJcblx0XHR0aGlzLmltYWdlUHJvY2Vzc29yPy51cGRhdGVTZXR0aW5ncyhzZXR0aW5ncyk7XHJcblx0fVxyXG5cclxuXHQvKipcclxuXHQgKiBTZXQgYW4gaW1hZ2UgcHJvcGVydHkgdmFsdWUgaW4gZnJvbnRtYXR0ZXJcclxuXHQgKi9cclxuXHRhc3luYyBzZXRQcm9wZXJ0eVZhbHVlKFxyXG5cdFx0bm90ZUZpbGU6IFRGaWxlLFxyXG5cdFx0cHJvcGVydHlOYW1lOiBzdHJpbmcsXHJcblx0XHRpbWFnZUZpbGU6IFRGaWxlLFxyXG5cdFx0YWx0VGV4dD86IHN0cmluZ1xyXG5cdCk6IFByb21pc2U8dm9pZD4ge1xyXG5cdFx0Y29uc3QgbGlua1ZhbHVlID0gdGhpcy5mb3JtYXRQcm9wZXJ0eUxpbmsoaW1hZ2VGaWxlLCBub3RlRmlsZSk7XHJcblxyXG5cdFx0dHJ5IHtcclxuXHRcdFx0aWYgKGlzTWR4RmlsZShub3RlRmlsZSkpIHtcclxuXHRcdFx0XHRhd2FpdCB0aGlzLnNldE1keFByb3BlcnR5KG5vdGVGaWxlLCBwcm9wZXJ0eU5hbWUsIGxpbmtWYWx1ZSwgYWx0VGV4dCk7XHJcblx0XHRcdH0gZWxzZSB7XHJcblx0XHRcdFx0YXdhaXQgdGhpcy5zZXRNZFByb3BlcnR5KG5vdGVGaWxlLCBwcm9wZXJ0eU5hbWUsIGxpbmtWYWx1ZSwgYWx0VGV4dCk7XHJcblx0XHRcdH1cclxuXHRcdFx0bmV3IE5vdGljZShgSW1hZ2UgYWRkZWQgdG8gcHJvcGVydHk6ICR7cHJvcGVydHlOYW1lfWApO1xyXG5cdFx0fSBjYXRjaCAoZXJyb3IpIHtcclxuXHRcdFx0Y29uc29sZS5lcnJvcignRmFpbGVkIHRvIHVwZGF0ZSBwcm9wZXJ0eTonLCBlcnJvcik7XHJcblx0XHRcdG5ldyBOb3RpY2UoYEZhaWxlZCB0byB1cGRhdGUgcHJvcGVydHk6ICR7ZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yLm1lc3NhZ2UgOiBTdHJpbmcoZXJyb3IpfWApO1xyXG5cdFx0XHR0aHJvdyBlcnJvcjtcclxuXHRcdH1cclxuXHR9XHJcblxyXG5cdC8qKlxyXG5cdCAqIFNldCBwcm9wZXJ0eSBpbiBNRCBmaWxlIHVzaW5nIE9ic2lkaWFuJ3MgQVBJXHJcblx0ICovXHJcblx0cHJpdmF0ZSBhc3luYyBzZXRNZFByb3BlcnR5KFxyXG5cdFx0ZmlsZTogVEZpbGUsXHJcblx0XHRwcm9wZXJ0eU5hbWU6IHN0cmluZyxcclxuXHRcdHZhbHVlOiBzdHJpbmcsXHJcblx0XHRhbHRUZXh0Pzogc3RyaW5nXHJcblx0KTogUHJvbWlzZTx2b2lkPiB7XHJcblx0XHRhd2FpdCB0aGlzLmFwcC5maWxlTWFuYWdlci5wcm9jZXNzRnJvbnRNYXR0ZXIoZmlsZSwgKGZyb250bWF0dGVyOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPikgPT4ge1xyXG5cdFx0XHRmcm9udG1hdHRlcltwcm9wZXJ0eU5hbWVdID0gdmFsdWU7XHJcblx0XHRcdGlmIChhbHRUZXh0ICYmIHRoaXMuc2V0dGluZ3MuYWx0VGV4dFByb3BlcnR5KSB7XHJcblx0XHRcdFx0ZnJvbnRtYXR0ZXJbdGhpcy5zZXR0aW5ncy5hbHRUZXh0UHJvcGVydHldID0gYWx0VGV4dDtcclxuXHRcdFx0fVxyXG5cdFx0fSk7XHJcblx0fVxyXG5cclxuXHQvKipcclxuXHQgKiBTZXQgcHJvcGVydHkgaW4gTURYIGZpbGUgdXNpbmcgY3VzdG9tIGhhbmRsZXJcclxuXHQgKi9cclxuXHRwcml2YXRlIGFzeW5jIHNldE1keFByb3BlcnR5KFxyXG5cdFx0ZmlsZTogVEZpbGUsXHJcblx0XHRwcm9wZXJ0eU5hbWU6IHN0cmluZyxcclxuXHRcdHZhbHVlOiBzdHJpbmcsXHJcblx0XHRhbHRUZXh0Pzogc3RyaW5nXHJcblx0KTogUHJvbWlzZTx2b2lkPiB7XHJcblx0XHRhd2FpdCBwcm9jZXNzTWR4RnJvbnRNYXR0ZXIodGhpcy5hcHAsIGZpbGUsIChmcm9udG1hdHRlcikgPT4ge1xyXG5cdFx0XHRmcm9udG1hdHRlcltwcm9wZXJ0eU5hbWVdID0gdmFsdWU7XHJcblx0XHRcdGlmIChhbHRUZXh0ICYmIHRoaXMuc2V0dGluZ3MuYWx0VGV4dFByb3BlcnR5KSB7XHJcblx0XHRcdFx0ZnJvbnRtYXR0ZXJbdGhpcy5zZXR0aW5ncy5hbHRUZXh0UHJvcGVydHldID0gYWx0VGV4dDtcclxuXHRcdFx0fVxyXG5cdFx0fSk7XHJcblx0fVxyXG5cclxuXHQvKipcclxuXHQgKiBGb3JtYXQgdGhlIGltYWdlIGxpbmsgYWNjb3JkaW5nIHRvIHNldHRpbmdzXHJcblx0ICogUHVibGljIG1ldGhvZCBzbyBQYXN0ZUhhbmRsZXIgY2FuIGdldCB0aGUgZm9ybWF0dGVkIHZhbHVlIGZvciBVSSB1cGRhdGVzXHJcblx0ICovXHJcblx0Zm9ybWF0UHJvcGVydHlMaW5rKGltYWdlRmlsZTogVEZpbGUsIG5vdGVGaWxlOiBURmlsZSk6IHN0cmluZyB7XHJcblx0XHQvLyBIYW5kbGUgT2JzaWRpYW5EZWZhdWx0IGZpcnN0IC0gdXNlIE9ic2lkaWFuJ3MgZ2VuZXJhdGVNYXJrZG93bkxpbmsgQVBJXHJcblx0XHRpZiAodGhpcy5zZXR0aW5ncy5wcm9wZXJ0eUxpbmtGb3JtYXQgPT09IFByb3BlcnR5TGlua0Zvcm1hdC5PYnNpZGlhbkRlZmF1bHQpIHtcclxuXHRcdFx0Ly8gVXNlIE9ic2lkaWFuJ3MgQVBJIHdoaWNoIHJlc3BlY3RzIHVzZU1hcmtkb3duTGlua3MsIG5ld0xpbmtGb3JtYXQsIGV0Yy5cclxuXHRcdFx0Y29uc3QgZ2VuZXJhdGVkTGluayA9IHRoaXMuYXBwLmZpbGVNYW5hZ2VyLmdlbmVyYXRlTWFya2Rvd25MaW5rKGltYWdlRmlsZSwgbm90ZUZpbGUucGF0aCk7XHJcblxyXG5cdFx0XHQvLyBFeHRyYWN0IHRoZSBsaW5rIHBhcnQgZm9yIHByb3BlcnRpZXNcclxuXHRcdFx0Ly8gT2JzaWRpYW4gbWF5IGdlbmVyYXRlOiAhW1twYXRoXV0gb3IgIVtdKHBhdGgpIG9yIFtbcGF0aF1dIG9yIFtdKHBhdGgpXHJcblx0XHRcdGlmIChnZW5lcmF0ZWRMaW5rLnN0YXJ0c1dpdGgoJyFbJykgJiYgZ2VuZXJhdGVkTGluay5pbmNsdWRlcygnXV0nKSkge1xyXG5cdFx0XHRcdC8vIFdpa2lsaW5rIHdpdGggZW1iZWQ6ICFbW3BhdGhdXSAtPiBbW3BhdGhdXVxyXG5cdFx0XHRcdHJldHVybiBnZW5lcmF0ZWRMaW5rLnN1YnN0cmluZygxKTtcclxuXHRcdFx0fSBlbHNlIGlmIChnZW5lcmF0ZWRMaW5rLnN0YXJ0c1dpdGgoJyFbJykgJiYgZ2VuZXJhdGVkTGluay5pbmNsdWRlcygnXSgnKSkge1xyXG5cdFx0XHRcdC8vIE1hcmtkb3duIGxpbmsgd2l0aCBlbWJlZDogIVtdKHBhdGgpIC0+IGV4dHJhY3QgcGF0aCBmcm9tIHBhcmVudGhlc2VzXHJcblx0XHRcdFx0Y29uc3QgbWF0Y2ggPSBnZW5lcmF0ZWRMaW5rLm1hdGNoKC8hXFxbLio/XFxdXFwoKC4qPylcXCkvKTtcclxuXHRcdFx0XHRyZXR1cm4gbWF0Y2ggJiYgbWF0Y2hbMV0gPyBtYXRjaFsxXSA6IGdlbmVyYXRlZExpbms7XHJcblx0XHRcdH0gZWxzZSBpZiAoZ2VuZXJhdGVkTGluay5zdGFydHNXaXRoKCdbWycpICYmIGdlbmVyYXRlZExpbmsuZW5kc1dpdGgoJ11dJykpIHtcclxuXHRcdFx0XHQvLyBXaWtpbGluayB3aXRob3V0IGVtYmVkOiBbW3BhdGhdXSAtPiBrZWVwIGFzIGlzXHJcblx0XHRcdFx0cmV0dXJuIGdlbmVyYXRlZExpbms7XHJcblx0XHRcdH0gZWxzZSBpZiAoZ2VuZXJhdGVkTGluay5pbmNsdWRlcygnXSgnKSkge1xyXG5cdFx0XHRcdC8vIE1hcmtkb3duIGxpbmsgd2l0aG91dCBlbWJlZDogW10ocGF0aCkgLT4gZXh0cmFjdCBwYXRoXHJcblx0XHRcdFx0Y29uc3QgbWF0Y2ggPSBnZW5lcmF0ZWRMaW5rLm1hdGNoKC9cXFsuKj9cXF1cXCgoLio/KVxcKS8pO1xyXG5cdFx0XHRcdHJldHVybiBtYXRjaCAmJiBtYXRjaFsxXSA/IG1hdGNoWzFdIDogZ2VuZXJhdGVkTGluaztcclxuXHRcdFx0fVxyXG5cdFx0XHQvLyBGYWxsYmFjazogcmV0dXJuIGFzLWlzXHJcblx0XHRcdHJldHVybiBnZW5lcmF0ZWRMaW5rO1xyXG5cdFx0fVxyXG5cclxuXHRcdGxldCBwYXRoVG9Vc2U6IHN0cmluZztcclxuXHJcblx0XHRzd2l0Y2ggKHRoaXMuc2V0dGluZ3MucHJvcGVydHlMaW5rRm9ybWF0KSB7XHJcblx0XHRcdGNhc2UgUHJvcGVydHlMaW5rRm9ybWF0LlJlbGF0aXZlUGF0aDpcclxuXHRcdFx0XHQvLyBVc2UgcmVsYXRpdmUgcGF0aDogYWx3YXlzIHVzZSAuL2ltYWdlLmpwZyBmb3JtYXQgZm9yIGNvbnNpc3RlbmN5XHJcblx0XHRcdFx0Ly8gVGhpcyB3b3JrcyB3aGV0aGVyIHNhbWUgZm9sZGVyIG9yIGRpZmZlcmVudCBmb2xkZXJcclxuXHRcdFx0XHRwYXRoVG9Vc2UgPSBgLi8ke2ltYWdlRmlsZS5uYW1lfWA7XHJcblx0XHRcdFx0YnJlYWs7XHJcblx0XHRcdGNhc2UgUHJvcGVydHlMaW5rRm9ybWF0LkN1c3RvbTpcclxuXHRcdFx0XHQvLyBGb3IgY3VzdG9tIGZvcm1hdCwgdXNlIGp1c3QgdGhlIGZpbGVuYW1lIHNvIHVzZXIgY2FuIGNvbnRyb2wgdGhlIGZ1bGwgcGF0aFxyXG5cdFx0XHRcdHBhdGhUb1VzZSA9IGltYWdlRmlsZS5uYW1lO1xyXG5cdFx0XHRcdGJyZWFrO1xyXG5cdFx0XHRjYXNlIFByb3BlcnR5TGlua0Zvcm1hdC5QYXRoOlxyXG5cdFx0XHRkZWZhdWx0OlxyXG5cdFx0XHRcdHBhdGhUb1VzZSA9IHRoaXMuZ2V0UmVsYXRpdmVQYXRoKG5vdGVGaWxlLCBpbWFnZUZpbGUpO1xyXG5cdFx0XHRcdGJyZWFrO1xyXG5cdFx0fVxyXG5cclxuXHRcdHN3aXRjaCAodGhpcy5zZXR0aW5ncy5wcm9wZXJ0eUxpbmtGb3JtYXQpIHtcclxuXHRcdFx0Y2FzZSBQcm9wZXJ0eUxpbmtGb3JtYXQuV2lraWxpbms6XHJcblx0XHRcdFx0cmV0dXJuIGBbWyR7cGF0aFRvVXNlfV1dYDtcclxuXHRcdFx0Y2FzZSBQcm9wZXJ0eUxpbmtGb3JtYXQuTWFya2Rvd246XHJcblx0XHRcdFx0cmV0dXJuIGAhW10oJHtlbmNvZGVVUkkocGF0aFRvVXNlKX0pYDtcclxuXHRcdFx0Y2FzZSBQcm9wZXJ0eUxpbmtGb3JtYXQuQ3VzdG9tOlxyXG5cdFx0XHRcdC8vIFJlcGxhY2Uge2ltYWdlLXVybH0gcGxhY2Vob2xkZXIgd2l0aCB0aGUgaW1hZ2UgZmlsZW5hbWVcclxuXHRcdFx0XHRyZXR1cm4gdGhpcy5zZXR0aW5ncy5jdXN0b21Qcm9wZXJ0eUxpbmtGb3JtYXQucmVwbGFjZShcclxuXHRcdFx0XHRcdC9cXHtpbWFnZS11cmxcXH0vZ2ksXHJcblx0XHRcdFx0XHRwYXRoVG9Vc2VcclxuXHRcdFx0XHQpO1xyXG5cdFx0XHRjYXNlIFByb3BlcnR5TGlua0Zvcm1hdC5SZWxhdGl2ZVBhdGg6XHJcblx0XHRcdGNhc2UgUHJvcGVydHlMaW5rRm9ybWF0LlBhdGg6XHJcblx0XHRcdGRlZmF1bHQ6XHJcblx0XHRcdFx0cmV0dXJuIHBhdGhUb1VzZTtcclxuXHRcdH1cclxuXHR9XHJcblxyXG5cdC8qKlxyXG5cdCAqIEdldCByZWxhdGl2ZSBwYXRoIGZyb20gbm90ZSB0byBpbWFnZVxyXG5cdCAqL1xyXG5cdHByaXZhdGUgZ2V0UmVsYXRpdmVQYXRoKGZyb21GaWxlOiBURmlsZSwgdG9GaWxlOiBURmlsZSk6IHN0cmluZyB7XHJcblx0XHQvLyBJZiB1c2luZyB3aWtpbGlua3MsIHdlIGNhbiB1c2UganVzdCB0aGUgZmlsZSBuYW1lXHJcblx0XHQvLyBBY2Nlc3MgT2JzaWRpYW4ncyBpbnRlcm5hbCBjb25maWcgKG5vdCBpbiBwdWJsaWMgQVBJIHR5cGVzIGJ1dCBhY2Nlc3NpYmxlIGF0IHJ1bnRpbWUpXHJcblx0XHRjb25zdCB2YXVsdENvbmZpZyA9ICh0aGlzLmFwcC52YXVsdCBhcyB1bmtub3duIGFzIHsgY29uZmlnPzogeyB1c2VNYXJrZG93bkxpbmtzPzogYm9vbGVhbiB9IH0pLmNvbmZpZztcclxuXHRcdGNvbnN0IHVzZU1hcmtkb3duTGlua3MgPSB2YXVsdENvbmZpZz8udXNlTWFya2Rvd25MaW5rcyA/PyBmYWxzZTtcclxuXHRcdGNvbnN0IHVzZVdpa2lsaW5rcyA9ICF1c2VNYXJrZG93bkxpbmtzO1xyXG5cclxuXHRcdGlmICh1c2VXaWtpbGlua3MgJiYgdGhpcy5zZXR0aW5ncy5wcm9wZXJ0eUxpbmtGb3JtYXQgPT09IFByb3BlcnR5TGlua0Zvcm1hdC5XaWtpbGluaykge1xyXG5cdFx0XHQvLyBGb3Igd2lraWxpbmtzLCBqdXN0IHVzZSB0aGUgZmlsZSBuYW1lXHJcblx0XHRcdHJldHVybiB0b0ZpbGUubmFtZTtcclxuXHRcdH1cclxuXHJcblx0XHQvLyBGb3IgbWFya2Rvd24gbGlua3MgYW5kIHBhdGhzLCB1c2UgcmVsYXRpdmUgcGF0aFxyXG5cdFx0cmV0dXJuIHRoaXMuc3RvcmFnZU1hbmFnZXIuZ2V0UmVsYXRpdmVQYXRoKGZyb21GaWxlLCB0b0ZpbGUpO1xyXG5cdH1cclxuXHJcblx0LyoqXHJcblx0ICogR2V0IHRoZSBjdXJyZW50IHZhbHVlIG9mIGEgcHJvcGVydHlcclxuXHQgKi9cclxuXHRnZXRQcm9wZXJ0eVZhbHVlKFxyXG5cdFx0ZmlsZTogVEZpbGUsXHJcblx0XHRwcm9wZXJ0eU5hbWU6IHN0cmluZ1xyXG5cdCk6IHVua25vd24ge1xyXG5cdFx0Y29uc3QgY2FjaGUgPSB0aGlzLmFwcC5tZXRhZGF0YUNhY2hlLmdldEZpbGVDYWNoZShmaWxlKTtcclxuXHRcdHJldHVybiBjYWNoZT8uZnJvbnRtYXR0ZXI/Lltwcm9wZXJ0eU5hbWVdO1xyXG5cdH1cclxuXHJcblx0LyoqXHJcblx0ICogQ2hlY2sgaWYgYSBwcm9wZXJ0eSBleGlzdHMgaW4gZnJvbnRtYXR0ZXJcclxuXHQgKi9cclxuXHRoYXNQcm9wZXJ0eShmaWxlOiBURmlsZSwgcHJvcGVydHlOYW1lOiBzdHJpbmcpOiBib29sZWFuIHtcclxuXHRcdGNvbnN0IGNhY2hlID0gdGhpcy5hcHAubWV0YWRhdGFDYWNoZS5nZXRGaWxlQ2FjaGUoZmlsZSk7XHJcblx0XHRyZXR1cm4gY2FjaGU/LmZyb250bWF0dGVyPy5bcHJvcGVydHlOYW1lXSAhPT0gdW5kZWZpbmVkO1xyXG5cdH1cclxuXHJcblx0LyoqXHJcblx0ICogSW5zZXJ0IGFuIGltYWdlIGZyb20gYSBVUkwgaW50byBhIHByb3BlcnR5XHJcblx0ICogRG93bmxvYWRzIHRoZSBpbWFnZSwgc2F2ZXMgaXQgbG9jYWxseSwgYW5kIHNldHMgdGhlIHByb3BlcnR5XHJcblx0ICogQHBhcmFtIHJlbW90ZUltYWdlIE9wdGlvbmFsIFJlbW90ZUltYWdlIG9iamVjdCBmb3IgZ2VuZXJhdGluZyByZWZlcnJhbCB0ZXh0XHJcblx0ICogQHBhcmFtIHN1Z2dlc3RlZE5hbWVPdmVycmlkZSBPcHRpb25hbCBvdmVycmlkZSBmb3Igc3VnZ2VzdGVkIG5hbWUgKGUuZy4sIGZyb20gc2VhcmNoIHRlcm0pXHJcblx0ICovXHJcblx0YXN5bmMgaW5zZXJ0SW1hZ2VGcm9tVXJsKFxyXG5cdFx0aW1hZ2VVcmw6IHN0cmluZyxcclxuXHRcdG5vdGVGaWxlOiBURmlsZSxcclxuXHRcdHByb3BlcnR5TmFtZTogc3RyaW5nLFxyXG5cdFx0cmVtb3RlSW1hZ2U/OiBSZW1vdGVJbWFnZSxcclxuXHRcdHN1Z2dlc3RlZE5hbWVPdmVycmlkZT86IHN0cmluZ1xyXG5cdCk6IFByb21pc2U8dm9pZD4ge1xyXG5cdFx0Ly8gVXNlIEltYWdlUHJvY2Vzc29yIHRvIGhhbmRsZSB0aGUgZG93bmxvYWQgYW5kIHNhdmVcclxuXHRcdC8vIFRoaXMgZW5zdXJlcyBjb25zaXN0ZW50IG5hbWluZywgZGVkdXBsaWNhdGlvbiwgYW5kIHJlbmFtZSBtb2RhbCBoYW5kbGluZ1xyXG5cdFx0Ly8gU2tpcCBkZXNjcmlwdGl2ZSBpbWFnZXMgZm9yIHByb3BlcnR5IGluc2VydGlvbnMgKGRpc3BsYXkgdGV4dCBkb2Vzbid0IGFwcGx5IHRvIHByb3BlcnRpZXMpXHJcblx0XHRjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLmltYWdlUHJvY2Vzc29yLnByb2Nlc3NJbWFnZVVybChcclxuXHRcdFx0aW1hZ2VVcmwsXHJcblx0XHRcdG5vdGVGaWxlLFxyXG5cdFx0XHR0cnVlLCAvLyBTaG93IHJlbmFtZSBtb2RhbCBpZiBlbmFibGVkXHJcblx0XHRcdHRydWUsIC8vIGlzUHJvcGVydHlJbnNlcnRpb24gLSBza2lwIGRlc2NyaXB0aXZlIGltYWdlc1xyXG5cdFx0XHRzdWdnZXN0ZWROYW1lT3ZlcnJpZGUgLy8gUGFzcyBzZWFyY2ggdGVybSBhcyBzdWdnZXN0ZWQgbmFtZVxyXG5cdFx0KTtcclxuXHJcblx0XHRpZiAoIXJlc3VsdC5zdWNjZXNzIHx8ICFyZXN1bHQuZmlsZSkge1xyXG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IocmVzdWx0LmVycm9yIHx8ICdGYWlsZWQgdG8gcHJvY2VzcyBpbWFnZScpO1xyXG5cdFx0fVxyXG5cclxuXHRcdC8vIFNldCB0aGUgcHJvcGVydHlcclxuXHRcdGF3YWl0IHRoaXMuc2V0UHJvcGVydHlWYWx1ZShub3RlRmlsZSwgcHJvcGVydHlOYW1lLCByZXN1bHQuZmlsZSwgcmVzdWx0LmRlc2NyaXB0aW9uKTtcclxuXHJcblx0XHQvLyBBcHBlbmQgcmVmZXJyYWwgdGV4dCBhdCBlbmQgb2YgZmlsZSBpZiBlbmFibGVkIGFuZCB3ZSBoYXZlIFJlbW90ZUltYWdlIGluZm9cclxuXHRcdGlmICh0aGlzLnNldHRpbmdzLmFwcGVuZFJlZmVycmFsICYmIHJlbW90ZUltYWdlICYmIHRoaXMucmVtb3RlU2VydmljZSkge1xyXG5cdFx0XHRjb25zdCByZWZlcnJhbFRleHQgPSB0aGlzLnJlbW90ZVNlcnZpY2UuZ2VuZXJhdGVSZWZlcnJhbFRleHQocmVtb3RlSW1hZ2UpO1xyXG5cdFx0XHRpZiAocmVmZXJyYWxUZXh0KSB7XHJcblx0XHRcdFx0Y29uc3QgY29udGVudCA9IGF3YWl0IHRoaXMuYXBwLnZhdWx0LnJlYWQobm90ZUZpbGUpO1xyXG5cdFx0XHRcdGNvbnN0IHVwZGF0ZWRDb250ZW50ID0gY29udGVudCArIHJlZmVycmFsVGV4dDtcclxuXHRcdFx0XHRhd2FpdCB0aGlzLmFwcC52YXVsdC5tb2RpZnkobm90ZUZpbGUsIHVwZGF0ZWRDb250ZW50KTtcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cdH1cclxufVxyXG4iLCAiLyoqXHJcbiAqIE1EWCBGcm9udG1hdHRlciBVdGlsaXRpZXNcclxuICogTWFudWFsIGZyb250bWF0dGVyIHBhcnNpbmcgYW5kIG1vZGlmaWNhdGlvbiBmb3IgTURYIGZpbGVzXHJcbiAqIE9ic2lkaWFuJ3MgbWV0YWRhdGFDYWNoZSBhbmQgcHJvY2Vzc0Zyb250TWF0dGVyIG9ubHkgd29yayBmb3IgLm1kIGZpbGVzXHJcbiAqL1xyXG5cclxuaW1wb3J0IHsgQXBwLCBURmlsZSwgcGFyc2VZYW1sLCBzdHJpbmdpZnlZYW1sIH0gZnJvbSAnb2JzaWRpYW4nO1xyXG5cclxuLyoqXHJcbiAqIENoZWNrIGlmIGEgZmlsZSBpcyBhbiBNRFggZmlsZVxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGlzTWR4RmlsZShmaWxlOiBURmlsZSk6IGJvb2xlYW4ge1xyXG5cdHJldHVybiBmaWxlLmV4dGVuc2lvbiA9PT0gJ21keCc7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBDaGVjayBpZiBhIGZpbGUgaXMgYSBtYXJrZG93biBmaWxlIChNRCBvciBNRFgpXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gaXNNYXJrZG93bkZpbGUoZmlsZTogVEZpbGUpOiBib29sZWFuIHtcclxuXHRyZXR1cm4gZmlsZS5leHRlbnNpb24gPT09ICdtZCcgfHwgZmlsZS5leHRlbnNpb24gPT09ICdtZHgnO1xyXG59XHJcblxyXG4vKipcclxuICogUGFyc2UgZnJvbnRtYXR0ZXIgZnJvbSByYXcgZmlsZSBjb250ZW50XHJcbiAqIFJldHVybnMgdGhlIGZyb250bWF0dGVyIG9iamVjdCBhbmQgdGhlIGJvZHkgY29udGVudCBzZXBhcmF0ZWx5XHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VNZHhGcm9udG1hdHRlcihcclxuXHRjb250ZW50OiBzdHJpbmdcclxuKTogeyBmcm9udG1hdHRlcjogUmVjb3JkPHN0cmluZywgdW5rbm93bj47IGJvZHk6IHN0cmluZyB9IHwgbnVsbCB7XHJcblx0Y29uc3QgZnJvbnRtYXR0ZXJSZWdleCA9IC9eLS0tXFxyP1xcbihbXFxzXFxTXSo/KVxccj9cXG4tLS1cXHI/XFxuLztcclxuXHRjb25zdCBtYXRjaCA9IGNvbnRlbnQubWF0Y2goZnJvbnRtYXR0ZXJSZWdleCk7XHJcblxyXG5cdGlmICghbWF0Y2gpIHtcclxuXHRcdC8vIE5vIGZyb250bWF0dGVyIGZvdW5kXHJcblx0XHRyZXR1cm4ge1xyXG5cdFx0XHRmcm9udG1hdHRlcjoge30sXHJcblx0XHRcdGJvZHk6IGNvbnRlbnQsXHJcblx0XHR9O1xyXG5cdH1cclxuXHJcblx0Y29uc3QgZnJvbnRtYXR0ZXJUZXh0ID0gbWF0Y2hbMV0gPz8gJyc7XHJcblx0Y29uc3QgYm9keUNvbnRlbnQgPSBjb250ZW50LnNsaWNlKG1hdGNoWzBdLmxlbmd0aCk7XHJcblxyXG5cdHRyeSB7XHJcblx0XHRjb25zdCBwYXJzZWQgPSBwYXJzZVlhbWwoZnJvbnRtYXR0ZXJUZXh0KSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB8IG51bGwgfCB1bmRlZmluZWQ7XHJcblx0XHRjb25zdCBmcm9udG1hdHRlciA9IHBhcnNlZCAmJiB0eXBlb2YgcGFyc2VkID09PSAnb2JqZWN0JyA/IHBhcnNlZCA6IHt9O1xyXG5cdFx0cmV0dXJuIHtcclxuXHRcdFx0ZnJvbnRtYXR0ZXIsXHJcblx0XHRcdGJvZHk6IGJvZHlDb250ZW50LFxyXG5cdFx0fTtcclxuXHR9IGNhdGNoIChlKSB7XHJcblx0XHRjb25zb2xlLmVycm9yKCdFcnJvciBwYXJzaW5nIE1EWCBwcm9wZXJ0aWVzOicsIGUpO1xyXG5cdFx0Ly8gUmV0dXJuIGVtcHR5IGZyb250bWF0dGVyIGJ1dCBwcmVzZXJ2ZSBib2R5XHJcblx0XHRyZXR1cm4ge1xyXG5cdFx0XHRmcm9udG1hdHRlcjoge30sXHJcblx0XHRcdGJvZHk6IGJvZHlDb250ZW50LFxyXG5cdFx0fTtcclxuXHR9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBSZWFkIGFuZCBwYXJzZSBmcm9udG1hdHRlciBmcm9tIGFuIE1EWCBmaWxlXHJcbiAqL1xyXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVhZE1keEZyb250bWF0dGVyKFxyXG5cdGFwcDogQXBwLFxyXG5cdGZpbGU6IFRGaWxlXHJcbik6IFByb21pc2U8UmVjb3JkPHN0cmluZywgdW5rbm93bj4gfCBudWxsPiB7XHJcblx0aWYgKCFpc01keEZpbGUoZmlsZSkpIHtcclxuXHRcdHJldHVybiBudWxsO1xyXG5cdH1cclxuXHJcblx0dHJ5IHtcclxuXHRcdGNvbnN0IGNvbnRlbnQgPSBhd2FpdCBhcHAudmF1bHQucmVhZChmaWxlKTtcclxuXHRcdGNvbnN0IHBhcnNlZCA9IHBhcnNlTWR4RnJvbnRtYXR0ZXIoY29udGVudCk7XHJcblx0XHRyZXR1cm4gcGFyc2VkID8gcGFyc2VkLmZyb250bWF0dGVyIDogbnVsbDtcclxuXHR9IGNhdGNoIChlKSB7XHJcblx0XHRjb25zb2xlLmVycm9yKGBFcnJvciByZWFkaW5nIE1EWCBwcm9wZXJ0aWVzIGZyb20gJHtmaWxlLnBhdGh9OmAsIGUpO1xyXG5cdFx0cmV0dXJuIG51bGw7XHJcblx0fVxyXG59XHJcblxyXG4vKipcclxuICogV3JpdGUgdXBkYXRlZCBmcm9udG1hdHRlciB0byBhbiBNRFggZmlsZVxyXG4gKi9cclxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHdyaXRlTWR4RnJvbnRtYXR0ZXIoXHJcblx0YXBwOiBBcHAsXHJcblx0ZmlsZTogVEZpbGUsXHJcblx0ZnJvbnRtYXR0ZXI6IFJlY29yZDxzdHJpbmcsIHVua25vd24+XHJcbik6IFByb21pc2U8dm9pZD4ge1xyXG5cdGlmICghaXNNZHhGaWxlKGZpbGUpKSB7XHJcblx0XHR0aHJvdyBuZXcgRXJyb3IoYEZpbGUgJHtmaWxlLnBhdGh9IGlzIG5vdCBhbiBNRFggZmlsZWApO1xyXG5cdH1cclxuXHJcblx0dHJ5IHtcclxuXHRcdGNvbnN0IGNvbnRlbnQgPSBhd2FpdCBhcHAudmF1bHQucmVhZChmaWxlKTtcclxuXHRcdGNvbnN0IHBhcnNlZCA9IHBhcnNlTWR4RnJvbnRtYXR0ZXIoY29udGVudCk7XHJcblxyXG5cdFx0aWYgKCFwYXJzZWQpIHtcclxuXHRcdFx0dGhyb3cgbmV3IEVycm9yKCdGYWlsZWQgdG8gcGFyc2UgZXhpc3RpbmcgZnJvbnRtYXR0ZXInKTtcclxuXHRcdH1cclxuXHJcblx0XHQvLyBTdHJpbmdpZnkgdGhlIHVwZGF0ZWQgZnJvbnRtYXR0ZXJcclxuXHRcdGNvbnN0IG5ld0Zyb250bWF0dGVyVGV4dCA9IHN0cmluZ2lmeVlhbWwoZnJvbnRtYXR0ZXIpLnRyaW0oKTtcclxuXHJcblx0XHQvLyBSZWNvbnN0cnVjdCBmaWxlIGNvbnRlbnRcclxuXHRcdGNvbnN0IG5ld0NvbnRlbnQgPSBgLS0tXFxuJHtuZXdGcm9udG1hdHRlclRleHR9XFxuLS0tXFxuJHtwYXJzZWQuYm9keX1gO1xyXG5cclxuXHRcdC8vIFdyaXRlIGJhY2sgdG8gZmlsZVxyXG5cdFx0YXdhaXQgYXBwLnZhdWx0Lm1vZGlmeShmaWxlLCBuZXdDb250ZW50KTtcclxuXHR9IGNhdGNoIChlKSB7XHJcblx0XHRjb25zb2xlLmVycm9yKGBFcnJvciB3cml0aW5nIE1EWCBwcm9wZXJ0aWVzIHRvICR7ZmlsZS5wYXRofTpgLCBlKTtcclxuXHRcdHRocm93IGU7XHJcblx0fVxyXG59XHJcblxyXG4vKipcclxuICogUHJvY2VzcyBmcm9udG1hdHRlciBmb3IgYW4gTURYIGZpbGUgKHNpbWlsYXIgQVBJIHRvIHByb2Nlc3NGcm9udE1hdHRlcilcclxuICogVGhlIGNhbGxiYWNrIHJlY2VpdmVzIHRoZSBmcm9udG1hdHRlciBvYmplY3QgYW5kIGNhbiBtb2RpZnkgaXRcclxuICovXHJcbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBwcm9jZXNzTWR4RnJvbnRNYXR0ZXIoXHJcblx0YXBwOiBBcHAsXHJcblx0ZmlsZTogVEZpbGUsXHJcblx0Y2FsbGJhY2s6IChmcm9udG1hdHRlcjogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pID0+IHZvaWRcclxuKTogUHJvbWlzZTx2b2lkPiB7XHJcblx0aWYgKCFpc01keEZpbGUoZmlsZSkpIHtcclxuXHRcdHRocm93IG5ldyBFcnJvcihgRmlsZSAke2ZpbGUucGF0aH0gaXMgbm90IGFuIE1EWCBmaWxlYCk7XHJcblx0fVxyXG5cclxuXHR0cnkge1xyXG5cdFx0Y29uc3QgY29udGVudCA9IGF3YWl0IGFwcC52YXVsdC5yZWFkKGZpbGUpO1xyXG5cdFx0Y29uc3QgcGFyc2VkID0gcGFyc2VNZHhGcm9udG1hdHRlcihjb250ZW50KTtcclxuXHJcblx0XHRpZiAoIXBhcnNlZCkge1xyXG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ0ZhaWxlZCB0byBwYXJzZSBleGlzdGluZyBmcm9udG1hdHRlcicpO1xyXG5cdFx0fVxyXG5cclxuXHRcdC8vIENyZWF0ZSBhIGNvcHkgb2YgdGhlIGZyb250bWF0dGVyIGZvciB0aGUgY2FsbGJhY2sgdG8gbW9kaWZ5XHJcblx0XHRjb25zdCBmcm9udG1hdHRlciA9IHsgLi4ucGFyc2VkLmZyb250bWF0dGVyIH07XHJcblxyXG5cdFx0Ly8gQ2FsbCB0aGUgY2FsbGJhY2sgdG8gbW9kaWZ5IGZyb250bWF0dGVyXHJcblx0XHRjYWxsYmFjayhmcm9udG1hdHRlcik7XHJcblxyXG5cdFx0Ly8gU3RyaW5naWZ5IHRoZSB1cGRhdGVkIGZyb250bWF0dGVyXHJcblx0XHRjb25zdCBuZXdGcm9udG1hdHRlclRleHQgPSBzdHJpbmdpZnlZYW1sKGZyb250bWF0dGVyKS50cmltKCk7XHJcblxyXG5cdFx0Ly8gUmVjb25zdHJ1Y3QgZmlsZSBjb250ZW50XHJcblx0XHRjb25zdCBuZXdDb250ZW50ID0gYC0tLVxcbiR7bmV3RnJvbnRtYXR0ZXJUZXh0fVxcbi0tLVxcbiR7cGFyc2VkLmJvZHl9YDtcclxuXHJcblx0XHQvLyBXcml0ZSBiYWNrIHRvIGZpbGVcclxuXHRcdGF3YWl0IGFwcC52YXVsdC5tb2RpZnkoZmlsZSwgbmV3Q29udGVudCk7XHJcblx0fSBjYXRjaCAoZSkge1xyXG5cdFx0Y29uc29sZS5lcnJvcihgRXJyb3IgcHJvY2Vzc2luZyBNRFggcHJvcGVydGllcyBmb3IgJHtmaWxlLnBhdGh9OmAsIGUpO1xyXG5cdFx0dGhyb3cgZTtcclxuXHR9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBHZXQgZnJvbnRtYXR0ZXIgZnJvbSBhbnkgbWFya2Rvd24gZmlsZSAoTUQgb3IgTURYKVxyXG4gKiBVc2VzIE9ic2lkaWFuJ3MgbWV0YWRhdGFDYWNoZSBmb3IgTUQgZmlsZXMsIG1hbnVhbCBwYXJzaW5nIGZvciBNRFhcclxuICovXHJcbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXRGcm9udG1hdHRlcihcclxuXHRhcHA6IEFwcCxcclxuXHRmaWxlOiBURmlsZVxyXG4pOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIHVua25vd24+IHwgbnVsbD4ge1xyXG5cdGlmIChpc01keEZpbGUoZmlsZSkpIHtcclxuXHRcdHJldHVybiBhd2FpdCByZWFkTWR4RnJvbnRtYXR0ZXIoYXBwLCBmaWxlKTtcclxuXHR9XHJcblx0XHJcblx0Ly8gRm9yIE1EIGZpbGVzLCB1c2UgT2JzaWRpYW4ncyBtZXRhZGF0YSBjYWNoZVxyXG5cdGNvbnN0IGNhY2hlID0gYXBwLm1ldGFkYXRhQ2FjaGUuZ2V0RmlsZUNhY2hlKGZpbGUpO1xyXG5cdHJldHVybiBjYWNoZT8uZnJvbnRtYXR0ZXIgPz8gbnVsbDtcclxufVxyXG5cclxuLyoqXHJcbiAqIFByb2Nlc3MgZnJvbnRtYXR0ZXIgZm9yIGFueSBtYXJrZG93biBmaWxlIChNRCBvciBNRFgpXHJcbiAqIFVzZXMgT2JzaWRpYW4ncyBwcm9jZXNzRnJvbnRNYXR0ZXIgZm9yIE1EIGZpbGVzLCBjdXN0b20gaGFuZGxpbmcgZm9yIE1EWFxyXG4gKi9cclxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHByb2Nlc3NGcm9udG1hdHRlcihcclxuXHRhcHA6IEFwcCxcclxuXHRmaWxlOiBURmlsZSxcclxuXHRjYWxsYmFjazogKGZyb250bWF0dGVyOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPikgPT4gdm9pZFxyXG4pOiBQcm9taXNlPHZvaWQ+IHtcclxuXHRpZiAoaXNNZHhGaWxlKGZpbGUpKSB7XHJcblx0XHRhd2FpdCBwcm9jZXNzTWR4RnJvbnRNYXR0ZXIoYXBwLCBmaWxlLCBjYWxsYmFjayk7XHJcblx0fSBlbHNlIHtcclxuXHRcdGF3YWl0IGFwcC5maWxlTWFuYWdlci5wcm9jZXNzRnJvbnRNYXR0ZXIoZmlsZSwgY2FsbGJhY2spO1xyXG5cdH1cclxufVxyXG4iLCAiLyoqXHJcbiAqIFBhc3RlIEhhbmRsZXIgU2VydmljZVxyXG4gKiBIYW5kbGVzIHBhc3RlIGV2ZW50cyBmb3IgaW1hZ2VzIGluIHRoZSBlZGl0b3IgYW5kIGZyb250bWF0dGVyIHByb3BlcnRpZXNcclxuICovXHJcblxyXG5pbXBvcnQgeyBBcHAsIE1hcmtkb3duVmlldywgTm90aWNlLCBFZGl0b3IgfSBmcm9tICdvYnNpZGlhbic7XHJcbmltcG9ydCB7IEltYWdlTWFuYWdlclNldHRpbmdzIH0gZnJvbSAnLi4vdHlwZXMnO1xyXG5pbXBvcnQgeyBJbWFnZVByb2Nlc3NvciB9IGZyb20gJy4vSW1hZ2VQcm9jZXNzb3InO1xyXG5pbXBvcnQgeyBQcm9wZXJ0eUhhbmRsZXIgfSBmcm9tICcuL1Byb3BlcnR5SGFuZGxlcic7XHJcblxyXG5leHBvcnQgY2xhc3MgUGFzdGVIYW5kbGVyIHtcclxuXHRwcml2YXRlIGFwcDogQXBwO1xyXG5cdHByaXZhdGUgc2V0dGluZ3M6IEltYWdlTWFuYWdlclNldHRpbmdzO1xyXG5cdHByaXZhdGUgaW1hZ2VQcm9jZXNzb3I6IEltYWdlUHJvY2Vzc29yO1xyXG5cdHByaXZhdGUgcHJvcGVydHlIYW5kbGVyOiBQcm9wZXJ0eUhhbmRsZXI7XHJcblxyXG5cdGNvbnN0cnVjdG9yKFxyXG5cdFx0YXBwOiBBcHAsXHJcblx0XHRzZXR0aW5nczogSW1hZ2VNYW5hZ2VyU2V0dGluZ3MsXHJcblx0XHRpbWFnZVByb2Nlc3NvcjogSW1hZ2VQcm9jZXNzb3IsXHJcblx0XHRwcm9wZXJ0eUhhbmRsZXI6IFByb3BlcnR5SGFuZGxlcixcclxuXHRcdG9ic2VydmFibGU/OiB7IHN1YnNjcmliZShmbjogKHNldHRpbmdzOiBJbWFnZU1hbmFnZXJTZXR0aW5ncykgPT4gdm9pZCk6IHZvaWQgfVxyXG5cdCkge1xyXG5cdFx0dGhpcy5hcHAgPSBhcHA7XHJcblx0XHR0aGlzLnNldHRpbmdzID0gc2V0dGluZ3M7XHJcblx0XHR0aGlzLmltYWdlUHJvY2Vzc29yID0gaW1hZ2VQcm9jZXNzb3I7XHJcblx0XHR0aGlzLnByb3BlcnR5SGFuZGxlciA9IHByb3BlcnR5SGFuZGxlcjtcclxuXHJcblx0XHQvLyBTdWJzY3JpYmUgdG8gc2V0dGluZ3MgdXBkYXRlcyBpZiBvYnNlcnZhYmxlIGlzIHByb3ZpZGVkXHJcblx0XHRvYnNlcnZhYmxlPy5zdWJzY3JpYmUoKG5ld1NldHRpbmdzKSA9PiB7XHJcblx0XHRcdHRoaXMudXBkYXRlU2V0dGluZ3MobmV3U2V0dGluZ3MpO1xyXG5cdFx0fSk7XHJcblx0fVxyXG5cclxuXHQvKipcclxuXHQgKiBVcGRhdGUgc2V0dGluZ3MgcmVmZXJlbmNlXHJcblx0ICovXHJcblx0dXBkYXRlU2V0dGluZ3Moc2V0dGluZ3M6IEltYWdlTWFuYWdlclNldHRpbmdzKTogdm9pZCB7XHJcblx0XHR0aGlzLnNldHRpbmdzID0gc2V0dGluZ3M7XHJcblx0fVxyXG5cclxuXHQvKipcclxuXHQgKiBIYW5kbGUgZWRpdG9yIHBhc3RlIGV2ZW50XHJcblx0ICogVGhpcyBpcyByZWdpc3RlcmVkIHZpYSB3b3Jrc3BhY2Uub24oJ2VkaXRvci1wYXN0ZScpXHJcblx0ICovXHJcblx0YXN5bmMgaGFuZGxlRWRpdG9yUGFzdGUoXHJcblx0XHRldnQ6IENsaXBib2FyZEV2ZW50LFxyXG5cdFx0ZWRpdG9yOiBFZGl0b3IsXHJcblx0XHR2aWV3OiBNYXJrZG93blZpZXdcclxuXHQpOiBQcm9taXNlPGJvb2xlYW4+IHtcclxuXHRcdGlmICghdGhpcy5zZXR0aW5ncy5zaG93UmVuYW1lRGlhbG9nIHx8ICF0aGlzLnNldHRpbmdzLmVuYWJsZVJlbmFtZU9uUGFzdGUpIHtcclxuXHRcdFx0cmV0dXJuIGZhbHNlOyAvLyBMZXQgT2JzaWRpYW4gaGFuZGxlIGl0XHJcblx0XHR9XHJcblxyXG5cdFx0Ly8gQ2hlY2sgaWYgd2UncmUgaW4gYSBmcm9udG1hdHRlciBwcm9wZXJ0eSBmaWVsZCAtIGlmIHNvLCBsZXQgcHJvcGVydHkgcGFzdGUgaGFuZGxlciB0YWtlIG92ZXJcclxuXHRcdGNvbnN0IGFjdGl2ZUVsID0gZG9jdW1lbnQuYWN0aXZlRWxlbWVudCBhcyBIVE1MRWxlbWVudDtcclxuXHRcdGlmIChhY3RpdmVFbCAmJiB0aGlzLmlzRnJvbnRtYXR0ZXJGaWVsZChhY3RpdmVFbCkpIHtcclxuXHRcdFx0cmV0dXJuIGZhbHNlOyAvLyBMZXQgcHJvcGVydHkgcGFzdGUgaGFuZGxlciBoYW5kbGUgaXRcclxuXHRcdH1cclxuXHJcblx0XHRjb25zdCBmaWxlcyA9IGV2dC5jbGlwYm9hcmREYXRhPy5maWxlcztcclxuXHRcdGlmICghZmlsZXMgfHwgZmlsZXMubGVuZ3RoID09PSAwKSB7XHJcblx0XHRcdHJldHVybiBmYWxzZTsgLy8gTm8gZmlsZXMsIGxldCBPYnNpZGlhbiBoYW5kbGUgaXRcclxuXHRcdH1cclxuXHJcblx0XHQvLyBDaGVjayBpZiBhbnkgb2YgdGhlIGZpbGVzIGFyZSBpbWFnZXNcclxuXHRcdGNvbnN0IGltYWdlRmlsZXM6IEZpbGVbXSA9IFtdO1xyXG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBmaWxlcy5sZW5ndGg7IGkrKykge1xyXG5cdFx0XHRjb25zdCBmaWxlID0gZmlsZXMuaXRlbShpKTtcclxuXHRcdFx0aWYgKGZpbGUgJiYgZmlsZS50eXBlLnN0YXJ0c1dpdGgoJ2ltYWdlLycpKSB7XHJcblx0XHRcdFx0aW1hZ2VGaWxlcy5wdXNoKGZpbGUpO1xyXG5cdFx0XHR9XHJcblx0XHR9XHJcblxyXG5cdFx0aWYgKGltYWdlRmlsZXMubGVuZ3RoID09PSAwKSB7XHJcblx0XHRcdHJldHVybiBmYWxzZTsgLy8gTm8gaW1hZ2VzLCBsZXQgT2JzaWRpYW4gaGFuZGxlIGl0XHJcblx0XHR9XHJcblxyXG5cdFx0Ly8gV2UncmUgaGFuZGxpbmcgdGhpcyAtIHByZXZlbnQgZGVmYXVsdFxyXG5cdFx0ZXZ0LnByZXZlbnREZWZhdWx0KCk7XHJcblxyXG5cdFx0Y29uc3QgYWN0aXZlRmlsZSA9IHZpZXcuZmlsZTtcclxuXHRcdGlmICghYWN0aXZlRmlsZSkge1xyXG5cdFx0XHRuZXcgTm90aWNlKCdObyBhY3RpdmUgZmlsZScpO1xyXG5cdFx0XHRyZXR1cm4gdHJ1ZTtcclxuXHRcdH1cclxuXHJcblx0XHQvLyBQcm9jZXNzIGVhY2ggaW1hZ2VcclxuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgaW1hZ2VGaWxlcy5sZW5ndGg7IGkrKykge1xyXG5cdFx0XHRjb25zdCBpbWFnZUZpbGUgPSBpbWFnZUZpbGVzW2ldO1xyXG5cdFx0XHRpZiAoIWltYWdlRmlsZSkgY29udGludWU7XHJcblxyXG5cdFx0XHRjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLmltYWdlUHJvY2Vzc29yLnByb2Nlc3NJbWFnZUZpbGUoXHJcblx0XHRcdFx0aW1hZ2VGaWxlLFxyXG5cdFx0XHRcdGFjdGl2ZUZpbGUsXHJcblx0XHRcdFx0dHJ1ZSAvLyBTaG93IHJlbmFtZSBtb2RhbFxyXG5cdFx0XHQpO1xyXG5cclxuXHRcdFx0aWYgKHJlc3VsdC5zdWNjZXNzICYmIHJlc3VsdC5saW5rVGV4dCkge1xyXG5cdFx0XHRcdC8vIEluc2VydCB0aGUgbGluayBhdCBjdXJzb3JcclxuXHRcdFx0XHRlZGl0b3IucmVwbGFjZVNlbGVjdGlvbihyZXN1bHQubGlua1RleHQpO1xyXG5cdFx0XHR9XHJcblx0XHR9XHJcblxyXG5cdFx0cmV0dXJuIHRydWU7XHJcblx0fVxyXG5cclxuXHQvKipcclxuXHQgKiBIYW5kbGUgcGFzdGUgaW50byBmcm9udG1hdHRlciBwcm9wZXJ0eVxyXG5cdCAqIFRoaXMgaXMgcmVnaXN0ZXJlZCB2aWEgZG9jdW1lbnQgcGFzdGUgZXZlbnQgd2l0aCBwcm9wZXJ0eSBkZXRlY3Rpb25cclxuXHQgKi9cclxuXHRhc3luYyBoYW5kbGVQcm9wZXJ0eVBhc3RlKGV2dDogQ2xpcGJvYXJkRXZlbnQpOiBQcm9taXNlPGJvb2xlYW4+IHtcclxuXHRcdGlmICghdGhpcy5zZXR0aW5ncy5zaG93UmVuYW1lRGlhbG9nIHx8ICF0aGlzLnNldHRpbmdzLmVuYWJsZVByb3BlcnR5UGFzdGUpIHtcclxuXHRcdFx0cmV0dXJuIGZhbHNlO1xyXG5cdFx0fVxyXG5cclxuXHRcdGNvbnN0IGFjdGl2ZUVsID0gZG9jdW1lbnQuYWN0aXZlRWxlbWVudCBhcyBIVE1MRWxlbWVudDtcclxuXHRcdGlmICghYWN0aXZlRWwpIHtcclxuXHRcdFx0cmV0dXJuIGZhbHNlO1xyXG5cdFx0fVxyXG5cclxuXHRcdC8vIENoZWNrIGlmIHdlJ3JlIGluIGEgZnJvbnRtYXR0ZXIgcHJvcGVydHkgZmllbGRcclxuXHRcdGlmICghdGhpcy5pc0Zyb250bWF0dGVyRmllbGQoYWN0aXZlRWwpKSB7XHJcblx0XHRcdHJldHVybiBmYWxzZTtcclxuXHRcdH1cclxuXHJcblx0XHQvLyBEZWJ1ZzogTG9nIHRoYXQgd2UgZGV0ZWN0ZWQgYSBwcm9wZXJ0eSBmaWVsZFxyXG5cdFx0aWYgKHRoaXMuc2V0dGluZ3MuZGVidWdNb2RlKSB7XHJcblx0XHRcdGNvbnNvbGUuZGVidWcoJ1tJbWFnZSBNYW5hZ2VyXSBQcm9wZXJ0eSBwYXN0ZSBkZXRlY3RlZCcsIHtcclxuXHRcdFx0XHRhY3RpdmVFbGVtZW50OiBhY3RpdmVFbC50YWdOYW1lLFxyXG5cdFx0XHRcdGNsYXNzZXM6IGFjdGl2ZUVsLmNsYXNzTmFtZSxcclxuXHRcdFx0XHRwcm9wZXJ0eU5hbWU6IHRoaXMuZ2V0UHJvcGVydHlOYW1lKGFjdGl2ZUVsKVxyXG5cdFx0XHR9KTtcclxuXHRcdH1cclxuXHJcblx0XHRjb25zdCBmaWxlcyA9IGV2dC5jbGlwYm9hcmREYXRhPy5maWxlcztcclxuXHRcdGlmICghZmlsZXMgfHwgZmlsZXMubGVuZ3RoID09PSAwKSB7XHJcblx0XHRcdHJldHVybiBmYWxzZTtcclxuXHRcdH1cclxuXHJcblx0XHQvLyBDaGVjayBmb3IgaW1hZ2UgZmlsZXNcclxuXHRcdGxldCBpbWFnZUZpbGU6IEZpbGUgfCBudWxsID0gbnVsbDtcclxuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgZmlsZXMubGVuZ3RoOyBpKyspIHtcclxuXHRcdFx0Y29uc3QgZiA9IGZpbGVzLml0ZW0oaSk7XHJcblx0XHRcdGlmIChmICYmIGYudHlwZS5zdGFydHNXaXRoKCdpbWFnZS8nKSkge1xyXG5cdFx0XHRcdGltYWdlRmlsZSA9IGY7XHJcblx0XHRcdFx0YnJlYWs7XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHJcblx0XHRpZiAoIWltYWdlRmlsZSkge1xyXG5cdFx0XHRyZXR1cm4gZmFsc2U7XHJcblx0XHR9XHJcblxyXG5cdFx0Ly8gRG91YmxlLWNoZWNrIHdlJ3JlIHN0aWxsIGluIGEgcHJvcGVydHkgZmllbGQgKGVsZW1lbnQgbWlnaHQgaGF2ZSBjaGFuZ2VkKVxyXG5cdFx0Ly8gYW5kIHRoYXQgd2UgaGF2ZSBhbiBhY3RpdmUgZmlsZSBiZWZvcmUgcHJldmVudGluZyBkZWZhdWx0XHJcblx0XHRjb25zdCBjdXJyZW50RWwgPSBkb2N1bWVudC5hY3RpdmVFbGVtZW50IGFzIEhUTUxFbGVtZW50O1xyXG5cdFx0aWYgKCFjdXJyZW50RWwgfHwgIXRoaXMuaXNGcm9udG1hdHRlckZpZWxkKGN1cnJlbnRFbCkpIHtcclxuXHRcdFx0cmV0dXJuIGZhbHNlO1xyXG5cdFx0fVxyXG5cclxuXHRcdGNvbnN0IGFjdGl2ZUZpbGUgPSB0aGlzLmFwcC53b3Jrc3BhY2UuZ2V0QWN0aXZlRmlsZSgpO1xyXG5cdFx0aWYgKCFhY3RpdmVGaWxlKSB7XHJcblx0XHRcdHJldHVybiBmYWxzZTtcclxuXHRcdH1cclxuXHJcblx0XHQvLyBXZSdyZSBoYW5kbGluZyB0aGlzIC0gc3RvcCBhbGwgcHJvcGFnYXRpb25cclxuXHRcdGV2dC5wcmV2ZW50RGVmYXVsdCgpO1xyXG5cdFx0ZXZ0LnN0b3BQcm9wYWdhdGlvbigpO1xyXG5cdFx0ZXZ0LnN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbigpO1xyXG5cclxuXHRcdC8vIEdldCB0aGUgcHJvcGVydHkgbmFtZSBiZWZvcmUgcHJvY2Vzc2luZ1xyXG5cdFx0Y29uc3QgcHJvcGVydHlOYW1lID0gdGhpcy5nZXRQcm9wZXJ0eU5hbWUoY3VycmVudEVsKTtcclxuXHRcdGlmICghcHJvcGVydHlOYW1lKSB7XHJcblx0XHRcdG5ldyBOb3RpY2UoJ0NvdWxkIG5vdCBkZXRlcm1pbmUgcHJvcGVydHkgbmFtZScpO1xyXG5cdFx0XHRyZXR1cm4gdHJ1ZTtcclxuXHRcdH1cclxuXHJcblx0XHQvLyBQcm9jZXNzIHRoZSBpbWFnZSAtIHNob3cgcmVuYW1lIG1vZGFsIGZvciBwcm9wZXJ0eSBwYXN0ZVxyXG5cdFx0Ly8gU2tpcCBkZXNjcmlwdGl2ZSBpbWFnZXMgZm9yIHByb3BlcnR5IGluc2VydGlvbnMgKGRpc3BsYXkgdGV4dCBkb2Vzbid0IGFwcGx5IHRvIHByb3BlcnRpZXMpXHJcblx0XHRjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLmltYWdlUHJvY2Vzc29yLnByb2Nlc3NJbWFnZUZpbGUoXHJcblx0XHRcdGltYWdlRmlsZSxcclxuXHRcdFx0YWN0aXZlRmlsZSxcclxuXHRcdFx0dHJ1ZSwgLy8gU2hvdyByZW5hbWUgbW9kYWwgZm9yIHByb3BlcnR5IHBhc3RlXHJcblx0XHRcdHRydWUgLy8gaXNQcm9wZXJ0eUluc2VydGlvbiAtIHNraXAgZGVzY3JpcHRpdmUgaW1hZ2VzXHJcblx0XHQpO1xyXG5cclxuXHRcdGlmIChyZXN1bHQuc3VjY2VzcyAmJiByZXN1bHQuZmlsZSkge1xyXG5cdFx0XHQvLyBHZXQgdGhlIGZvcm1hdHRlZCBsaW5rIHZhbHVlXHJcblx0XHRcdGNvbnN0IGxpbmtWYWx1ZSA9IHRoaXMucHJvcGVydHlIYW5kbGVyLmZvcm1hdFByb3BlcnR5TGluayhyZXN1bHQuZmlsZSwgYWN0aXZlRmlsZSk7XHJcblxyXG5cdFx0XHQvLyBVcGRhdGUgdGhlIGZyb250bWF0dGVyIHByb3BlcnR5IGRpcmVjdGx5XHJcblx0XHRcdGF3YWl0IHRoaXMucHJvcGVydHlIYW5kbGVyLnNldFByb3BlcnR5VmFsdWUoXHJcblx0XHRcdFx0YWN0aXZlRmlsZSxcclxuXHRcdFx0XHRwcm9wZXJ0eU5hbWUsXHJcblx0XHRcdFx0cmVzdWx0LmZpbGUsXHJcblx0XHRcdFx0cmVzdWx0LmRlc2NyaXB0aW9uXHJcblx0XHRcdCk7XHJcblxyXG5cdFx0XHQvLyBXYWl0IGZvciBPYnNpZGlhbiB0byBwcm9jZXNzIHRoZSBmaWxlIGNoYW5nZSBhbmQgdXBkYXRlIG1ldGFkYXRhIGNhY2hlXHJcblx0XHRcdGF3YWl0IG5ldyBQcm9taXNlKHJlc29sdmUgPT4gc2V0VGltZW91dChyZXNvbHZlLCAzMDApKTtcclxuXHJcblx0XHRcdC8vIFRyeSBtdWx0aXBsZSBhcHByb2FjaGVzIHRvIHVwZGF0ZSB0aGUgVUlcclxuXHRcdFx0Ly8gQXBwcm9hY2ggMTogRmluZCBhbmQgdXBkYXRlIHRoZSBpbnB1dCBmaWVsZCBkaXJlY3RseVxyXG5cdFx0XHRjb25zdCBwcm9wZXJ0eUVsID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihcclxuXHRcdFx0XHRgLm1ldGFkYXRhLXByb3BlcnR5W2RhdGEtcHJvcGVydHkta2V5PVwiJHtwcm9wZXJ0eU5hbWV9XCJdYFxyXG5cdFx0XHQpO1xyXG5cclxuXHRcdFx0aWYgKHRoaXMuc2V0dGluZ3MuZGVidWdNb2RlKSB7XHJcblx0XHRcdFx0Y29uc29sZS5kZWJ1ZygnW0ltYWdlIE1hbmFnZXJdIFVwZGF0aW5nIHByb3BlcnR5IFVJJywge1xyXG5cdFx0XHRcdFx0cHJvcGVydHlOYW1lLFxyXG5cdFx0XHRcdFx0bGlua1ZhbHVlLFxyXG5cdFx0XHRcdFx0cHJvcGVydHlFbEZvdW5kOiAhIXByb3BlcnR5RWxcclxuXHRcdFx0XHR9KTtcclxuXHRcdFx0fVxyXG5cclxuXHRcdFx0Y29uc3QgaW5wdXRFbCA9IHByb3BlcnR5RWw/LnF1ZXJ5U2VsZWN0b3IoXHJcblx0XHRcdFx0Jy5tZXRhZGF0YS1pbnB1dC1sb25ndGV4dCwgLm1ldGFkYXRhLWlucHV0LXRleHQsIGlucHV0Lm1ldGFkYXRhLWlucHV0LCB0ZXh0YXJlYS5tZXRhZGF0YS1pbnB1dCdcclxuXHRcdFx0KSBhcyBIVE1MRWxlbWVudCB8IEhUTUxJbnB1dEVsZW1lbnQgfCBIVE1MVGV4dEFyZWFFbGVtZW50IHwgbnVsbDtcclxuXHJcblx0XHRcdGlmIChpbnB1dEVsKSB7XHJcblx0XHRcdFx0aWYgKHRoaXMuc2V0dGluZ3MuZGVidWdNb2RlKSB7XHJcblx0XHRcdFx0XHRjb25zdCBjdXJyZW50VmFsdWUgPSBpbnB1dEVsIGluc3RhbmNlb2YgSFRNTElucHV0RWxlbWVudCB8fCBpbnB1dEVsIGluc3RhbmNlb2YgSFRNTFRleHRBcmVhRWxlbWVudFxyXG5cdFx0XHRcdFx0XHQ/IGlucHV0RWwudmFsdWVcclxuXHRcdFx0XHRcdFx0OiBpbnB1dEVsLnRleHRDb250ZW50IHx8IGlucHV0RWwuaW5uZXJUZXh0O1xyXG5cdFx0XHRcdFx0Y29uc29sZS5kZWJ1ZygnW0ltYWdlIE1hbmFnZXJdIEZvdW5kIGlucHV0IGZpZWxkLCB1cGRhdGluZyB2YWx1ZScsIHtcclxuXHRcdFx0XHRcdFx0ZWxlbWVudFR5cGU6IGlucHV0RWwudGFnTmFtZSxcclxuXHRcdFx0XHRcdFx0Y3VycmVudFZhbHVlLFxyXG5cdFx0XHRcdFx0XHRuZXdWYWx1ZTogbGlua1ZhbHVlXHJcblx0XHRcdFx0XHR9KTtcclxuXHRcdFx0XHR9XHJcblxyXG5cdFx0XHRcdC8vIEhhbmRsZSBib3RoIGlucHV0L3RleHRhcmVhIGVsZW1lbnRzIGFuZCBjb250ZW50ZWRpdGFibGUgZGl2c1xyXG5cdFx0XHRcdGlmIChpbnB1dEVsIGluc3RhbmNlb2YgSFRNTElucHV0RWxlbWVudCB8fCBpbnB1dEVsIGluc3RhbmNlb2YgSFRNTFRleHRBcmVhRWxlbWVudCkge1xyXG5cdFx0XHRcdFx0Ly8gU3RhbmRhcmQgaW5wdXQvdGV4dGFyZWFcclxuXHRcdFx0XHRcdGlucHV0RWwudmFsdWUgPSBsaW5rVmFsdWU7XHJcblx0XHRcdFx0fSBlbHNlIHtcclxuXHRcdFx0XHRcdC8vIENvbnRlbnRlZGl0YWJsZSBkaXYgKHVzZWQgZm9yIGxvbmd0ZXh0IHByb3BlcnRpZXMpXHJcblx0XHRcdFx0XHRpbnB1dEVsLnRleHRDb250ZW50ID0gbGlua1ZhbHVlO1xyXG5cdFx0XHRcdFx0aW5wdXRFbC5pbm5lclRleHQgPSBsaW5rVmFsdWU7XHJcblx0XHRcdFx0fVxyXG5cclxuXHRcdFx0XHQvLyBUcmlnZ2VyIG11bHRpcGxlIGV2ZW50cyB0byBlbnN1cmUgT2JzaWRpYW4gcmVjb2duaXplcyB0aGUgY2hhbmdlXHJcblx0XHRcdFx0Y29uc3QgaW5wdXRFdmVudCA9IG5ldyBFdmVudCgnaW5wdXQnLCB7IGJ1YmJsZXM6IHRydWUsIGNhbmNlbGFibGU6IHRydWUgfSk7XHJcblx0XHRcdFx0Y29uc3QgY2hhbmdlRXZlbnQgPSBuZXcgRXZlbnQoJ2NoYW5nZScsIHsgYnViYmxlczogdHJ1ZSwgY2FuY2VsYWJsZTogdHJ1ZSB9KTtcclxuXHRcdFx0XHRjb25zdCBibHVyRXZlbnQgPSBuZXcgRXZlbnQoJ2JsdXInLCB7IGJ1YmJsZXM6IHRydWUsIGNhbmNlbGFibGU6IHRydWUgfSk7XHJcblxyXG5cdFx0XHRcdGlucHV0RWwuZGlzcGF0Y2hFdmVudChpbnB1dEV2ZW50KTtcclxuXHJcblx0XHRcdFx0Ly8gU21hbGwgZGVsYXkgYmVmb3JlIGNoYW5nZSBldmVudFxyXG5cdFx0XHRcdHNldFRpbWVvdXQoKCkgPT4ge1xyXG5cdFx0XHRcdFx0aW5wdXRFbC5kaXNwYXRjaEV2ZW50KGNoYW5nZUV2ZW50KTtcclxuXHJcblx0XHRcdFx0XHQvLyBGb2N1cyBhbmQgYmx1ciB0byB0cmlnZ2VyIE9ic2lkaWFuJ3MgdXBkYXRlIG1lY2hhbmlzbVxyXG5cdFx0XHRcdFx0aWYgKGlucHV0RWwgaW5zdGFuY2VvZiBIVE1MRWxlbWVudCkge1xyXG5cdFx0XHRcdFx0XHRpbnB1dEVsLmZvY3VzKCk7XHJcblx0XHRcdFx0XHRcdHNldFRpbWVvdXQoKCkgPT4ge1xyXG5cdFx0XHRcdFx0XHRcdGlucHV0RWwuYmx1cigpO1xyXG5cdFx0XHRcdFx0XHRcdGlucHV0RWwuZGlzcGF0Y2hFdmVudChibHVyRXZlbnQpO1xyXG5cclxuXHRcdFx0XHRcdFx0XHQvLyBGb2N1cyB0aGUgZWRpdG9yIHRvIGNvbXBsZXRlIHRoZSBhY3Rpb25cclxuXHRcdFx0XHRcdFx0XHRzZXRUaW1lb3V0KCgpID0+IHtcclxuXHRcdFx0XHRcdFx0XHRcdGNvbnN0IHZpZXcgPSB0aGlzLmFwcC53b3Jrc3BhY2UuZ2V0QWN0aXZlVmlld09mVHlwZShNYXJrZG93blZpZXcpO1xyXG5cdFx0XHRcdFx0XHRcdFx0aWYgKHZpZXc/LmVkaXRvcikge1xyXG5cdFx0XHRcdFx0XHRcdFx0XHR2aWV3LmVkaXRvci5mb2N1cygpO1xyXG5cdFx0XHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHRcdH0sIDUwKTtcclxuXHRcdFx0XHRcdFx0fSwgNTApO1xyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdH0sIDUwKTtcclxuXHRcdFx0fSBlbHNlIHtcclxuXHRcdFx0XHQvLyBJZiB3ZSBjYW4ndCBmaW5kIHRoZSBpbnB1dCwganVzdCBmb2N1cyB0aGUgZWRpdG9yXHJcblx0XHRcdFx0Y29uc3QgdmlldyA9IHRoaXMuYXBwLndvcmtzcGFjZS5nZXRBY3RpdmVWaWV3T2ZUeXBlKE1hcmtkb3duVmlldyk7XHJcblx0XHRcdFx0aWYgKHZpZXc/LmVkaXRvcikge1xyXG5cdFx0XHRcdFx0dmlldy5lZGl0b3IuZm9jdXMoKTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHJcblx0XHRyZXR1cm4gdHJ1ZTtcclxuXHR9XHJcblxyXG5cdC8qKlxyXG5cdCAqIENoZWNrIGlmIGFuIGVsZW1lbnQgaXMgYSBzdXBwb3J0ZWQgZnJvbnRtYXR0ZXIgZmllbGRcclxuXHQgKiBXb3JrcyBmb3IgYm90aCBNRCBhbmQgTURYIGZpbGVzXHJcblx0ICovXHJcblx0cHJpdmF0ZSBpc0Zyb250bWF0dGVyRmllbGQoZWxlbWVudDogSFRNTEVsZW1lbnQpOiBib29sZWFuIHtcclxuXHRcdC8vIENoZWNrIGlmIGVsZW1lbnQgaXMgaW5zaWRlIGEgbWV0YWRhdGEgcHJvcGVydHkgY29udGFpbmVyXHJcblx0XHRjb25zdCBwcm9wZXJ0eUVsID0gZWxlbWVudC5jbG9zZXN0KCcubWV0YWRhdGEtcHJvcGVydHknKTtcclxuXHRcdGlmICghcHJvcGVydHlFbCkge1xyXG5cdFx0XHRyZXR1cm4gZmFsc2U7XHJcblx0XHR9XHJcblxyXG5cdFx0Ly8gQ2hlY2sgZm9yIHZhcmlvdXMgcHJvcGVydHkgaW5wdXQgdHlwZXMgdGhhdCBjYW4gYWNjZXB0IHRleHQvaW1hZ2VzXHJcblx0XHQvLyBPYnNpZGlhbiB1c2VzIGRpZmZlcmVudCBjbGFzc2VzIGZvciBkaWZmZXJlbnQgcHJvcGVydHkgdHlwZXNcclxuXHRcdC8vIExvbmd0ZXh0IHByb3BlcnRpZXMgdXNlIGNvbnRlbnRlZGl0YWJsZSBkaXZzLCBub3QgaW5wdXQvdGV4dGFyZWFcclxuXHRcdHJldHVybiAoXHJcblx0XHRcdGVsZW1lbnQubWF0Y2hlcygnLm1ldGFkYXRhLWlucHV0LWxvbmd0ZXh0JykgfHxcclxuXHRcdFx0ZWxlbWVudC5tYXRjaGVzKCcubWV0YWRhdGEtaW5wdXQtdGV4dCcpIHx8XHJcblx0XHRcdGVsZW1lbnQubWF0Y2hlcygnaW5wdXQubWV0YWRhdGEtaW5wdXQnKSB8fFxyXG5cdFx0XHRlbGVtZW50Lm1hdGNoZXMoJ3RleHRhcmVhLm1ldGFkYXRhLWlucHV0JykgfHxcclxuXHRcdFx0Ly8gQWxzbyBjaGVjayBpZiB0aGUgZWxlbWVudCBpdHNlbGYgaXMgYW4gaW5wdXQvdGV4dGFyZWEvZGl2IGluc2lkZSBhIHByb3BlcnR5XHJcblx0XHRcdCgoZWxlbWVudCBpbnN0YW5jZW9mIEhUTUxJbnB1dEVsZW1lbnQgfHxcclxuXHRcdFx0XHRlbGVtZW50IGluc3RhbmNlb2YgSFRNTFRleHRBcmVhRWxlbWVudCB8fFxyXG5cdFx0XHRcdChlbGVtZW50IGluc3RhbmNlb2YgSFRNTERpdkVsZW1lbnQgJiYgZWxlbWVudC5jbGFzc0xpc3QuY29udGFpbnMoJ21ldGFkYXRhLWlucHV0LWxvbmd0ZXh0JykpKSAmJlxyXG5cdFx0XHRcdHByb3BlcnR5RWwgIT09IG51bGwpXHJcblx0XHQpO1xyXG5cdH1cclxuXHJcblx0LyoqXHJcblx0ICogR2V0IHRoZSBwcm9wZXJ0eSBuYW1lIGZyb20gYSBmcm9udG1hdHRlciBmaWVsZCBlbGVtZW50XHJcblx0ICovXHJcblx0cHJpdmF0ZSBnZXRQcm9wZXJ0eU5hbWUoZWxlbWVudDogSFRNTEVsZW1lbnQpOiBzdHJpbmcgfCBudWxsIHtcclxuXHRcdGNvbnN0IHByb3BlcnR5RWwgPSBlbGVtZW50LmNsb3Nlc3QoJy5tZXRhZGF0YS1wcm9wZXJ0eScpO1xyXG5cdFx0cmV0dXJuIHByb3BlcnR5RWw/LmdldEF0dHJpYnV0ZSgnZGF0YS1wcm9wZXJ0eS1rZXknKSA/PyBudWxsO1xyXG5cdH1cclxufVxyXG5cclxuZXhwb3J0IGNsYXNzIERyb3BIYW5kbGVyIHtcclxuXHRwcml2YXRlIGFwcDogQXBwO1xyXG5cdHByaXZhdGUgc2V0dGluZ3M6IEltYWdlTWFuYWdlclNldHRpbmdzO1xyXG5cdHByaXZhdGUgaW1hZ2VQcm9jZXNzb3I6IEltYWdlUHJvY2Vzc29yO1xyXG5cclxuXHRjb25zdHJ1Y3RvcihcclxuXHRcdGFwcDogQXBwLFxyXG5cdFx0c2V0dGluZ3M6IEltYWdlTWFuYWdlclNldHRpbmdzLFxyXG5cdFx0aW1hZ2VQcm9jZXNzb3I6IEltYWdlUHJvY2Vzc29yLFxyXG5cdFx0b2JzZXJ2YWJsZT86IHsgc3Vic2NyaWJlKGZuOiAoc2V0dGluZ3M6IEltYWdlTWFuYWdlclNldHRpbmdzKSA9PiB2b2lkKTogdm9pZCB9XHJcblx0KSB7XHJcblx0XHR0aGlzLmFwcCA9IGFwcDtcclxuXHRcdHRoaXMuc2V0dGluZ3MgPSBzZXR0aW5ncztcclxuXHRcdHRoaXMuaW1hZ2VQcm9jZXNzb3IgPSBpbWFnZVByb2Nlc3NvcjtcclxuXHJcblx0XHQvLyBTdWJzY3JpYmUgdG8gc2V0dGluZ3MgdXBkYXRlcyBpZiBvYnNlcnZhYmxlIGlzIHByb3ZpZGVkXHJcblx0XHRvYnNlcnZhYmxlPy5zdWJzY3JpYmUoKG5ld1NldHRpbmdzKSA9PiB7XHJcblx0XHRcdHRoaXMudXBkYXRlU2V0dGluZ3MobmV3U2V0dGluZ3MpO1xyXG5cdFx0fSk7XHJcblx0fVxyXG5cclxuXHQvKipcclxuXHQgKiBVcGRhdGUgc2V0dGluZ3MgcmVmZXJlbmNlXHJcblx0ICovXHJcblx0dXBkYXRlU2V0dGluZ3Moc2V0dGluZ3M6IEltYWdlTWFuYWdlclNldHRpbmdzKTogdm9pZCB7XHJcblx0XHR0aGlzLnNldHRpbmdzID0gc2V0dGluZ3M7XHJcblx0fVxyXG5cclxuXHQvKipcclxuXHQgKiBIYW5kbGUgZWRpdG9yIGRyb3AgZXZlbnRcclxuXHQgKi9cclxuXHRhc3luYyBoYW5kbGVFZGl0b3JEcm9wKFxyXG5cdFx0ZXZ0OiBEcmFnRXZlbnQsXHJcblx0XHRlZGl0b3I6IEVkaXRvcixcclxuXHRcdHZpZXc6IE1hcmtkb3duVmlld1xyXG5cdCk6IFByb21pc2U8Ym9vbGVhbj4ge1xyXG5cdFx0aWYgKCF0aGlzLnNldHRpbmdzLnNob3dSZW5hbWVEaWFsb2cgfHwgIXRoaXMuc2V0dGluZ3MuZW5hYmxlUmVuYW1lT25Ecm9wKSB7XHJcblx0XHRcdHJldHVybiBmYWxzZTtcclxuXHRcdH1cclxuXHJcblx0XHRjb25zdCBmaWxlcyA9IGV2dC5kYXRhVHJhbnNmZXI/LmZpbGVzO1xyXG5cdFx0aWYgKCFmaWxlcyB8fCBmaWxlcy5sZW5ndGggPT09IDApIHtcclxuXHRcdFx0cmV0dXJuIGZhbHNlO1xyXG5cdFx0fVxyXG5cclxuXHRcdC8vIENoZWNrIGZvciBpbWFnZSBmaWxlc1xyXG5cdFx0Y29uc3QgaW1hZ2VGaWxlczogRmlsZVtdID0gW107XHJcblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IGZpbGVzLmxlbmd0aDsgaSsrKSB7XHJcblx0XHRcdGNvbnN0IGYgPSBmaWxlcy5pdGVtKGkpO1xyXG5cdFx0XHRpZiAoZiAmJiBmLnR5cGUuc3RhcnRzV2l0aCgnaW1hZ2UvJykpIHtcclxuXHRcdFx0XHRpbWFnZUZpbGVzLnB1c2goZik7XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHJcblx0XHRpZiAoaW1hZ2VGaWxlcy5sZW5ndGggPT09IDApIHtcclxuXHRcdFx0cmV0dXJuIGZhbHNlO1xyXG5cdFx0fVxyXG5cclxuXHRcdC8vIFdlJ3JlIGhhbmRsaW5nIHRoaXNcclxuXHRcdGV2dC5wcmV2ZW50RGVmYXVsdCgpO1xyXG5cclxuXHRcdGNvbnN0IGFjdGl2ZUZpbGUgPSB2aWV3LmZpbGU7XHJcblx0XHRpZiAoIWFjdGl2ZUZpbGUpIHtcclxuXHRcdFx0bmV3IE5vdGljZSgnTm8gYWN0aXZlIGZpbGUnKTtcclxuXHRcdFx0cmV0dXJuIHRydWU7XHJcblx0XHR9XHJcblxyXG5cdFx0Ly8gUHJvY2VzcyBlYWNoIGltYWdlXHJcblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IGltYWdlRmlsZXMubGVuZ3RoOyBpKyspIHtcclxuXHRcdFx0Y29uc3QgaW1hZ2VGaWxlID0gaW1hZ2VGaWxlc1tpXTtcclxuXHRcdFx0aWYgKCFpbWFnZUZpbGUpIGNvbnRpbnVlO1xyXG5cclxuXHRcdFx0Y29uc3QgcmVzdWx0ID0gYXdhaXQgdGhpcy5pbWFnZVByb2Nlc3Nvci5wcm9jZXNzSW1hZ2VGaWxlKFxyXG5cdFx0XHRcdGltYWdlRmlsZSxcclxuXHRcdFx0XHRhY3RpdmVGaWxlLFxyXG5cdFx0XHRcdHRydWVcclxuXHRcdFx0KTtcclxuXHJcblx0XHRcdGlmIChyZXN1bHQuc3VjY2VzcyAmJiByZXN1bHQubGlua1RleHQpIHtcclxuXHRcdFx0XHRlZGl0b3IucmVwbGFjZVNlbGVjdGlvbihyZXN1bHQubGlua1RleHQpO1xyXG5cdFx0XHR9XHJcblx0XHR9XHJcblxyXG5cdFx0cmV0dXJuIHRydWU7XHJcblx0fVxyXG59XHJcbiIsICIvKipcclxuICogUmVtb3RlIEltYWdlIFNlcnZpY2VcclxuICogQVBJIGludGVncmF0aW9ucyBmb3IgVW5zcGxhc2gsIFBleGVscywgYW5kIFBpeGFiYXlcclxuICovXHJcblxyXG5pbXBvcnQgeyBBcHAsIHJlcXVlc3RVcmwsIHJlcXVpcmVBcGlWZXJzaW9uIH0gZnJvbSAnb2JzaWRpYW4nO1xyXG5pbXBvcnQgeyBJbWFnZU1hbmFnZXJTZXR0aW5ncywgSW1hZ2VQcm92aWRlciwgSW1hZ2VPcmllbnRhdGlvbiwgUmVtb3RlSW1hZ2UsIEltYWdlU2l6ZSB9IGZyb20gJy4uL3R5cGVzJztcclxuXHJcbi8vIFVuc3BsYXNoIHByb3h5IFVSTCAoYnVpbHQtaW4gZmFsbGJhY2spIC0gbWF0Y2hlcyBJbWFnZSBNYW5hZ2VyIHBhdHRlcm5cclxuY29uc3QgVU5TUExBU0hfUFJPWFkgPSAnaHR0cHM6Ly9pbnNlcnQtdW5zcGxhc2gtaW1hZ2UuY2xvdWR5OTEwMS5jb20vJztcclxuXHJcbmV4cG9ydCBjbGFzcyBSZW1vdGVJbWFnZVNlcnZpY2Uge1xyXG5cdHByaXZhdGUgc2V0dGluZ3M6IEltYWdlTWFuYWdlclNldHRpbmdzO1xyXG5cdHByaXZhdGUgYXBwOiBBcHA7XHJcblxyXG5cdGNvbnN0cnVjdG9yKGFwcDogQXBwLCBzZXR0aW5nczogSW1hZ2VNYW5hZ2VyU2V0dGluZ3MsIG9ic2VydmFibGU/OiB7IHN1YnNjcmliZShmbjogKHNldHRpbmdzOiBJbWFnZU1hbmFnZXJTZXR0aW5ncykgPT4gdm9pZCk6IHZvaWQgfSkge1xyXG5cdFx0dGhpcy5hcHAgPSBhcHA7XHJcblx0XHR0aGlzLnNldHRpbmdzID0gc2V0dGluZ3M7XHJcblxyXG5cdFx0Ly8gU3Vic2NyaWJlIHRvIHNldHRpbmdzIHVwZGF0ZXMgaWYgb2JzZXJ2YWJsZSBpcyBwcm92aWRlZFxyXG5cdFx0b2JzZXJ2YWJsZT8uc3Vic2NyaWJlKChuZXdTZXR0aW5ncykgPT4ge1xyXG5cdFx0XHR0aGlzLnVwZGF0ZVNldHRpbmdzKG5ld1NldHRpbmdzKTtcclxuXHRcdH0pO1xyXG5cdH1cclxuXHJcblx0LyoqXHJcblx0ICogVXBkYXRlIHNldHRpbmdzIHJlZmVyZW5jZVxyXG5cdCAqL1xyXG5cdHVwZGF0ZVNldHRpbmdzKHNldHRpbmdzOiBJbWFnZU1hbmFnZXJTZXR0aW5ncyk6IHZvaWQge1xyXG5cdFx0dGhpcy5zZXR0aW5ncyA9IHNldHRpbmdzO1xyXG5cdH1cclxuXHJcblx0LyoqXHJcblx0ICogU2VhcmNoIGZvciBpbWFnZXMgZnJvbSB0aGUgc3BlY2lmaWVkIHByb3ZpZGVyXHJcblx0ICovXHJcblx0YXN5bmMgc2VhcmNoKHF1ZXJ5OiBzdHJpbmcsIHByb3ZpZGVyPzogSW1hZ2VQcm92aWRlciwgcGFnZTogbnVtYmVyID0gMSk6IFByb21pc2U8UmVtb3RlSW1hZ2VbXT4ge1xyXG5cdFx0Y29uc3QgdGFyZ2V0UHJvdmlkZXIgPSBwcm92aWRlciA/PyB0aGlzLnNldHRpbmdzLmRlZmF1bHRQcm92aWRlcjtcclxuXHJcblx0XHRzd2l0Y2ggKHRhcmdldFByb3ZpZGVyKSB7XHJcblx0XHRcdGNhc2UgSW1hZ2VQcm92aWRlci5VbnNwbGFzaDpcclxuXHRcdFx0XHRyZXR1cm4gYXdhaXQgdGhpcy5zZWFyY2hVbnNwbGFzaChxdWVyeSwgcGFnZSk7XHJcblx0XHRcdGNhc2UgSW1hZ2VQcm92aWRlci5QZXhlbHM6XHJcblx0XHRcdFx0cmV0dXJuIGF3YWl0IHRoaXMuc2VhcmNoUGV4ZWxzKHF1ZXJ5LCBwYWdlKTtcclxuXHRcdFx0Y2FzZSBJbWFnZVByb3ZpZGVyLlBpeGFiYXk6XHJcblx0XHRcdFx0cmV0dXJuIGF3YWl0IHRoaXMuc2VhcmNoUGl4YWJheShxdWVyeSwgcGFnZSk7XHJcblx0XHRcdGRlZmF1bHQ6XHJcblx0XHRcdFx0dGhyb3cgbmV3IEVycm9yKGBVbnN1cHBvcnRlZCBwcm92aWRlcjogJHt0YXJnZXRQcm92aWRlcn1gKTtcclxuXHRcdH1cclxuXHR9XHJcblxyXG5cdC8qKlxyXG5cdCAqIFNlYXJjaCBVbnNwbGFzaFxyXG5cdCAqL1xyXG5cdHByaXZhdGUgYXN5bmMgc2VhcmNoVW5zcGxhc2gocXVlcnk6IHN0cmluZywgcGFnZTogbnVtYmVyKTogUHJvbWlzZTxSZW1vdGVJbWFnZVtdPiB7XHJcblx0XHRsZXQgcHJveHlVcmwgPSB0aGlzLnNldHRpbmdzLnVuc3BsYXNoUHJveHlTZXJ2ZXIgfHwgVU5TUExBU0hfUFJPWFk7XHJcblx0XHQvLyBFbnN1cmUgcHJveHkgVVJMIGVuZHMgd2l0aCBzbGFzaCBmb3IgVVJMIGNvbnN0cnVjdG9yXHJcblx0XHRpZiAoIXByb3h5VXJsLmVuZHNXaXRoKCcvJykpIHtcclxuXHRcdFx0cHJveHlVcmwgKz0gJy8nO1xyXG5cdFx0fVxyXG5cdFx0Y29uc3Qgb3JpZW50YXRpb24gPSB0aGlzLm1hcE9yaWVudGF0aW9uKHRoaXMuc2V0dGluZ3MuZGVmYXVsdE9yaWVudGF0aW9uKTtcclxuXHJcblx0XHQvLyBVc2UgVVJMIGNvbnN0cnVjdG9yIHBhdHRlcm5cclxuXHRcdGNvbnN0IHVybCA9IG5ldyBVUkwoJy9zZWFyY2gvcGhvdG9zJywgcHJveHlVcmwpO1xyXG5cdFx0dXJsLnNlYXJjaFBhcmFtcy5zZXQoJ3F1ZXJ5JywgcXVlcnkpO1xyXG5cdFx0dXJsLnNlYXJjaFBhcmFtcy5zZXQoJ3BhZ2UnLCBTdHJpbmcocGFnZSkpO1xyXG5cdFx0dXJsLnNlYXJjaFBhcmFtcy5zZXQoJ3Blcl9wYWdlJywgJzIwJyk7XHJcblxyXG5cdFx0aWYgKG9yaWVudGF0aW9uKSB7XHJcblx0XHRcdHVybC5zZWFyY2hQYXJhbXMuc2V0KCdvcmllbnRhdGlvbicsIG9yaWVudGF0aW9uKTtcclxuXHRcdH1cclxuXHJcblx0XHRjb25zdCByZXNwb25zZSA9IGF3YWl0IHJlcXVlc3RVcmwoeyB1cmw6IHVybC50b1N0cmluZygpIH0pO1xyXG5cdFx0aWYgKHJlc3BvbnNlLnN0YXR1cyA+PSA0MDApIHtcclxuXHRcdFx0Y29uc29sZS5lcnJvcignVW5zcGxhc2ggQVBJIGVycm9yOicsIHJlc3BvbnNlLnN0YXR1cywgcmVzcG9uc2UudGV4dCk7XHJcblx0XHRcdHRocm93IG5ldyBFcnJvcihgVW5zcGxhc2ggc2VhcmNoIGZhaWxlZDogJHtyZXNwb25zZS5zdGF0dXN9IC0gJHtyZXNwb25zZS50ZXh0fWApO1xyXG5cdFx0fVxyXG5cclxuXHRcdGNvbnN0IGRhdGEgPSByZXNwb25zZS5qc29uIGFzIFVuc3BsYXNoU2VhcmNoUmVzcG9uc2U7XHJcblx0XHRpZiAoIWRhdGEgfHwgIWRhdGEucmVzdWx0cykge1xyXG5cdFx0XHRjb25zb2xlLmVycm9yKCdJbnZhbGlkIFVuc3BsYXNoIHJlc3BvbnNlOicsIGRhdGEpO1xyXG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgcmVzcG9uc2UgZnJvbSBVbnNwbGFzaCBBUEknKTtcclxuXHRcdH1cclxuXHJcblx0XHRjb25zdCByZXN1bHRzOiBVbnNwbGFzaFBob3RvW10gPSBkYXRhLnJlc3VsdHMgPz8gW107XHJcblxyXG5cdFx0cmV0dXJuIHJlc3VsdHMubWFwKChwaG90bykgPT4gdGhpcy5tYXBVbnNwbGFzaFBob3RvKHBob3RvKSk7XHJcblx0fVxyXG5cclxuXHQvKipcclxuXHQgKiBHZXQgUGV4ZWxzIEFQSSBrZXkgZnJvbSBTZWNyZXRTdG9yYWdlIG9yIGZhbGwgYmFjayB0byBwbGFpbnRleHRcclxuXHQgKi9cclxuXHRwcml2YXRlIGdldFBleGVsc0FwaUtleSgpOiBzdHJpbmcgfCBudWxsIHtcclxuXHRcdC8vIFRyeSBzZWNyZXQgZmlyc3QgaWYgYXZhaWxhYmxlICgxLjExLjQrKVxyXG5cdFx0aWYgKHJlcXVpcmVBcGlWZXJzaW9uKCcxLjExLjQnKSAmJiB0aGlzLnNldHRpbmdzLnBleGVsc0FwaUtleVNlY3JldElkKSB7XHJcblx0XHRcdC8vIEFjY2VzcyBzZWNyZXRTdG9yYWdlIHZpYSB0eXBlIGFzc2VydGlvbiAobWF5IG5vdCBiZSBpbiB0eXBlIGRlZmluaXRpb25zKVxyXG5cdFx0XHRjb25zdCBzZWNyZXRTdG9yYWdlID0gKHRoaXMuYXBwIGFzIHVua25vd24gYXMgeyBzZWNyZXRTdG9yYWdlPzogeyBnZXRTZWNyZXQoaWQ6IHN0cmluZyk6IHN0cmluZyB8IG51bGwgfSB9KS5zZWNyZXRTdG9yYWdlO1xyXG5cdFx0XHRpZiAoc2VjcmV0U3RvcmFnZSkge1xyXG5cdFx0XHRcdGNvbnN0IHNlY3JldCA9IHNlY3JldFN0b3JhZ2UuZ2V0U2VjcmV0KHRoaXMuc2V0dGluZ3MucGV4ZWxzQXBpS2V5U2VjcmV0SWQpO1xyXG5cdFx0XHRcdGlmIChzZWNyZXQpIHtcclxuXHRcdFx0XHRcdHJldHVybiBzZWNyZXQ7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblx0XHR9XHJcblx0XHQvLyBGYWxsIGJhY2sgdG8gcGxhaW50ZXh0XHJcblx0XHRyZXR1cm4gdGhpcy5zZXR0aW5ncy5wZXhlbHNBcGlLZXkgfHwgbnVsbDtcclxuXHR9XHJcblxyXG5cdC8qKlxyXG5cdCAqIEdldCBQaXhhYmF5IEFQSSBrZXkgZnJvbSBTZWNyZXRTdG9yYWdlIG9yIGZhbGwgYmFjayB0byBwbGFpbnRleHRcclxuXHQgKi9cclxuXHRwcml2YXRlIGdldFBpeGFiYXlBcGlLZXkoKTogc3RyaW5nIHwgbnVsbCB7XHJcblx0XHQvLyBUcnkgc2VjcmV0IGZpcnN0IGlmIGF2YWlsYWJsZSAoMS4xMS40KylcclxuXHRcdGlmIChyZXF1aXJlQXBpVmVyc2lvbignMS4xMS40JykgJiYgdGhpcy5zZXR0aW5ncy5waXhhYmF5QXBpS2V5U2VjcmV0SWQpIHtcclxuXHRcdFx0Ly8gQWNjZXNzIHNlY3JldFN0b3JhZ2UgdmlhIHR5cGUgYXNzZXJ0aW9uIChtYXkgbm90IGJlIGluIHR5cGUgZGVmaW5pdGlvbnMpXHJcblx0XHRcdGNvbnN0IHNlY3JldFN0b3JhZ2UgPSAodGhpcy5hcHAgYXMgdW5rbm93biBhcyB7IHNlY3JldFN0b3JhZ2U/OiB7IGdldFNlY3JldChpZDogc3RyaW5nKTogc3RyaW5nIHwgbnVsbCB9IH0pLnNlY3JldFN0b3JhZ2U7XHJcblx0XHRcdGlmIChzZWNyZXRTdG9yYWdlKSB7XHJcblx0XHRcdFx0Y29uc3Qgc2VjcmV0ID0gc2VjcmV0U3RvcmFnZS5nZXRTZWNyZXQodGhpcy5zZXR0aW5ncy5waXhhYmF5QXBpS2V5U2VjcmV0SWQpO1xyXG5cdFx0XHRcdGlmIChzZWNyZXQpIHtcclxuXHRcdFx0XHRcdHJldHVybiBzZWNyZXQ7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblx0XHR9XHJcblx0XHQvLyBGYWxsIGJhY2sgdG8gcGxhaW50ZXh0XHJcblx0XHRyZXR1cm4gdGhpcy5zZXR0aW5ncy5waXhhYmF5QXBpS2V5IHx8IG51bGw7XHJcblx0fVxyXG5cclxuXHQvKipcclxuXHQgKiBTZWFyY2ggUGV4ZWxzXHJcblx0ICovXHJcblx0cHJpdmF0ZSBhc3luYyBzZWFyY2hQZXhlbHMocXVlcnk6IHN0cmluZywgcGFnZTogbnVtYmVyKTogUHJvbWlzZTxSZW1vdGVJbWFnZVtdPiB7XHJcblx0XHRjb25zdCBhcGlLZXkgPSB0aGlzLmdldFBleGVsc0FwaUtleSgpO1xyXG5cdFx0aWYgKCFhcGlLZXkpIHtcclxuXHRcdFx0Y29uc3QgZXJyb3JNc2cgPSByZXF1aXJlQXBpVmVyc2lvbignMS4xMS40JylcclxuXHRcdFx0XHQ/ICdQZXhlbHMgQVBJIGtleSBpcyByZXF1aXJlZC4gUGxlYXNlIGNvbmZpZ3VyZSBpdCBpbiBzZXR0aW5ncyAodXNlIFNlY3JldFN0b3JhZ2Ugb24gT2JzaWRpYW4gMS4xMS40KyBvciBlbnRlciBwbGFpbnRleHQgb24gb2xkZXIgdmVyc2lvbnMpLidcclxuXHRcdFx0XHQ6ICdQZXhlbHMgQVBJIGtleSBpcyByZXF1aXJlZC4gUGxlYXNlIGNvbmZpZ3VyZSBpdCBpbiBzZXR0aW5ncy4nO1xyXG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoZXJyb3JNc2cpO1xyXG5cdFx0fVxyXG5cclxuXHRcdGNvbnN0IG9yaWVudGF0aW9uID0gdGhpcy5tYXBPcmllbnRhdGlvbih0aGlzLnNldHRpbmdzLmRlZmF1bHRPcmllbnRhdGlvbik7XHJcblxyXG5cdFx0Y29uc3QgcGFyYW1zID0gbmV3IFVSTFNlYXJjaFBhcmFtcyh7XHJcblx0XHRcdHF1ZXJ5LFxyXG5cdFx0XHRwYWdlOiBTdHJpbmcocGFnZSksXHJcblx0XHRcdHBlcl9wYWdlOiAnMjAnLFxyXG5cdFx0fSk7XHJcblxyXG5cdFx0aWYgKG9yaWVudGF0aW9uKSB7XHJcblx0XHRcdHBhcmFtcy5zZXQoJ29yaWVudGF0aW9uJywgb3JpZW50YXRpb24pO1xyXG5cdFx0fVxyXG5cclxuXHRcdGNvbnN0IHVybCA9IGBodHRwczovL2FwaS5wZXhlbHMuY29tL3YxL3NlYXJjaD8ke3BhcmFtcy50b1N0cmluZygpfWA7XHJcblxyXG5cdFx0Y29uc3QgcmVzcG9uc2UgPSBhd2FpdCByZXF1ZXN0VXJsKHtcclxuXHRcdFx0dXJsLFxyXG5cdFx0XHRoZWFkZXJzOiB7XHJcblx0XHRcdFx0QXV0aG9yaXphdGlvbjogYXBpS2V5LFxyXG5cdFx0XHR9LFxyXG5cdFx0fSk7XHJcblxyXG5cdFx0aWYgKHJlc3BvbnNlLnN0YXR1cyA+PSA0MDApIHtcclxuXHRcdFx0dGhyb3cgbmV3IEVycm9yKGBQZXhlbHMgc2VhcmNoIGZhaWxlZDogJHtyZXNwb25zZS5zdGF0dXN9YCk7XHJcblx0XHR9XHJcblxyXG5cdFx0Y29uc3QgZGF0YSA9IHJlc3BvbnNlLmpzb24gYXMgUGV4ZWxzU2VhcmNoUmVzcG9uc2U7XHJcblx0XHRjb25zdCBwaG90b3M6IFBleGVsc1Bob3RvW10gPSBkYXRhLnBob3RvcyA/PyBbXTtcclxuXHJcblx0XHRyZXR1cm4gcGhvdG9zLm1hcCgocGhvdG8pID0+IHRoaXMubWFwUGV4ZWxzUGhvdG8ocGhvdG8pKTtcclxuXHR9XHJcblxyXG5cdC8qKlxyXG5cdCAqIFNlYXJjaCBQaXhhYmF5XHJcblx0ICovXHJcblx0cHJpdmF0ZSBhc3luYyBzZWFyY2hQaXhhYmF5KHF1ZXJ5OiBzdHJpbmcsIHBhZ2U6IG51bWJlcik6IFByb21pc2U8UmVtb3RlSW1hZ2VbXT4ge1xyXG5cdFx0Y29uc3QgYXBpS2V5ID0gdGhpcy5nZXRQaXhhYmF5QXBpS2V5KCk7XHJcblx0XHRpZiAoIWFwaUtleSkge1xyXG5cdFx0XHRjb25zdCBlcnJvck1zZyA9IHJlcXVpcmVBcGlWZXJzaW9uKCcxLjExLjQnKVxyXG5cdFx0XHRcdD8gJ1BpeGFiYXkgQVBJIGtleSBpcyByZXF1aXJlZC4gUGxlYXNlIGNvbmZpZ3VyZSBpdCBpbiBzZXR0aW5ncyAodXNlIFNlY3JldFN0b3JhZ2Ugb24gT2JzaWRpYW4gMS4xMS40KyBvciBlbnRlciBwbGFpbnRleHQgb24gb2xkZXIgdmVyc2lvbnMpLidcclxuXHRcdFx0XHQ6ICdQaXhhYmF5IEFQSSBrZXkgaXMgcmVxdWlyZWQuIFBsZWFzZSBjb25maWd1cmUgaXQgaW4gc2V0dGluZ3MuJztcclxuXHRcdFx0dGhyb3cgbmV3IEVycm9yKGVycm9yTXNnKTtcclxuXHRcdH1cclxuXHJcblx0XHRjb25zdCBvcmllbnRhdGlvbiA9IHRoaXMubWFwUGl4YWJheU9yaWVudGF0aW9uKHRoaXMuc2V0dGluZ3MuZGVmYXVsdE9yaWVudGF0aW9uKTtcclxuXHJcblx0XHRjb25zdCBwYXJhbXMgPSBuZXcgVVJMU2VhcmNoUGFyYW1zKHtcclxuXHRcdFx0a2V5OiBhcGlLZXksXHJcblx0XHRcdHE6IHF1ZXJ5LFxyXG5cdFx0XHRwYWdlOiBTdHJpbmcocGFnZSksXHJcblx0XHRcdHBlcl9wYWdlOiAnMjAnLFxyXG5cdFx0XHRpbWFnZV90eXBlOiAncGhvdG8nLFxyXG5cdFx0fSk7XHJcblxyXG5cdFx0aWYgKG9yaWVudGF0aW9uKSB7XHJcblx0XHRcdHBhcmFtcy5zZXQoJ29yaWVudGF0aW9uJywgb3JpZW50YXRpb24pO1xyXG5cdFx0fVxyXG5cclxuXHRcdGNvbnN0IHVybCA9IGBodHRwczovL3BpeGFiYXkuY29tL2FwaS8/JHtwYXJhbXMudG9TdHJpbmcoKX1gO1xyXG5cclxuXHRcdGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgcmVxdWVzdFVybCh7IHVybCB9KTtcclxuXHRcdGlmIChyZXNwb25zZS5zdGF0dXMgPj0gNDAwKSB7XHJcblx0XHRcdHRocm93IG5ldyBFcnJvcihgUGl4YWJheSBzZWFyY2ggZmFpbGVkOiAke3Jlc3BvbnNlLnN0YXR1c31gKTtcclxuXHRcdH1cclxuXHJcblx0XHRjb25zdCBkYXRhID0gcmVzcG9uc2UuanNvbiBhcyBQaXhhYmF5U2VhcmNoUmVzcG9uc2U7XHJcblx0XHRjb25zdCBoaXRzOiBQaXhhYmF5SGl0W10gPSBkYXRhLmhpdHMgPz8gW107XHJcblxyXG5cdFx0cmV0dXJuIGhpdHMubWFwKChoaXQpID0+IHRoaXMubWFwUGl4YWJheUhpdChoaXQpKTtcclxuXHR9XHJcblxyXG5cdC8qKlxyXG5cdCAqIEdldCB0aGUgZG93bmxvYWQgVVJMIGZvciBhbiBpbWFnZSBiYXNlZCBvbiBzaXplIHByZWZlcmVuY2VcclxuXHQgKi9cclxuXHRnZXREb3dubG9hZFVybChpbWFnZTogUmVtb3RlSW1hZ2UsIHNpemU/OiBJbWFnZVNpemUpOiBzdHJpbmcge1xyXG5cdFx0Y29uc3QgdGFyZ2V0U2l6ZSA9IHNpemUgPz8gdGhpcy5zZXR0aW5ncy5kZWZhdWx0SW1hZ2VTaXplO1xyXG5cdFx0c3dpdGNoICh0YXJnZXRTaXplKSB7XHJcblx0XHRcdGNhc2UgSW1hZ2VTaXplLk9yaWdpbmFsOlxyXG5cdFx0XHRcdHJldHVybiBpbWFnZS5mdWxsVXJsO1xyXG5cdFx0XHRjYXNlIEltYWdlU2l6ZS5MYXJnZTpcclxuXHRcdFx0XHRyZXR1cm4gaW1hZ2UucmVndWxhclVybDtcclxuXHRcdFx0Y2FzZSBJbWFnZVNpemUuTWVkaXVtOlxyXG5cdFx0XHRcdHJldHVybiBpbWFnZS5yZWd1bGFyVXJsO1xyXG5cdFx0XHRjYXNlIEltYWdlU2l6ZS5TbWFsbDpcclxuXHRcdFx0XHRyZXR1cm4gaW1hZ2UudGh1bWJuYWlsVXJsO1xyXG5cdFx0XHRkZWZhdWx0OlxyXG5cdFx0XHRcdHJldHVybiBpbWFnZS5yZWd1bGFyVXJsO1xyXG5cdFx0fVxyXG5cdH1cclxuXHJcblx0LyoqXHJcblx0ICogRG93bmxvYWQgYW4gaW1hZ2UgYW5kIHJldHVybiB0aGUgYmluYXJ5IGRhdGFcclxuXHQgKi9cclxuXHRhc3luYyBkb3dubG9hZEltYWdlKGltYWdlOiBSZW1vdGVJbWFnZSk6IFByb21pc2U8QXJyYXlCdWZmZXI+IHtcclxuXHRcdGNvbnN0IHVybCA9IHRoaXMuZ2V0RG93bmxvYWRVcmwoaW1hZ2UpO1xyXG5cdFx0Y29uc3QgcmVzcG9uc2UgPSBhd2FpdCByZXF1ZXN0VXJsKHsgdXJsIH0pO1xyXG5cclxuXHRcdGlmIChyZXNwb25zZS5zdGF0dXMgPj0gNDAwKSB7XHJcblx0XHRcdHRocm93IG5ldyBFcnJvcihgRmFpbGVkIHRvIGRvd25sb2FkIGltYWdlOiAke3Jlc3BvbnNlLnN0YXR1c31gKTtcclxuXHRcdH1cclxuXHJcblx0XHRyZXR1cm4gcmVzcG9uc2UuYXJyYXlCdWZmZXI7XHJcblx0fVxyXG5cclxuXHQvKipcclxuXHQgKiBHZW5lcmF0ZSByZWZlcnJhbCB0ZXh0IGZvciBhbiBpbWFnZSAoYXR0cmlidXRpb24pXHJcblx0ICovXHJcblx0Z2VuZXJhdGVSZWZlcnJhbFRleHQoaW1hZ2U6IFJlbW90ZUltYWdlKTogc3RyaW5nIHtcclxuXHRcdGlmICghdGhpcy5zZXR0aW5ncy5pbnNlcnRSZWZlcnJhbCkge1xyXG5cdFx0XHRyZXR1cm4gJyc7XHJcblx0XHR9XHJcblxyXG5cdFx0Y29uc3QgYmFja2xpbmsgPSB0aGlzLnNldHRpbmdzLmluc2VydEJhY2tMaW5rICYmIGltYWdlLnBhZ2VVcmxcclxuXHRcdFx0PyBgW0JhY2tsaW5rXSgke2ltYWdlLnBhZ2VVcmx9KSB8IGBcclxuXHRcdFx0OiAnJztcclxuXHJcblx0XHRsZXQgcmVmZXJyYWwgPSAnJztcclxuXHRcdHN3aXRjaCAoaW1hZ2UucHJvdmlkZXIpIHtcclxuXHRcdFx0Y2FzZSBJbWFnZVByb3ZpZGVyLlVuc3BsYXNoOlxyXG5cdFx0XHRcdGlmIChpbWFnZS5hdXRob3IgJiYgaW1hZ2UuYXV0aG9yVXJsKSB7XHJcblx0XHRcdFx0XHRjb25zdCB1dG0gPSAndXRtX3NvdXJjZT1PYnNpZGlhbiUyMEltYWdlJTIwTWFuYWdlciZ1dG1fbWVkaXVtPXJlZmVycmFsJztcclxuXHRcdFx0XHRcdHJlZmVycmFsID0gYFxcbioke2JhY2tsaW5rfVBob3RvIGJ5IFske2ltYWdlLmF1dGhvcn1dKCR7aW1hZ2UuYXV0aG9yVXJsfSkgb24gW1Vuc3BsYXNoXShodHRwczovL3Vuc3BsYXNoLmNvbS8/JHt1dG19KSpcXG5gO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0XHRicmVhaztcclxuXHRcdFx0Y2FzZSBJbWFnZVByb3ZpZGVyLlBleGVsczpcclxuXHRcdFx0XHRpZiAoaW1hZ2UuYXV0aG9yICYmIGltYWdlLmF1dGhvclVybCkge1xyXG5cdFx0XHRcdFx0cmVmZXJyYWwgPSBgXFxuKiR7YmFja2xpbmt9UGhvdG8gYnkgWyR7aW1hZ2UuYXV0aG9yfV0oJHtpbWFnZS5hdXRob3JVcmx9KSBvbiBbUGV4ZWxzXShodHRwczovL3d3dy5wZXhlbHMuY29tLykqXFxuYDtcclxuXHRcdFx0XHR9XHJcblx0XHRcdFx0YnJlYWs7XHJcblx0XHRcdGNhc2UgSW1hZ2VQcm92aWRlci5QaXhhYmF5OlxyXG5cdFx0XHRcdGlmIChpbWFnZS5hdXRob3IgJiYgaW1hZ2UuYXV0aG9yVXJsKSB7XHJcblx0XHRcdFx0XHRyZWZlcnJhbCA9IGBcXG4qJHtiYWNrbGlua31JbWFnZSBieSBbJHtpbWFnZS5hdXRob3J9XSgke2ltYWdlLmF1dGhvclVybH0pIG9uIFtQaXhhYmF5XShodHRwczovL3BpeGFiYXkuY29tLykqXFxuYDtcclxuXHRcdFx0XHR9XHJcblx0XHRcdFx0YnJlYWs7XHJcblx0XHR9XHJcblxyXG5cdFx0cmV0dXJuIHJlZmVycmFsO1xyXG5cdH1cclxuXHJcblx0LyoqXHJcblx0ICogTWFwIG9yaWVudGF0aW9uIHNldHRpbmcgdG8gQVBJIHBhcmFtZXRlclxyXG5cdCAqL1xyXG5cdHByaXZhdGUgbWFwT3JpZW50YXRpb24ob3JpZW50YXRpb246IEltYWdlT3JpZW50YXRpb24pOiBzdHJpbmcgfCBudWxsIHtcclxuXHRcdHN3aXRjaCAob3JpZW50YXRpb24pIHtcclxuXHRcdFx0Y2FzZSBJbWFnZU9yaWVudGF0aW9uLkxhbmRzY2FwZTpcclxuXHRcdFx0XHRyZXR1cm4gJ2xhbmRzY2FwZSc7XHJcblx0XHRcdGNhc2UgSW1hZ2VPcmllbnRhdGlvbi5Qb3J0cmFpdDpcclxuXHRcdFx0XHRyZXR1cm4gJ3BvcnRyYWl0JztcclxuXHRcdFx0Y2FzZSBJbWFnZU9yaWVudGF0aW9uLlNxdWFyZTpcclxuXHRcdFx0XHRyZXR1cm4gJ3NxdWFyaXNoJztcclxuXHRcdFx0ZGVmYXVsdDpcclxuXHRcdFx0XHRyZXR1cm4gbnVsbDtcclxuXHRcdH1cclxuXHR9XHJcblxyXG5cdC8qKlxyXG5cdCAqIE1hcCBvcmllbnRhdGlvbiBmb3IgUGl4YWJheSAoZGlmZmVyZW50IHZhbHVlcylcclxuXHQgKi9cclxuXHRwcml2YXRlIG1hcFBpeGFiYXlPcmllbnRhdGlvbihvcmllbnRhdGlvbjogSW1hZ2VPcmllbnRhdGlvbik6IHN0cmluZyB8IG51bGwge1xyXG5cdFx0c3dpdGNoIChvcmllbnRhdGlvbikge1xyXG5cdFx0XHRjYXNlIEltYWdlT3JpZW50YXRpb24uTGFuZHNjYXBlOlxyXG5cdFx0XHRcdHJldHVybiAnaG9yaXpvbnRhbCc7XHJcblx0XHRcdGNhc2UgSW1hZ2VPcmllbnRhdGlvbi5Qb3J0cmFpdDpcclxuXHRcdFx0XHRyZXR1cm4gJ3ZlcnRpY2FsJztcclxuXHRcdFx0ZGVmYXVsdDpcclxuXHRcdFx0XHRyZXR1cm4gbnVsbDtcclxuXHRcdH1cclxuXHR9XHJcblxyXG5cdC8qKlxyXG5cdCAqIE1hcCBVbnNwbGFzaCBwaG90byB0byBSZW1vdGVJbWFnZVxyXG5cdCAqL1xyXG5cdHByaXZhdGUgbWFwVW5zcGxhc2hQaG90byhwaG90bzogVW5zcGxhc2hQaG90byk6IFJlbW90ZUltYWdlIHtcclxuXHRcdHJldHVybiB7XHJcblx0XHRcdGlkOiBwaG90by5pZCxcclxuXHRcdFx0cHJvdmlkZXI6IEltYWdlUHJvdmlkZXIuVW5zcGxhc2gsXHJcblx0XHRcdHRodW1ibmFpbFVybDogcGhvdG8udXJscy50aHVtYixcclxuXHRcdFx0cmVndWxhclVybDogcGhvdG8udXJscy5yZWd1bGFyLFxyXG5cdFx0XHRmdWxsVXJsOiBwaG90by51cmxzLmZ1bGwsXHJcblx0XHRcdGRvd25sb2FkVXJsOiBwaG90by5saW5rcy5kb3dubG9hZF9sb2NhdGlvbiB8fCBwaG90by5saW5rcy5kb3dubG9hZCxcclxuXHRcdFx0d2lkdGg6IHBob3RvLndpZHRoLFxyXG5cdFx0XHRoZWlnaHQ6IHBob3RvLmhlaWdodCxcclxuXHRcdFx0ZGVzY3JpcHRpb246IHBob3RvLmRlc2NyaXB0aW9uID8/IHBob3RvLmFsdF9kZXNjcmlwdGlvbiA/PyAnJyxcclxuXHRcdFx0YXV0aG9yOiBwaG90by51c2VyLm5hbWUsXHJcblx0XHRcdGF1dGhvclVybDogcGhvdG8udXNlci5saW5rcy5odG1sLFxyXG5cdFx0XHRwYWdlVXJsOiBwaG90by5saW5rcy5odG1sLFxyXG5cdFx0fTtcclxuXHR9XHJcblxyXG5cdC8qKlxyXG5cdCAqIE1hcCBQZXhlbHMgcGhvdG8gdG8gUmVtb3RlSW1hZ2VcclxuXHQgKi9cclxuXHRwcml2YXRlIG1hcFBleGVsc1Bob3RvKHBob3RvOiBQZXhlbHNQaG90byk6IFJlbW90ZUltYWdlIHtcclxuXHRcdHJldHVybiB7XHJcblx0XHRcdGlkOiBTdHJpbmcocGhvdG8uaWQpLFxyXG5cdFx0XHRwcm92aWRlcjogSW1hZ2VQcm92aWRlci5QZXhlbHMsXHJcblx0XHRcdHRodW1ibmFpbFVybDogcGhvdG8uc3JjLnRpbnksXHJcblx0XHRcdHJlZ3VsYXJVcmw6IHBob3RvLnNyYy5sYXJnZSxcclxuXHRcdFx0ZnVsbFVybDogcGhvdG8uc3JjLm9yaWdpbmFsLFxyXG5cdFx0XHRkb3dubG9hZFVybDogcGhvdG8uc3JjLm9yaWdpbmFsLFxyXG5cdFx0XHR3aWR0aDogcGhvdG8ud2lkdGgsXHJcblx0XHRcdGhlaWdodDogcGhvdG8uaGVpZ2h0LFxyXG5cdFx0XHRkZXNjcmlwdGlvbjogcGhvdG8uYWx0ID8/ICcnLFxyXG5cdFx0XHRhdXRob3I6IHBob3RvLnBob3RvZ3JhcGhlcixcclxuXHRcdFx0YXV0aG9yVXJsOiBwaG90by5waG90b2dyYXBoZXJfdXJsLFxyXG5cdFx0XHRwYWdlVXJsOiBwaG90by51cmwsXHJcblx0XHR9O1xyXG5cdH1cclxuXHJcblx0LyoqXHJcblx0ICogTWFwIFBpeGFiYXkgaGl0IHRvIFJlbW90ZUltYWdlXHJcblx0ICovXHJcblx0cHJpdmF0ZSBtYXBQaXhhYmF5SGl0KGhpdDogUGl4YWJheUhpdCk6IFJlbW90ZUltYWdlIHtcclxuXHRcdHJldHVybiB7XHJcblx0XHRcdGlkOiBTdHJpbmcoaGl0LmlkKSxcclxuXHRcdFx0cHJvdmlkZXI6IEltYWdlUHJvdmlkZXIuUGl4YWJheSxcclxuXHRcdFx0dGh1bWJuYWlsVXJsOiBoaXQucHJldmlld1VSTCxcclxuXHRcdFx0cmVndWxhclVybDogaGl0LndlYmZvcm1hdFVSTCxcclxuXHRcdFx0ZnVsbFVybDogaGl0LmxhcmdlSW1hZ2VVUkwsXHJcblx0XHRcdGRvd25sb2FkVXJsOiBoaXQubGFyZ2VJbWFnZVVSTCxcclxuXHRcdFx0d2lkdGg6IGhpdC5pbWFnZVdpZHRoLFxyXG5cdFx0XHRoZWlnaHQ6IGhpdC5pbWFnZUhlaWdodCxcclxuXHRcdFx0ZGVzY3JpcHRpb246IGhpdC50YWdzLFxyXG5cdFx0XHRhdXRob3I6IGhpdC51c2VyLFxyXG5cdFx0XHRhdXRob3JVcmw6IGBodHRwczovL3BpeGFiYXkuY29tL3VzZXJzLyR7aGl0LnVzZXJ9LSR7aGl0LnVzZXJfaWR9L2AsXHJcblx0XHRcdHBhZ2VVcmw6IGhpdC5wYWdlVVJMLFxyXG5cdFx0fTtcclxuXHR9XHJcbn1cclxuXHJcbi8vIFR5cGUgZGVmaW5pdGlvbnMgZm9yIEFQSSByZXNwb25zZXNcclxuXHJcbmludGVyZmFjZSBVbnNwbGFzaFNlYXJjaFJlc3BvbnNlIHtcclxuXHRyZXN1bHRzOiBVbnNwbGFzaFBob3RvW107XHJcbn1cclxuXHJcbmludGVyZmFjZSBQZXhlbHNTZWFyY2hSZXNwb25zZSB7XHJcblx0cGhvdG9zOiBQZXhlbHNQaG90b1tdO1xyXG59XHJcblxyXG5pbnRlcmZhY2UgUGl4YWJheVNlYXJjaFJlc3BvbnNlIHtcclxuXHRoaXRzOiBQaXhhYmF5SGl0W107XHJcbn1cclxuXHJcbmludGVyZmFjZSBVbnNwbGFzaFBob3RvIHtcclxuXHRpZDogc3RyaW5nO1xyXG5cdHdpZHRoOiBudW1iZXI7XHJcblx0aGVpZ2h0OiBudW1iZXI7XHJcblx0ZGVzY3JpcHRpb246IHN0cmluZyB8IG51bGw7XHJcblx0YWx0X2Rlc2NyaXB0aW9uOiBzdHJpbmcgfCBudWxsO1xyXG5cdHVybHM6IHtcclxuXHRcdHJhdzogc3RyaW5nO1xyXG5cdFx0ZnVsbDogc3RyaW5nO1xyXG5cdFx0cmVndWxhcjogc3RyaW5nO1xyXG5cdFx0c21hbGw6IHN0cmluZztcclxuXHRcdHRodW1iOiBzdHJpbmc7XHJcblx0fTtcclxuXHRsaW5rczoge1xyXG5cdFx0aHRtbDogc3RyaW5nO1xyXG5cdFx0ZG93bmxvYWQ6IHN0cmluZztcclxuXHRcdGRvd25sb2FkX2xvY2F0aW9uPzogc3RyaW5nO1xyXG5cdH07XHJcblx0dXNlcjoge1xyXG5cdFx0bmFtZTogc3RyaW5nO1xyXG5cdFx0bGlua3M6IHtcclxuXHRcdFx0aHRtbDogc3RyaW5nO1xyXG5cdFx0fTtcclxuXHR9O1xyXG59XHJcblxyXG5pbnRlcmZhY2UgUGV4ZWxzUGhvdG8ge1xyXG5cdGlkOiBudW1iZXI7XHJcblx0d2lkdGg6IG51bWJlcjtcclxuXHRoZWlnaHQ6IG51bWJlcjtcclxuXHR1cmw6IHN0cmluZztcclxuXHRwaG90b2dyYXBoZXI6IHN0cmluZztcclxuXHRwaG90b2dyYXBoZXJfdXJsOiBzdHJpbmc7XHJcblx0YWx0OiBzdHJpbmcgfCBudWxsO1xyXG5cdHNyYzoge1xyXG5cdFx0b3JpZ2luYWw6IHN0cmluZztcclxuXHRcdGxhcmdlOiBzdHJpbmc7XHJcblx0XHRtZWRpdW06IHN0cmluZztcclxuXHRcdHNtYWxsOiBzdHJpbmc7XHJcblx0XHR0aW55OiBzdHJpbmc7XHJcblx0fTtcclxufVxyXG5cclxuaW50ZXJmYWNlIFBpeGFiYXlIaXQge1xyXG5cdGlkOiBudW1iZXI7XHJcblx0cGFnZVVSTDogc3RyaW5nO1xyXG5cdHByZXZpZXdVUkw6IHN0cmluZztcclxuXHR3ZWJmb3JtYXRVUkw6IHN0cmluZztcclxuXHRsYXJnZUltYWdlVVJMOiBzdHJpbmc7XHJcblx0aW1hZ2VXaWR0aDogbnVtYmVyO1xyXG5cdGltYWdlSGVpZ2h0OiBudW1iZXI7XHJcblx0dGFnczogc3RyaW5nO1xyXG5cdHVzZXI6IHN0cmluZztcclxuXHR1c2VyX2lkOiBudW1iZXI7XHJcbn1cclxuIiwgIi8qKlxyXG4gKiBMb2NhbCBDb252ZXJzaW9uIFNlcnZpY2VcclxuICogQ29udmVydHMgcmVtb3RlL2V4dGVybmFsIGltYWdlcyB0byBsb2NhbCBmaWxlc1xyXG4gKi9cclxuXHJcbmltcG9ydCB7IEFwcCwgVEZpbGUsIHJlcXVlc3RVcmwgfSBmcm9tICdvYnNpZGlhbic7XHJcbmltcG9ydCB7IEltYWdlTWFuYWdlclNldHRpbmdzIH0gZnJvbSAnLi4vdHlwZXMnO1xyXG5pbXBvcnQgeyBTdG9yYWdlTWFuYWdlciB9IGZyb20gJy4vU3RvcmFnZU1hbmFnZXInO1xyXG5pbXBvcnQgeyBJbWFnZVByb2Nlc3NvciB9IGZyb20gJy4vSW1hZ2VQcm9jZXNzb3InO1xyXG5pbXBvcnQgeyBpc01hcmtkb3duRmlsZSB9IGZyb20gJy4uL3V0aWxzL21keC1mcm9udG1hdHRlcic7XHJcblxyXG4vLyBSZWdleCBwYXR0ZXJucyBmb3IgZmluZGluZyBleHRlcm5hbCBpbWFnZXNcclxuLy8gVXBkYXRlZCB0byBoYW5kbGUgVVJMcyB3aXRoIHF1ZXJ5IHBhcmFtZXRlcnMgYW5kIGZyYWdtZW50c1xyXG5jb25zdCBNQVJLRE9XTl9JTUFHRV9SRUdFWCA9IC8hXFxbKFteXFxdXSopXFxdXFwoKGh0dHBzPzpcXC9cXC9bXlxccyldKylcXCkvZztcclxuY29uc3QgSFRNTF9JTUFHRV9SRUdFWCA9IC88aW1nW14+XStzcmM9W1wiJ10oaHR0cHM/OlxcL1xcL1teXCInXSspW1wiJ11bXj5dKj4vZztcclxuXHJcbmV4cG9ydCBjbGFzcyBMb2NhbENvbnZlcnNpb25TZXJ2aWNlIHtcclxuXHRwcml2YXRlIGFwcDogQXBwO1xyXG5cdHByaXZhdGUgc2V0dGluZ3M6IEltYWdlTWFuYWdlclNldHRpbmdzO1xyXG5cdHByaXZhdGUgc3RvcmFnZU1hbmFnZXI6IFN0b3JhZ2VNYW5hZ2VyO1xyXG5cdHByaXZhdGUgaW1hZ2VQcm9jZXNzb3I6IEltYWdlUHJvY2Vzc29yO1xyXG5cclxuXHRjb25zdHJ1Y3RvcihhcHA6IEFwcCwgc2V0dGluZ3M6IEltYWdlTWFuYWdlclNldHRpbmdzLCBzdG9yYWdlTWFuYWdlcjogU3RvcmFnZU1hbmFnZXIsIGltYWdlUHJvY2Vzc29yOiBJbWFnZVByb2Nlc3Nvciwgb2JzZXJ2YWJsZT86IHsgc3Vic2NyaWJlKGZuOiAoc2V0dGluZ3M6IEltYWdlTWFuYWdlclNldHRpbmdzKSA9PiB2b2lkKTogdm9pZCB9KSB7XHJcblx0XHR0aGlzLmFwcCA9IGFwcDtcclxuXHRcdHRoaXMuc2V0dGluZ3MgPSBzZXR0aW5ncztcclxuXHRcdHRoaXMuc3RvcmFnZU1hbmFnZXIgPSBzdG9yYWdlTWFuYWdlcjtcclxuXHRcdHRoaXMuaW1hZ2VQcm9jZXNzb3IgPSBpbWFnZVByb2Nlc3NvcjtcclxuXHJcblx0XHQvLyBTdWJzY3JpYmUgdG8gc2V0dGluZ3MgdXBkYXRlcyBpZiBvYnNlcnZhYmxlIGlzIHByb3ZpZGVkXHJcblx0XHRvYnNlcnZhYmxlPy5zdWJzY3JpYmUoKG5ld1NldHRpbmdzKSA9PiB7XHJcblx0XHRcdHRoaXMudXBkYXRlU2V0dGluZ3MobmV3U2V0dGluZ3MpO1xyXG5cdFx0fSk7XHJcblx0fVxyXG5cclxuXHQvKipcclxuXHQgKiBVcGRhdGUgc2V0dGluZ3MgcmVmZXJlbmNlXHJcblx0ICovXHJcblx0dXBkYXRlU2V0dGluZ3Moc2V0dGluZ3M6IEltYWdlTWFuYWdlclNldHRpbmdzKTogdm9pZCB7XHJcblx0XHR0aGlzLnNldHRpbmdzID0gc2V0dGluZ3M7XHJcblx0XHR0aGlzLmltYWdlUHJvY2Vzc29yPy51cGRhdGVTZXR0aW5ncyhzZXR0aW5ncyk7XHJcblx0fVxyXG5cclxuXHQvKipcclxuXHQgKiBQcm9jZXNzIGEgZmlsZSB0byBjb252ZXJ0IGFsbCByZW1vdGUgaW1hZ2VzIHRvIGxvY2FsXHJcblx0ICogQHBhcmFtIGZpbGUgLSBUaGUgZmlsZSB0byBwcm9jZXNzXHJcblx0ICogQHBhcmFtIGlzQmFja2dyb3VuZCAtIElmIHRydWUsIHNraXAgY29udmVyc2lvbiBpZiB1c2VyIGludGVyYWN0aW9uIChtb2RhbCkgd291bGQgYmUgcmVxdWlyZWRcclxuXHQgKi9cclxuXHRhc3luYyBwcm9jZXNzRmlsZShmaWxlOiBURmlsZSwgaXNCYWNrZ3JvdW5kOiBib29sZWFuID0gZmFsc2UpOiBQcm9taXNlPG51bWJlcj4ge1xyXG5cdFx0aWYgKCFpc01hcmtkb3duRmlsZShmaWxlKSkge1xyXG5cdFx0XHRyZXR1cm4gMDtcclxuXHRcdH1cclxuXHJcblx0XHRjb25zdCBjb250ZW50ID0gYXdhaXQgdGhpcy5hcHAudmF1bHQucmVhZChmaWxlKTtcclxuXHRcdGNvbnN0IHsgbmV3Q29udGVudCwgY291bnQgfSA9IGF3YWl0IHRoaXMucHJvY2Vzc0NvbnRlbnQoY29udGVudCwgZmlsZSwgaXNCYWNrZ3JvdW5kKTtcclxuXHJcblx0XHRpZiAoY291bnQgPiAwKSB7XHJcblx0XHRcdGF3YWl0IHRoaXMuYXBwLnZhdWx0Lm1vZGlmeShmaWxlLCBuZXdDb250ZW50KTtcclxuXHRcdH1cclxuXHJcblx0XHRyZXR1cm4gY291bnQ7XHJcblx0fVxyXG5cclxuXHQvKipcclxuXHQgKiBQcm9jZXNzIGNvbnRlbnQgYW5kIHJlcGxhY2UgcmVtb3RlIGltYWdlcyB3aXRoIGxvY2FsXHJcblx0ICovXHJcblx0cHJpdmF0ZSBhc3luYyBwcm9jZXNzQ29udGVudChcclxuXHRcdGNvbnRlbnQ6IHN0cmluZyxcclxuXHRcdHNvdXJjZUZpbGU6IFRGaWxlLFxyXG5cdFx0aXNCYWNrZ3JvdW5kOiBib29sZWFuID0gZmFsc2VcclxuXHQpOiBQcm9taXNlPHsgbmV3Q29udGVudDogc3RyaW5nOyBjb3VudDogbnVtYmVyIH0+IHtcclxuXHRcdGxldCBuZXdDb250ZW50ID0gY29udGVudDtcclxuXHRcdGxldCBjb3VudCA9IDA7XHJcblxyXG5cdFx0Ly8gRmluZCBhbGwgZXh0ZXJuYWwgaW1hZ2UgVVJMcyAobm93IGFzeW5jIC0gdmVyaWZpZXMgd2l0aCBIRUFEIHJlcXVlc3RzKVxyXG5cdFx0Y29uc3QgZXh0ZXJuYWxJbWFnZXMgPSBhd2FpdCB0aGlzLmZpbmRFeHRlcm5hbEltYWdlcyhjb250ZW50LCBzb3VyY2VGaWxlKTtcclxuXHJcblx0XHRmb3IgKGNvbnN0IGltYWdlIG9mIGV4dGVybmFsSW1hZ2VzKSB7XHJcblx0XHRcdHRyeSB7XHJcblx0XHRcdFx0Ly8gSWYgYmFja2dyb3VuZCBhbmQgbW9kYWxzIGFyZSByZXF1aXJlZCBidXQgbm90IGFsbG93ZWQsIHNraXAgdGhpcyBpbWFnZVxyXG5cdFx0XHRcdC8vIE5vdGU6IGF1dG9SZW5hbWUgc2V0dGluZyBpcyBoYW5kbGVkIHdpdGhpbiByZW5hbWVJbWFnZUZpbGUsIFxyXG5cdFx0XHRcdC8vIGJ1dCB3ZSBjaGVjayBpdCBoZXJlIHRvIGF2b2lkIGRvd25sb2FkaW5nIGlmIHdlJ3JlIGdvaW5nIHRvIHNraXAgYW55d2F5XHJcblx0XHRcdFx0aWYgKGlzQmFja2dyb3VuZCAmJiAhdGhpcy5zZXR0aW5ncy5hdXRvUmVuYW1lKSB7XHJcblx0XHRcdFx0XHQvLyBTa2lwIGNvbnZlcnNpb24gdG8gYXZvaWQgc2hvd2luZyBhIG1vZGFsIGluIHRoZSBiYWNrZ3JvdW5kXHJcblx0XHRcdFx0XHRjb250aW51ZTtcclxuXHRcdFx0XHR9XHJcblxyXG5cdFx0XHRcdC8vIERvd25sb2FkIGFuZCBzYXZlIHRlbXBvcmFyaWx5XHJcblx0XHRcdFx0Y29uc3QgdGVtcFBhdGggPSBhd2FpdCB0aGlzLmRvd25sb2FkQW5kU2F2ZShpbWFnZS51cmwsIHNvdXJjZUZpbGUpO1xyXG5cdFx0XHRcdGlmICghdGVtcFBhdGgpIHtcclxuXHRcdFx0XHRcdGNvbnRpbnVlO1xyXG5cdFx0XHRcdH1cclxuXHJcblx0XHRcdFx0Y29uc3QgdGVtcEZpbGUgPSB0aGlzLmFwcC52YXVsdC5nZXRBYnN0cmFjdEZpbGVCeVBhdGgodGVtcFBhdGgpO1xyXG5cdFx0XHRcdGlmICghKHRlbXBGaWxlIGluc3RhbmNlb2YgVEZpbGUpKSB7XHJcblx0XHRcdFx0XHRjb250aW51ZTtcclxuXHRcdFx0XHR9XHJcblxyXG5cdFx0XHRcdC8vIFNob3cgcmVuYW1lIG1vZGFsIGlmIGVuYWJsZWQgKGFsd2F5cyBzaG93IGZvciBjb252ZXJzaW9uLCB1bmxlc3MgYXV0by1yZW5hbWUgaXMgb24pXHJcblx0XHRcdFx0bGV0IGZpbmFsRmlsZTogVEZpbGUgPSB0ZW1wRmlsZTtcclxuXHJcblx0XHRcdFx0Ly8gR2VuZXJhdGUgc3VnZ2VzdGVkIG5hbWUgZnJvbSBhbHQgdGV4dCBvciBVUkxcclxuXHRcdFx0XHRjb25zdCBzdWdnZXN0ZWROYW1lID0gaW1hZ2UuYWx0XHJcblx0XHRcdFx0XHQ/IHRoaXMuc3RvcmFnZU1hbmFnZXIuc2FuaXRpemVGaWxlTmFtZShpbWFnZS5hbHQpXHJcblx0XHRcdFx0XHQ6IHRlbXBGaWxlLmJhc2VuYW1lO1xyXG5cclxuXHRcdFx0XHQvLyBVc2UgSW1hZ2VQcm9jZXNzb3IncyByZW5hbWUgZmxvdyAod2hpY2ggaGFuZGxlcyBkZXNjcmlwdGl2ZSBpbWFnZXMgYW5kIHJlbmFtZSBtb2RhbClcclxuXHRcdFx0XHQvLyBGb3IgY29udmVyc2lvbiwgYWx3YXlzIHNob3cgcmVuYW1lIG1vZGFsIHVubGVzcyBhdXRvLXJlbmFtZSBpcyBlbmFibGVkXHJcblx0XHRcdFx0Y29uc3QgcmVzdWx0ID0gYXdhaXQgdGhpcy5pbWFnZVByb2Nlc3Nvci5yZW5hbWVJbWFnZUZpbGUoXHJcblx0XHRcdFx0XHR0ZW1wRmlsZSxcclxuXHRcdFx0XHRcdHN1Z2dlc3RlZE5hbWUsXHJcblx0XHRcdFx0XHRzb3VyY2VGaWxlXHJcblx0XHRcdFx0KTtcclxuXHJcblx0XHRcdFx0aWYgKHJlc3VsdCAmJiByZXN1bHQuZmlsZSkge1xyXG5cdFx0XHRcdFx0ZmluYWxGaWxlID0gcmVzdWx0LmZpbGU7XHJcblx0XHRcdFx0fSBlbHNlIHtcclxuXHRcdFx0XHRcdC8vIFVzZXIgY2FuY2VsbGVkIHJlbmFtZSwgc2tpcCB0aGlzIGltYWdlXHJcblx0XHRcdFx0XHRhd2FpdCB0aGlzLmFwcC5maWxlTWFuYWdlci50cmFzaEZpbGUodGVtcEZpbGUpO1xyXG5cdFx0XHRcdFx0Y29udGludWU7XHJcblx0XHRcdFx0fVxyXG5cclxuXHRcdFx0XHQvLyBVcGRhdGUgdGhlIGNvbnRlbnQgd2l0aCB0aGUgZmluYWwgZmlsZVxyXG5cdFx0XHRcdC8vIFRoZSByZXBsYWNlbWVudCBmdW5jdGlvbiBuZWVkcyB0aGUgZnVsbCBwYXRoIHRvIGdlbmVyYXRlIHByb3BlciByZWxhdGl2ZSBsaW5rc1xyXG5cdFx0XHRcdG5ld0NvbnRlbnQgPSBuZXdDb250ZW50LnJlcGxhY2UoaW1hZ2UuZnVsbE1hdGNoLCBpbWFnZS5yZXBsYWNlbWVudChmaW5hbEZpbGUucGF0aCkpO1xyXG5cdFx0XHRcdGNvdW50Kys7XHJcblx0XHRcdH0gY2F0Y2ggKGVycm9yKSB7XHJcblx0XHRcdFx0Y29uc29sZS5lcnJvcihgRmFpbGVkIHRvIGNvbnZlcnQgaW1hZ2U6ICR7aW1hZ2UudXJsfWAsIGVycm9yKTtcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cclxuXHRcdHJldHVybiB7IG5ld0NvbnRlbnQsIGNvdW50IH07XHJcblx0fVxyXG5cclxuXHQvKipcclxuXHQgKiBDaGVjayBpZiBhIHBvc2l0aW9uIGluIGNvbnRlbnQgaXMgaW5zaWRlIGEgY29kZSBibG9ja1xyXG5cdCAqL1xyXG5cdHByaXZhdGUgaXNJbnNpZGVDb2RlQmxvY2soY29udGVudDogc3RyaW5nLCBwb3NpdGlvbjogbnVtYmVyKTogYm9vbGVhbiB7XHJcblx0XHQvLyBDaGVjayBmb3IgZmVuY2VkIGNvZGUgYmxvY2tzIChgYGAuLi5gYGApXHJcblx0XHRjb25zdCBmZW5jZWRDb2RlQmxvY2tSZWdleCA9IC9gYGBbXFxzXFxTXSo/YGBgL2c7XHJcblx0XHRsZXQgbWF0Y2g7XHJcblx0XHR3aGlsZSAoKG1hdGNoID0gZmVuY2VkQ29kZUJsb2NrUmVnZXguZXhlYyhjb250ZW50KSkgIT09IG51bGwpIHtcclxuXHRcdFx0Y29uc3Qgc3RhcnQgPSBtYXRjaC5pbmRleDtcclxuXHRcdFx0Y29uc3QgZW5kID0gc3RhcnQgKyBtYXRjaFswXS5sZW5ndGg7XHJcblx0XHRcdGlmIChwb3NpdGlvbiA+PSBzdGFydCAmJiBwb3NpdGlvbiA8IGVuZCkge1xyXG5cdFx0XHRcdHJldHVybiB0cnVlO1xyXG5cdFx0XHR9XHJcblx0XHR9XHJcblxyXG5cdFx0Ly8gQ2hlY2sgZm9yIGlubGluZSBjb2RlIChgLi4uYClcclxuXHRcdC8vIFdlIG5lZWQgdG8gYmUgY2FyZWZ1bCAtIG9ubHkgbWF0Y2ggYmFja3RpY2tzIHRoYXQgYXJlbid0IHBhcnQgb2YgZmVuY2VkIGJsb2Nrc1xyXG5cdFx0Ly8gRmlyc3QsIG1hcmsgYWxsIGZlbmNlZCBjb2RlIGJsb2NrIHBvc2l0aW9uc1xyXG5cdFx0Y29uc3QgZmVuY2VkUG9zaXRpb25zOiBib29sZWFuW10gPSBBcnJheS5mcm9tKHsgbGVuZ3RoOiBjb250ZW50Lmxlbmd0aCB9LCAoKSA9PiBmYWxzZSk7XHJcblx0XHRjb25zdCBmZW5jZWRSZWdleCA9IC9gYGBbXFxzXFxTXSo/YGBgL2c7XHJcblx0XHR3aGlsZSAoKG1hdGNoID0gZmVuY2VkUmVnZXguZXhlYyhjb250ZW50KSkgIT09IG51bGwpIHtcclxuXHRcdFx0Zm9yIChsZXQgaSA9IG1hdGNoLmluZGV4OyBpIDwgbWF0Y2guaW5kZXggKyBtYXRjaFswXS5sZW5ndGg7IGkrKykge1xyXG5cdFx0XHRcdGZlbmNlZFBvc2l0aW9uc1tpXSA9IHRydWU7XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHJcblx0XHQvLyBOb3cgY2hlY2sgZm9yIGlubGluZSBjb2RlLCBidXQgc2tpcCBwb3NpdGlvbnMgaW5zaWRlIGZlbmNlZCBibG9ja3NcclxuXHRcdGNvbnN0IGlubGluZUNvZGVSZWdleCA9IC9gW15gXFxuXStgL2c7XHJcblx0XHR3aGlsZSAoKG1hdGNoID0gaW5saW5lQ29kZVJlZ2V4LmV4ZWMoY29udGVudCkpICE9PSBudWxsKSB7XHJcblx0XHRcdC8vIFNraXAgaWYgdGhpcyBtYXRjaCBpcyBpbnNpZGUgYSBmZW5jZWQgY29kZSBibG9ja1xyXG5cdFx0XHRpZiAoZmVuY2VkUG9zaXRpb25zW21hdGNoLmluZGV4XSkge1xyXG5cdFx0XHRcdGNvbnRpbnVlO1xyXG5cdFx0XHR9XHJcblx0XHRcdGNvbnN0IHN0YXJ0ID0gbWF0Y2guaW5kZXg7XHJcblx0XHRcdGNvbnN0IGVuZCA9IHN0YXJ0ICsgbWF0Y2hbMF0ubGVuZ3RoO1xyXG5cdFx0XHRpZiAocG9zaXRpb24gPj0gc3RhcnQgJiYgcG9zaXRpb24gPCBlbmQpIHtcclxuXHRcdFx0XHRyZXR1cm4gdHJ1ZTtcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cclxuXHRcdHJldHVybiBmYWxzZTtcclxuXHR9XHJcblxyXG5cdC8qKlxyXG5cdCAqIEZpbmQgYWxsIGV4dGVybmFsIGltYWdlcyBpbiBjb250ZW50XHJcblx0ICogVmVyaWZpZXMgZWFjaCBVUkwgd2l0aCBIRUFEIHJlcXVlc3QgdG8gZW5zdXJlIGl0IGFjdHVhbGx5IHNlcnZlcyBhbiBpbWFnZVxyXG5cdCAqL1xyXG5cdHByaXZhdGUgYXN5bmMgZmluZEV4dGVybmFsSW1hZ2VzKGNvbnRlbnQ6IHN0cmluZywgc291cmNlRmlsZTogVEZpbGUpOiBQcm9taXNlPEV4dGVybmFsSW1hZ2VNYXRjaFtdPiB7XHJcblx0XHRjb25zdCBjYW5kaWRhdGVNYXRjaGVzOiBBcnJheTx7XHJcblx0XHRcdGZ1bGxNYXRjaDogc3RyaW5nO1xyXG5cdFx0XHR1cmw6IHN0cmluZztcclxuXHRcdFx0YWx0Pzogc3RyaW5nO1xyXG5cdFx0XHRyZXBsYWNlbWVudDogKGxvY2FsUGF0aDogc3RyaW5nKSA9PiBzdHJpbmc7XHJcblx0XHR9PiA9IFtdO1xyXG5cclxuXHRcdC8vIE1hcmtkb3duIGltYWdlczogIVthbHRdKHVybClcclxuXHRcdGxldCBtYXRjaDtcclxuXHRcdGNvbnN0IG1kUmVnZXggPSBuZXcgUmVnRXhwKE1BUktET1dOX0lNQUdFX1JFR0VYLnNvdXJjZSwgJ2cnKTtcclxuXHRcdHdoaWxlICgobWF0Y2ggPSBtZFJlZ2V4LmV4ZWMoY29udGVudCkpICE9PSBudWxsKSB7XHJcblx0XHRcdGNvbnN0IG1hdGNoSW5kZXggPSBtYXRjaC5pbmRleDtcclxuXHRcdFx0Ly8gU2tpcCBpZiBpbnNpZGUgYSBjb2RlIGJsb2NrXHJcblx0XHRcdGlmICh0aGlzLmlzSW5zaWRlQ29kZUJsb2NrKGNvbnRlbnQsIG1hdGNoSW5kZXgpKSB7XHJcblx0XHRcdFx0Y29udGludWU7XHJcblx0XHRcdH1cclxuXHJcblx0XHRcdGNvbnN0IGZ1bGxNYXRjaCA9IG1hdGNoWzBdO1xyXG5cdFx0XHRjb25zdCBhbHQgPSBtYXRjaFsxXSA/PyAnJztcclxuXHRcdFx0Y29uc3QgdXJsID0gbWF0Y2hbMl07XHJcblx0XHRcdC8vIE9ubHkgcHJvY2VzcyBpZiBpdCdzIGFuIGV4dGVybmFsIFVSTCBhbmQgcGFzc2VzIHByZWxpbWluYXJ5IGZpbHRlclxyXG5cdFx0XHRpZiAodXJsICYmIHRoaXMuaXNFeHRlcm5hbFVybCh1cmwpICYmIHRoaXMuaXNJbWFnZVVybCh1cmwpKSB7XHJcblx0XHRcdFx0Y29uc3Qgc291cmNlRmlsZVJlZiA9IHNvdXJjZUZpbGU7IC8vIENhcHR1cmUgZm9yIGNsb3N1cmVcclxuXHRcdFx0XHRjYW5kaWRhdGVNYXRjaGVzLnB1c2goe1xyXG5cdFx0XHRcdFx0ZnVsbE1hdGNoLFxyXG5cdFx0XHRcdFx0dXJsLFxyXG5cdFx0XHRcdFx0YWx0LFxyXG5cdFx0XHRcdFx0cmVwbGFjZW1lbnQ6IChsb2NhbFBhdGg6IHN0cmluZykgPT4ge1xyXG5cdFx0XHRcdFx0XHQvLyBHZXQgdGhlIHNhdmVkIGZpbGUgdG8gZ2VuZXJhdGUgcHJvcGVyIG1hcmtkb3duIGxpbmtcclxuXHRcdFx0XHRcdFx0Y29uc3Qgc2F2ZWRGaWxlID0gdGhpcy5hcHAudmF1bHQuZ2V0QWJzdHJhY3RGaWxlQnlQYXRoKGxvY2FsUGF0aCk7XHJcblx0XHRcdFx0XHRcdGlmIChzYXZlZEZpbGUgaW5zdGFuY2VvZiBURmlsZSkge1xyXG5cdFx0XHRcdFx0XHRcdGNvbnN0IGxpbmsgPSB0aGlzLnN0b3JhZ2VNYW5hZ2VyLmdlbmVyYXRlTWFya2Rvd25MaW5rKHNhdmVkRmlsZSwgc291cmNlRmlsZVJlZi5wYXRoKTtcclxuXHRcdFx0XHRcdFx0XHQvLyBJZiB3ZSBoYXZlIGFsdCB0ZXh0IGFuZCBsaW5rIGlzIHdpa2lsaW5rLCBhZGQgZGlzcGxheSB0ZXh0XHJcblx0XHRcdFx0XHRcdFx0aWYgKGFsdCAmJiBsaW5rLnN0YXJ0c1dpdGgoJyFbJykgJiYgbGluay5pbmNsdWRlcygnXV0nKSkge1xyXG5cdFx0XHRcdFx0XHRcdFx0cmV0dXJuIGxpbmsucmVwbGFjZSgnXV0nLCBgfCR7YWx0fV1dYCk7XHJcblx0XHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHRcdC8vIEZvciBtYXJrZG93biBsaW5rcywgcmVwbGFjZSB0aGUgVVJMIGJ1dCBrZWVwIGFsdFxyXG5cdFx0XHRcdFx0XHRcdGlmIChsaW5rLnN0YXJ0c1dpdGgoJyFbJykgJiYgbGluay5pbmNsdWRlcygnXSgnKSkge1xyXG5cdFx0XHRcdFx0XHRcdFx0Ly8gRXh0cmFjdCBqdXN0IHRoZSBwYXRoIHBhcnQgZnJvbSB0aGUgZ2VuZXJhdGVkIGxpbmsgYW5kIHVzZSBpdCB3aXRoIGFsdFxyXG5cdFx0XHRcdFx0XHRcdFx0Y29uc3QgcGF0aE1hdGNoID0gbGluay5tYXRjaCgvXFxdXFwoKFteKV0rKVxcKS8pO1xyXG5cdFx0XHRcdFx0XHRcdFx0aWYgKHBhdGhNYXRjaCkge1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRyZXR1cm4gYCFbJHthbHR9XSgke3BhdGhNYXRjaFsxXX0pYDtcclxuXHRcdFx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0XHRcdHJldHVybiBgIVske2FsdH1dKCR7ZW5jb2RlVVJJKGxvY2FsUGF0aCl9KWA7XHJcblx0XHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHRcdHJldHVybiBsaW5rO1xyXG5cdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdC8vIEZhbGxiYWNrIC0gdXNlIHJlbGF0aXZlIHBhdGhcclxuXHRcdFx0XHRcdFx0Y29uc3QgbG9jYWxGaWxlID0gdGhpcy5hcHAudmF1bHQuZ2V0QWJzdHJhY3RGaWxlQnlQYXRoKGxvY2FsUGF0aCk7XHJcblx0XHRcdFx0XHRcdGlmIChsb2NhbEZpbGUgaW5zdGFuY2VvZiBURmlsZSkge1xyXG5cdFx0XHRcdFx0XHRcdGNvbnN0IHJlbGF0aXZlUGF0aCA9IHRoaXMuc3RvcmFnZU1hbmFnZXIuZ2V0UmVsYXRpdmVQYXRoKHNvdXJjZUZpbGVSZWYsIGxvY2FsRmlsZSk7XHJcblx0XHRcdFx0XHRcdFx0cmV0dXJuIGAhWyR7YWx0fV0oJHtlbmNvZGVVUkkocmVsYXRpdmVQYXRoKX0pYDtcclxuXHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHRyZXR1cm4gYCFbJHthbHR9XSgke2VuY29kZVVSSShsb2NhbFBhdGgpfSlgO1xyXG5cdFx0XHRcdFx0fSxcclxuXHRcdFx0XHR9KTtcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cclxuXHRcdC8vIEhUTUwgaW1hZ2VzOiA8aW1nIHNyYz1cInVybFwiPlxyXG5cdFx0Y29uc3QgaHRtbFJlZ2V4ID0gbmV3IFJlZ0V4cChIVE1MX0lNQUdFX1JFR0VYLnNvdXJjZSwgJ2cnKTtcclxuXHRcdHdoaWxlICgobWF0Y2ggPSBodG1sUmVnZXguZXhlYyhjb250ZW50KSkgIT09IG51bGwpIHtcclxuXHRcdFx0Y29uc3QgbWF0Y2hJbmRleCA9IG1hdGNoLmluZGV4O1xyXG5cdFx0XHQvLyBTa2lwIGlmIGluc2lkZSBhIGNvZGUgYmxvY2tcclxuXHRcdFx0aWYgKHRoaXMuaXNJbnNpZGVDb2RlQmxvY2soY29udGVudCwgbWF0Y2hJbmRleCkpIHtcclxuXHRcdFx0XHRjb250aW51ZTtcclxuXHRcdFx0fVxyXG5cdFx0XHRjb25zdCBmdWxsTWF0Y2ggPSBtYXRjaFswXTtcclxuXHRcdFx0Y29uc3QgdXJsID0gbWF0Y2hbMV07XHJcblx0XHRcdC8vIE9ubHkgcHJvY2VzcyBpZiBpdCdzIGFuIGV4dGVybmFsIFVSTCBhbmQgcGFzc2VzIHByZWxpbWluYXJ5IGZpbHRlclxyXG5cdFx0XHRpZiAodXJsICYmIHRoaXMuaXNFeHRlcm5hbFVybCh1cmwpICYmIHRoaXMuaXNJbWFnZVVybCh1cmwpKSB7XHJcblx0XHRcdFx0Y2FuZGlkYXRlTWF0Y2hlcy5wdXNoKHtcclxuXHRcdFx0XHRcdGZ1bGxNYXRjaCxcclxuXHRcdFx0XHRcdHVybCxcclxuXHRcdFx0XHRcdHJlcGxhY2VtZW50OiAobG9jYWxQYXRoOiBzdHJpbmcpID0+IGAhW10oJHtlbmNvZGVVUkkobG9jYWxQYXRoKX0pYCxcclxuXHRcdFx0XHR9KTtcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cclxuXHRcdC8vIFZlcmlmeSBlYWNoIGNhbmRpZGF0ZSBVUkwgd2l0aCBIRUFEIHJlcXVlc3RcclxuXHRcdGNvbnN0IHZlcmlmaWVkTWF0Y2hlczogRXh0ZXJuYWxJbWFnZU1hdGNoW10gPSBbXTtcclxuXHRcdGZvciAoY29uc3QgY2FuZGlkYXRlIG9mIGNhbmRpZGF0ZU1hdGNoZXMpIHtcclxuXHRcdFx0Y29uc3QgaXNJbWFnZSA9IGF3YWl0IHRoaXMudmVyaWZ5SW1hZ2VVcmwoY2FuZGlkYXRlLnVybCk7XHJcblx0XHRcdGlmIChpc0ltYWdlKSB7XHJcblx0XHRcdFx0dmVyaWZpZWRNYXRjaGVzLnB1c2goY2FuZGlkYXRlKTtcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cclxuXHRcdHJldHVybiB2ZXJpZmllZE1hdGNoZXM7XHJcblx0fVxyXG5cclxuXHQvKipcclxuXHQgKiBDaGVjayBpZiBhIFVSTCBpcyBleHRlcm5hbFxyXG5cdCAqL1xyXG5cdHByaXZhdGUgaXNFeHRlcm5hbFVybCh1cmw6IHN0cmluZyk6IGJvb2xlYW4ge1xyXG5cdFx0dHJ5IHtcclxuXHRcdFx0Y29uc3QgcGFyc2VkID0gbmV3IFVSTCh1cmwpO1xyXG5cdFx0XHRyZXR1cm4gWydodHRwOicsICdodHRwczonXS5pbmNsdWRlcyhwYXJzZWQucHJvdG9jb2wpO1xyXG5cdFx0fSBjYXRjaCB7XHJcblx0XHRcdHJldHVybiBmYWxzZTtcclxuXHRcdH1cclxuXHR9XHJcblxyXG5cdC8qKlxyXG5cdCAqIENoZWNrIGlmIGEgVVJMIHNob3VsZCBiZSBjb25zaWRlcmVkIGZvciBpbWFnZSBjb252ZXJzaW9uXHJcblx0ICogUmV0dXJucyBmYWxzZSBmb3Iga25vd24gbm9uLWltYWdlIGVtYmVkIGRvbWFpbnMgKFlvdVR1YmUsIGV0Yy4pXHJcblx0ICogVGhpcyBpcyBhIHByZWxpbWluYXJ5IGZpbHRlciAtIGFjdHVhbCBpbWFnZSB2ZXJpZmljYXRpb24gaGFwcGVucyB2aWEgSEVBRCByZXF1ZXN0XHJcblx0ICovXHJcblx0cHJpdmF0ZSBpc0ltYWdlVXJsKHVybDogc3RyaW5nKTogYm9vbGVhbiB7XHJcblx0XHR0cnkge1xyXG5cdFx0XHRjb25zdCBwYXJzZWQgPSBuZXcgVVJMKHVybCk7XHJcblx0XHRcdGNvbnN0IGhvc3RuYW1lID0gcGFyc2VkLmhvc3RuYW1lLnRvTG93ZXJDYXNlKCk7XHJcblxyXG5cdFx0XHQvLyBFeGNsdWRlIGtub3duIG5vbi1pbWFnZSBlbWJlZCBkb21haW5zXHJcblx0XHRcdGNvbnN0IG5vbkltYWdlRG9tYWlucyA9IFtcclxuXHRcdFx0XHQneW91dHViZS5jb20nLFxyXG5cdFx0XHRcdCd3d3cueW91dHViZS5jb20nLFxyXG5cdFx0XHRcdCd5b3V0dS5iZScsXHJcblx0XHRcdFx0J20ueW91dHViZS5jb20nLFxyXG5cdFx0XHRcdCd5b3V0dWJlLW5vY29va2llLmNvbScsXHJcblx0XHRcdFx0J3d3dy55b3V0dWJlLW5vY29va2llLmNvbScsXHJcblx0XHRcdFx0J3ZpbWVvLmNvbScsXHJcblx0XHRcdFx0J3d3dy52aW1lby5jb20nLFxyXG5cdFx0XHRcdCdzcG90aWZ5LmNvbScsXHJcblx0XHRcdFx0J29wZW4uc3BvdGlmeS5jb20nLFxyXG5cdFx0XHRcdCdzb3VuZGNsb3VkLmNvbScsXHJcblx0XHRcdFx0J3d3dy5zb3VuZGNsb3VkLmNvbScsXHJcblx0XHRcdF07XHJcblxyXG5cdFx0XHRpZiAobm9uSW1hZ2VEb21haW5zLnNvbWUoZG9tYWluID0+IGhvc3RuYW1lID09PSBkb21haW4gfHwgaG9zdG5hbWUuZW5kc1dpdGgoJy4nICsgZG9tYWluKSkpIHtcclxuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XHJcblx0XHRcdH1cclxuXHJcblx0XHRcdC8vIEFsbG93IGFsbCBvdGhlciBleHRlcm5hbCBVUkxzIC0gd2UnbGwgdmVyaWZ5IHdpdGggSEVBRCByZXF1ZXN0XHJcblx0XHRcdHJldHVybiB0cnVlO1xyXG5cdFx0fSBjYXRjaCB7XHJcblx0XHRcdHJldHVybiBmYWxzZTtcclxuXHRcdH1cclxuXHR9XHJcblxyXG5cdC8qKlxyXG5cdCAqIFZlcmlmeSBpZiBhIFVSTCBhY3R1YWxseSBzZXJ2ZXMgYW4gaW1hZ2UgYnkgY2hlY2tpbmcgQ29udGVudC1UeXBlIGhlYWRlclxyXG5cdCAqIFVzZXMgSEVBRCByZXF1ZXN0IHRvIGF2b2lkIGRvd25sb2FkaW5nIG5vbi1pbWFnZSBjb250ZW50XHJcblx0ICovXHJcblx0cHJpdmF0ZSBhc3luYyB2ZXJpZnlJbWFnZVVybCh1cmw6IHN0cmluZyk6IFByb21pc2U8Ym9vbGVhbj4ge1xyXG5cdFx0dHJ5IHtcclxuXHRcdFx0Y29uc3QgcmVzcG9uc2UgPSBhd2FpdCByZXF1ZXN0VXJsKHsgdXJsLCBtZXRob2Q6ICdIRUFEJyB9KTtcclxuXHRcdFx0Y29uc3QgY29udGVudFR5cGUgPSByZXNwb25zZS5oZWFkZXJzWydjb250ZW50LXR5cGUnXT8udG9Mb3dlckNhc2UoKSA/PyAnJztcclxuXHJcblx0XHRcdC8vIENoZWNrIGlmIENvbnRlbnQtVHlwZSBzdGFydHMgd2l0aCAnaW1hZ2UvJ1xyXG5cdFx0XHRyZXR1cm4gY29udGVudFR5cGUuc3RhcnRzV2l0aCgnaW1hZ2UvJyk7XHJcblx0XHR9IGNhdGNoIHtcclxuXHRcdFx0Ly8gT24gZXJyb3IgKG5ldHdvcmsgaXNzdWVzLCBDT1JTLCBldGMuKSwgcmV0dXJuIGZhbHNlIHRvIHNraXAgdGhpcyBVUkxcclxuXHRcdFx0cmV0dXJuIGZhbHNlO1xyXG5cdFx0fVxyXG5cdH1cclxuXHJcblx0LyoqXHJcblx0ICogRG93bmxvYWQgYW4gaW1hZ2UgYW5kIHNhdmUgaXQgbG9jYWxseVxyXG5cdCAqIEluY2x1ZGVzIENvbnRlbnQtVHlwZSB2YWxpZGF0aW9uIGFzIGEgc2FmZXR5IG5ldFxyXG5cdCAqL1xyXG5cdHByaXZhdGUgYXN5bmMgZG93bmxvYWRBbmRTYXZlKHVybDogc3RyaW5nLCBzb3VyY2VGaWxlOiBURmlsZSk6IFByb21pc2U8c3RyaW5nIHwgbnVsbD4ge1xyXG5cdFx0dHJ5IHtcclxuXHRcdFx0Y29uc3QgcmVzcG9uc2UgPSBhd2FpdCByZXF1ZXN0VXJsKHsgdXJsIH0pO1xyXG5cdFx0XHRpZiAocmVzcG9uc2Uuc3RhdHVzID49IDQwMCkge1xyXG5cdFx0XHRcdHRocm93IG5ldyBFcnJvcihgSFRUUCAke3Jlc3BvbnNlLnN0YXR1c31gKTtcclxuXHRcdFx0fVxyXG5cclxuXHRcdFx0Y29uc3QgY29udGVudFR5cGUgPSByZXNwb25zZS5oZWFkZXJzWydjb250ZW50LXR5cGUnXSA/PyAnJztcclxuXHJcblx0XHRcdC8vIFNhZmV0eSBuZXQ6IHZlcmlmeSBDb250ZW50LVR5cGUgaXMgYWN0dWFsbHkgYW4gaW1hZ2VcclxuXHRcdFx0Ly8gVGhpcyBwcm92aWRlcyBkZWZlbnNlIGluIGRlcHRoIGluIGNhc2UgSEVBRCByZXF1ZXN0IHdhcyBieXBhc3NlZCBvciBDb250ZW50LVR5cGUgY2hhbmdlZFxyXG5cdFx0XHRpZiAoIWNvbnRlbnRUeXBlLnRvTG93ZXJDYXNlKCkuc3RhcnRzV2l0aCgnaW1hZ2UvJykpIHtcclxuXHRcdFx0XHRjb25zb2xlLndhcm4oYFNraXBwaW5nICR7dXJsfTogQ29udGVudC1UeXBlIGlzICR7Y29udGVudFR5cGV9LCBub3QgYW4gaW1hZ2VgKTtcclxuXHRcdFx0XHRyZXR1cm4gbnVsbDtcclxuXHRcdFx0fVxyXG5cclxuXHRcdFx0Y29uc3QgZXh0ZW5zaW9uID0gdGhpcy5zdG9yYWdlTWFuYWdlci5nZXRFeHRlbnNpb25Gcm9tTWltZVR5cGUoY29udGVudFR5cGUpO1xyXG5cdFx0XHRjb25zdCBhcnJheUJ1ZmZlciA9IHJlc3BvbnNlLmFycmF5QnVmZmVyO1xyXG5cclxuXHRcdFx0Ly8gR2VuZXJhdGUgYSBuYW1lIGJhc2VkIG9uIFVSTCBvciBoYXNoXHJcblx0XHRcdGNvbnN0IHVybFBhdGggPSBuZXcgVVJMKHVybCkucGF0aG5hbWU7XHJcblx0XHRcdGNvbnN0IHVybEZpbGVOYW1lID0gdXJsUGF0aC5zcGxpdCgnLycpLnBvcCgpPy5zcGxpdCgnLicpWzBdID8/ICdpbWFnZSc7XHJcblx0XHRcdGNvbnN0IGJhc2VOYW1lID0gdGhpcy5zdG9yYWdlTWFuYWdlci5zYW5pdGl6ZUZpbGVOYW1lKHVybEZpbGVOYW1lKTtcclxuXHJcblx0XHRcdGNvbnN0IGZpbGVQYXRoID0gYXdhaXQgdGhpcy5zdG9yYWdlTWFuYWdlci5nZXRBdmFpbGFibGVQYXRoKGJhc2VOYW1lLCBleHRlbnNpb24sIHNvdXJjZUZpbGUpO1xyXG5cdFx0XHRhd2FpdCB0aGlzLnN0b3JhZ2VNYW5hZ2VyLnNhdmVGaWxlKGFycmF5QnVmZmVyLCBmaWxlUGF0aCk7XHJcblxyXG5cdFx0XHQvLyBSZXR1cm4gZnVsbCB2YXVsdCBwYXRoIC0gdGhlIHJlcGxhY2VtZW50IGZ1bmN0aW9uIHdpbGwgaGFuZGxlIGNvbnZlcnNpb25cclxuXHRcdFx0cmV0dXJuIGZpbGVQYXRoO1xyXG5cdFx0fSBjYXRjaCAoZXJyb3IpIHtcclxuXHRcdFx0Y29uc29sZS5lcnJvcihgRmFpbGVkIHRvIGRvd25sb2FkICR7dXJsfTpgLCBlcnJvcik7XHJcblx0XHRcdHJldHVybiBudWxsO1xyXG5cdFx0fVxyXG5cdH1cclxuXHJcblx0LyoqXHJcblx0ICogUHJvY2VzcyBhbGwgZmlsZXMgaW4gdGhlIHZhdWx0XHJcblx0ICovXHJcblx0YXN5bmMgcHJvY2Vzc0FsbEZpbGVzKCk6IFByb21pc2U8bnVtYmVyPiB7XHJcblx0XHRjb25zdCBmaWxlcyA9IHRoaXMuYXBwLnZhdWx0LmdldE1hcmtkb3duRmlsZXMoKTtcclxuXHRcdGxldCB0b3RhbENvdW50ID0gMDtcclxuXHJcblx0XHRmb3IgKGNvbnN0IGZpbGUgb2YgZmlsZXMpIHtcclxuXHRcdFx0aWYgKHRoaXMuc2V0dGluZ3Muc3VwcG9ydGVkRXh0ZW5zaW9ucy5pbmNsdWRlcyhmaWxlLmV4dGVuc2lvbikpIHtcclxuXHRcdFx0XHRjb25zdCBjb3VudCA9IGF3YWl0IHRoaXMucHJvY2Vzc0ZpbGUoZmlsZSk7XHJcblx0XHRcdFx0dG90YWxDb3VudCArPSBjb3VudDtcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cclxuXHRcdHJldHVybiB0b3RhbENvdW50O1xyXG5cdH1cclxuXHJcblx0LyoqXHJcblx0ICogUmVnaXN0ZXIgZXZlbnQgaGFuZGxlcnMgZm9yIGF1dG9tYXRpYyBjb252ZXJzaW9uXHJcblx0ICovXHJcblx0cmVnaXN0ZXJFdmVudEhhbmRsZXJzKFxyXG5cdFx0b25Ob3RlT3BlbjogKGZpbGU6IFRGaWxlKSA9PiB2b2lkLFxyXG5cdFx0b25Ob3RlU2F2ZTogKGZpbGU6IFRGaWxlKSA9PiB2b2lkXHJcblx0KTogdm9pZCB7XHJcblx0XHQvLyBUaGVzZSBoYW5kbGVycyBzaG91bGQgYmUgcmVnaXN0ZXJlZCBieSB0aGUgbWFpbiBwbHVnaW5cclxuXHRcdC8vIFRoaXMgbWV0aG9kIGlzIHByb3ZpZGVkIGZvciBkb2N1bWVudGF0aW9uIHB1cnBvc2VzXHJcblx0fVxyXG59XHJcblxyXG5pbnRlcmZhY2UgRXh0ZXJuYWxJbWFnZU1hdGNoIHtcclxuXHRmdWxsTWF0Y2g6IHN0cmluZztcclxuXHR1cmw6IHN0cmluZztcclxuXHRhbHQ/OiBzdHJpbmc7XHJcblx0cmVwbGFjZW1lbnQ6IChsb2NhbFBhdGg6IHN0cmluZykgPT4gc3RyaW5nO1xyXG59XHJcbiIsICIvKipcbiAqIEJhbm5lciBTZXJ2aWNlXG4gKiBIYW5kbGVzIGJhbm5lciBpbWFnZSByZW5kZXJpbmcgZnJvbSBmcm9udG1hdHRlciBwcm9wZXJ0aWVzXG4gKiBTdXBwb3J0cyBib3RoIE1EIGFuZCBNRFggZmlsZXMgdmlhIG1keC1mcm9udG1hdHRlciB1dGlsaXRpZXNcbiAqL1xuXG5pbXBvcnQge1xuXHRBcHAsXG5cdE1hcmtkb3duVmlldyxcblx0UGxhdGZvcm0sXG5cdFRGaWxlLFxuXHRXb3Jrc3BhY2VMZWFmLFxuXHRyZXF1ZXN0VXJsLFxufSBmcm9tICdvYnNpZGlhbic7XG5pbXBvcnQgKiBhcyBPYnNpZGlhbk1vZHVsZSBmcm9tICdvYnNpZGlhbic7XG5cbi8qKlxuICogSGVscGVyIHRvIHNldCBDU1MgcHJvcGVydGllcyBvbiBhbiBlbGVtZW50XG4gKiBVc2VzIHNldENzc1Byb3BlcnRpZXMgaWYgYXZhaWxhYmxlIChPYnNpZGlhbiAxLjExLjArKSwgZmFsbHMgYmFjayB0byBzdHlsZS5zZXRQcm9wZXJ0eVxuICovXG5mdW5jdGlvbiBzZXRDc3NQcm9wZXJ0aWVzKGVsZW1lbnQ6IEhUTUxFbGVtZW50LCBwcm9wczogUmVjb3JkPHN0cmluZywgc3RyaW5nPik6IHZvaWQge1xuXHQvLyBUcnkgdG8gdXNlIHNldENzc1Byb3BlcnRpZXMgaWYgYXZhaWxhYmxlXG5cdGNvbnN0IG9ic2lkaWFuID0gT2JzaWRpYW5Nb2R1bGUgYXMgdW5rbm93biBhcyB7IHNldENzc1Byb3BlcnRpZXM/OiAoZWw6IEhUTUxFbGVtZW50LCBwcm9wczogUmVjb3JkPHN0cmluZywgc3RyaW5nPikgPT4gdm9pZCB9O1xuXHRpZiAodHlwZW9mIG9ic2lkaWFuLnNldENzc1Byb3BlcnRpZXMgPT09ICdmdW5jdGlvbicpIHtcblx0XHRvYnNpZGlhbi5zZXRDc3NQcm9wZXJ0aWVzKGVsZW1lbnQsIHByb3BzKTtcblx0fSBlbHNlIHtcblx0XHQvLyBGYWxsYmFjayBmb3Igb2xkZXIgdmVyc2lvbnNcblx0XHRmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiBPYmplY3QuZW50cmllcyhwcm9wcykpIHtcblx0XHRcdGVsZW1lbnQuc3R5bGUuc2V0UHJvcGVydHkoa2V5LCB2YWx1ZSk7XG5cdFx0fVxuXHR9XG59XG5pbXBvcnQge1xuXHRJbWFnZU1hbmFnZXJTZXR0aW5ncyxcblx0QmFubmVyRGV2aWNlU2V0dGluZ3MsXG5cdEJhbm5lckltYWdlT3B0aW9ucyxcblx0QmFubmVyRGF0YSxcblx0QmFubmVyQ29udGVudFR5cGUsXG5cdEJhbm5lckljb25UeXBlLFxuXHREZXZpY2VUeXBlLFxufSBmcm9tICcuLi90eXBlcyc7XG5pbXBvcnQgeyBnZXRGcm9udG1hdHRlciB9IGZyb20gJy4uL3V0aWxzL21keC1mcm9udG1hdHRlcic7XG5cbi8vIENTUyBjbGFzcyBuYW1lc1xuY29uc3QgQ1NTX0NMQVNTRVMgPSB7XG5cdE1haW46ICdpbWFnZS1tYW5hZ2VyLWJhbm5lcicsXG5cdENvbnRlbnQ6ICdiYW5uZXItY29udGVudCcsXG5cdEljb246ICdiYW5uZXItaWNvbicsXG5cdFN0YXRpYzogJ3N0YXRpYycsXG59IGFzIGNvbnN0O1xuXG4vLyBSZWd1bGFyIGV4cHJlc3Npb25zIGZvciBwYXJzaW5nIGltYWdlIGxpbmtzXG5jb25zdCBQQVRURVJOUyA9IHtcblx0V2lraWxpbms6IC9eIT9cXFtcXFsoW15cXF1dKz8pKFxcfChbXlxcXV0rPykpP1xcXVxcXSQvLFxuXHRNYXJrZG93bjogL14hP1xcWyhbXlxcXV0qKVxcXVxcKChbXildKz8pXFwpJC8sXG5cdE1hcmtkb3duQmFyZTogL14hPzwoW14+XSspPiQvLFxuXHRXZWJsaW5rOiAvXmh0dHBzPzpcXC9cXC8vaSxcbn07XG5cbi8qKlxuICogU3RvcmUgZm9yIGJhbm5lciBkYXRhIHBlciBsZWFmXG4gKi9cbmNvbnN0IGJhbm5lckRhdGFTdG9yZSA9IG5ldyBNYXA8c3RyaW5nLCBCYW5uZXJEYXRhPigpO1xuXG5leHBvcnQgY2xhc3MgQmFubmVyU2VydmljZSB7XG5cdHByaXZhdGUgYXBwOiBBcHA7XG5cdHByaXZhdGUgc2V0dGluZ3M6IEltYWdlTWFuYWdlclNldHRpbmdzO1xuXG5cdGNvbnN0cnVjdG9yKGFwcDogQXBwLCBzZXR0aW5nczogSW1hZ2VNYW5hZ2VyU2V0dGluZ3MsIG9ic2VydmFibGU/OiB7IHN1YnNjcmliZShmbjogKHNldHRpbmdzOiBJbWFnZU1hbmFnZXJTZXR0aW5ncykgPT4gdm9pZCk6IHZvaWQgfSkge1xuXHRcdHRoaXMuYXBwID0gYXBwO1xuXHRcdHRoaXMuc2V0dGluZ3MgPSBzZXR0aW5ncztcblxuXHRcdC8vIFN1YnNjcmliZSB0byBzZXR0aW5ncyB1cGRhdGVzIGlmIG9ic2VydmFibGUgaXMgcHJvdmlkZWRcblx0XHRvYnNlcnZhYmxlPy5zdWJzY3JpYmUoKG5ld1NldHRpbmdzKSA9PiB7XG5cdFx0XHR0aGlzLnVwZGF0ZVNldHRpbmdzKG5ld1NldHRpbmdzKTtcblx0XHRcdHRoaXMuYXBwbHlTZXR0aW5ncygpO1xuXHRcdH0pO1xuXHR9XG5cblx0LyoqXG5cdCAqIFVwZGF0ZSBzZXR0aW5ncyByZWZlcmVuY2Vcblx0ICovXG5cdHVwZGF0ZVNldHRpbmdzKHNldHRpbmdzOiBJbWFnZU1hbmFnZXJTZXR0aW5ncyk6IHZvaWQge1xuXHRcdHRoaXMuc2V0dGluZ3MgPSBzZXR0aW5ncztcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXQgdGhlIGN1cnJlbnQgZGV2aWNlIHR5cGVcblx0ICovXG5cdGdldEN1cnJlbnREZXZpY2UoKTogRGV2aWNlVHlwZSB7XG5cdFx0aWYgKFBsYXRmb3JtLmlzUGhvbmUpIHtcblx0XHRcdHJldHVybiBEZXZpY2VUeXBlLlBob25lO1xuXHRcdH1cblx0XHRpZiAoUGxhdGZvcm0uaXNUYWJsZXQpIHtcblx0XHRcdHJldHVybiBEZXZpY2VUeXBlLlRhYmxldDtcblx0XHR9XG5cdFx0cmV0dXJuIERldmljZVR5cGUuRGVza3RvcDtcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXQgZGV2aWNlLXNwZWNpZmljIHNldHRpbmdzXG5cdCAqL1xuXHRnZXREZXZpY2VTZXR0aW5ncygpOiBCYW5uZXJEZXZpY2VTZXR0aW5ncyB7XG5cdFx0Y29uc3QgZGV2aWNlID0gdGhpcy5nZXRDdXJyZW50RGV2aWNlKCk7XG5cdFx0cmV0dXJuIHRoaXMuc2V0dGluZ3MuYmFubmVyW2RldmljZV07XG5cdH1cblxuXHQvKipcblx0ICogUHJvY2VzcyBhbGwgb3BlbiBtYXJrZG93biB2aWV3c1xuXHQgKi9cblx0cHJvY2Vzc0FsbChmb3JjZTogYm9vbGVhbiA9IGZhbHNlKTogdm9pZCB7XG5cdFx0Y29uc3QgZGV2aWNlU2V0dGluZ3MgPSB0aGlzLmdldERldmljZVNldHRpbmdzKCk7XG5cblx0XHR0aGlzLmFwcC53b3Jrc3BhY2UuaXRlcmF0ZVJvb3RMZWF2ZXMoKGxlYWY6IFdvcmtzcGFjZUxlYWYpID0+IHtcblx0XHRcdGNvbnN0IHZpZXcgPSBsZWFmLnZpZXcgYXMgTWFya2Rvd25WaWV3O1xuXHRcdFx0aWYgKHZpZXcgaW5zdGFuY2VvZiBNYXJrZG93blZpZXcpIHtcblx0XHRcdFx0aWYgKGRldmljZVNldHRpbmdzLmVuYWJsZWQpIHtcblx0XHRcdFx0XHRjb25zdCBmaWxlID0gdmlldz8uZmlsZSB8fCBudWxsO1xuXHRcdFx0XHRcdHZvaWQgdGhpcy5wcm9jZXNzKGZpbGUsIHZpZXcsIGZvcmNlKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHR0aGlzLnJlbW92ZSh2aWV3KTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH0pO1xuXHR9XG5cblx0LyoqXG5cdCAqIFByb2Nlc3MgYSBzaW5nbGUgZmlsZS92aWV3XG5cdCAqL1xuXHRhc3luYyBwcm9jZXNzKGZpbGU6IFRGaWxlIHwgbnVsbCwgdmlldz86IE1hcmtkb3duVmlldywgZm9yY2U6IGJvb2xlYW4gPSBmYWxzZSk6IFByb21pc2U8dm9pZD4ge1xuXHRcdGNvbnN0IGRhdGEgPSBhd2FpdCB0aGlzLmNvbXB1dGUoZmlsZSwgdmlldyk7XG5cdFx0aWYgKCFkYXRhKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0aWYgKGZvcmNlKSB7XG5cdFx0XHRkYXRhLm5lZWRzVXBkYXRlID0gdHJ1ZTtcblx0XHR9XG5cblx0XHRpZiAoIWRhdGEuaW1hZ2UpIHtcblx0XHRcdHRoaXMucmVtb3ZlKHZpZXcsIGRhdGEpO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHRpZiAoIWRhdGEuaWNvbikge1xuXHRcdFx0ZGF0YS5uZWVkc1VwZGF0ZSA9IHRydWU7XG5cdFx0fVxuXG5cdFx0Y29uc3QgZGV2aWNlU2V0dGluZ3MgPSB0aGlzLmdldERldmljZVNldHRpbmdzKCk7XG5cdFx0aWYgKGRldmljZVNldHRpbmdzLmVuYWJsZWQpIHtcblx0XHRcdGF3YWl0IHRoaXMucmVuZGVyKGRhdGEsIHZpZXcsIGZvcmNlKTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogQ29tcHV0ZSBiYW5uZXIgZGF0YSBmcm9tIGZyb250bWF0dGVyXG5cdCAqL1xuXHRhc3luYyBjb21wdXRlKGZpbGU6IFRGaWxlIHwgbnVsbCwgdGFyZ2V0Vmlldz86IE1hcmtkb3duVmlldyk6IFByb21pc2U8QmFubmVyRGF0YSB8IG51bGw+IHtcblx0XHRjb25zdCB2aWV3ID0gdGFyZ2V0VmlldyB8fCB0aGlzLmdldEFjdGl2ZVZpZXcoKTtcblx0XHRpZiAoIWZpbGUgfHwgISh2aWV3IGluc3RhbmNlb2YgTWFya2Rvd25WaWV3KSkge1xuXHRcdFx0cmV0dXJuIG51bGw7XG5cdFx0fVxuXG5cdFx0Ly8gRWFybHkgZXhpdDogY2hlY2sgaWYgYmFubmVyIGlzIGVuYWJsZWRcblx0XHRjb25zdCBkZXZpY2VTZXR0aW5ncyA9IHRoaXMuZ2V0RGV2aWNlU2V0dGluZ3MoKTtcblx0XHRpZiAoIWRldmljZVNldHRpbmdzLmVuYWJsZWQpIHtcblx0XHRcdHJldHVybiBudWxsO1xuXHRcdH1cblxuXHRcdC8vIEVhcmx5IGV4aXQ6IGNoZWNrIGlmIGZpbGUgZXh0ZW5zaW9uIGlzIHN1cHBvcnRlZFxuXHRcdC8vIEFsc28gYWxsb3cgJ21kJyBhcyBhIGZhbGxiYWNrIGluIGNhc2UgdXNlciBkaWRuJ3QgaW5jbHVkZSBpdCBpbiBzdXBwb3J0ZWRFeHRlbnNpb25zXG5cdFx0aWYgKCF0aGlzLnNldHRpbmdzLnN1cHBvcnRlZEV4dGVuc2lvbnMuaW5jbHVkZXMoZmlsZS5leHRlbnNpb24pICYmIGZpbGUuZXh0ZW5zaW9uICE9PSAnbWQnKSB7XG5cdFx0XHRyZXR1cm4gbnVsbDtcblx0XHR9XG5cblx0XHQvLyBHZXQgbGVhZiBJRCBmb3IgZGF0YSBzdG9yZVxuXHRcdC8vIEB0cy1leHBlY3QtZXJyb3IgLSBsZWFmLmlkIGV4aXN0cyBidXQgaXMgbm90IGluIHR5cGUgZGVmaW5pdGlvbnNcblx0XHRjb25zdCBsZWFmSWQgPSB2aWV3Py5sZWFmPy5pZCBhcyBzdHJpbmcgfCB1bmRlZmluZWQ7XG5cdFx0aWYgKCFsZWFmSWQpIHtcblx0XHRcdHJldHVybiBudWxsO1xuXHRcdH1cblxuXHRcdGNvbnN0IG9sZERhdGEgPSBiYW5uZXJEYXRhU3RvcmUuZ2V0KGxlYWZJZCkgfHwgdGhpcy5jcmVhdGVEZWZhdWx0QmFubmVyRGF0YSgpO1xuXHRcdGNvbnN0IG5ld0RhdGEgPSB0aGlzLmNyZWF0ZURlZmF1bHRCYW5uZXJEYXRhKHZpZXcsIG9sZERhdGEudmlld01vZGUpO1xuXG5cdFx0Ly8gRm9yIE1EIGZpbGVzICh3aGljaCBoYXZlIG1ldGFkYXRhIGNhY2hlKSwgY2hlY2sgY2FjaGUgZmlyc3QgdG8gc2VlIGlmIGJhbm5lciBwcm9wZXJ0eSBleGlzdHNcblx0XHQvLyBUaGlzIGF2b2lkcyByZWFkaW5nIHRoZSBmdWxsIGZpbGUgaWYgdGhlcmUncyBubyBiYW5uZXIgcHJvcGVydHlcblx0XHQvLyBCVVQ6IE9ubHkgdXNlIHRoaXMgYXMgYW4gb3B0aW1pemF0aW9uIGlmIGNhY2hlIGlzIGFscmVhZHkgcG9wdWxhdGVkXG5cdFx0Ly8gSWYgY2FjaGUgaXMgbnVsbCAobm90IHJlYWR5IHlldCksIHdlIG11c3QgcmVhZCBmcm9udG1hdHRlciB0byBiZSBzdXJlXG5cdFx0Ly8gTm90ZTogT25seSBNRCBmaWxlcyBoYXZlIG1ldGFkYXRhIGNhY2hlIGluIE9ic2lkaWFuOyBvdGhlciBleHRlbnNpb25zIChNRFgsIGV0Yy4pIGRvbid0XG5cdFx0aWYgKGZpbGUuZXh0ZW5zaW9uID09PSAnbWQnKSB7XG5cdFx0XHRjb25zdCBjYWNoZSA9IHRoaXMuYXBwLm1ldGFkYXRhQ2FjaGUuZ2V0RmlsZUNhY2hlKGZpbGUpO1xuXHRcdFx0Ly8gT25seSBza2lwIGlmIGNhY2hlIGV4aXN0cyBBTkQgaGFzIGJlZW4gcG9wdWxhdGVkIChmcm9udG1hdHRlciBpcyBub3QgbnVsbC91bmRlZmluZWQpXG5cdFx0XHQvLyBJZiBjYWNoZSBpcyBudWxsIG9yIGZyb250bWF0dGVyIGlzIG1pc3NpbmcsIHdlIG5lZWQgdG8gcmVhZCB0aGUgZmlsZSB0byBiZSBzdXJlXG5cdFx0XHRpZiAoY2FjaGU/LmZyb250bWF0dGVyICE9IG51bGwpIHtcblx0XHRcdFx0Y29uc3QgcHJvcGVydHlTZXR0aW5ncyA9IHRoaXMuc2V0dGluZ3MuYmFubmVyLnByb3BlcnRpZXM7XG5cdFx0XHRcdGNvbnN0IGltYWdlUHJvcCA9IHByb3BlcnR5U2V0dGluZ3MuaW1hZ2VQcm9wZXJ0eTtcblx0XHRcdFx0Y29uc3QgaWNvblByb3AgPSBwcm9wZXJ0eVNldHRpbmdzLmljb25Qcm9wZXJ0eTtcblxuXHRcdFx0XHQvLyBDaGVjayBpZiBoaWRlIHByb3BlcnR5IGlzIGVuYWJsZWQgYW5kIHNldCB0byB0cnV0aHkgdmFsdWVcblx0XHRcdFx0aWYgKHByb3BlcnR5U2V0dGluZ3MuaGlkZVByb3BlcnR5RW5hYmxlZCAmJiBwcm9wZXJ0eVNldHRpbmdzLmhpZGVQcm9wZXJ0eSkge1xuXHRcdFx0XHRcdGNvbnN0IGhpZGVQcm9wID0gcHJvcGVydHlTZXR0aW5ncy5oaWRlUHJvcGVydHk7XG5cdFx0XHRcdFx0Y29uc3QgaGlkZVZhbHVlOiB1bmtub3duID0gY2FjaGUuZnJvbnRtYXR0ZXJbaGlkZVByb3BdO1xuXHRcdFx0XHRcdGlmIChoaWRlVmFsdWUgPT09IHRydWUgfHwgaGlkZVZhbHVlID09PSAndHJ1ZScgfHwgaGlkZVZhbHVlID09PSAxIHx8IGhpZGVWYWx1ZSA9PT0gJzEnKSB7XG5cdFx0XHRcdFx0XHRyZXR1cm4gbmV3RGF0YTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBDaGVjayBpZiBiYW5uZXIgb3IgaWNvbiBwcm9wZXJ0eSBleGlzdHMgaW4gY2FjaGVcblx0XHRcdFx0Y29uc3QgaGFzQmFubmVyUHJvcGVydHkgPSBjYWNoZS5mcm9udG1hdHRlcltpbWFnZVByb3BdICE9IG51bGw7XG5cdFx0XHRcdGNvbnN0IGhhc0ljb25Qcm9wZXJ0eSA9IGRldmljZVNldHRpbmdzLmljb25FbmFibGVkICYmIGNhY2hlLmZyb250bWF0dGVyW2ljb25Qcm9wXSAhPSBudWxsO1xuXG5cdFx0XHRcdC8vIElmIGNhY2hlIGlzIHBvcHVsYXRlZCBhbmQgbm8gYmFubmVyL2ljb24gcHJvcGVydHkgZXhpc3RzLCByZXR1cm4gZWFybHlcblx0XHRcdFx0Ly8gVGhpcyBpcyBzYWZlIGJlY2F1c2UgdGhlIGNhY2hlIGlzIGRlZmluaXRpdmUgZm9yIE1EIGZpbGVzXG5cdFx0XHRcdGlmICghaGFzQmFubmVyUHJvcGVydHkgJiYgIWhhc0ljb25Qcm9wZXJ0eSkge1xuXHRcdFx0XHRcdHJldHVybiBuZXdEYXRhO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHQvLyBJZiBjYWNoZSBpcyBudWxsIG9yIGZyb250bWF0dGVyIG5vdCBwb3B1bGF0ZWQgeWV0LCBjb250aW51ZSB0byByZWFkIGZyb250bWF0dGVyXG5cdFx0XHQvLyBUaGlzIGVuc3VyZXMgYmFubmVycyBsb2FkIGNvcnJlY3RseSBldmVuIGlmIGNhY2hlIGlzbid0IHJlYWR5XG5cdFx0fVxuXHRcdC8vIEZvciBub24tTUQgZmlsZXMgKE1EWCwgZXRjLiksIHdlIGFsd2F5cyBuZWVkIHRvIHJlYWQgdGhlIGZpbGUgKG5vIGNhY2hlIGF2YWlsYWJsZSlcblxuXHRcdC8vIEdldCBmcm9udG1hdHRlciB1c2luZyBNRFgtY29tcGF0aWJsZSB1dGlsaXR5XG5cdFx0Y29uc3QgZnJvbnRtYXR0ZXIgPSBhd2FpdCBnZXRGcm9udG1hdHRlcih0aGlzLmFwcCwgZmlsZSk7XG5cdFx0aWYgKCFmcm9udG1hdHRlcikge1xuXHRcdFx0cmV0dXJuIG5ld0RhdGE7XG5cdFx0fVxuXG5cdFx0Y29uc3QgcHJvcGVydHlTZXR0aW5ncyA9IHRoaXMuc2V0dGluZ3MuYmFubmVyLnByb3BlcnRpZXM7XG5cblx0XHQvLyBDaGVjayBpZiBoaWRlIHByb3BlcnR5IGlzIGVuYWJsZWQgYW5kIHNldCB0byB0cnV0aHkgdmFsdWVcblx0XHRpZiAocHJvcGVydHlTZXR0aW5ncy5oaWRlUHJvcGVydHlFbmFibGVkICYmIHByb3BlcnR5U2V0dGluZ3MuaGlkZVByb3BlcnR5KSB7XG5cdFx0XHRjb25zdCBoaWRlUHJvcCA9IHByb3BlcnR5U2V0dGluZ3MuaGlkZVByb3BlcnR5O1xuXHRcdFx0Y29uc3QgaGlkZVZhbHVlOiB1bmtub3duID0gZnJvbnRtYXR0ZXJbaGlkZVByb3BdO1xuXHRcdFx0aWYgKGhpZGVWYWx1ZSA9PT0gdHJ1ZSB8fCBoaWRlVmFsdWUgPT09ICd0cnVlJyB8fCBoaWRlVmFsdWUgPT09IDEgfHwgaGlkZVZhbHVlID09PSAnMScpIHtcblx0XHRcdFx0cmV0dXJuIG5ld0RhdGE7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Y29uc3QgaW1hZ2VQcm9wID0gcHJvcGVydHlTZXR0aW5ncy5pbWFnZVByb3BlcnR5O1xuXHRcdGNvbnN0IGljb25Qcm9wID0gcHJvcGVydHlTZXR0aW5ncy5pY29uUHJvcGVydHk7XG5cblx0XHQvLyBQYXJzZSBpbWFnZSBwcm9wZXJ0eVxuXHRcdGNvbnN0IGltYWdlVmFsdWUgPSBmcm9udG1hdHRlcltpbWFnZVByb3BdO1xuXHRcdGlmIChpbWFnZVZhbHVlICYmIHR5cGVvZiBpbWFnZVZhbHVlID09PSAnc3RyaW5nJykge1xuXHRcdFx0bmV3RGF0YS5pbWFnZSA9IGltYWdlVmFsdWU7XG5cdFx0XHRuZXdEYXRhLmZpbGVwYXRoID0gZmlsZS5wYXRoO1xuXG5cdFx0XHRpZiAob2xkRGF0YS5maWxlcGF0aCAhPT0gbmV3RGF0YS5maWxlcGF0aCkge1xuXHRcdFx0XHRuZXdEYXRhLm5lZWRzVXBkYXRlID0gdHJ1ZTtcblx0XHRcdFx0bmV3RGF0YS5pc0ltYWdlQ2hhbmdlID0gdHJ1ZTtcblx0XHRcdH0gZWxzZSBpZiAob2xkRGF0YS5pbWFnZSAhPT0gbmV3RGF0YS5pbWFnZSkge1xuXHRcdFx0XHRuZXdEYXRhLm5lZWRzVXBkYXRlID0gdHJ1ZTtcblx0XHRcdFx0bmV3RGF0YS5pc0ltYWdlQ2hhbmdlID0gdHJ1ZTtcblxuXHRcdFx0XHQvLyBDaGVjayBpZiBvbmx5IGltYWdlIHByb3BlcnRpZXMgKG9mZnNldCwgcmVwZWF0KSBjaGFuZ2VkXG5cdFx0XHRcdGlmIChhd2FpdCB0aGlzLmlzSW1hZ2VQcm9wZXJ0aWVzVXBkYXRlKG9sZERhdGEuaW1hZ2UsIG5ld0RhdGEuaW1hZ2UsIHZpZXcpKSB7XG5cdFx0XHRcdFx0bmV3RGF0YS5pc0ltYWdlUHJvcHNVcGRhdGUgPSB0cnVlO1xuXHRcdFx0XHRcdG5ld0RhdGEuaXNJbWFnZUNoYW5nZSA9IGZhbHNlO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gUGFyc2UgaWNvbiBwcm9wZXJ0eSBpZiBlbmFibGVkXG5cdFx0aWYgKGRldmljZVNldHRpbmdzLmljb25FbmFibGVkKSB7XG5cdFx0XHRjb25zdCBpY29uVmFsdWUgPSBmcm9udG1hdHRlcltpY29uUHJvcF07XG5cdFx0XHRpZiAoaWNvblZhbHVlICYmIHR5cGVvZiBpY29uVmFsdWUgPT09ICdzdHJpbmcnKSB7XG5cdFx0XHRcdG5ld0RhdGEuaWNvbiA9IGljb25WYWx1ZTtcblx0XHRcdFx0aWYgKG9sZERhdGEuaWNvbiAhPT0gbmV3RGF0YS5pY29uKSB7XG5cdFx0XHRcdFx0bmV3RGF0YS5uZWVkc1VwZGF0ZSA9IHRydWU7XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSBpZiAob2xkRGF0YS5pY29uKSB7XG5cdFx0XHRcdG5ld0RhdGEuaWNvbiA9IG51bGw7XG5cdFx0XHRcdG5ld0RhdGEubmVlZHNVcGRhdGUgPSB0cnVlO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHJldHVybiBuZXdEYXRhO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJlbmRlciBiYW5uZXIgaW4gdGhlIHZpZXdcblx0ICovXG5cdGFzeW5jIHJlbmRlcihkYXRhOiBCYW5uZXJEYXRhLCB0YXJnZXRWaWV3PzogTWFya2Rvd25WaWV3LCBmb3JjZTogYm9vbGVhbiA9IGZhbHNlKTogUHJvbWlzZTx2b2lkPiB7XG5cdFx0Y29uc3QgeyBpbWFnZSwgdmlld01vZGUsIGxhc3RWaWV3TW9kZSB9ID0gZGF0YTtcblx0XHRjb25zdCB2aWV3ID0gdGFyZ2V0VmlldyB8fCB0aGlzLmdldEFjdGl2ZVZpZXcoKTtcblxuXHRcdGlmICghdmlldyB8fCAhKHZpZXcgaW5zdGFuY2VvZiBNYXJrZG93blZpZXcpKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0Y29uc3QgY29udGFpbmVyID0gdmlldy5jb250YWluZXJFbDtcblx0XHRpZiAoIWNvbnRhaW5lcikge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdGNvbnN0IGNvbnRhaW5lcnM6IE5vZGVMaXN0T2Y8SFRNTEVsZW1lbnQ+ID0gY29udGFpbmVyLnF1ZXJ5U2VsZWN0b3JBbGwoXG5cdFx0XHQnLmNtLXNjcm9sbGVyLCAubWFya2Rvd24tcmVhZGluZy12aWV3ID4gLm1hcmtkb3duLXByZXZpZXctdmlldydcblx0XHQpO1xuXG5cdFx0Ly8gQWZ0ZXIgc3dpdGNoaW5nIGF3YXkgKGUuZy4gdG8gYW4gaW1hZ2UpIGFuZCBiYWNrLCB0aGUgTWFya2Rvd24gdmlldyBpcyByZWNyZWF0ZWQgYW5kXG5cdFx0Ly8gYmFubmVyIG5vZGVzIGFyZSBnb25lLCBidXQgc3RvcmVkIGRhdGEgc3RpbGwgbWF0Y2hlcyBcdTIwMTQgd2l0aG91dCB0aGlzIHdlJ2Qgc2tpcCByZW5kZXIuXG5cdFx0Y29uc3QgYmFubmVyTWlzc2luZyA9XG5cdFx0XHQhIWltYWdlICYmXG5cdFx0XHRjb250YWluZXJzLmxlbmd0aCA+IDAgJiZcblx0XHRcdEFycmF5LmZyb20oY29udGFpbmVycykuc29tZSgoYykgPT4gIWMucXVlcnlTZWxlY3RvcihgLiR7Q1NTX0NMQVNTRVMuTWFpbn1gKSk7XG5cblx0XHRpZiAoYmFubmVyTWlzc2luZykge1xuXHRcdFx0ZGF0YS5uZWVkc1VwZGF0ZSA9IHRydWU7XG5cdFx0XHRkYXRhLmlzSW1hZ2VDaGFuZ2UgPSB0cnVlO1xuXHRcdH1cblxuXHRcdGlmICghZm9yY2UgJiYgIWRhdGEubmVlZHNVcGRhdGUgJiYgbGFzdFZpZXdNb2RlID09PSB2aWV3TW9kZSAmJiAhYmFubmVyTWlzc2luZykge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdGlmIChjb250YWluZXJzLmxlbmd0aCA9PT0gMCkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdGNvbnN0IGltYWdlT3B0aW9ucyA9IGF3YWl0IHRoaXMucGFyc2VMaW5rKGltYWdlIHx8ICcnLCB2aWV3KTtcblx0XHRjb25zdCBiYW5uZXJzID0gdGhpcy51cGRhdGVCYW5uZXJFbGVtZW50cyhkYXRhLCBpbWFnZU9wdGlvbnMsIGNvbnRhaW5lcnMpO1xuXG5cdFx0Ly8gVXBkYXRlIGljb25cblx0XHRhd2FpdCB0aGlzLnVwZGF0ZUljb25zKGRhdGEsIGJhbm5lcnMsIHZpZXcpO1xuXG5cdFx0aWYgKGRhdGEuaXNJbWFnZUNoYW5nZSkge1xuXHRcdFx0dGhpcy5pbmplY3RCYW5uZXJzKGJhbm5lcnMsIGNvbnRhaW5lcnMpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aGlzLnJlcGxhY2VCYW5uZXJzKGJhbm5lcnMpO1xuXHRcdH1cblxuXHRcdGRhdGEubGFzdFZpZXdNb2RlID0gdmlld01vZGU7XG5cdFx0Y29udGFpbmVyLmRhdGFzZXQuaW1CYW5uZXIgPSAnJztcblxuXHRcdC8vIFN0b3JlIGRhdGEgZm9yIHRoaXMgbGVhZlxuXHRcdC8vIEB0cy1leHBlY3QtZXJyb3IgLSBsZWFmLmlkIGV4aXN0cyBidXQgaXMgbm90IGluIHR5cGUgZGVmaW5pdGlvbnNcblx0XHRjb25zdCBsZWFmSWQgPSB2aWV3Py5sZWFmPy5pZCBhcyBzdHJpbmcgfCB1bmRlZmluZWQ7XG5cdFx0aWYgKGxlYWZJZCkge1xuXHRcdFx0YmFubmVyRGF0YVN0b3JlLnNldChsZWFmSWQsIGRhdGEpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBVcGRhdGUgYmFubmVyIERPTSBlbGVtZW50c1xuXHQgKi9cblx0cHJpdmF0ZSB1cGRhdGVCYW5uZXJFbGVtZW50cyhcblx0XHRkYXRhOiBCYW5uZXJEYXRhLFxuXHRcdGltZ09wdGlvbnM6IEJhbm5lckltYWdlT3B0aW9ucyxcblx0XHRjb250YWluZXJzOiBOb2RlTGlzdE9mPEhUTUxFbGVtZW50PlxuXHQpOiBIVE1MRWxlbWVudFtdIHtcblx0XHRjb25zdCB7IGlzSW1hZ2VDaGFuZ2UsIGlzSW1hZ2VQcm9wc1VwZGF0ZSB9ID0gZGF0YTtcblx0XHRjb25zdCBiYW5uZXJzOiBIVE1MRWxlbWVudFtdID0gW107XG5cblx0XHRjb250YWluZXJzLmZvckVhY2goY29udGFpbmVyID0+IHtcblx0XHRcdGxldCBlbGVtZW50ID0gY29udGFpbmVyLnF1ZXJ5U2VsZWN0b3IoYC4ke0NTU19DTEFTU0VTLk1haW59YCkgYXMgSFRNTEVsZW1lbnQ7XG5cdFx0XHRpZiAoIWVsZW1lbnQpIHtcblx0XHRcdFx0ZWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuXHRcdFx0XHRlbGVtZW50LmNsYXNzTGlzdC5hZGQoQ1NTX0NMQVNTRVMuTWFpbik7XG5cdFx0XHR9XG5cblx0XHRcdGxldCBjb250ZW50ID0gZWxlbWVudC5xdWVyeVNlbGVjdG9yKGAuJHtDU1NfQ0xBU1NFUy5Db250ZW50fWApIGFzIEhUTUxFbGVtZW50O1xuXHRcdFx0aWYgKCFjb250ZW50KSB7XG5cdFx0XHRcdGNvbnRlbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcblx0XHRcdFx0Y29udGVudC5jbGFzc0xpc3QuYWRkKENTU19DTEFTU0VTLkNvbnRlbnQpO1xuXHRcdFx0XHRlbGVtZW50LmFwcGVuZENoaWxkKGNvbnRlbnQpO1xuXHRcdFx0fVxuXG5cdFx0XHRiYW5uZXJzLnB1c2goZWxlbWVudCk7XG5cblx0XHRcdGlmIChpc0ltYWdlQ2hhbmdlIHx8IGlzSW1hZ2VQcm9wc1VwZGF0ZSkge1xuXHRcdFx0XHRpZiAoaXNJbWFnZUNoYW5nZSkge1xuXHRcdFx0XHRcdGVsZW1lbnQuY2xhc3NMaXN0LnJlbW92ZShDU1NfQ0xBU1NFUy5TdGF0aWMpO1xuXHRcdFx0XHRcdGNvbnRlbnQuZmlyc3RDaGlsZD8ucmVtb3ZlKCk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBVc2Ugc2V0Q3NzUHJvcGVydGllcyBmb3IgZHluYW1pYyBzdHlsZXNcblx0XHRcdFx0Y29uc3QgY3NzVmFyczogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHtcblx0XHRcdFx0XHQnLS1pbS1iYW5uZXItaW1nLXgnOiBgJHtpbWdPcHRpb25zLnh9cHhgLFxuXHRcdFx0XHRcdCctLWltLWJhbm5lci1pbWcteSc6IGAke2ltZ09wdGlvbnMueX1weGAsXG5cdFx0XHRcdFx0Jy0taW0tYmFubmVyLXNpemUnOiBpbWdPcHRpb25zLnJlcGVhdGFibGUgPyAnYXV0bycgOiAnY292ZXInLFxuXHRcdFx0XHRcdCctLWltLWJhbm5lci1yZXBlYXQnOiBpbWdPcHRpb25zLnJlcGVhdGFibGUgPyAncmVwZWF0JyA6ICduby1yZXBlYXQnLFxuXHRcdFx0XHRcdCctLWltLWJhbm5lci11cmwnOiAnbm9uZScsXG5cdFx0XHRcdH07XG5cblx0XHRcdFx0aWYgKGltZ09wdGlvbnMudHlwZSA9PT0gQmFubmVyQ29udGVudFR5cGUuVmlkZW8pIHtcblx0XHRcdFx0XHRjb25zdCB2aWRlbyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3ZpZGVvJyk7XG5cdFx0XHRcdFx0dmlkZW8uY29udHJvbHMgPSBmYWxzZTtcblx0XHRcdFx0XHR2aWRlby5hdXRvcGxheSA9IHRydWU7XG5cdFx0XHRcdFx0dmlkZW8ubXV0ZWQgPSB0cnVlO1xuXHRcdFx0XHRcdHZpZGVvLmxvb3AgPSB0cnVlO1xuXHRcdFx0XHRcdHZpZGVvLnNyYyA9IGltZ09wdGlvbnMudXJsLnJlcGxhY2UoL15cInxcIiQvZywgJycpO1xuXHRcdFx0XHRcdGNvbnRlbnQuYXBwZW5kQ2hpbGQodmlkZW8pO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdGNzc1ZhcnNbJy0taW0tYmFubmVyLXVybCddID0gYHVybCgke2ltZ09wdGlvbnMudXJsfSlgO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0c2V0Q3NzUHJvcGVydGllcyhjb250YWluZXIsIGNzc1ZhcnMpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXG5cdFx0cmV0dXJuIGJhbm5lcnM7XG5cdH1cblxuXHQvKipcblx0ICogVXBkYXRlIGljb24gZWxlbWVudHMgb24gYmFubmVyc1xuXHQgKi9cblx0cHJpdmF0ZSBhc3luYyB1cGRhdGVJY29ucyhkYXRhOiBCYW5uZXJEYXRhLCBiYW5uZXJzOiBIVE1MRWxlbWVudFtdLCB2aWV3PzogTWFya2Rvd25WaWV3KTogUHJvbWlzZTx2b2lkPiB7XG5cdFx0Y29uc3QgZGV2aWNlU2V0dGluZ3MgPSB0aGlzLmdldERldmljZVNldHRpbmdzKCk7XG5cdFx0bGV0IGNhbGN1bGF0ZWRGb250U2l6ZTogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG5cblx0XHRmb3IgKGNvbnN0IGJhbm5lciBvZiBiYW5uZXJzKSB7XG5cdFx0XHRjb25zdCB7IGljb24gfSA9IGRhdGE7XG5cdFx0XHRsZXQgaWNvbkNvbnRhaW5lcjogSFRNTEVsZW1lbnQgfCBudWxsID0gYmFubmVyLnF1ZXJ5U2VsZWN0b3IoYC4ke0NTU19DTEFTU0VTLkljb259YCk7XG5cdFx0XHRjb25zdCBoYXNDb250YWluZXIgPSBpY29uQ29udGFpbmVyICE9PSBudWxsO1xuXG5cdFx0XHRpZiAoaGFzQ29udGFpbmVyKSB7XG5cdFx0XHRcdGljb25Db250YWluZXI/LmNsYXNzTGlzdC5hZGQoQ1NTX0NMQVNTRVMuU3RhdGljKTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKGRldmljZVNldHRpbmdzLmljb25FbmFibGVkICYmIGljb24pIHtcblx0XHRcdFx0aWYgKCFoYXNDb250YWluZXIpIHtcblx0XHRcdFx0XHRpY29uQ29udGFpbmVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG5cdFx0XHRcdFx0aWNvbkNvbnRhaW5lci5jbGFzc0xpc3QuYWRkKENTU19DTEFTU0VTLkljb24pO1xuXHRcdFx0XHRcdGNvbnN0IGlubmVyRGl2ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG5cdFx0XHRcdFx0aWNvbkNvbnRhaW5lci5hcHBlbmRDaGlsZChpbm5lckRpdik7XG5cdFx0XHRcdFx0YmFubmVyLnByZXBlbmQoaWNvbkNvbnRhaW5lcik7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRjb25zdCBpY29uRWxlbWVudCA9IGljb25Db250YWluZXI/LnF1ZXJ5U2VsZWN0b3IoJ2RpdicpIGFzIEhUTUxFbGVtZW50O1xuXHRcdFx0XHRpZiAoIWljb25FbGVtZW50KSBjb250aW51ZTtcblxuXHRcdFx0XHRjb25zdCBpY29uRGF0YSA9IGF3YWl0IHRoaXMucGFyc2VJY29uKGljb24sIHZpZXcpO1xuXG5cdFx0XHRcdC8vIEVzY2FwZSBzcGVjaWFsIGNoYXJhY3RlcnMgaW4gdGhlIHZhbHVlIGZvciBDU1Ncblx0XHRcdFx0bGV0IHZhbHVlID0gaWNvbkRhdGEudmFsdWU/LnJlcGxhY2UoLyhbIy46W1xcXFxdXCJdKS9nLCAnXFxcXCQxJykgfHwgJyc7XG5cdFx0XHRcdGljb25FbGVtZW50LmRhdGFzZXQudHlwZSA9IGljb25EYXRhLnR5cGU7XG5cblx0XHRcdFx0aWYgKGljb25EYXRhLnR5cGUgPT09IEJhbm5lckljb25UeXBlLkxpbmspIHtcblx0XHRcdFx0XHRzZXRDc3NQcm9wZXJ0aWVzKGljb25FbGVtZW50LCB7XG5cdFx0XHRcdFx0XHQnLS1pbS1iYW5uZXItaWNvbi12YWx1ZSc6IGB1cmwoJHt2YWx1ZX0pYCxcblx0XHRcdFx0XHR9KTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHQvLyBUZXh0L2Vtb2ppIGljb25cblx0XHRcdFx0XHRjYWxjdWxhdGVkRm9udFNpemUgPSBjYWxjdWxhdGVkRm9udFNpemUgPz8gdGhpcy5jYWxjdWxhdGVGb250U2l6ZSh2YWx1ZSwgZGV2aWNlU2V0dGluZ3MuaWNvblNpemUpO1xuXHRcdFx0XHRcdHNldENzc1Byb3BlcnRpZXMoaWNvbkVsZW1lbnQsIHtcblx0XHRcdFx0XHRcdCctLWltLWJhbm5lci1pY29uLXZhbHVlJzogYFwiJHt2YWx1ZX1cImAsXG5cdFx0XHRcdFx0XHQnLS1pbS1iYW5uZXItaWNvbi1mb250c2l6ZSc6IGNhbGN1bGF0ZWRGb250U2l6ZSxcblx0XHRcdFx0XHR9KTtcblx0XHRcdFx0fVxuXHRcdFx0fSBlbHNlIGlmIChoYXNDb250YWluZXIgJiYgaWNvbkNvbnRhaW5lcikge1xuXHRcdFx0XHRkYXRhLmljb24gPSBudWxsO1xuXHRcdFx0XHRpY29uQ29udGFpbmVyLnJlbW92ZSgpO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBJbmplY3QgYmFubmVycyBpbnRvIGNvbnRhaW5lcnNcblx0ICovXG5cdHByaXZhdGUgaW5qZWN0QmFubmVycyhiYW5uZXJzOiBIVE1MRWxlbWVudFtdLCBjb250YWluZXJzOiBOb2RlTGlzdE9mPEhUTUxFbGVtZW50Pik6IHZvaWQge1xuXHRcdGNvbnN0IGRldmljZVNldHRpbmdzID0gdGhpcy5nZXREZXZpY2VTZXR0aW5ncygpO1xuXHRcdGNvbnN0IHNob3VsZEFuaW1hdGUgPSBkZXZpY2VTZXR0aW5ncy5hbmltYXRpb247XG5cblx0XHRjb250YWluZXJzLmZvckVhY2goKGNvbnRhaW5lciwgaW5kZXgpID0+IHtcblx0XHRcdGNvbnN0IGJhbm5lciA9IGJhbm5lcnNbaW5kZXhdO1xuXHRcdFx0aWYgKGJhbm5lcikge1xuXHRcdFx0XHQvLyBSZW1vdmUgc3RhdGljIGNsYXNzIGlmIGl0IGV4aXN0cyB0byBhbGxvdyBhbmltYXRpb25cblx0XHRcdFx0YmFubmVyLmNsYXNzTGlzdC5yZW1vdmUoQ1NTX0NMQVNTRVMuU3RhdGljKTtcblx0XHRcdFx0Y29udGFpbmVyLnByZXBlbmQoYmFubmVyKTtcblxuXHRcdFx0XHRpZiAoc2hvdWxkQW5pbWF0ZSkge1xuXHRcdFx0XHRcdC8vIEZvcmNlIHJlZmxvdyBhbmQgc3RhcnQgYW5pbWF0aW9uIG9uIG5leHQgZnJhbWVcblx0XHRcdFx0XHR2b2lkIGJhbm5lci5vZmZzZXRIZWlnaHQ7IC8vIEZvcmNlIHJlZmxvd1xuXHRcdFx0XHRcdHJlcXVlc3RBbmltYXRpb25GcmFtZSgoKSA9PiB7XG5cdFx0XHRcdFx0XHQvLyBBbmltYXRpb24gc2hvdWxkIHN0YXJ0IG5vd1xuXHRcdFx0XHRcdFx0YmFubmVyLm9uYW5pbWF0aW9uZW5kID0gKCkgPT4ge1xuXHRcdFx0XHRcdFx0XHRiYW5uZXIuY2xhc3NMaXN0LmFkZChDU1NfQ0xBU1NFUy5TdGF0aWMpO1xuXHRcdFx0XHRcdFx0fTtcblx0XHRcdFx0XHR9KTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHQvLyBBbmltYXRpb24gZGlzYWJsZWQgLSBhZGQgc3RhdGljIGNsYXNzIGltbWVkaWF0ZWx5XG5cdFx0XHRcdFx0YmFubmVyLmNsYXNzTGlzdC5hZGQoQ1NTX0NMQVNTRVMuU3RhdGljKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH0pO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJlcGxhY2UgYmFubmVycyAobm8gYW5pbWF0aW9uKVxuXHQgKi9cblx0cHJpdmF0ZSByZXBsYWNlQmFubmVycyhiYW5uZXJzOiBIVE1MRWxlbWVudFtdKTogdm9pZCB7XG5cdFx0YmFubmVycy5mb3JFYWNoKGJhbm5lciA9PiB7XG5cdFx0XHRiYW5uZXIuY2xhc3NMaXN0LmFkZChDU1NfQ0xBU1NFUy5TdGF0aWMpO1xuXHRcdH0pO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJlbW92ZSBiYW5uZXIgZnJvbSB2aWV3XG5cdCAqL1xuXHRyZW1vdmUodmlldz86IE1hcmtkb3duVmlldywgZGF0YT86IEJhbm5lckRhdGEpOiB2b2lkIHtcblx0XHRjb25zdCB0YXJnZXRWaWV3ID0gdmlldyB8fCBkYXRhPy5maWxlcGF0aCA/IHRoaXMuZ2V0QWN0aXZlVmlldygpIDogbnVsbDtcblx0XHRpZiAoISh0YXJnZXRWaWV3IGluc3RhbmNlb2YgTWFya2Rvd25WaWV3KSkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdGNvbnN0IGNvbnRhaW5lciA9IHRhcmdldFZpZXcuY29udGFpbmVyRWw7XG5cdFx0aWYgKCFjb250YWluZXIpIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRjb25zdCB0YXJnZXRzID0gY29udGFpbmVyLnF1ZXJ5U2VsZWN0b3JBbGwoYC4ke0NTU19DTEFTU0VTLk1haW59YCk7XG5cdFx0dGFyZ2V0cy5mb3JFYWNoKHQgPT4gdC5yZW1vdmUoKSk7XG5cblx0XHQvLyBAdHMtZXhwZWN0LWVycm9yIC0gbGVhZi5pZCBleGlzdHMgYnV0IGlzIG5vdCBpbiB0eXBlIGRlZmluaXRpb25zXG5cdFx0Y29uc3QgbGVhZklkID0gdGFyZ2V0Vmlldz8ubGVhZj8uaWQgYXMgc3RyaW5nIHwgdW5kZWZpbmVkO1xuXHRcdGlmIChsZWFmSWQpIHtcblx0XHRcdGJhbm5lckRhdGFTdG9yZS5kZWxldGUobGVhZklkKTtcblx0XHR9XG5cdFx0ZGVsZXRlIGNvbnRhaW5lci5kYXRhc2V0LmltQmFubmVyO1xuXHR9XG5cblx0LyoqXG5cdCAqIEFwcGx5IGN1cnJlbnQgc2V0dGluZ3MgdG8gRE9NXG5cdCAqL1xuXHRhcHBseVNldHRpbmdzKCk6IHZvaWQge1xuXHRcdGNvbnN0IGRldmljZVNldHRpbmdzID0gdGhpcy5nZXREZXZpY2VTZXR0aW5ncygpO1xuXHRcdGNvbnN0IGhlaWdodCA9IGRldmljZVNldHRpbmdzLmhlaWdodDtcblx0XHRjb25zdCBub3RlT2Zmc2V0ID0gZGV2aWNlU2V0dGluZ3Mubm90ZU9mZnNldDtcblx0XHRjb25zdCB2aWV3T2Zmc2V0ID0gZGV2aWNlU2V0dGluZ3Mudmlld09mZnNldDtcblx0XHRjb25zdCByYWRpdXMgPSBkZXZpY2VTZXR0aW5ncy5iYW5uZXJSYWRpdXNFbmFibGVkID8gZGV2aWNlU2V0dGluZ3MuYm9yZGVyUmFkaXVzIDogWzAsIDAsIDAsIDBdO1xuXHRcdGNvbnN0IHBhZGRpbmcgPSBkZXZpY2VTZXR0aW5ncy5wYWRkaW5nO1xuXHRcdGNvbnN0IGZhZGUgPSBkZXZpY2VTZXR0aW5ncy5mYWRlO1xuXG5cdFx0Y29uc3QgY3NzVmFyczogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHtcblx0XHRcdCctLWltLWJhbm5lci1oZWlnaHQnOiBgJHtoZWlnaHR9cHhgLFxuXHRcdFx0Jy0taW0tYmFubmVyLW5vdGUtb2Zmc2V0JzogYCR7bm90ZU9mZnNldH1weGAsXG5cdFx0XHQnLS1pbS1iYW5uZXItdmlldy1vZmZzZXQnOiBgJHt2aWV3T2Zmc2V0fXB4YCxcblx0XHRcdCctLWltLWJhbm5lci1yYWRpdXMnOiBgJHtyYWRpdXNbMF19cHggJHtyYWRpdXNbMV19cHggJHtyYWRpdXNbMl19cHggJHtyYWRpdXNbM119cHhgLFxuXHRcdFx0Jy0taW0tYmFubmVyLXBhZGRpbmcnOiBgJHtwYWRkaW5nfXB4YCxcblx0XHRcdCctLWltLWJhbm5lci1tYXNrJzogZmFkZSA/ICdyZXZlcnQtbGF5ZXInIDogJ2luaXRpYWwnLFxuXHRcdFx0Jy0taW0tYmFubmVyLW1hc2std2Via2l0JzogZmFkZSA/ICdyZXZlcnQtbGF5ZXInIDogJ2luaXRpYWwnLFxuXHRcdH07XG5cblx0XHRpZiAoZGV2aWNlU2V0dGluZ3MuaWNvbkVuYWJsZWQpIHtcblx0XHRcdGNvbnN0IGljb25GcmFtZSA9IGRldmljZVNldHRpbmdzLmljb25GcmFtZSA/PyB0cnVlO1xuXHRcdFx0Y3NzVmFyc1snLS1pbS1iYW5uZXItaWNvbi1zaXplLXcnXSA9IGAke2RldmljZVNldHRpbmdzLmljb25TaXplfXB4YDtcblx0XHRcdGNzc1ZhcnNbJy0taW0tYmFubmVyLWljb24tc2l6ZS1oJ10gPSBgJHtkZXZpY2VTZXR0aW5ncy5pY29uU2l6ZX1weGA7XG5cdFx0XHRjc3NWYXJzWyctLWltLWJhbm5lci1pY29uLXJhZGl1cyddID0gYCR7ZGV2aWNlU2V0dGluZ3MuaWNvblJhZGl1c31weGA7XG5cdFx0XHRjc3NWYXJzWyctLWltLWJhbm5lci1pY29uLWFsaWduLWgnXSA9IGRldmljZVNldHRpbmdzLmljb25BbGlnbm1lbnRIO1xuXHRcdFx0Y3NzVmFyc1snLS1pbS1iYW5uZXItaWNvbi1hbGlnbi12J10gPSBkZXZpY2VTZXR0aW5ncy5pY29uQWxpZ25tZW50Vjtcblx0XHRcdGNzc1ZhcnNbJy0taW0tYmFubmVyLWljb24tb2Zmc2V0LXgnXSA9IGAke2RldmljZVNldHRpbmdzLmljb25PZmZzZXRYfXB4YDtcblx0XHRcdGNzc1ZhcnNbJy0taW0tYmFubmVyLWljb24tb2Zmc2V0LXknXSA9IGAke2RldmljZVNldHRpbmdzLmljb25PZmZzZXRZfXB4YDtcblx0XHRcdGNzc1ZhcnNbJy0taW0tYmFubmVyLWljb24tYm9yZGVyJ10gPSBpY29uRnJhbWUgPyBgJHtkZXZpY2VTZXR0aW5ncy5pY29uQm9yZGVyfXB4YCA6ICcwcHgnO1xuXHRcdFx0Y3NzVmFyc1snLS1pbS1iYW5uZXItaWNvbi1iYWNrZ3JvdW5kJ10gPSBpY29uRnJhbWUgJiYgZGV2aWNlU2V0dGluZ3MuaWNvbkJhY2tncm91bmQgPyAncmV2ZXJ0LWxheWVyJyA6ICd0cmFuc3BhcmVudCc7XG5cdFx0fVxuXG5cdFx0c2V0Q3NzUHJvcGVydGllcyhkb2N1bWVudC5ib2R5LCBjc3NWYXJzKTtcblxuXHRcdHRoaXMucHJvY2Vzc0FsbCh0cnVlKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBQYXJzZSBpbWFnZSBsaW5rIHN0cmluZyBpbnRvIG9wdGlvbnNcblx0ICovXG5cdGFzeW5jIHBhcnNlTGluayhzdHI6IHN0cmluZywgdmlldz86IE1hcmtkb3duVmlldyB8IG51bGwpOiBQcm9taXNlPEJhbm5lckltYWdlT3B0aW9ucz4ge1xuXHRcdGxldCB1cmw6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuXHRcdGxldCBkaXNwbGF5VGV4dDogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG5cdFx0bGV0IGV4dGVybmFsID0gZmFsc2U7XG5cdFx0bGV0IG9ic2lkaWFuVXJsID0gZmFsc2U7XG5cdFx0bGV0IG9wdGlvbnMgPSB7IHg6IDAsIHk6IDAsIHJlcGVhdGFibGU6IGZhbHNlIH07XG5cblx0XHQvLyBUcnkgd2lraWxpbmsgZm9ybWF0XG5cdFx0Y29uc3Qgd2lraWxpbmtNYXRjaCA9IHN0ci5tYXRjaChQQVRURVJOUy5XaWtpbGluayk7XG5cdFx0aWYgKHdpa2lsaW5rTWF0Y2gpIHtcblx0XHRcdHVybCA9IHdpa2lsaW5rTWF0Y2hbMV0/LnRyaW0oKSA/PyBudWxsO1xuXHRcdFx0ZGlzcGxheVRleHQgPSB3aWtpbGlua01hdGNoWzNdPy50cmltKCkgPz8gbnVsbDtcblx0XHR9XG5cblx0XHQvLyBUcnkgbWFya2Rvd24gZm9ybWF0XG5cdFx0Y29uc3QgbWFya2Rvd25NYXRjaCA9IHN0ci5tYXRjaChQQVRURVJOUy5NYXJrZG93bik7XG5cdFx0Y29uc3QgbWFya2Rvd25CYXJlTWF0Y2ggPSBzdHIubWF0Y2goUEFUVEVSTlMuTWFya2Rvd25CYXJlKTtcblx0XHRpZiAobWFya2Rvd25NYXRjaCkge1xuXHRcdFx0ZGlzcGxheVRleHQgPSBtYXJrZG93bk1hdGNoWzFdPy50cmltKCkgPz8gbnVsbDtcblx0XHRcdHVybCA9IG1hcmtkb3duTWF0Y2hbMl0/LnRyaW0oKSA/PyBudWxsO1xuXHRcdH0gZWxzZSBpZiAobWFya2Rvd25CYXJlTWF0Y2gpIHtcblx0XHRcdHVybCA9IG1hcmtkb3duQmFyZU1hdGNoWzFdPy50cmltKCkgPz8gbnVsbDtcblx0XHRcdGRpc3BsYXlUZXh0ID0gbnVsbDtcblx0XHR9XG5cblx0XHQvLyBEZWZhdWx0IHRvIHJhdyBzdHJpbmdcblx0XHRpZiAoIXVybCkge1xuXHRcdFx0dXJsID0gc3RyO1xuXHRcdFx0ZGlzcGxheVRleHQgPSBudWxsO1xuXHRcdH1cblxuXHRcdGV4dGVybmFsID0gUEFUVEVSTlMuV2VibGluay50ZXN0KHVybCk7XG5cblx0XHQvLyBIYW5kbGUgb2JzaWRpYW46Ly8gVVJMc1xuXHRcdGlmICh0aGlzLmlzT2JzaWRpYW5VcmwodXJsKSkge1xuXHRcdFx0Y29uc3QgdXJsU3RyID0gdXJsLnJlcGxhY2UoJ29ic2lkaWFuOi8vb3BlbicsICcnKTtcblx0XHRcdGNvbnN0IHBhcmFtcyA9IG5ldyBVUkxTZWFyY2hQYXJhbXModXJsU3RyKTtcblx0XHRcdGNvbnN0IGZpbGUgPSBwYXJhbXMuZ2V0KCdmaWxlJyk7XG5cdFx0XHRpZiAoZmlsZSkge1xuXHRcdFx0XHR1cmwgPSBmaWxlO1xuXHRcdFx0XHRvYnNpZGlhblVybCA9IHRydWU7XG5cdFx0XHRcdGV4dGVybmFsID0gZmFsc2U7XG5cdFx0XHRcdGRpc3BsYXlUZXh0ID0gbnVsbDtcblx0XHRcdH1cblx0XHR9XG5cblx0XHQvLyBIYW5kbGUgZmlsZTovLyBVUkxzXG5cdFx0aWYgKHVybC5zdGFydHNXaXRoKCdmaWxlOicpKSB7XG5cdFx0XHR1cmwgPSB1cmwucmVwbGFjZSgvXmZpbGU6XFwvezEsfS8sIFBsYXRmb3JtLnJlc291cmNlUGF0aFByZWZpeCk7XG5cdFx0XHRleHRlcm5hbCA9IHRydWU7XG5cdFx0fVxuXG5cdFx0Ly8gUGFyc2Ugb2Zmc2V0L3JlcGVhdCBmcm9tIGhhc2ggZm9yIGV4dGVybmFsIFVSTHNcblx0XHRjb25zdCBoYXNoSW5kZXggPSB1cmwuaW5kZXhPZignIycpO1xuXHRcdGlmICgoZXh0ZXJuYWwgfHwgb2JzaWRpYW5VcmwpICYmIGhhc2hJbmRleCAhPT0gLTEpIHtcblx0XHRcdG9wdGlvbnMgPSB0aGlzLnBhcnNlSW1hZ2VQcm9wZXJ0aWVzKHVybC5zdWJzdHJpbmcoaGFzaEluZGV4ICsgMSkpO1xuXHRcdFx0dXJsID0gdXJsLnJlcGxhY2UoLyMuKi8sICcnKS50cmltKCk7XG5cdFx0fVxuXG5cdFx0Ly8gUGFyc2Ugb2Zmc2V0L3JlcGVhdCBmcm9tIGRpc3BsYXkgdGV4dFxuXHRcdGlmIChkaXNwbGF5VGV4dCkge1xuXHRcdFx0b3B0aW9ucyA9IHRoaXMucGFyc2VJbWFnZVByb3BlcnRpZXMoZGlzcGxheVRleHQpO1xuXHRcdH1cblxuXHRcdC8vIFJlc29sdmUgaW50ZXJuYWwgcGF0aHNcblx0XHRpZiAoIWV4dGVybmFsKSB7XG5cdFx0XHRjb25zdCB2YXVsdCA9IHRoaXMuYXBwLnZhdWx0O1xuXHRcdFx0bGV0IGZpbGU6IFRGaWxlIHwgbnVsbCA9IG51bGw7XG5cblx0XHRcdC8vIEhhbmRsZSBhYnNvbHV0ZS1mcm9tLXJvb3QgcGF0aHMgKGUuZy4gL2ltYWdlcy9ibG9nLzEuanBnKVxuXHRcdFx0Ly8gQ2hlY2sgaWYgVmF1bHQgQ01TIGhhcyBhIHB1YmxpYyBwYXRoIHJlc29sdmVyIGF2YWlsYWJsZVxuXHRcdFx0aWYgKHVybC5zdGFydHNXaXRoKCcvJykgJiYgIXVybC5zdGFydHNXaXRoKCcvLycpKSB7XG5cdFx0XHRcdGNvbnN0IHZhdWx0Q21zID0gKHRoaXMuYXBwIGFzIHVua25vd24gYXMgeyBwbHVnaW5zPzogeyBwbHVnaW5zPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gfSB9KS5wbHVnaW5zPy5wbHVnaW5zPy5bJ3ZhdWx0LWNtcyddIGFzIHsgcmVzb2x2ZVB1YmxpY1BhdGg/OiAocGF0aDogc3RyaW5nKSA9PiBzdHJpbmcgfCBudWxsIH0gfCB1bmRlZmluZWQ7XG5cdFx0XHRcdGNvbnN0IHJlc29sdmVkID0gdmF1bHRDbXM/LnJlc29sdmVQdWJsaWNQYXRoPy4odXJsKTtcblx0XHRcdFx0aWYgKHJlc29sdmVkKSB7XG5cdFx0XHRcdFx0dXJsID0gcmVzb2x2ZWQ7XG5cdFx0XHRcdFx0ZXh0ZXJuYWwgPSB0cnVlO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdGlmICghZXh0ZXJuYWwpIHtcblx0XHRcdFx0Ly8gVHJ5IHJlc29sdmluZyByZWxhdGl2ZSB0byB0aGUgY3VycmVudCBub3RlIGZpcnN0IChoYW5kbGVzIGJhcmUgZmlsZW5hbWVzIGxpa2UgXCJjb3Zlci5wbmdcIilcblx0XHRcdFx0aWYgKHZpZXc/LmZpbGUpIHtcblx0XHRcdFx0XHRjb25zdCByZXNvbHZlZFBhdGggPSB0aGlzLmFwcC5tZXRhZGF0YUNhY2hlLmdldEZpcnN0TGlua3BhdGhEZXN0KHVybCwgdmlldy5maWxlLnBhdGgpO1xuXHRcdFx0XHRcdGlmIChyZXNvbHZlZFBhdGgpIHtcblx0XHRcdFx0XHRcdGZpbGUgPSByZXNvbHZlZFBhdGg7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gRmFsbGJhY2sgdG8gZXhhY3QgcGF0aC9uYW1lIG1hdGNoaW5nXG5cdFx0XHRcdGlmICghZmlsZSkge1xuXHRcdFx0XHRcdGNvbnN0IGZpbGVzID0gdmF1bHQuZ2V0RmlsZXMoKS5maWx0ZXIoZiA9PiBmLnBhdGggPT09IHVybCB8fCBmLm5hbWUgPT09IHVybCk7XG5cdFx0XHRcdFx0ZmlsZSA9IGZpbGVzLmZpbmQoZiA9PiBmLnBhdGggPT09IHVybCkgfHwgZmlsZXMuZmluZChmID0+IGYubmFtZSA9PT0gdXJsKSB8fCBudWxsO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0aWYgKGZpbGUpIHtcblx0XHRcdFx0XHR1cmwgPSB2YXVsdC5nZXRSZXNvdXJjZVBhdGgoZmlsZSk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblx0XHQvLyBEZXRlY3QgY29udGVudCB0eXBlXG5cdFx0bGV0IHR5cGU6IEJhbm5lckNvbnRlbnRUeXBlIHwgbnVsbCA9IG51bGw7XG5cdFx0dHJ5IHtcblx0XHRcdGNvbnN0IHVybE9iaiA9IG5ldyBVUkwodXJsKTtcblx0XHRcdGNvbnN0IGV4dGVuc2lvbiA9IHVybE9iai5wYXRobmFtZS5zcGxpdCgnLicpLnBvcCgpPy50b0xvd2VyQ2FzZSgpO1xuXHRcdFx0Y29uc3QgaW1hZ2VFeHRlbnNpb25zID0gWydqcGcnLCAnanBlZycsICdwbmcnLCAnZ2lmJywgJ3N2ZycsICd3ZWJwJ107XG5cdFx0XHRjb25zdCB2aWRlb0V4dGVuc2lvbnMgPSBbJ21wNCcsICd3ZWJtJywgJ29nZycsICdvZ3YnLCAnbW92J107XG5cblx0XHRcdGlmIChleHRlbnNpb24gJiYgaW1hZ2VFeHRlbnNpb25zLmluY2x1ZGVzKGV4dGVuc2lvbikpIHtcblx0XHRcdFx0dHlwZSA9IEJhbm5lckNvbnRlbnRUeXBlLkltYWdlO1xuXHRcdFx0fSBlbHNlIGlmIChleHRlbnNpb24gJiYgdmlkZW9FeHRlbnNpb25zLmluY2x1ZGVzKGV4dGVuc2lvbikpIHtcblx0XHRcdFx0dHlwZSA9IEJhbm5lckNvbnRlbnRUeXBlLlZpZGVvO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBGYWxsYmFjayB0byBIRUFEIHJlcXVlc3QgaWYgdHlwZSBub3QgZGV0ZWN0ZWRcblx0XHRcdGlmICghdHlwZSkge1xuXHRcdFx0XHR0cnkge1xuXHRcdFx0XHRcdGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgcmVxdWVzdFVybCh7IHVybCwgbWV0aG9kOiAnSEVBRCcgfSk7XG5cdFx0XHRcdFx0Y29uc3QgY29udGVudFR5cGUgPSByZXNwb25zZT8uaGVhZGVyc1snY29udGVudC10eXBlJ10gfHwgbnVsbDtcblx0XHRcdFx0XHRpZiAoY29udGVudFR5cGUpIHtcblx0XHRcdFx0XHRcdGlmIChjb250ZW50VHlwZS5pbmNsdWRlcygnaW1hZ2UnKSkge1xuXHRcdFx0XHRcdFx0XHR0eXBlID0gQmFubmVyQ29udGVudFR5cGUuSW1hZ2U7XG5cdFx0XHRcdFx0XHR9IGVsc2UgaWYgKGNvbnRlbnRUeXBlLmluY2x1ZGVzKCd2aWRlbycpKSB7XG5cdFx0XHRcdFx0XHRcdHR5cGUgPSBCYW5uZXJDb250ZW50VHlwZS5WaWRlbztcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0gY2F0Y2gge1xuXHRcdFx0XHRcdC8vIElnbm9yZSBIRUFEIHJlcXVlc3QgZXJyb3JzXG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9IGNhdGNoIHtcblx0XHRcdC8vIElnbm9yZSBVUkwgcGFyc2luZyBlcnJvcnNcblx0XHR9XG5cblx0XHRyZXR1cm4ge1xuXHRcdFx0dXJsOiBgXCIke3VybC50cmltKCkucmVwbGFjZSgvKFtcIlxcXFxdKS9nLCAnXFxcXCQxJyl9XCJgLFxuXHRcdFx0ZXh0ZXJuYWwsXG5cdFx0XHR0eXBlLFxuXHRcdFx0Li4ub3B0aW9ucyxcblx0XHR9O1xuXHR9XG5cblx0LyoqXG5cdCAqIFBhcnNlIGltYWdlIHByb3BlcnRpZXMgKG9mZnNldCwgcmVwZWF0KSBmcm9tIHN0cmluZ1xuXHQgKi9cblx0cHJpdmF0ZSBwYXJzZUltYWdlUHJvcGVydGllcyhzdHI6IHN0cmluZyk6IHsgeDogbnVtYmVyOyB5OiBudW1iZXI7IHJlcGVhdGFibGU6IGJvb2xlYW4gfSB7XG5cdFx0Y29uc3QgdmFsdWVzID0gc3RyLnRvTG93ZXJDYXNlKCk7XG5cdFx0Y29uc3QgcmVwZWF0YWJsZSA9IHZhbHVlcy5pbmNsdWRlcygncmVwZWF0Jyk7XG5cblx0XHRjb25zdCBzaXplcyA9IHN0ci5zcGxpdCgveHwsLyk7XG5cdFx0Y29uc3QgbnVtYmVycyA9IHNpemVzLmZpbHRlcih2ID0+ICFpc05hTihwYXJzZUludCh2LnRyaW0oKSwgMTApKSk7XG5cblx0XHRsZXQgeCA9IDA7XG5cdFx0bGV0IHkgPSAwO1xuXG5cdFx0Y29uc3QgbnVtMCA9IG51bWJlcnNbMF07XG5cdFx0Y29uc3QgbnVtMSA9IG51bWJlcnNbMV07XG5cdFx0aWYgKG51bWJlcnMubGVuZ3RoID09PSAyICYmIG51bTAgJiYgbnVtMSkge1xuXHRcdFx0eCA9IHBhcnNlSW50KG51bTAudHJpbSgpLCAxMCk7XG5cdFx0XHR5ID0gcGFyc2VJbnQobnVtMS50cmltKCksIDEwKTtcblx0XHR9IGVsc2UgaWYgKG51bWJlcnMubGVuZ3RoID09PSAxICYmIG51bTApIHtcblx0XHRcdHkgPSBwYXJzZUludChudW0wLnRyaW0oKSwgMTApO1xuXHRcdH1cblxuXHRcdHJldHVybiB7IHgsIHksIHJlcGVhdGFibGUgfTtcblx0fVxuXG5cdC8qKlxuXHQgKiBQYXJzZSBpY29uIHByb3BlcnR5XG5cdCAqL1xuXHRhc3luYyBwYXJzZUljb24oaWNvbjogc3RyaW5nLCB2aWV3PzogTWFya2Rvd25WaWV3IHwgbnVsbCk6IFByb21pc2U8eyB2YWx1ZTogc3RyaW5nIHwgbnVsbDsgdHlwZTogQmFubmVySWNvblR5cGUgfT4ge1xuXHRcdGNvbnN0IHN0ciA9IGljb24gfHwgJyc7XG5cdFx0Y29uc3QgcmVzdWx0ID0geyB2YWx1ZTogbnVsbCBhcyBzdHJpbmcgfCBudWxsLCB0eXBlOiBCYW5uZXJJY29uVHlwZS5UZXh0IH07XG5cblx0XHQvLyBDaGVjayBpZiBpdCdzIGEgbGluayBmb3JtYXQgKGV4cGxpY2l0IHBhdHRlcm5zIG9yIGZpbGUgcGF0aCB3aXRoIGltYWdlIGV4dGVuc2lvbilcblx0XHRjb25zdCBpc0V4cGxpY2l0TGluayA9XG5cdFx0XHRQQVRURVJOUy5XaWtpbGluay50ZXN0KHN0cikgfHxcblx0XHRcdFBBVFRFUk5TLk1hcmtkb3duLnRlc3Qoc3RyKSB8fFxuXHRcdFx0UEFUVEVSTlMuTWFya2Rvd25CYXJlLnRlc3Qoc3RyKSB8fFxuXHRcdFx0UEFUVEVSTlMuV2VibGluay50ZXN0KHN0cikgfHxcblx0XHRcdHRoaXMuaXNPYnNpZGlhblVybChzdHIpO1xuXG5cdFx0Ly8gQ2hlY2sgaWYgaXQgbG9va3MgbGlrZSBhIGZpbGUgcGF0aCAoaGFzIGltYWdlIGV4dGVuc2lvbilcblx0XHRjb25zdCBpbWFnZUV4dGVuc2lvbnMgPSAvXFwuKGpwZ3xqcGVnfHBuZ3xnaWZ8c3ZnfHdlYnB8Ym1wfGljb3xhdmlmKSQvaTtcblx0XHRjb25zdCBpc0ZpbGVQYXRoID0gaW1hZ2VFeHRlbnNpb25zLnRlc3Qoc3RyKTtcblxuXHRcdGlmIChpc0V4cGxpY2l0TGluayB8fCBpc0ZpbGVQYXRoKSB7XG5cdFx0XHRyZXN1bHQudHlwZSA9IEJhbm5lckljb25UeXBlLkxpbms7XG5cdFx0XHRjb25zdCBkYXRhID0gYXdhaXQgdGhpcy5wYXJzZUxpbmsoc3RyLCB2aWV3KTtcblx0XHRcdHJlc3VsdC52YWx1ZSA9IGRhdGEudXJsO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRyZXN1bHQudmFsdWUgPSBzdHI7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHJlc3VsdDtcblx0fVxuXG5cdC8qKlxuXHQgKiBDaGVjayBpZiBvbmx5IGltYWdlIHByb3BlcnRpZXMgY2hhbmdlZCAobm90IHRoZSBVUkwpXG5cdCAqL1xuXHRwcml2YXRlIGFzeW5jIGlzSW1hZ2VQcm9wZXJ0aWVzVXBkYXRlKFxuXHRcdG9sZFN0cjogc3RyaW5nIHwgbnVsbCxcblx0XHRuZXdTdHI6IHN0cmluZyB8IG51bGwsXG5cdFx0dmlldz86IE1hcmtkb3duVmlldyB8IG51bGxcblx0KTogUHJvbWlzZTxib29sZWFuPiB7XG5cdFx0aWYgKCFvbGRTdHIgfHwgIW5ld1N0cikge1xuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblx0XHRjb25zdCBvbGRPcHQgPSBhd2FpdCB0aGlzLnBhcnNlTGluayhvbGRTdHIsIHZpZXcpO1xuXHRcdGNvbnN0IG5ld09wdCA9IGF3YWl0IHRoaXMucGFyc2VMaW5rKG5ld1N0ciwgdmlldyk7XG5cdFx0cmV0dXJuIG9sZE9wdC51cmwgPT09IG5ld09wdC51cmw7XG5cdH1cblxuXHQvKipcblx0ICogUmVzb2x2ZSBhYnNvbHV0ZS1mcm9tLXJvb3QgaW1hZ2UgcGF0aHMgKGUuZy4gL2ltYWdlcy9ibG9nLzEuanBnKVxuXHQgKiBVc2VzIHRoZSBjb25maWd1cmVkIHByb2plY3Qgcm9vdCB0byBmaW5kIGZpbGVzIGluIHRoZSBwdWJsaWMvIGZvbGRlci5cblx0ICogUmV0dXJucyBhIGZpbGU6Ly8gVVJMIGlmIGZvdW5kLCBudWxsIG90aGVyd2lzZS5cblx0ICovXG5cdC8qKlxuXHQgKiBDaGVjayBpZiBVUkwgaXMgYW4gb2JzaWRpYW46Ly8gVVJMXG5cdCAqL1xuXHRwcml2YXRlIGlzT2JzaWRpYW5VcmwodXJsOiBzdHJpbmcpOiBib29sZWFuIHtcblx0XHRyZXR1cm4gdXJsLnN0YXJ0c1dpdGgoJ29ic2lkaWFuOi8vb3BlbicpO1xuXHR9XG5cblx0LyoqXG5cdCAqIENhbGN1bGF0ZSBmb250IHNpemUgdG8gZml0IHRleHQgaW4gaWNvblxuXHQgKiBVc2VzIGFjdHVhbCBET00gbWVhc3VyZW1lbnQgZm9yIGFjY3VyYXRlIHNpemluZ1xuXHQgKi9cblx0cHJpdmF0ZSBjYWxjdWxhdGVGb250U2l6ZSh0ZXh0Q29udGVudDogc3RyaW5nLCBpY29uU2l6ZTogbnVtYmVyKTogc3RyaW5nIHtcblx0XHRjb25zdCB0ZW1wID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc3BhbicpO1xuXHRcdHRlbXAuYWRkQ2xhc3MoJ2ltLW1lYXN1cmUtdGVtcCcpO1xuXHRcdC8vIFVzZSBzZXRDc3NQcm9wZXJ0aWVzIGZvciBzdHlsZSBtYW5pcHVsYXRpb24gKHJlcXVpcmVkIGZvciBtZWFzdXJlbWVudCBlbGVtZW50KVxuXHRcdC8vIFRoaXMgZWxlbWVudCBpcyB0ZW1wb3JhcnkgYW5kIGltbWVkaWF0ZWx5IHJlbW92ZWQgYWZ0ZXIgbWVhc3VyZW1lbnRcblx0XHRzZXRDc3NQcm9wZXJ0aWVzKHRlbXAsIHtcblx0XHRcdHBvc2l0aW9uOiAnYWJzb2x1dGUnLFxuXHRcdFx0dmlzaWJpbGl0eTogJ2hpZGRlbicsXG5cdFx0XHQnd2hpdGUtc3BhY2UnOiAnbm93cmFwJyxcblx0XHRcdHBhZGRpbmc6ICcwJyxcblx0XHRcdG1hcmdpbjogJzAnLFxuXHRcdFx0bGVmdDogJy05OTk5cHgnLFxuXHRcdH0pO1xuXHRcdHRlbXAudGV4dENvbnRlbnQgPSB0ZXh0Q29udGVudC50b1VwcGVyQ2FzZSgpO1xuXHRcdGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQodGVtcCk7XG5cblx0XHRjb25zdCBjaGVja1dpZHRoID0gaWNvblNpemUgLSAxNjtcblx0XHRsZXQgZm9udFNpemUgPSBpY29uU2l6ZTsgLy8gU3RhcnQgYmlnXG5cdFx0c2V0Q3NzUHJvcGVydGllcyh0ZW1wLCB7ICdmb250LXNpemUnOiBgJHtmb250U2l6ZX1weGAgfSk7XG5cblx0XHR3aGlsZSAodGVtcC5vZmZzZXRXaWR0aCA+IGNoZWNrV2lkdGggJiYgZm9udFNpemUgPiAxKSB7XG5cdFx0XHRmb250U2l6ZSAtPSAxO1xuXHRcdFx0c2V0Q3NzUHJvcGVydGllcyh0ZW1wLCB7ICdmb250LXNpemUnOiBgJHtmb250U2l6ZX1weGAgfSk7XG5cdFx0fVxuXG5cdFx0ZG9jdW1lbnQuYm9keS5yZW1vdmVDaGlsZCh0ZW1wKTtcblx0XHRyZXR1cm4gYCR7Zm9udFNpemV9cHhgO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldCBhY3RpdmUgbWFya2Rvd24gdmlld1xuXHQgKi9cblx0cHJpdmF0ZSBnZXRBY3RpdmVWaWV3KCk6IE1hcmtkb3duVmlldyB8IG51bGwge1xuXHRcdHJldHVybiB0aGlzLmFwcC53b3Jrc3BhY2UuZ2V0QWN0aXZlVmlld09mVHlwZShNYXJrZG93blZpZXcpO1xuXHR9XG5cblx0LyoqXG5cdCAqIENyZWF0ZSBkZWZhdWx0IGJhbm5lciBkYXRhIG9iamVjdFxuXHQgKi9cblx0cHJpdmF0ZSBjcmVhdGVEZWZhdWx0QmFubmVyRGF0YSh2aWV3PzogTWFya2Rvd25WaWV3IHwgbnVsbCwgbGFzdFZpZXdNb2RlPzogJ3NvdXJjZScgfCAncHJldmlldycgfCBudWxsKTogQmFubmVyRGF0YSB7XG5cdFx0bGV0IHZpZXdNb2RlOiAnc291cmNlJyB8ICdwcmV2aWV3JyB8IG51bGwgPSBudWxsO1xuXHRcdGlmICh2aWV3KSB7XG5cdFx0XHRjb25zdCBtb2RlID0gdmlldy5nZXRNb2RlKCk7XG5cdFx0XHR2aWV3TW9kZSA9IG1vZGUgPT09ICdwcmV2aWV3JyA/ICdwcmV2aWV3JyA6ICdzb3VyY2UnO1xuXHRcdH1cblx0XHRyZXR1cm4ge1xuXHRcdFx0ZmlsZXBhdGg6IG51bGwsXG5cdFx0XHRpbWFnZTogbnVsbCxcblx0XHRcdGljb246IG51bGwsXG5cdFx0XHR2aWV3TW9kZSxcblx0XHRcdGxhc3RWaWV3TW9kZTogbGFzdFZpZXdNb2RlIHx8IG51bGwsXG5cdFx0XHRpc0ltYWdlUHJvcHNVcGRhdGU6IGZhbHNlLFxuXHRcdFx0aXNJbWFnZUNoYW5nZTogZmFsc2UsXG5cdFx0XHRuZWVkc1VwZGF0ZTogZmFsc2UsXG5cdFx0fTtcblx0fVxuXG5cdC8qKlxuXHQgKiBDbGVhbnVwIHdoZW4gcGx1Z2luIHVubG9hZHNcblx0ICovXG5cdGRlc3Ryb3koKTogdm9pZCB7XG5cdFx0Ly8gUmVtb3ZlIGFsbCBiYW5uZXJzXG5cdFx0ZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbChgLiR7Q1NTX0NMQVNTRVMuTWFpbn1gKS5mb3JFYWNoKGVsID0+IGVsLnJlbW92ZSgpKTtcblxuXHRcdC8vIENsZWFyIGRhdGEgc3RvcmVcblx0XHRiYW5uZXJEYXRhU3RvcmUuY2xlYXIoKTtcblx0fVxufVxuIiwgIi8qKlxyXG4gKiBGaWxlIFBpY2tlciBNb2RhbFxyXG4gKiBPcGVucyB0aGUgT1MgbmF0aXZlIGZpbGUgZGlhbG9nIGZvciBzZWxlY3RpbmcgbG9jYWwgaW1hZ2VzXHJcbiAqL1xyXG5cclxuaW1wb3J0IHsgQXBwLCBNb2RhbCwgTm90aWNlLCBNYXJrZG93blZpZXcsIFRGaWxlIH0gZnJvbSAnb2JzaWRpYW4nO1xyXG5pbXBvcnQgeyBJbWFnZVByb2Nlc3NvciB9IGZyb20gJy4uL3NlcnZpY2VzL0ltYWdlUHJvY2Vzc29yJztcclxuaW1wb3J0IHsgUHJvcGVydHlIYW5kbGVyIH0gZnJvbSAnLi4vc2VydmljZXMvUHJvcGVydHlIYW5kbGVyJztcclxuXHJcbmV4cG9ydCBjbGFzcyBGaWxlUGlja2VyTW9kYWwgZXh0ZW5kcyBNb2RhbCB7XHJcblx0cHJpdmF0ZSBpbWFnZVByb2Nlc3NvcjogSW1hZ2VQcm9jZXNzb3I7XHJcblx0cHJpdmF0ZSBwcm9wZXJ0eUhhbmRsZXI6IFByb3BlcnR5SGFuZGxlcjtcclxuXHRwcml2YXRlIGluc2VydFRvUHJvcGVydHk6IGJvb2xlYW47XHJcblx0cHJpdmF0ZSBwcm9wZXJ0eU5hbWU/OiBzdHJpbmc7XHJcblxyXG5cdGNvbnN0cnVjdG9yKFxyXG5cdFx0YXBwOiBBcHAsXHJcblx0XHRpbWFnZVByb2Nlc3NvcjogSW1hZ2VQcm9jZXNzb3IsXHJcblx0XHRwcm9wZXJ0eUhhbmRsZXI6IFByb3BlcnR5SGFuZGxlcixcclxuXHRcdGluc2VydFRvUHJvcGVydHk6IGJvb2xlYW4gPSBmYWxzZSxcclxuXHRcdHByb3BlcnR5TmFtZT86IHN0cmluZ1xyXG5cdCkge1xyXG5cdFx0c3VwZXIoYXBwKTtcclxuXHRcdHRoaXMuaW1hZ2VQcm9jZXNzb3IgPSBpbWFnZVByb2Nlc3NvcjtcclxuXHRcdHRoaXMucHJvcGVydHlIYW5kbGVyID0gcHJvcGVydHlIYW5kbGVyO1xyXG5cdFx0dGhpcy5pbnNlcnRUb1Byb3BlcnR5ID0gaW5zZXJ0VG9Qcm9wZXJ0eTtcclxuXHRcdHRoaXMucHJvcGVydHlOYW1lID0gcHJvcGVydHlOYW1lO1xyXG5cdH1cclxuXHJcblx0b25PcGVuKCk6IHZvaWQge1xyXG5cdFx0Y29uc3QgeyBjb250ZW50RWwgfSA9IHRoaXM7XHJcblxyXG5cdFx0Ly8gQ3JlYXRlIGhpZGRlbiBmaWxlIGlucHV0XHJcblx0XHRjb25zdCBpbnB1dCA9IGNvbnRlbnRFbC5jcmVhdGVFbCgnaW5wdXQnLCB7XHJcblx0XHRcdHR5cGU6ICdmaWxlJyxcclxuXHRcdFx0YXR0cjoge1xyXG5cdFx0XHRcdGFjY2VwdDogJ2ltYWdlLyonLFxyXG5cdFx0XHRcdG11bHRpcGxlOiAndHJ1ZScsXHJcblx0XHRcdFx0c3R5bGU6ICdkaXNwbGF5OiBub25lOycsXHJcblx0XHRcdH0sXHJcblx0XHR9KTtcclxuXHJcblx0XHQvLyBIYW5kbGUgZmlsZSBzZWxlY3Rpb25cclxuXHRcdGlucHV0LmFkZEV2ZW50TGlzdGVuZXIoJ2NoYW5nZScsICgpID0+IHsgdm9pZCB0aGlzLmhhbmRsZUZpbGVTZWxlY3Rpb24oaW5wdXQpOyB9KTtcclxuXHJcblx0XHQvLyBIYW5kbGUgY2FuY2VsXHJcblx0XHRpbnB1dC5hZGRFdmVudExpc3RlbmVyKCdjYW5jZWwnLCAoKSA9PiB7XHJcblx0XHRcdHRoaXMuY2xvc2UoKTtcclxuXHRcdH0pO1xyXG5cclxuXHRcdC8vIFRyaWdnZXIgdGhlIGZpbGUgZGlhbG9nIGltbWVkaWF0ZWx5XHJcblx0XHRpbnB1dC5jbGljaygpO1xyXG5cdH1cclxuXHJcblx0cHJpdmF0ZSBhc3luYyBoYW5kbGVGaWxlU2VsZWN0aW9uKGlucHV0OiBIVE1MSW5wdXRFbGVtZW50KTogUHJvbWlzZTx2b2lkPiB7XHJcblx0XHRcdHRoaXMuY2xvc2UoKTtcclxuXHJcblx0XHRcdGNvbnN0IGZpbGVzID0gaW5wdXQuZmlsZXM7XHJcblx0XHRcdGlmICghZmlsZXMgfHwgZmlsZXMubGVuZ3RoID09PSAwKSB7XHJcblx0XHRcdFx0bmV3IE5vdGljZSgnTm8gZmlsZXMgc2VsZWN0ZWQnKTtcclxuXHRcdFx0XHRyZXR1cm47XHJcblx0XHRcdH1cclxuXHJcblx0XHRcdGNvbnN0IGFjdGl2ZUZpbGUgPSB0aGlzLmdldEFjdGl2ZUZpbGUoKTtcclxuXHRcdFx0aWYgKCFhY3RpdmVGaWxlKSB7XHJcblx0XHRcdFx0bmV3IE5vdGljZSgnTm8gYWN0aXZlIGZpbGUnKTtcclxuXHRcdFx0XHRyZXR1cm47XHJcblx0XHRcdH1cclxuXHJcblx0XHRcdGNvbnN0IHZpZXcgPSB0aGlzLmFwcC53b3Jrc3BhY2UuZ2V0QWN0aXZlVmlld09mVHlwZShNYXJrZG93blZpZXcpO1xyXG5cdFx0XHRjb25zdCBlZGl0b3IgPSB2aWV3Py5lZGl0b3I7XHJcblxyXG5cdFx0XHQvLyBQcm9jZXNzIGVhY2ggc2VsZWN0ZWQgZmlsZVxyXG5cdFx0XHRmb3IgKGxldCBpID0gMDsgaSA8IGZpbGVzLmxlbmd0aDsgaSsrKSB7XHJcblx0XHRcdFx0Y29uc3QgZmlsZSA9IGZpbGVzLml0ZW0oaSk7XHJcblx0XHRcdFx0aWYgKCFmaWxlIHx8ICFmaWxlLnR5cGUuc3RhcnRzV2l0aCgnaW1hZ2UvJykpIHtcclxuXHRcdFx0XHRcdGNvbnRpbnVlO1xyXG5cdFx0XHRcdH1cclxuXHJcblx0XHRcdFx0aWYgKHRoaXMuaW5zZXJ0VG9Qcm9wZXJ0eSkge1xyXG5cdFx0XHRcdFx0Ly8gVmFsaWRhdGUgcHJvcGVydHkgbmFtZVxyXG5cdFx0XHRcdFx0aWYgKCF0aGlzLnByb3BlcnR5TmFtZSB8fCB0aGlzLnByb3BlcnR5TmFtZS50cmltKCkgPT09ICcnKSB7XHJcblx0XHRcdFx0XHRcdG5ldyBOb3RpY2UoJ1BsZWFzZSBzcGVjaWZ5IGEgcHJvcGVydHkgbmFtZSBpbiBzZXR0aW5ncycpO1xyXG5cdFx0XHRcdFx0XHRyZXR1cm47XHJcblx0XHRcdFx0XHR9XHJcblxyXG5cdFx0XHRcdFx0Ly8gSW5zZXJ0IGludG8gcHJvcGVydHkgKGNyZWF0ZSBpZiBpdCBkb2Vzbid0IGV4aXN0KVxyXG5cdFx0XHRcdFx0Ly8gU2tpcCBkZXNjcmlwdGl2ZSBpbWFnZXMgZm9yIHByb3BlcnR5IGluc2VydGlvbnMgKGRpc3BsYXkgdGV4dCBkb2Vzbid0IGFwcGx5IHRvIHByb3BlcnRpZXMpXHJcblx0XHRcdFx0XHRjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLmltYWdlUHJvY2Vzc29yLnByb2Nlc3NJbWFnZUZpbGUoXHJcblx0XHRcdFx0XHRcdGZpbGUsXHJcblx0XHRcdFx0XHRcdGFjdGl2ZUZpbGUsXHJcblx0XHRcdFx0XHRcdHRydWUsIC8vIFNob3cgcmVuYW1lIG1vZGFsXHJcblx0XHRcdFx0XHRcdHRydWUgLy8gaXNQcm9wZXJ0eUluc2VydGlvbiAtIHNraXAgZGVzY3JpcHRpdmUgaW1hZ2VzXHJcblx0XHRcdFx0XHQpO1xyXG5cclxuXHRcdFx0XHRcdGlmIChyZXN1bHQuc3VjY2VzcyAmJiByZXN1bHQuZmlsZSkge1xyXG5cdFx0XHRcdFx0XHRhd2FpdCB0aGlzLnByb3BlcnR5SGFuZGxlci5zZXRQcm9wZXJ0eVZhbHVlKFxyXG5cdFx0XHRcdFx0XHRcdGFjdGl2ZUZpbGUsXHJcblx0XHRcdFx0XHRcdFx0dGhpcy5wcm9wZXJ0eU5hbWUsXHJcblx0XHRcdFx0XHRcdFx0cmVzdWx0LmZpbGVcclxuXHRcdFx0XHRcdFx0KTtcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHR9IGVsc2Uge1xyXG5cdFx0XHRcdFx0Ly8gSW5zZXJ0IGludG8gbm90ZSBib2R5XHJcblx0XHRcdFx0XHRjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLmltYWdlUHJvY2Vzc29yLnByb2Nlc3NJbWFnZUZpbGUoXHJcblx0XHRcdFx0XHRcdGZpbGUsXHJcblx0XHRcdFx0XHRcdGFjdGl2ZUZpbGUsXHJcblx0XHRcdFx0XHRcdHRydWUgLy8gU2hvdyByZW5hbWUgbW9kYWxcclxuXHRcdFx0XHRcdCk7XHJcblxyXG5cdFx0XHRcdFx0aWYgKHJlc3VsdC5zdWNjZXNzICYmIHJlc3VsdC5saW5rVGV4dCAmJiBlZGl0b3IpIHtcclxuXHRcdFx0XHRcdFx0ZWRpdG9yLnJlcGxhY2VTZWxlY3Rpb24ocmVzdWx0LmxpbmtUZXh0KTtcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHR9XHJcblx0XHRcdH1cclxuXHJcblx0XHRuZXcgTm90aWNlKGBBZGRlZCAke2ZpbGVzLmxlbmd0aH0gaW1hZ2UocylgKTtcclxuXHR9XHJcblxyXG5cdHByaXZhdGUgZ2V0QWN0aXZlRmlsZSgpOiBURmlsZSB8IG51bGwge1xyXG5cdFx0Y29uc3QgdmlldyA9IHRoaXMuYXBwLndvcmtzcGFjZS5nZXRBY3RpdmVWaWV3T2ZUeXBlKE1hcmtkb3duVmlldyk7XHJcblx0XHRyZXR1cm4gdmlldz8uZmlsZSA/PyBudWxsO1xyXG5cdH1cclxuXHJcblx0b25DbG9zZSgpOiB2b2lkIHtcclxuXHRcdGNvbnN0IHsgY29udGVudEVsIH0gPSB0aGlzO1xyXG5cdFx0Y29udGVudEVsLmVtcHR5KCk7XHJcblx0fVxyXG59XHJcblxyXG4vKipcclxuICogT3BlbiB0aGUgZmlsZSBwaWNrZXIgYW5kIHByb2Nlc3Mgc2VsZWN0ZWQgaW1hZ2VzXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gb3BlbkZpbGVQaWNrZXIoXHJcblx0YXBwOiBBcHAsXHJcblx0aW1hZ2VQcm9jZXNzb3I6IEltYWdlUHJvY2Vzc29yLFxyXG5cdHByb3BlcnR5SGFuZGxlcjogUHJvcGVydHlIYW5kbGVyLFxyXG5cdGluc2VydFRvUHJvcGVydHk6IGJvb2xlYW4gPSBmYWxzZSxcclxuXHRwcm9wZXJ0eU5hbWU/OiBzdHJpbmdcclxuKTogdm9pZCB7XHJcblx0bmV3IEZpbGVQaWNrZXJNb2RhbChhcHAsIGltYWdlUHJvY2Vzc29yLCBwcm9wZXJ0eUhhbmRsZXIsIGluc2VydFRvUHJvcGVydHksIHByb3BlcnR5TmFtZSkub3BlbigpO1xyXG59XHJcbiIsICIvKipcclxuICogUmVtb3RlIFNlYXJjaCBNb2RhbFxyXG4gKiBTZWFyY2ggYW5kIGluc2VydCBpbWFnZXMgZnJvbSBVbnNwbGFzaCwgUGV4ZWxzLCBhbmQgUGl4YWJheVxyXG4gKi9cclxuXHJcbmltcG9ydCB7IEFwcCwgTW9kYWwsIE5vdGljZSwgTWFya2Rvd25WaWV3LCBURmlsZSwgZGVib3VuY2UgfSBmcm9tICdvYnNpZGlhbic7XHJcbmltcG9ydCB7IEltYWdlUHJvdmlkZXIsIFJlbW90ZUltYWdlLCBJbWFnZU1hbmFnZXJTZXR0aW5ncywgSW1hZ2VTaXplIH0gZnJvbSAnLi4vdHlwZXMnO1xyXG5pbXBvcnQgeyBSZW1vdGVJbWFnZVNlcnZpY2UgfSBmcm9tICcuLi9zZXJ2aWNlcy9SZW1vdGVJbWFnZVNlcnZpY2UnO1xyXG5pbXBvcnQgeyBJbWFnZVByb2Nlc3NvciB9IGZyb20gJy4uL3NlcnZpY2VzL0ltYWdlUHJvY2Vzc29yJztcclxuaW1wb3J0IHsgUHJvcGVydHlIYW5kbGVyIH0gZnJvbSAnLi4vc2VydmljZXMvUHJvcGVydHlIYW5kbGVyJztcclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgUmVtb3RlU2VhcmNoT3B0aW9ucyB7XHJcblx0aW5zZXJ0VG9Qcm9wZXJ0eT86IGJvb2xlYW47XHJcblx0cHJvcGVydHlOYW1lPzogc3RyaW5nO1xyXG59XHJcblxyXG5leHBvcnQgY2xhc3MgUmVtb3RlU2VhcmNoTW9kYWwgZXh0ZW5kcyBNb2RhbCB7XHJcblx0cHJpdmF0ZSBzZXR0aW5nczogSW1hZ2VNYW5hZ2VyU2V0dGluZ3M7XHJcblx0cHJpdmF0ZSByZW1vdGVTZXJ2aWNlOiBSZW1vdGVJbWFnZVNlcnZpY2U7XHJcblx0cHJpdmF0ZSBpbWFnZVByb2Nlc3NvcjogSW1hZ2VQcm9jZXNzb3I7XHJcblx0cHJpdmF0ZSBwcm9wZXJ0eUhhbmRsZXI6IFByb3BlcnR5SGFuZGxlcjtcclxuXHRwcml2YXRlIG9wdGlvbnM6IFJlbW90ZVNlYXJjaE9wdGlvbnM7XHJcblxyXG5cdHByaXZhdGUgY29udGFpbmVyOiBIVE1MRWxlbWVudCB8IG51bGwgPSBudWxsO1xyXG5cdHByaXZhdGUgcXVlcnlJbnB1dDogSFRNTElucHV0RWxlbWVudCB8IG51bGwgPSBudWxsO1xyXG5cdHByaXZhdGUgcHJvdmlkZXJTZWxlY3Q6IEhUTUxTZWxlY3RFbGVtZW50IHwgbnVsbCA9IG51bGw7XHJcblx0cHJpdmF0ZSBzaXplU2VsZWN0OiBIVE1MU2VsZWN0RWxlbWVudCB8IG51bGwgPSBudWxsO1xyXG5cdHByaXZhdGUgc2Nyb2xsQXJlYTogSFRNTEVsZW1lbnQgfCBudWxsID0gbnVsbDtcclxuXHRwcml2YXRlIGltYWdlc0xpc3Q6IEhUTUxFbGVtZW50IHwgbnVsbCA9IG51bGw7XHJcblx0cHJpdmF0ZSBsb2FkaW5nQ29udGFpbmVyOiBIVE1MRWxlbWVudCB8IG51bGwgPSBudWxsO1xyXG5cclxuXHRwcml2YXRlIGN1cnJlbnRRdWVyeTogc3RyaW5nID0gJyc7XHJcblx0cHJpdmF0ZSBjdXJyZW50UHJvdmlkZXI6IEltYWdlUHJvdmlkZXI7XHJcblx0cHJpdmF0ZSBjdXJyZW50UGFnZTogbnVtYmVyID0gMTtcclxuXHRwcml2YXRlIGN1cnJlbnRSZXN1bHRzOiBSZW1vdGVJbWFnZVtdID0gW107XHJcblx0cHJpdmF0ZSBpc0xvYWRpbmc6IGJvb2xlYW4gPSBmYWxzZTtcclxuXHRwcml2YXRlIHNlbGVjdGVkSW1hZ2U6IG51bWJlciA9IDA7XHJcblxyXG5cdGNvbnN0cnVjdG9yKFxyXG5cdFx0YXBwOiBBcHAsXHJcblx0XHRzZXR0aW5nczogSW1hZ2VNYW5hZ2VyU2V0dGluZ3MsXHJcblx0XHRyZW1vdGVTZXJ2aWNlOiBSZW1vdGVJbWFnZVNlcnZpY2UsXHJcblx0XHRpbWFnZVByb2Nlc3NvcjogSW1hZ2VQcm9jZXNzb3IsXHJcblx0XHRwcm9wZXJ0eUhhbmRsZXI6IFByb3BlcnR5SGFuZGxlcixcclxuXHRcdG9wdGlvbnM6IFJlbW90ZVNlYXJjaE9wdGlvbnMgPSB7fVxyXG5cdCkge1xyXG5cdFx0c3VwZXIoYXBwKTtcclxuXHRcdHRoaXMuc2V0dGluZ3MgPSBzZXR0aW5ncztcclxuXHRcdHRoaXMucmVtb3RlU2VydmljZSA9IHJlbW90ZVNlcnZpY2U7XHJcblx0XHR0aGlzLmltYWdlUHJvY2Vzc29yID0gaW1hZ2VQcm9jZXNzb3I7XHJcblx0XHR0aGlzLnByb3BlcnR5SGFuZGxlciA9IHByb3BlcnR5SGFuZGxlcjtcclxuXHRcdHRoaXMub3B0aW9ucyA9IG9wdGlvbnM7XHJcblx0XHR0aGlzLmN1cnJlbnRQcm92aWRlciA9IHNldHRpbmdzLmRlZmF1bHRQcm92aWRlcjtcclxuXHRcdHRoaXMuY29udGFpbmVyRWwuYWRkQ2xhc3MoJ2ltYWdlLWluc2VydGVyLWNvbnRhaW5lcicpO1xyXG5cdH1cclxuXHJcblx0b25PcGVuKCk6IHZvaWQge1xyXG5cdFx0Y29uc3QgeyBjb250ZW50RWwgfSA9IHRoaXM7XHJcblxyXG5cdFx0Ly8gTWFpbiBjb250YWluZXJcclxuXHRcdHRoaXMuY29udGFpbmVyID0gY29udGVudEVsLmNyZWF0ZURpdih7IGNsczogJ2NvbnRhaW5lcicgfSk7XHJcblxyXG5cdFx0Ly8gSW5wdXQgZ3JvdXBcclxuXHRcdGNvbnN0IGlucHV0R3JvdXAgPSB0aGlzLmNvbnRhaW5lci5jcmVhdGVEaXYoeyBjbHM6ICdpbnB1dC1ncm91cCcgfSk7XHJcblxyXG5cdFx0Ly8gUXVlcnkgaW5wdXRcclxuXHRcdHRoaXMucXVlcnlJbnB1dCA9IGlucHV0R3JvdXAuY3JlYXRlRWwoJ2lucHV0Jywge1xyXG5cdFx0XHR0eXBlOiAndGV4dCcsXHJcblx0XHRcdGNsczogJ3F1ZXJ5LWlucHV0JyxcclxuXHRcdFx0YXR0cjogeyBwbGFjZWhvbGRlcjogJ1NlYXJjaCBpbWFnZXMuLi4nLCBhdXRvZm9jdXM6ICd0cnVlJyB9LFxyXG5cdFx0fSk7XHJcblxyXG5cdFx0Ly8gUHJvdmlkZXIgc2VsZWN0b3JcclxuXHRcdHRoaXMucHJvdmlkZXJTZWxlY3QgPSBpbnB1dEdyb3VwLmNyZWF0ZUVsKCdzZWxlY3QnLCB7IGNsczogJ3NlbGVjdG9yJyB9KTtcclxuXHRcdHRoaXMucHJvdmlkZXJTZWxlY3QuY3JlYXRlRWwoJ29wdGlvbicsIHsgdGV4dDogJ1Vuc3BsYXNoJywgdmFsdWU6IEltYWdlUHJvdmlkZXIuVW5zcGxhc2ggfSk7XHJcblx0XHR0aGlzLnByb3ZpZGVyU2VsZWN0LmNyZWF0ZUVsKCdvcHRpb24nLCB7IHRleHQ6ICdQZXhlbHMnLCB2YWx1ZTogSW1hZ2VQcm92aWRlci5QZXhlbHMgfSk7XHJcblx0XHR0aGlzLnByb3ZpZGVyU2VsZWN0LmNyZWF0ZUVsKCdvcHRpb24nLCB7IHRleHQ6ICdQaXhhYmF5JywgdmFsdWU6IEltYWdlUHJvdmlkZXIuUGl4YWJheSB9KTtcclxuXHRcdHRoaXMucHJvdmlkZXJTZWxlY3QudmFsdWUgPSB0aGlzLmN1cnJlbnRQcm92aWRlcjtcclxuXHJcblx0XHQvLyBTaXplIHNlbGVjdG9yXHJcblx0XHR0aGlzLnNpemVTZWxlY3QgPSBpbnB1dEdyb3VwLmNyZWF0ZUVsKCdzZWxlY3QnLCB7IGNsczogJ3NlbGVjdG9yJyB9KTtcclxuXHRcdHRoaXMuc2l6ZVNlbGVjdC5jcmVhdGVFbCgnb3B0aW9uJywgeyB0ZXh0OiAnT3JpZ2luYWwnLCB2YWx1ZTogSW1hZ2VTaXplLk9yaWdpbmFsIH0pO1xyXG5cdFx0dGhpcy5zaXplU2VsZWN0LmNyZWF0ZUVsKCdvcHRpb24nLCB7IHRleHQ6ICdMYXJnZScsIHZhbHVlOiBJbWFnZVNpemUuTGFyZ2UgfSk7XHJcblx0XHR0aGlzLnNpemVTZWxlY3QuY3JlYXRlRWwoJ29wdGlvbicsIHsgdGV4dDogJ01lZGl1bScsIHZhbHVlOiBJbWFnZVNpemUuTWVkaXVtIH0pO1xyXG5cdFx0dGhpcy5zaXplU2VsZWN0LmNyZWF0ZUVsKCdvcHRpb24nLCB7IHRleHQ6ICdTbWFsbCcsIHZhbHVlOiBJbWFnZVNpemUuU21hbGwgfSk7XHJcblx0XHR0aGlzLnNpemVTZWxlY3QudmFsdWUgPSB0aGlzLnNldHRpbmdzLmRlZmF1bHRJbWFnZVNpemU7XHJcblxyXG5cdFx0Ly8gTG9hZGluZyBjb250YWluZXJcclxuXHRcdHRoaXMubG9hZGluZ0NvbnRhaW5lciA9IHRoaXMuY29udGFpbmVyLmNyZWF0ZURpdih7IGNsczogJ2xvYWRpbmctY29udGFpbmVyJyB9KTtcclxuXHRcdGNvbnN0IGxvYWRlckljb24gPSB0aGlzLmxvYWRpbmdDb250YWluZXIuY3JlYXRlRGl2KHsgY2xzOiAnbG9hZGVyLWljb24nIH0pO1xyXG5cdFx0Y29uc3Qgc3ZnID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKCdodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZycsICdzdmcnKTtcclxuXHRcdHN2Zy5zZXRBdHRyaWJ1dGUoJ3dpZHRoJywgJzI0Jyk7XHJcblx0XHRzdmcuc2V0QXR0cmlidXRlKCdoZWlnaHQnLCAnMjQnKTtcclxuXHRcdHN2Zy5zZXRBdHRyaWJ1dGUoJ3ZpZXdCb3gnLCAnMCAwIDI0IDI0Jyk7XHJcblx0XHRzdmcuc2V0QXR0cmlidXRlKCdmaWxsJywgJ25vbmUnKTtcclxuXHRcdHN2Zy5zZXRBdHRyaWJ1dGUoJ3N0cm9rZScsICdjdXJyZW50Q29sb3InKTtcclxuXHRcdHN2Zy5zZXRBdHRyaWJ1dGUoJ3N0cm9rZS13aWR0aCcsICcyJyk7XHJcblx0XHRzdmcuc2V0QXR0cmlidXRlKCdzdHJva2UtbGluZWNhcCcsICdyb3VuZCcpO1xyXG5cdFx0c3ZnLnNldEF0dHJpYnV0ZSgnc3Ryb2tlLWxpbmVqb2luJywgJ3JvdW5kJyk7XHJcblx0XHRzdmcuY2xhc3NMaXN0LmFkZCgnbHVjaWRlJywgJ2x1Y2lkZS1sb2FkZXItY2lyY2xlJyk7XHJcblx0XHRjb25zdCBwYXRoID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKCdodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZycsICdwYXRoJyk7XHJcblx0XHRwYXRoLnNldEF0dHJpYnV0ZSgnZCcsICdNMjEgMTJhOSA5IDAgMSAxLTYuMjE5LTguNTYnKTtcclxuXHRcdHN2Zy5hcHBlbmRDaGlsZChwYXRoKTtcclxuXHRcdGxvYWRlckljb24uYXBwZW5kQ2hpbGQoc3ZnKTtcclxuXHRcdHRoaXMuc2hvd0xvYWRpbmcoZmFsc2UpO1xyXG5cclxuXHRcdC8vIFNjcm9sbCBhcmVhXHJcblx0XHR0aGlzLnNjcm9sbEFyZWEgPSB0aGlzLmNvbnRhaW5lci5jcmVhdGVEaXYoeyBjbHM6ICdzY3JvbGwtYXJlYScgfSk7XHJcblx0XHR0aGlzLmltYWdlc0xpc3QgPSB0aGlzLnNjcm9sbEFyZWEuY3JlYXRlRGl2KHsgY2xzOiAnaW1hZ2VzLWxpc3QnIH0pO1xyXG5cclxuXHRcdC8vIEV2ZW50IGxpc3RlbmVyc1xyXG5cdFx0dGhpcy5zZXR1cEV2ZW50TGlzdGVuZXJzKCk7XHJcblxyXG5cdFx0Ly8gRm9jdXMgaW5wdXRcclxuXHRcdHNldFRpbWVvdXQoKCkgPT4ge1xyXG5cdFx0XHR0aGlzLnF1ZXJ5SW5wdXQ/LmZvY3VzKCk7XHJcblx0XHR9LCA1MCk7XHJcblx0fVxyXG5cclxuXHRwcml2YXRlIHNldHVwRXZlbnRMaXN0ZW5lcnMoKTogdm9pZCB7XHJcblx0XHQvLyBEZWJvdW5jZWQgc2VhcmNoXHJcblx0XHRjb25zdCBkZWJvdW5jZWRTZWFyY2ggPSBkZWJvdW5jZSgocXVlcnk6IHN0cmluZykgPT4ge1xyXG5cdFx0XHRpZiAocXVlcnkudHJpbSgpKSB7XHJcblx0XHRcdFx0dm9pZCB0aGlzLnBlcmZvcm1TZWFyY2gocXVlcnksIHRydWUpO1xyXG5cdFx0XHR9IGVsc2Uge1xyXG5cdFx0XHRcdHRoaXMuY2xlYXJSZXN1bHRzKCk7XHJcblx0XHRcdH1cclxuXHRcdH0sIDEwMDAsIHRydWUpO1xyXG5cclxuXHRcdC8vIFF1ZXJ5IGlucHV0XHJcblx0XHR0aGlzLnF1ZXJ5SW5wdXQ/LmFkZEV2ZW50TGlzdGVuZXIoJ2lucHV0JywgKGUpID0+IHtcclxuXHRcdFx0Y29uc3QgcXVlcnkgPSAoZS50YXJnZXQgYXMgSFRNTElucHV0RWxlbWVudCkudmFsdWU7XHJcblx0XHRcdHRoaXMuY3VycmVudFF1ZXJ5ID0gcXVlcnk7XHJcblx0XHRcdHRoaXMuc2hvd0xvYWRpbmcodHJ1ZSk7XHJcblx0XHRcdGRlYm91bmNlZFNlYXJjaChxdWVyeSk7XHJcblx0XHR9KTtcclxuXHJcblx0XHR0aGlzLnF1ZXJ5SW5wdXQ/LmFkZEV2ZW50TGlzdGVuZXIoJ2tleWRvd24nLCAoZSkgPT4ge1xyXG5cdFx0XHRpZiAoZS5rZXkgPT09ICdFbnRlcicpIHtcclxuXHRcdFx0XHRlLnByZXZlbnREZWZhdWx0KCk7XHJcblx0XHRcdFx0Y29uc3QgcXVlcnkgPSB0aGlzLnF1ZXJ5SW5wdXQ/LnZhbHVlLnRyaW0oKSB8fCAnJztcclxuXHRcdFx0XHRpZiAocXVlcnkpIHtcclxuXHRcdFx0XHRcdHZvaWQgdGhpcy5wZXJmb3JtU2VhcmNoKHF1ZXJ5LCB0cnVlKTtcclxuXHRcdFx0XHR9IGVsc2UgaWYgKHRoaXMuY3VycmVudFJlc3VsdHMubGVuZ3RoID4gMCAmJiB0aGlzLnNlbGVjdGVkSW1hZ2UgPCB0aGlzLmN1cnJlbnRSZXN1bHRzLmxlbmd0aCkge1xyXG5cdFx0XHRcdFx0Ly8gSW5zZXJ0IHNlbGVjdGVkIGltYWdlIG9uIEVudGVyXHJcblx0XHRcdFx0XHRjb25zdCBpbWFnZSA9IHRoaXMuY3VycmVudFJlc3VsdHNbdGhpcy5zZWxlY3RlZEltYWdlXTtcclxuXHRcdFx0XHRcdGlmIChpbWFnZSkge1xyXG5cdFx0XHRcdFx0XHR2b2lkIHRoaXMuaW5zZXJ0SW1hZ2UoaW1hZ2UpO1xyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdH1cclxuXHRcdFx0fSBlbHNlIGlmIChlLmN0cmxLZXkgJiYgZS5rZXkgPT09ICduJykge1xyXG5cdFx0XHRcdGUucHJldmVudERlZmF1bHQoKTtcclxuXHRcdFx0XHRpZiAodGhpcy5jdXJyZW50UmVzdWx0cy5sZW5ndGggPiAwKSB7XHJcblx0XHRcdFx0XHR0aGlzLnNlbGVjdGVkSW1hZ2UgPSAodGhpcy5zZWxlY3RlZEltYWdlICsgMSkgJSB0aGlzLmN1cnJlbnRSZXN1bHRzLmxlbmd0aDtcclxuXHRcdFx0XHRcdHRoaXMucmVuZGVyUmVzdWx0cygpO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0fSBlbHNlIGlmIChlLmN0cmxLZXkgJiYgZS5rZXkgPT09ICdwJykge1xyXG5cdFx0XHRcdGUucHJldmVudERlZmF1bHQoKTtcclxuXHRcdFx0XHRpZiAodGhpcy5jdXJyZW50UmVzdWx0cy5sZW5ndGggPiAwKSB7XHJcblx0XHRcdFx0XHR0aGlzLnNlbGVjdGVkSW1hZ2UgPSAodGhpcy5zZWxlY3RlZEltYWdlIC0gMSArIHRoaXMuY3VycmVudFJlc3VsdHMubGVuZ3RoKSAlIHRoaXMuY3VycmVudFJlc3VsdHMubGVuZ3RoO1xyXG5cdFx0XHRcdFx0dGhpcy5yZW5kZXJSZXN1bHRzKCk7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblx0XHR9KTtcclxuXHJcblx0XHQvLyBQcm92aWRlciBjaGFuZ2VcclxuXHRcdHRoaXMucHJvdmlkZXJTZWxlY3Q/LmFkZEV2ZW50TGlzdGVuZXIoJ2NoYW5nZScsIChlKSA9PiB7XHJcblx0XHRcdHRoaXMuY3VycmVudFByb3ZpZGVyID0gKGUudGFyZ2V0IGFzIEhUTUxTZWxlY3RFbGVtZW50KS52YWx1ZSBhcyBJbWFnZVByb3ZpZGVyO1xyXG5cdFx0XHRpZiAodGhpcy5jdXJyZW50UXVlcnkpIHtcclxuXHRcdFx0XHR0aGlzLnNob3dMb2FkaW5nKHRydWUpO1xyXG5cdFx0XHRcdHZvaWQgdGhpcy5wZXJmb3JtU2VhcmNoKHRoaXMuY3VycmVudFF1ZXJ5LCB0cnVlKTtcclxuXHRcdFx0fVxyXG5cdFx0fSk7XHJcblxyXG5cdFx0Ly8gU2l6ZSBjaGFuZ2VcclxuXHRcdHRoaXMuc2l6ZVNlbGVjdD8uYWRkRXZlbnRMaXN0ZW5lcignY2hhbmdlJywgKGUpID0+IHtcclxuXHRcdFx0Y29uc3Qgc2l6ZSA9IChlLnRhcmdldCBhcyBIVE1MU2VsZWN0RWxlbWVudCkudmFsdWUgYXMgSW1hZ2VTaXplO1xyXG5cdFx0XHR0aGlzLnNldHRpbmdzLmRlZmF1bHRJbWFnZVNpemUgPSBzaXplO1xyXG5cdFx0XHQvLyBSZS1zZWFyY2ggaWYgd2UgaGF2ZSBhIHF1ZXJ5XHJcblx0XHRcdGlmICh0aGlzLmN1cnJlbnRRdWVyeSkge1xyXG5cdFx0XHRcdHRoaXMuc2hvd0xvYWRpbmcodHJ1ZSk7XHJcblx0XHRcdFx0dm9pZCB0aGlzLnBlcmZvcm1TZWFyY2godGhpcy5jdXJyZW50UXVlcnksIHRydWUpO1xyXG5cdFx0XHR9XHJcblx0XHR9KTtcclxuXHR9XHJcblxyXG5cdHByaXZhdGUgYXN5bmMgcGVyZm9ybVNlYXJjaChxdWVyeTogc3RyaW5nLCByZXNldFBhZ2U6IGJvb2xlYW4gPSBmYWxzZSk6IFByb21pc2U8dm9pZD4ge1xyXG5cdFx0aWYgKHRoaXMuaXNMb2FkaW5nKSByZXR1cm47XHJcblxyXG5cdFx0dGhpcy5jdXJyZW50UXVlcnkgPSBxdWVyeTtcclxuXHRcdGlmIChyZXNldFBhZ2UpIHtcclxuXHRcdFx0dGhpcy5jdXJyZW50UGFnZSA9IDE7XHJcblx0XHR9XHJcblx0XHR0aGlzLmlzTG9hZGluZyA9IHRydWU7XHJcblx0XHR0aGlzLnNob3dMb2FkaW5nKHRydWUpO1xyXG5cclxuXHRcdHRyeSB7XHJcblx0XHRcdHRoaXMuY3VycmVudFJlc3VsdHMgPSBhd2FpdCB0aGlzLnJlbW90ZVNlcnZpY2Uuc2VhcmNoKFxyXG5cdFx0XHRcdHF1ZXJ5LFxyXG5cdFx0XHRcdHRoaXMuY3VycmVudFByb3ZpZGVyLFxyXG5cdFx0XHRcdHRoaXMuY3VycmVudFBhZ2VcclxuXHRcdFx0KTtcclxuXHRcdFx0dGhpcy5zZWxlY3RlZEltYWdlID0gMDtcclxuXHRcdFx0dGhpcy5yZW5kZXJSZXN1bHRzKCk7XHJcblx0XHR9IGNhdGNoIChlcnJvcikge1xyXG5cdFx0XHRjb25zb2xlLmVycm9yKCdTZWFyY2ggZmFpbGVkOicsIGVycm9yKTtcclxuXHRcdFx0Y29uc3QgZXJyb3JNc2cgPSBlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IubWVzc2FnZSA6ICdTZWFyY2ggZmFpbGVkJztcclxuXHRcdFx0bmV3IE5vdGljZShgUmVxdWVzdCBmYWlsZWQsIHN0YXR1cyAke2Vycm9yTXNnfWApO1xyXG5cdFx0XHR0aGlzLnJlbmRlckVycm9yKGVycm9yTXNnKTtcclxuXHRcdH0gZmluYWxseSB7XHJcblx0XHRcdHRoaXMuaXNMb2FkaW5nID0gZmFsc2U7XHJcblx0XHRcdHRoaXMuc2hvd0xvYWRpbmcoZmFsc2UpO1xyXG5cdFx0fVxyXG5cdH1cclxuXHJcblx0cHJpdmF0ZSByZW5kZXJSZXN1bHRzKCk6IHZvaWQge1xyXG5cdFx0aWYgKCF0aGlzLmltYWdlc0xpc3QpIHJldHVybjtcclxuXHRcdHRoaXMuaW1hZ2VzTGlzdC5lbXB0eSgpO1xyXG5cclxuXHRcdGlmICh0aGlzLmN1cnJlbnRSZXN1bHRzLmxlbmd0aCA9PT0gMCkge1xyXG5cdFx0XHRjb25zdCBub1Jlc3VsdCA9IHRoaXMuaW1hZ2VzTGlzdC5jcmVhdGVEaXYoeyBjbHM6ICduby1yZXN1bHQtY29udGFpbmVyJyB9KTtcclxuXHRcdFx0bm9SZXN1bHQuc2V0VGV4dCgnTm8gcmVzdWx0cyBmb3VuZCcpO1xyXG5cdFx0XHRyZXR1cm47XHJcblx0XHR9XHJcblxyXG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLmN1cnJlbnRSZXN1bHRzLmxlbmd0aDsgaSsrKSB7XHJcblx0XHRcdGNvbnN0IGltYWdlID0gdGhpcy5jdXJyZW50UmVzdWx0c1tpXTtcclxuXHRcdFx0aWYgKCFpbWFnZSkgY29udGludWU7XHJcblxyXG5cdFx0XHRjb25zdCByZXN1bHQgPSB0aGlzLmltYWdlc0xpc3QuY3JlYXRlRGl2KHtcclxuXHRcdFx0XHRjbHM6IGBxdWVyeS1yZXN1bHQke2kgPT09IHRoaXMuc2VsZWN0ZWRJbWFnZSA/ICcgaXMtc2VsZWN0ZWQnIDogJyd9YCxcclxuXHRcdFx0fSk7XHJcblxyXG5cdFx0XHRyZXN1bHQuY3JlYXRlRWwoJ2ltZycsIHtcclxuXHRcdFx0XHRhdHRyOiB7XHJcblx0XHRcdFx0XHRzcmM6IGltYWdlLnRodW1ibmFpbFVybCxcclxuXHRcdFx0XHRcdGFsdDogaW1hZ2UuZGVzY3JpcHRpb24gfHwgJ0ltYWdlJyxcclxuXHRcdFx0XHR9LFxyXG5cdFx0XHR9KTtcclxuXHJcblx0XHRcdHJlc3VsdC5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsICgpID0+IHtcclxuXHRcdFx0XHR2b2lkIHRoaXMuaW5zZXJ0SW1hZ2UoaW1hZ2UpO1xyXG5cdFx0XHR9KTtcclxuXHJcblx0XHRcdHJlc3VsdC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZW1vdmUnLCAoKSA9PiB7XHJcblx0XHRcdFx0dGhpcy5zZWxlY3RlZEltYWdlID0gaTtcclxuXHRcdFx0XHR0aGlzLnJlbmRlclJlc3VsdHMoKTtcclxuXHRcdFx0fSk7XHJcblx0XHR9XHJcblxyXG5cdFx0Ly8gUGFnaW5hdGlvblxyXG5cdFx0dGhpcy5yZW5kZXJQYWdpbmF0aW9uKCk7XHJcblx0fVxyXG5cclxuXHRwcml2YXRlIHJlbmRlclBhZ2luYXRpb24oKTogdm9pZCB7XHJcblx0XHRpZiAoIXRoaXMuc2Nyb2xsQXJlYSkgcmV0dXJuO1xyXG5cclxuXHRcdC8vIFJlbW92ZSBleGlzdGluZyBwYWdpbmF0aW9uXHJcblx0XHRjb25zdCBleGlzdGluZ1BhZ2luYXRpb24gPSB0aGlzLnNjcm9sbEFyZWEucXVlcnlTZWxlY3RvcignLnBhZ2luYXRpb24nKTtcclxuXHRcdGlmIChleGlzdGluZ1BhZ2luYXRpb24pIHtcclxuXHRcdFx0ZXhpc3RpbmdQYWdpbmF0aW9uLnJlbW92ZSgpO1xyXG5cdFx0fVxyXG5cclxuXHRcdC8vIENoZWNrIGlmIHdlIGhhdmUgbW9yZSBwYWdlcyAoc2ltcGxpZmllZCAtIHdvdWxkIG5lZWQgYWN0dWFsIHBhZ2luYXRpb24gaW5mbyBmcm9tIEFQSSlcclxuXHRcdGNvbnN0IGhhc01vcmUgPSB0aGlzLmN1cnJlbnRSZXN1bHRzLmxlbmd0aCA+PSAyMDtcclxuXHJcblx0XHRpZiAoaGFzTW9yZSB8fCB0aGlzLmN1cnJlbnRQYWdlID4gMSkge1xyXG5cdFx0XHRjb25zdCBwYWdpbmF0aW9uID0gdGhpcy5zY3JvbGxBcmVhLmNyZWF0ZURpdih7IGNsczogJ3BhZ2luYXRpb24nIH0pO1xyXG5cclxuXHRcdFx0aWYgKHRoaXMuY3VycmVudFBhZ2UgPiAxKSB7XHJcblx0XHRcdFx0Y29uc3QgcHJldkJ0biA9IHBhZ2luYXRpb24uY3JlYXRlRWwoJ2J1dHRvbicsIHsgY2xzOiAnYnRuJywgdGV4dDogJ1ByZXZpb3VzJyB9KTtcclxuXHRcdFx0XHRwcmV2QnRuLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgKCkgPT4ge1xyXG5cdFx0XHRcdFx0dGhpcy5jdXJyZW50UGFnZS0tO1xyXG5cdFx0XHRcdFx0dGhpcy5zaG93TG9hZGluZyh0cnVlKTtcclxuXHRcdFx0XHRcdHZvaWQgdGhpcy5wZXJmb3JtU2VhcmNoKHRoaXMuY3VycmVudFF1ZXJ5KTtcclxuXHRcdFx0XHR9KTtcclxuXHRcdFx0fVxyXG5cclxuXHRcdFx0aWYgKGhhc01vcmUpIHtcclxuXHRcdFx0XHRjb25zdCBuZXh0QnRuID0gcGFnaW5hdGlvbi5jcmVhdGVFbCgnYnV0dG9uJywgeyBjbHM6ICdidG4nLCB0ZXh0OiAnTmV4dCcgfSk7XHJcblx0XHRcdFx0bmV4dEJ0bi5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsICgpID0+IHtcclxuXHRcdFx0XHRcdHRoaXMuY3VycmVudFBhZ2UrKztcclxuXHRcdFx0XHRcdHRoaXMuc2hvd0xvYWRpbmcodHJ1ZSk7XHJcblx0XHRcdFx0XHR2b2lkIHRoaXMucGVyZm9ybVNlYXJjaCh0aGlzLmN1cnJlbnRRdWVyeSk7XHJcblx0XHRcdFx0fSk7XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHR9XHJcblxyXG5cdHByaXZhdGUgcmVuZGVyRXJyb3IobWVzc2FnZTogc3RyaW5nKTogdm9pZCB7XHJcblx0XHRpZiAoIXRoaXMuaW1hZ2VzTGlzdCkgcmV0dXJuO1xyXG5cdFx0dGhpcy5pbWFnZXNMaXN0LmVtcHR5KCk7XHJcblx0XHRjb25zdCBlcnJvckRpdiA9IHRoaXMuaW1hZ2VzTGlzdC5jcmVhdGVEaXYoeyBjbHM6ICduby1yZXN1bHQtY29udGFpbmVyIGVycm9yLXRleHQnIH0pO1xyXG5cdFx0ZXJyb3JEaXYuc2V0VGV4dChgRXJyb3I6ICR7bWVzc2FnZX1gKTtcclxuXHR9XHJcblxyXG5cdHByaXZhdGUgY2xlYXJSZXN1bHRzKCk6IHZvaWQge1xyXG5cdFx0aWYgKHRoaXMuaW1hZ2VzTGlzdCkge1xyXG5cdFx0XHR0aGlzLmltYWdlc0xpc3QuZW1wdHkoKTtcclxuXHRcdH1cclxuXHRcdHRoaXMuY3VycmVudFJlc3VsdHMgPSBbXTtcclxuXHR9XHJcblxyXG5cdHByaXZhdGUgc2hvd0xvYWRpbmcoc2hvdzogYm9vbGVhbik6IHZvaWQge1xyXG5cdFx0aWYgKHRoaXMubG9hZGluZ0NvbnRhaW5lcikge1xyXG5cdFx0XHR0aGlzLmxvYWRpbmdDb250YWluZXIuc3R5bGUuZGlzcGxheSA9IHNob3cgPyAnZmxleCcgOiAnbm9uZSc7XHJcblx0XHR9XHJcblx0XHRpZiAodGhpcy5zY3JvbGxBcmVhKSB7XHJcblx0XHRcdGlmIChzaG93KSB7XHJcblx0XHRcdFx0dGhpcy5zY3JvbGxBcmVhLmFkZENsYXNzKCdsb2FkaW5nJyk7XHJcblx0XHRcdH0gZWxzZSB7XHJcblx0XHRcdFx0dGhpcy5zY3JvbGxBcmVhLnJlbW92ZUNsYXNzKCdsb2FkaW5nJyk7XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHR9XHJcblxyXG5cdHByaXZhdGUgYXN5bmMgaW5zZXJ0SW1hZ2UoaW1hZ2U6IFJlbW90ZUltYWdlKTogUHJvbWlzZTx2b2lkPiB7XHJcblx0XHR0aGlzLmNsb3NlKCk7XHJcblxyXG5cdFx0Y29uc3QgYWN0aXZlRmlsZSA9IHRoaXMuZ2V0QWN0aXZlRmlsZSgpO1xyXG5cdFx0aWYgKCFhY3RpdmVGaWxlKSB7XHJcblx0XHRcdG5ldyBOb3RpY2UoJ05vIGFjdGl2ZSBmaWxlJyk7XHJcblx0XHRcdHJldHVybjtcclxuXHRcdH1cclxuXHJcblx0XHR0cnkge1xyXG5cdFx0XHQvLyBHZXQgZG93bmxvYWQgVVJMIGJhc2VkIG9uIHNpemVcclxuXHRcdFx0Y29uc3QgZG93bmxvYWRVcmwgPSB0aGlzLnJlbW90ZVNlcnZpY2UuZ2V0RG93bmxvYWRVcmwoaW1hZ2UsIHRoaXMuc2V0dGluZ3MuZGVmYXVsdEltYWdlU2l6ZSk7XHJcblxyXG5cdFx0XHRpZiAodGhpcy5vcHRpb25zLmluc2VydFRvUHJvcGVydHkpIHtcclxuXHRcdFx0XHQvLyBWYWxpZGF0ZSBwcm9wZXJ0eSBuYW1lXHJcblx0XHRcdFx0aWYgKCF0aGlzLm9wdGlvbnMucHJvcGVydHlOYW1lIHx8IHRoaXMub3B0aW9ucy5wcm9wZXJ0eU5hbWUudHJpbSgpID09PSAnJykge1xyXG5cdFx0XHRcdFx0bmV3IE5vdGljZSgnUGxlYXNlIHNwZWNpZnkgYSBwcm9wZXJ0eSBuYW1lIGluIHNldHRpbmdzJyk7XHJcblx0XHRcdFx0XHRyZXR1cm47XHJcblx0XHRcdFx0fVxyXG5cclxuXHRcdFx0XHQvLyBJbnNlcnQgaW50byBwcm9wZXJ0eSAoY3JlYXRlIGlmIGl0IGRvZXNuJ3QgZXhpc3QpXHJcblx0XHRcdFx0Ly8gUGFzcyBSZW1vdGVJbWFnZSBzbyBQcm9wZXJ0eUhhbmRsZXIgY2FuIGdlbmVyYXRlIHJlZmVycmFsIHRleHQgaWYgbmVlZGVkXHJcblx0XHRcdFx0YXdhaXQgdGhpcy5wcm9wZXJ0eUhhbmRsZXIuaW5zZXJ0SW1hZ2VGcm9tVXJsKFxyXG5cdFx0XHRcdFx0ZG93bmxvYWRVcmwsXHJcblx0XHRcdFx0XHRhY3RpdmVGaWxlLFxyXG5cdFx0XHRcdFx0dGhpcy5vcHRpb25zLnByb3BlcnR5TmFtZSxcclxuXHRcdFx0XHRcdGltYWdlLCAvLyBQYXNzIFJlbW90ZUltYWdlIGZvciByZWZlcnJhbCB0ZXh0IGdlbmVyYXRpb25cclxuXHRcdFx0XHRcdHRoaXMuY3VycmVudFF1ZXJ5IC8vIFBhc3Mgc2VhcmNoIHRlcm0gYXMgc3VnZ2VzdGVkIG5hbWVcclxuXHRcdFx0XHQpO1xyXG5cdFx0XHR9IGVsc2Uge1xyXG5cdFx0XHRcdC8vIEluc2VydCBpbnRvIG5vdGUgYm9keVxyXG5cdFx0XHRcdGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMuaW1hZ2VQcm9jZXNzb3IucHJvY2Vzc0ltYWdlVXJsKFxyXG5cdFx0XHRcdFx0ZG93bmxvYWRVcmwsXHJcblx0XHRcdFx0XHRhY3RpdmVGaWxlLFxyXG5cdFx0XHRcdFx0dHJ1ZSwgLy8gU2hvdyByZW5hbWUgbW9kYWxcclxuXHRcdFx0XHRcdGZhbHNlLCAvLyBOb3QgcHJvcGVydHkgaW5zZXJ0aW9uXHJcblx0XHRcdFx0XHR0aGlzLmN1cnJlbnRRdWVyeSAvLyBQYXNzIHNlYXJjaCB0ZXJtIGFzIHN1Z2dlc3RlZCBuYW1lXHJcblx0XHRcdFx0KTtcclxuXHJcblx0XHRcdFx0aWYgKHJlc3VsdC5zdWNjZXNzICYmIHJlc3VsdC5saW5rVGV4dCkge1xyXG5cdFx0XHRcdFx0Ly8gR2VuZXJhdGUgcmVmZXJyYWwgdGV4dCBhbmQgYXBwZW5kIGl0XHJcblx0XHRcdFx0XHRjb25zdCByZWZlcnJhbFRleHQgPSB0aGlzLnJlbW90ZVNlcnZpY2UuZ2VuZXJhdGVSZWZlcnJhbFRleHQoaW1hZ2UpO1xyXG5cdFx0XHRcdFx0Y29uc3QgZnVsbFRleHQgPSByZXN1bHQubGlua1RleHQgKyByZWZlcnJhbFRleHQ7XHJcblxyXG5cdFx0XHRcdFx0Y29uc3QgdmlldyA9IHRoaXMuYXBwLndvcmtzcGFjZS5nZXRBY3RpdmVWaWV3T2ZUeXBlKE1hcmtkb3duVmlldyk7XHJcblx0XHRcdFx0XHRpZiAodmlldz8uZWRpdG9yKSB7XHJcblx0XHRcdFx0XHRcdHZpZXcuZWRpdG9yLnJlcGxhY2VTZWxlY3Rpb24oZnVsbFRleHQpO1xyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdH1cclxuXHRcdFx0fVxyXG5cdFx0fSBjYXRjaCAoZXJyb3IpIHtcclxuXHRcdFx0Y29uc29sZS5lcnJvcignRmFpbGVkIHRvIGluc2VydCBpbWFnZTonLCBlcnJvcik7XHJcblx0XHRcdG5ldyBOb3RpY2UoYEZhaWxlZCB0byBpbnNlcnQgaW1hZ2U6ICR7ZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yLm1lc3NhZ2UgOiBTdHJpbmcoZXJyb3IpfWApO1xyXG5cdFx0fVxyXG5cdH1cclxuXHJcblx0cHJpdmF0ZSBnZXRBY3RpdmVGaWxlKCk6IFRGaWxlIHwgbnVsbCB7XHJcblx0XHRjb25zdCB2aWV3ID0gdGhpcy5hcHAud29ya3NwYWNlLmdldEFjdGl2ZVZpZXdPZlR5cGUoTWFya2Rvd25WaWV3KTtcclxuXHRcdHJldHVybiB2aWV3Py5maWxlID8/IG51bGw7XHJcblx0fVxyXG5cclxuXHRvbkNsb3NlKCk6IHZvaWQge1xyXG5cdFx0Y29uc3QgeyBjb250ZW50RWwgfSA9IHRoaXM7XHJcblx0XHRjb250ZW50RWwuZW1wdHkoKTtcclxuXHR9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBPcGVuIHRoZSByZW1vdGUgc2VhcmNoIG1vZGFsXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gb3BlblJlbW90ZVNlYXJjaChcclxuXHRhcHA6IEFwcCxcclxuXHRzZXR0aW5nczogSW1hZ2VNYW5hZ2VyU2V0dGluZ3MsXHJcblx0cmVtb3RlU2VydmljZTogUmVtb3RlSW1hZ2VTZXJ2aWNlLFxyXG5cdGltYWdlUHJvY2Vzc29yOiBJbWFnZVByb2Nlc3NvcixcclxuXHRwcm9wZXJ0eUhhbmRsZXI6IFByb3BlcnR5SGFuZGxlcixcclxuXHRvcHRpb25zOiBSZW1vdGVTZWFyY2hPcHRpb25zID0ge31cclxuKTogdm9pZCB7XHJcblx0bmV3IFJlbW90ZVNlYXJjaE1vZGFsKGFwcCwgc2V0dGluZ3MsIHJlbW90ZVNlcnZpY2UsIGltYWdlUHJvY2Vzc29yLCBwcm9wZXJ0eUhhbmRsZXIsIG9wdGlvbnMpLm9wZW4oKTtcclxufVxyXG4iXSwKICAibWFwcGluZ3MiOiAiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQWlGTyxTQUFTLGlCQUNmLEtBQ0EsT0FDQSxTQUNBLGNBQXNCLFdBQ3RCLGFBQXFCLFVBQ0k7QUFDekIsUUFBTSxRQUFRLElBQUksYUFBYSxLQUFLLE9BQU8sU0FBUyxhQUFhLFVBQVU7QUFDM0UsU0FBTyxNQUFNLG1CQUFtQjtBQUNqQztBQTFGQSxJQUtBQSxtQkFNYTtBQVhiO0FBQUE7QUFLQSxJQUFBQSxvQkFBMkI7QUFNcEIsSUFBTSxlQUFOLGNBQTJCLHdCQUFNO0FBQUEsTUFPdkMsWUFDQyxLQUNBLE9BQ0EsU0FDQSxjQUFzQixX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QUFDLENBQUM7QUFBQSxFQUMvRDtBQUFBO0FBQUE7QUFBQTtBQUFBLEVBS0EsTUFBTSxlQUE4QjtBQUNuQyxVQUFNLEtBQUssU0FBUyxLQUFLLFFBQVE7QUFHakMsU0FBSyxtQkFBbUIsT0FBTyxLQUFLLFFBQVE7QUFBQSxFQUM3QztBQUFBO0FBQUE7QUFBQTtBQUFBLEVBS1EsT0FBTyxNQUF1QjtBQWhjdkM7QUFpY0UsU0FBSSxVQUFLLGFBQUwsbUJBQWUsV0FBVztBQUM3QixjQUFRLE1BQU0sbUJBQW1CLEdBQUcsSUFBSTtBQUFBLElBQ3pDO0FBQUEsRUFDRDtBQUNEOyIsCiAgIm5hbWVzIjogWyJpbXBvcnRfb2JzaWRpYW4iLCAiaW1wb3J0X29ic2lkaWFuIiwgImltcG9ydF9vYnNpZGlhbiIsICJpbXBvcnRfb2JzaWRpYW4iLCAiaW1wb3J0X29ic2lkaWFuIiwgImltcG9ydF9vYnNpZGlhbiIsICJmaW5hbE5hbWUiLCAiaW1wb3J0X29ic2lkaWFuIiwgImltcG9ydF9vYnNpZGlhbiIsICJpbXBvcnRfb2JzaWRpYW4iLCAiaW1wb3J0X29ic2lkaWFuIiwgImltcG9ydF9vYnNpZGlhbiIsICJpbXBvcnRfb2JzaWRpYW4iLCAicHJvcGVydHlTZXR0aW5ncyIsICJpbWFnZVByb3AiLCAiaWNvblByb3AiLCAiaW1wb3J0X29ic2lkaWFuIiwgImltcG9ydF9vYnNpZGlhbiIsICJfYSIsICJvcGVuQ29uZmlybU1vZGFsIl0KfQo=